This commit is contained in:
Gilles Soulier
2026-01-05 16:08:01 +01:00
parent dcba044cd6
commit c67befc549
2215 changed files with 26743 additions and 329 deletions

View File

@@ -100,27 +100,36 @@ function escapeHtml(text) {
// Copy text to clipboard
async function copyToClipboard(text) {
try {
await navigator.clipboard.writeText(text);
return true;
} catch (err) {
console.error('Failed to copy:', err);
// Fallback for older browsers
const textArea = document.createElement('textarea');
textArea.value = text;
textArea.style.position = 'fixed';
textArea.style.left = '-999999px';
document.body.appendChild(textArea);
textArea.select();
// Try modern clipboard API first
if (navigator.clipboard && navigator.clipboard.writeText) {
try {
document.execCommand('copy');
document.body.removeChild(textArea);
await navigator.clipboard.writeText(text);
return true;
} catch (err) {
document.body.removeChild(textArea);
return false;
console.error('Clipboard API failed:', err);
// Fall through to fallback method
}
}
// Fallback for older browsers or non-HTTPS contexts
const textArea = document.createElement('textarea');
textArea.value = text;
textArea.style.position = 'fixed';
textArea.style.left = '-999999px';
textArea.style.top = '0';
document.body.appendChild(textArea);
textArea.focus();
textArea.select();
try {
const successful = document.execCommand('copy');
document.body.removeChild(textArea);
return successful;
} catch (err) {
console.error('Fallback copy failed:', err);
document.body.removeChild(textArea);
return false;
}
}
// Show toast notification
@@ -432,6 +441,75 @@ function renderMarkdown(text) {
return `<div class="markdown-block">${html}</div>`;
}
// Additional utility functions for peripherals module
function formatDateTime(dateString) {
if (!dateString) return 'N/A';
const date = new Date(dateString);
return date.toLocaleString('fr-FR', {
year: 'numeric',
month: 'long',
day: 'numeric',
hour: '2-digit',
minute: '2-digit'
});
}
function formatBytes(bytes) {
return formatFileSize(bytes);
}
function showSuccess(message) {
showToast(message, 'success');
}
function showInfo(message) {
showToast(message, 'info');
}
// API request helper
async function apiRequest(endpoint, options = {}) {
const config = window.CONFIG || { API_BASE_URL: 'http://localhost:8007/api' };
const url = `${config.API_BASE_URL}${endpoint}`;
const defaultOptions = {
headers: {}
};
// Don't set Content-Type for FormData (browser will set it with boundary)
if (options.body && !(options.body instanceof FormData)) {
defaultOptions.headers['Content-Type'] = 'application/json';
}
const response = await fetch(url, {
...defaultOptions,
...options,
headers: {
...defaultOptions.headers,
...options.headers
}
});
if (!response.ok) {
let message = `HTTP ${response.status}: ${response.statusText}`;
try {
const data = await response.json();
if (data && typeof data === 'object') {
message = data.detail || data.message || message;
}
} catch (error) {
// Ignore JSON parse errors and keep default message.
}
throw new Error(message);
}
// Handle 204 No Content
if (response.status === 204) {
return null;
}
return response.json();
}
window.BenchUtils = {
formatDate,
formatRelativeTime,
@@ -461,5 +539,10 @@ window.BenchUtils = {
formatStorage,
formatCache,
formatTemperature,
renderMarkdown
renderMarkdown,
formatDateTime,
formatBytes,
showSuccess,
showInfo,
apiRequest
};