GwenONERA
first
e4361b1
Raw
History Blame Contribute Delete
6.5 kB
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 = '<option disabled selected>Erreur de chargement</option>';
}
}
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 = '<tr><td colspan="8">Erreur lors du chargement des données.</td></tr>';
}
}
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 = `
<td>${escapeHtml(m.display_name)}</td>
<td style="color: ${f1Color}">${m.f1.toFixed(3)}</td>
<td style="color: ${precColor}">${m.precision.toFixed(3)}</td>
<td style="color: ${recColor}">${m.recall.toFixed(3)}</td>
<td class="cell-clickable" data-label="${escapeHtml(m.label)}" data-outcome="fn">${m.fn}</td>
<td class="cell-clickable" data-label="${escapeHtml(m.label)}" data-outcome="fp">${m.fp}</td>
<td class="cell-clickable" data-label="${escapeHtml(m.label)}" data-outcome="tn">${m.tn}</td>
<td class="cell-clickable" data-label="${escapeHtml(m.label)}" data-outcome="tp">${m.tp}</td>
`;
tbody.appendChild(tr);
});
const macroColor = getMetricColor(macroF1);
tfoot.innerHTML = `
<tr>
<td style="font-style:italic;">Macro avg</td>
<td style="color: ${macroColor}">${macroF1.toFixed(3)}</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
`;
// 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 = '<div class="instances-empty">Aucune phrase à afficher.</div>';
}
} catch (err) {
console.error('Failed to load instances', err);
instancesTitle.textContent = "Erreur de chargement";
instancesList.innerHTML = '<div class="instances-empty">Impossible de charger les instances.</div>';
}
}
function clearInstances() {
instancesTitle.textContent = "Cliquez sur une cellule pour voir les instances";
instancesList.innerHTML = '<div class="instances-empty">Aucune phrase à afficher.</div>';
if (selectedCell) {
selectedCell.classList.remove('cell-selected');
selectedCell = null;
}
}
function escapeHtml(unsafe) {
return (unsafe || '').toString()
.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;")
.replace(/'/g, "&#039;");
}
});