diff --git a/frontend/210.png b/frontend/210.png deleted file mode 100755 index d539a82..0000000 Binary files a/frontend/210.png and /dev/null differ diff --git a/frontend/app/test-chart/page.tsx b/frontend/app/test-chart/page.tsx deleted file mode 100644 index 686a2ac..0000000 --- a/frontend/app/test-chart/page.tsx +++ /dev/null @@ -1,70 +0,0 @@ -'use client'; -import { useState, useMemo } from 'react'; -import SignalGraphView from '@/components/nodes/signal-graph-node/signal-graph-full'; -import { GlobalProvider } from '@/context/GlobalContext'; - -const WINDOW_SIZE = 200; // how many points visible at once - -export default function TestChartPage() { - const [allData, setAllData] = useState([]); - const [windowStart, setWindowStart] = useState(0); - - const handleFile = (e: React.ChangeEvent) => { - const file = e.target.files?.[0]; - if (!file) return; - const reader = new FileReader(); - reader.onload = (event) => { - const text = event.target?.result as string; - const lines = text.trim().split('\n'); - const parsed = lines.slice(1).map(line => { - const values = line.split(','); - const timeOnly = values[0].trim().split(' ')[1]?.slice(0, 12) ?? values[0]; - return { - time: timeOnly, - signal1: Number(values[1]), - signal2: Number(values[2]), - signal3: Number(values[3]), - signal4: Number(values[4]), - }; - }); - setAllData(parsed); - setWindowStart(0); - }; - reader.readAsText(file); - }; - - // only the visible slice - const visibleData = useMemo( - () => allData.slice(windowStart, windowStart + WINDOW_SIZE), - [allData, windowStart] - ); - - const maxStart = Math.max(0, allData.length - WINDOW_SIZE); - - return ( - -
- - - - {allData.length > 0 && ( -
- - {allData.length} rows — showing {windowStart + 1}–{Math.min(windowStart + WINDOW_SIZE, allData.length)} - - setWindowStart(Number(e.target.value))} - className="w-full" - /> -
- )} - - {allData.length > 0 && } -
-
- ); -} \ No newline at end of file diff --git a/frontend/arm5 b/frontend/arm5 deleted file mode 100755 index 87fbf5f..0000000 Binary files a/frontend/arm5 and /dev/null differ diff --git a/frontend/arm6 b/frontend/arm6 deleted file mode 100755 index 7954bd5..0000000 Binary files a/frontend/arm6 and /dev/null differ diff --git a/frontend/arm7 b/frontend/arm7 deleted file mode 100755 index 312a445..0000000 Binary files a/frontend/arm7 and /dev/null differ diff --git a/frontend/components/nodes/signal-graph-node/signal-graph-full.tsx b/frontend/components/nodes/signal-graph-node/signal-graph-full.tsx index ff3188f..ad3222b 100644 --- a/frontend/components/nodes/signal-graph-node/signal-graph-full.tsx +++ b/frontend/components/nodes/signal-graph-node/signal-graph-full.tsx @@ -7,10 +7,17 @@ import { ResponsiveContainer, XAxis, YAxis, + Brush, } from 'recharts'; import { useGlobalContext } from '@/context/GlobalContext'; -import { DivideCircle } from 'lucide-react'; import { Button } from '@/components/ui/button'; +import { + Dialog, + DialogContent, + DialogHeader, + DialogTitle, + DialogTrigger, +} from '@/components/ui/dialog'; interface SignalGraphViewProps { @@ -24,15 +31,26 @@ interface SignalGraphViewProps { } +const TABLE_PREVIEW_ROWS = 50; + export default function SignalGraphView({ data }: SignalGraphViewProps) { const { dataStreaming, setDataStreaming } = useGlobalContext(); const [selectedSignal, setSelectedSignal] = useState(null); - const signals = [ - {key: 'signal1', colour: '#0000ff', name: 'Signal 1'}, - {key: 'signal2', colour: '#00ff00', name: 'Signal 2'}, - {key: 'signal3', colour: '#FF00D0', name: 'Signal 3'}, - {key: 'signal4', colour: '#FFFF00', name: 'Signal 4'}, + const [brushRange, setBrushRange] = useState<{ start: number; end: number } | null>(null); + + const activeBrushStart = brushRange?.start ?? 0; + const activeBrushEnd = brushRange?.end ?? Math.max(0, data.length - 1); + const visibleCount = activeBrushEnd - activeBrushStart + 1; + + const timeStart = data.length > 0 ? data[0].time : null; + const timeEnd = data.length > 0 ? data[data.length - 1].time : null; + + const signals = [ + {key: 'signal1', colour: '#0000ff', name: 'Channel 1'}, + {key: 'signal2', colour: '#00ff00', name: 'Channel 2'}, + {key: 'signal3', colour: '#FF00D0', name: 'Channel 3'}, + {key: 'signal4', colour: '#FF0000', name: 'Channel 4'}, ]; const handleStartStop = () => { @@ -41,10 +59,8 @@ export default function SignalGraphView({ data }: SignalGraphViewProps) { return ( - // take full height of the container
- {/* ---- HEAD BUTTONS ---- */}
- -
- {/* ---- TOP HALF: CHART ---- */} -
+
- + - + Number(v).toFixed(1)} + width={70} + tick={{ fontSize: 15, fill: '#666' }} + label={{ value: 'Amplitude (µV)', angle: -90, position: 'insideLeft', dy: 60, dx: -10 }} /> {signals.map((s) => ( ))} + { + if (range.startIndex !== undefined && range.endIndex !== undefined) { + setBrushRange({ start: range.startIndex, end: range.endIndex }); + } + }} + /> + {/* X axis label — pinned to left of brush */} +
Time (HH:MM:SS.mmm)
{/* Signal selector */}
{signals.map((s) => { const isSelected = selectedSignal === s.key; const anySelected = selectedSignal !== null; - - return ( @@ -117,13 +142,42 @@ export default function SignalGraphView({ data }: SignalGraphViewProps) {
+ {/* ---- DISPLAY INFO ---- */} +
+ Buffered points: {data.length} + Visible window: {visibleCount} samples (~{(visibleCount / 256).toFixed(2)}s at 256Hz) - drag the brush to scroll + {data.length > 0 && ( + Full time range: {timeStart} to {timeEnd} + )} + Y-axis: auto-scaled to actual signal range (µV) + Channels: 4 (EEG) +
{/* ---- BOTTOM HALF: TABLE ---- */}
- +
+ Last {TABLE_PREVIEW_ROWS} samples + + + + + + + + All data: {data.length} points + + +
+ +
+
+
+
+
-
); } diff --git a/frontend/components/nodes/signal-graph-node/signal-graph-node.tsx b/frontend/components/nodes/signal-graph-node/signal-graph-node.tsx index 8c85d08..aa768b1 100644 --- a/frontend/components/nodes/signal-graph-node/signal-graph-node.tsx +++ b/frontend/components/nodes/signal-graph-node/signal-graph-node.tsx @@ -17,7 +17,7 @@ import SignalGraphView from './signal-graph-full'; export default function SignalGraphNode({ id }: { id?: string }) { const { dataStreaming } = useGlobalContext(); - const { renderData } = useNodeData(20, 10); + const { renderData } = useNodeData(500, 10); const processedData = renderData; const reactFlowInstance = useReactFlow(); diff --git a/frontend/components/ui-data-table/data-table.tsx b/frontend/components/ui-data-table/data-table.tsx index ea54119..b682998 100644 --- a/frontend/components/ui-data-table/data-table.tsx +++ b/frontend/components/ui-data-table/data-table.tsx @@ -45,16 +45,16 @@ const DataTable: React.FC = ({ rowCount = 8, data = [] }) => { Time - Signal 1 + Channel 1 - Signal 2 + Channel 2 - Signal 3 + Channel 3 - Signal 4 + Channel 4 diff --git a/frontend/context/WebSocketContext.tsx b/frontend/context/WebSocketContext.tsx index 1045179..7b22d55 100644 --- a/frontend/context/WebSocketContext.tsx +++ b/frontend/context/WebSocketContext.tsx @@ -34,8 +34,11 @@ const DEFAULT_PROCESSING_CONFIG: ProcessingConfig = { function formatTimestamp(raw: any): string { const s = String(raw); - // ISO 8601: "2026-03-11T03:55:22.715574979Z" - extract "03:55:22" - if (s.includes('T')) return s.slice(11, 19); + // ISO 8601 with T: "2026-03-11T03:55:22.715574979Z" + if (s.includes('T')) return s.slice(11, 23); + // Space-separated: "2025-07-17 21:13:42.408185+00" + const spaceIdx = s.indexOf(' '); + if (spaceIdx !== -1) return s.slice(spaceIdx + 1, spaceIdx + 13); return s; } diff --git a/frontend/m68k b/frontend/m68k deleted file mode 100755 index 64c2ed9..0000000 Binary files a/frontend/m68k and /dev/null differ diff --git a/frontend/ppc b/frontend/ppc deleted file mode 100755 index 8abe4ae..0000000 Binary files a/frontend/ppc and /dev/null differ diff --git a/frontend/sh4 b/frontend/sh4 deleted file mode 100755 index eea370b..0000000 Binary files a/frontend/sh4 and /dev/null differ diff --git a/frontend/spc b/frontend/spc deleted file mode 100755 index 5eb7bbe..0000000 Binary files a/frontend/spc and /dev/null differ diff --git a/frontend/x86 b/frontend/x86 deleted file mode 100755 index 6aa83bf..0000000 Binary files a/frontend/x86 and /dev/null differ diff --git a/fullstack-moss-app b/fullstack-moss-app deleted file mode 160000 index 42890df..0000000 --- a/fullstack-moss-app +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 42890df0532dc8ae5234c71e442a51a44f537bd9