document.addEventListener('DOMContentLoaded', () => { const configSelect = document.getElementById('config-select'); const tbody = document.getElementById('metrics-tbody'); const tfoot = document.getElementById('metrics-tfoot'); const instancesList = document.getElementById('instances-list'); const instancesTitle = document.getElementById('instances-title'); let currentConfig = null; let selectedCell = null; // Initialize fetchConfigs(); configSelect.addEventListener('change', (e) => { currentConfig = e.target.value; loadMetrics(currentConfig); clearInstances(); }); async function fetchConfigs() { try { const res = await fetch('/api/configs'); const data = await res.json(); configSelect.innerHTML = ''; if (data.configs.length === 0) { const opt = document.createElement('option'); opt.text = 'Aucune configuration trouvée'; opt.disabled = true; configSelect.appendChild(opt); return; } data.configs.forEach((conf, idx) => { const opt = document.createElement('option'); opt.value = conf; opt.text = conf; if (idx === 0) { opt.selected = true; currentConfig = conf; } configSelect.appendChild(opt); }); if (currentConfig) { loadMetrics(currentConfig); } } catch (err) { console.error('Failed to fetch configs', err); configSelect.innerHTML = ''; } } async function loadMetrics(configName) { try { const res = await fetch(`/api/configs/${encodeURIComponent(configName)}/metrics`); const data = await res.json(); renderTable(data.metrics, data.macro_f1); } catch (err) { console.error('Failed to load metrics', err); tbody.innerHTML = 'Erreur lors du chargement des données.'; } } function getMetricColor(value) { if (value >= 0.8) return 'var(--metric-good)'; if (value >= 0.5) return 'var(--metric-ok)'; return 'var(--metric-bad)'; } function renderTable(metrics, macroF1) { tbody.innerHTML = ''; metrics.forEach(m => { const tr = document.createElement('tr'); const f1Color = getMetricColor(m.f1); const precColor = getMetricColor(m.precision); const recColor = getMetricColor(m.recall); tr.innerHTML = ` ${escapeHtml(m.display_name)} ${m.f1.toFixed(3)} ${m.precision.toFixed(3)} ${m.recall.toFixed(3)} ${m.fn} ${m.fp} ${m.tn} ${m.tp} `; tbody.appendChild(tr); }); const macroColor = getMetricColor(macroF1); tfoot.innerHTML = ` Macro avg ${macroF1.toFixed(3)} `; // Attach event listeners to clickable cells const clickableCells = tbody.querySelectorAll('.cell-clickable'); clickableCells.forEach(cell => { cell.addEventListener('click', onCellClick); }); } async function onCellClick(e) { if (!currentConfig) return; const cell = e.currentTarget; const label = cell.getAttribute('data-label'); const outcome = cell.getAttribute('data-outcome'); // Manage selection state if (selectedCell) { selectedCell.classList.remove('cell-selected'); } selectedCell = cell; selectedCell.classList.add('cell-selected'); try { const res = await fetch(`/api/configs/${encodeURIComponent(currentConfig)}/instances?label=${encodeURIComponent(label)}&outcome=${encodeURIComponent(outcome)}`); const data = await res.json(); instancesTitle.textContent = data.title; instancesList.innerHTML = ''; if (data.texts && data.texts.length > 0) { data.texts.forEach(text => { const div = document.createElement('div'); div.className = 'instance-item'; div.textContent = text; instancesList.appendChild(div); }); } else { instancesList.innerHTML = '
Aucune phrase à afficher.
'; } } catch (err) { console.error('Failed to load instances', err); instancesTitle.textContent = "Erreur de chargement"; instancesList.innerHTML = '
Impossible de charger les instances.
'; } } function clearInstances() { instancesTitle.textContent = "Cliquez sur une cellule pour voir les instances"; instancesList.innerHTML = '
Aucune phrase à afficher.
'; if (selectedCell) { selectedCell.classList.remove('cell-selected'); selectedCell = null; } } function escapeHtml(unsafe) { return (unsafe || '').toString() .replace(/&/g, "&") .replace(//g, ">") .replace(/"/g, """) .replace(/'/g, "'"); } });