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

127
frontend_src/Sidebar.tsx Normal file
View File

@@ -0,0 +1,127 @@
import { useState, useMemo } from 'react';
import Plot from 'react-plotly.js';
import { Node, DataWindow } from '../types';
interface SidebarProps {
selectedNode: Node | null;
dataWindow: DataWindow | null;
loading: boolean;
sampleRate: number;
}
type ViewMode = 'waveform' | 'rms';
function Sidebar({ selectedNode, dataWindow, loading, sampleRate }: SidebarProps) {
const [viewMode, setViewMode] = useState<ViewMode>('waveform');
const [showRaw, setShowRaw] = useState(false);
const samples = dataWindow?.samples || [];
const startTs = dataWindow?.startTimestamp || 0;
// Calcul RMS glissant
const rmsData = useMemo(() => {
if (samples.length === 0) return [];
const windowSize = 20;
const result = [];
for (let i = 0; i < samples.length; i++) {
const start = Math.max(0, i - windowSize);
const window = samples.slice(start, i + 1);
const rms = Math.sqrt(window.reduce((a, b) => a + b*b, 0) / window.length);
result.push(rms);
}
return result;
}, [samples]);
// Formatter pour le X (DD hh:mm:ss)
const formatXAxis = (ts: number) => {
const d = new Date(ts * 1000);
const day = d.getDate().toString().padStart(2, '0');
const h = d.getHours().toString().padStart(2, '0');
const m = d.getMinutes().toString().padStart(2, '0');
const s = d.getSeconds().toString().padStart(2, '0');
return `${day} ${h}:${m}:${s}`;
};
const xValues = useMemo(() => {
return samples.map((_, i) => formatXAxis(startTs + i / sampleRate));
}, [samples, startTs, sampleRate]);
const plotData: any[] = [];
if (samples.length > 0) {
if (viewMode === 'waveform') {
plotData.push({
x: xValues,
y: samples,
type: 'scatter',
mode: 'lines',
name: 'ADC Brute',
line: { color: '#4ade80', width: 1.5 }
});
} else {
plotData.push({
x: xValues,
y: rmsData,
type: 'scatter',
mode: 'lines',
name: 'RMS',
line: { color: '#fbbf24', width: 2 }
});
}
}
return (
<aside className="sidebar" style={{ width: '450px', background: '#1e293b', borderLeft: '1px solid #334155', display: 'flex', flexDirection: 'column', height: '100%' }}>
<div style={{ padding: '20px', borderBottom: '1px solid #334155' }}>
<h2 style={{ margin: 0, color: '#f8fafc' }}>Analyse Node</h2>
</div>
<div style={{ flex: 1, overflowY: 'auto', padding: '20px' }}>
{selectedNode ? (
<>
<div style={{ marginBottom: '20px', background: '#0f172a', padding: '15px', borderRadius: '8px' }}>
<h3 style={{ margin: '0 0 10px 0', color: '#38bdf8' }}>Node b{selectedNode.id}</h3>
<p style={{ margin: '5px 0', fontSize: '0.9rem' }}>E: {selectedNode.position?.easting.toFixed(0)} N: {selectedNode.position?.northing.toFixed(0)}</p>
</div>
<div style={{ display: 'flex', gap: '5px', marginBottom: '15px' }}>
<button onClick={() => setViewMode('waveform')} style={{ flex: 1, padding: '8px', background: viewMode === 'waveform' ? '#3b82f6' : '#334155', border: 'none', color: '#fff', borderRadius: '4px', cursor: 'pointer' }}>Waveform (Brute)</button>
<button onClick={() => setViewMode('rms')} style={{ flex: 1, padding: '8px', background: viewMode === 'rms' ? '#3b82f6' : '#334155', border: 'none', color: '#fff', borderRadius: '4px', cursor: 'pointer' }}>RMS</button>
</div>
{loading ? (
<div style={{ textAlign: 'center', padding: '40px', color: '#94a3b8' }}>Chargement</div>
) : samples.length > 0 ? (
<>
<div style={{ background: '#000', borderRadius: '8px', overflow: 'hidden', height: '300px' }}>
<Plot
data={plotData}
layout={{
autosize: true,
height: 300,
margin: { t: 10, b: 60, l: 50, r: 10 },
paper_bgcolor: 'rgba(0,0,0,0)',
plot_bgcolor: 'rgba(0,0,0,0)',
font: { color: '#94a3b8', size: 10 },
xaxis: {
gridcolor: '#1e293b',
zerolinecolor: '#334155',
tickangle: -45,
nticks: 5
},
yaxis: { gridcolor: '#1e293b', zerolinecolor: '#334155', title: 'Amplitude' }
}}
config={{ responsive: true, displayModeBar: true }}
style={{ width: '100%' }}
/>
</div>
{/* Stats... */}
</>
) : null}
</>
) : null}
</div>
</aside>
);
}
export default Sidebar;