This commit is contained in:
Martino Ferrari
2026-04-26 11:01:55 +02:00
parent 91b42027c9
commit e83e183673
17 changed files with 1009 additions and 182 deletions
+59 -2
View File
@@ -1,5 +1,5 @@
import { h } from 'preact';
import { useState } from 'preact/hooks';
import { useState, useMemo } from 'preact/hooks';
import InterfaceList from './InterfaceList';
import Canvas from './Canvas';
import { wsClient } from './lib/ws';
@@ -11,11 +11,23 @@ interface Props {
onEdit?: (iface?: Interface) => void;
}
/** Format a Date as a datetime-local input value (YYYY-MM-DDTHH:MM) */
function toLocalInput(d: Date): string {
const pad = (n: number) => String(n).padStart(2, '0');
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}T${pad(d.getHours())}:${pad(d.getMinutes())}`;
}
export default function ViewMode({ onEdit }: Props) {
const [currentInterface, setCurrentInterface] = useState<Interface | null>(null);
const [parseError, setParseError] = useState<string | null>(null);
const [wsStatus, setWsStatus] = useState('connecting');
// Historical time range — null means live
const now = useMemo(() => new Date(), []);
const [startInput, setStartInput] = useState(() => toLocalInput(new Date(now.getTime() - 3600_000)));
const [endInput, setEndInput] = useState(() => toLocalInput(now));
const [timeRange, setTimeRange] = useState<{ start: string; end: string } | null>(null);
useEffect(() => {
const unsub = wsClient.status.subscribe(setWsStatus);
return unsub;
@@ -41,6 +53,19 @@ export default function ViewMode({ onEdit }: Props) {
}
}
function handleLoadHistory() {
if (!startInput || !endInput) return;
const start = new Date(startInput).toISOString();
const end = new Date(endInput).toISOString();
setTimeRange({ start, end });
}
function handleGoLive() {
setTimeRange(null);
}
const isLive = timeRange === null;
return (
<div class="view-mode">
<header class="toolbar">
@@ -51,6 +76,38 @@ export default function ViewMode({ onEdit }: Props) {
)}
</div>
<div class="toolbar-center">
{/* Time range picker */}
<div class="time-nav">
<button
class={`toolbar-btn${isLive ? ' toolbar-btn-active' : ''}`}
title="Switch to live data"
onClick={handleGoLive}
>
Live
</button>
<input
class="time-input"
type="datetime-local"
value={startInput}
onInput={(e) => setStartInput((e.target as HTMLInputElement).value)}
title="History start"
/>
<span class="time-sep"></span>
<input
class="time-input"
type="datetime-local"
value={endInput}
onInput={(e) => setEndInput((e.target as HTMLInputElement).value)}
title="History end"
/>
<button
class="toolbar-btn"
title="Load historical data for this time range"
onClick={handleLoadHistory}
>
Load
</button>
</div>
{parseError && (
<span class="parse-error" title={parseError}>Parse error check console</span>
)}
@@ -84,7 +141,7 @@ export default function ViewMode({ onEdit }: Props) {
}
}}
/>
<Canvas iface={currentInterface} onNavigate={handleNavigate} />
<Canvas iface={currentInterface} onNavigate={handleNavigate} timeRange={timeRange} />
</div>
</div>
);