Fix coverage: add /api/coverage route, remove stray gather code from loadCoverage

This commit is contained in:
Floppyrj45
2026-02-19 14:53:10 +01:00
parent 61b25ab734
commit bbd6a22b57
80 changed files with 27884 additions and 1 deletions

View File

@@ -0,0 +1,113 @@
import { useState, useEffect, useMemo } from 'react';
import Plot from 'react-plotly.js';
interface SeismicSectionProps {
nodes: any[];
currentTime: number;
channel: string;
visible: boolean;
onClose: () => void;
}
const API_BASE = '/seismic/api';
function SeismicSection({ nodes, currentTime, channel, visible, onClose }: SeismicSectionProps) {
const [data, setData] = useState<any>(null);
const [viewMode, setViewMode] = useState<'day' | 'global'>('day');
const [loading, setLoading] = useState(false);
useEffect(() => {
if (!visible) return;
setLoading(true);
const url = viewMode === 'global'
? `${API_BASE}/global-history?channel=${channel}`
: `${API_BASE}/rms-timeline?date=${new Date(currentTime * 1000).toISOString().split('T')[0]}&channel=${channel}`;
fetch(url)
.then(r => r.json())
.then(d => {
setData(d.nodes);
setLoading(false);
})
.catch(() => setLoading(false));
}, [visible, viewMode, channel, currentTime]);
useEffect(() => {
if (!visible) return;
const handleEscape = (e: KeyboardEvent) => {
if (e.key === 'Escape') onClose();
};
document.addEventListener('keydown', handleEscape);
return () => document.removeEventListener('keydown', handleEscape);
}, [visible, onClose]);
const plotData = useMemo(() => {
if (!data) return [];
const traces: any[] = [];
const nodeIds = Object.keys(data).sort();
nodeIds.forEach((id, index) => {
const points = data[id];
if (!points || points.length === 0) return;
const maxRms = Math.max(...points.map((p: any) => p.rms)) || 1;
traces.push({
x: points.map((p: any) => new Date(p.ts * 1000)),
y: points.map((p: any) => (p.rms / maxRms) * 0.9 + index),
type: 'scatter',
mode: 'lines',
name: `Node ${id}`,
line: { color: '#4ade80', width: 1 },
fill: 'tonexty',
showlegend: false
});
});
return traces;
}, [data]);
if (!visible) return null;
return (
<div style={{ position: 'fixed', top: '0', left: '0', right: '0', bottom: '0', background: '#0f172a', zIndex: 3000, display: 'flex', flexDirection: 'column', overflowBehavior: 'contain' }}>
<div style={{ padding: '15px 20px', display: 'flex', justifyContent: 'space-between', alignItems: 'center', background: '#1e293b' }}>
<div>
<h2 style={{ margin: 0, display: 'inline', marginRight: '20px' }}>Vue Sismique Globale</h2>
<div style={{ display: 'inline-flex', gap: '5px', background: '#0f172a', padding: '3px', borderRadius: '4px' }}>
<button onClick={() => setViewMode('day')} style={{ background: viewMode === 'day' ? '#3b82f6' : 'transparent', color: '#fff', border: 'none', padding: '5px 15px', cursor: 'pointer' }}>Journée</button>
<button onClick={() => setViewMode('global')} style={{ background: viewMode === 'global' ? '#3b82f6' : 'transparent', color: '#fff', border: 'none', padding: '5px 15px', cursor: 'pointer' }}>Toute la période (12j)</button>
</div>
</div>
<button onClick={onClose} style={{ background: '#ef4444', color: '#fff', border: 'none', padding: '8px 20px', borderRadius: '4px', cursor: 'pointer' }}>Fermer</button>
</div>
<div style={{ flex: 1, padding: '10px' }}>
{loading ? <div style={{ textAlign: 'center', marginTop: '20%' }}>Fusion des données</div> : (
<Plot
data={plotData}
layout={{
autosize: true,
paper_bgcolor: 'rgba(0,0,0,0)',
plot_bgcolor: 'rgba(0,0,0,0)',
margin: { t: 10, b: 50, l: 60, r: 20 },
font: { color: '#94a3b8' },
xaxis: { gridcolor: '#1e293b', title: 'Temps' },
yaxis: {
gridcolor: '#1e293b',
tickvals: plotData.map((_, i) => i),
ticktext: Object.keys(data || {}).sort().map(id => `b${id}`)
}
}}
config={{ responsive: true }}
style={{ width: '100%', height: '100%' }}
/>
)}
</div>
</div>
);
}
export default SeismicSection;