refactor(frontend): polish ExportDataModal (derived selection, safe URL revoke, error escape)

This commit is contained in:
Experiments DB Dev
2026-07-06 15:46:52 -04:00
parent ea76cf9cd2
commit 0bf3fc479b
+13 -9
View File
@@ -15,7 +15,7 @@ function triggerDownload(filename, text) {
document.body.appendChild(a); document.body.appendChild(a);
a.click(); a.click();
document.body.removeChild(a); document.body.removeChild(a);
URL.revokeObjectURL(url); setTimeout(() => URL.revokeObjectURL(url), 0);
} }
export default function ExportDataModal({ experimentTitle, experimentId, dailyTemplate, animals, onClose }) { export default function ExportDataModal({ experimentTitle, experimentId, dailyTemplate, animals, onClose }) {
@@ -37,12 +37,9 @@ export default function ExportDataModal({ experimentTitle, experimentId, dailyTe
const params = useMemo(() => listExportableParams(dailyTemplate, statuses), [dailyTemplate, statuses]); const params = useMemo(() => listExportableParams(dailyTemplate, statuses), [dailyTemplate, statuses]);
// Default the selection to the first parameter once params are available. // Derive the effective selection: the user's pick, else the first parameter.
useEffect(() => { const effectiveId = selectedId ?? params[0]?.id ?? null;
if (selectedId === null && params.length > 0) setSelectedId(params[0].id); const selectedParam = params.find((p) => p.id === effectiveId) ?? null;
}, [params, selectedId]);
const selectedParam = params.find((p) => p.id === selectedId) ?? null;
const matrix = useMemo( const matrix = useMemo(
() => (selectedParam ? buildMatrix(statuses, animals, selectedParam) : { columns: [], rows: [] }), () => (selectedParam ? buildMatrix(statuses, animals, selectedParam) : { columns: [], rows: [] }),
@@ -69,7 +66,14 @@ export default function ExportDataModal({ experimentTitle, experimentId, dailyTe
} }
if (loading) return <p className="text-sm text-gray-400" aria-live="polite">Loading data</p>; if (loading) return <p className="text-sm text-gray-400" aria-live="polite">Loading data</p>;
if (error) return <Alert type="error" message={error} />; if (error) return (
<div className="space-y-4">
<Alert type="error" message={error} />
<div className="flex justify-end">
<Button variant="secondary" onClick={onClose}>Close</Button>
</div>
</div>
);
return ( return (
<div className="space-y-4"> <div className="space-y-4">
@@ -81,7 +85,7 @@ export default function ExportDataModal({ experimentTitle, experimentId, dailyTe
<label htmlFor="export-param" className="block text-xs font-medium text-gray-500 mb-1">Parameter</label> <label htmlFor="export-param" className="block text-xs font-medium text-gray-500 mb-1">Parameter</label>
<select <select
id="export-param" id="export-param"
value={selectedId ?? ''} value={effectiveId ?? ''}
onChange={(e) => setSelectedId(e.target.value)} onChange={(e) => setSelectedId(e.target.value)}
className="w-full border border-gray-200 rounded px-2 py-1.5 text-sm bg-white focus:outline-none focus:ring-1 focus:ring-indigo-400" className="w-full border border-gray-200 rounded px-2 py-1.5 text-sm bg-white focus:outline-none focus:ring-1 focus:ring-indigo-400"
> >