Add historian persistence and dashboard trend charts

This commit is contained in:
litoral05
2026-05-20 17:27:54 +01:00
parent 9fcf67c7ae
commit a30d41d031
16 changed files with 1304 additions and 48 deletions
+63 -47
View File
@@ -1,3 +1,4 @@
import { ReactNode, useState } from "react";
import { Sidebar } from "../navigation/Sidebar";
import { TopBar } from "./TopBar";
import { BottomStatusBar } from "./BottomStatusBar";
@@ -5,62 +6,77 @@ import { useTelemetryStream } from "../../features/telemetry/hooks/useTelemetryS
import { useNotifications } from "../../features/notifications/hooks/useNotifications";
import { useCurrentUser } from "../../features/auth/hooks/useCurrentUser";
import { useRuntimeConfig } from "../../features/system/hooks/useRuntimeConfig";
import type { TelemetrySnapshot } from "../../types/telemetry";
import { useState } from "react";
type AppShellRenderProps = {
theme: "dark" | "light";
snapshots: TelemetrySnapshot[];
};
type AppShellProps = {
children: React.ReactNode;
children: (props: AppShellRenderProps) => ReactNode;
};
export function AppShell({ children }: AppShellProps) {
const telemetry = useTelemetryStream();
const notifications = useNotifications();
const currentUser = useCurrentUser();
const [theme, setTheme] = useState<"dark" | "light">("dark");
const runtime = useRuntimeConfig();
const telemetry = useTelemetryStream();
const notifications = useNotifications();
const currentUser = useCurrentUser();
const runtime = useRuntimeConfig();
const toggleTheme = () => {
setTheme((current) => (current === "dark" ? "light" : "dark"));
};
const [theme, setTheme] = useState<"dark" | "light">("dark");
const isDark = theme === "dark";
return (
<div className={isDark ? "min-h-screen bg-[#0E1A24] text-[#EAF2FA]" : "min-h-screen bg-[#F4F7FA] text-[#102030]"}>
<div className="flex min-h-screen">
<div className="relative">
<Sidebar theme={theme} />
<div className="pointer-events-none absolute right-0 top-0 h-full w-2 bg-gradient-to-r from-[#3A5064]/6 to-transparent blur-sm" />
</div>
const toggleTheme = () => {
setTheme((current) => (current === "dark" ? "light" : "dark"));
};
<div className="flex min-h-screen flex-1 flex-col">
<TopBar
connected={telemetry.connected}
lastTimestamp={telemetry.lastTimestamp}
notificationCount={notifications.unreadCount}
userInitials={currentUser.initials}
theme={theme}
onToggleTheme={toggleTheme}
/>
const isDark = theme === "dark";
<main
className={
isDark
? "flex-1 overflow-y-auto bg-[#0E1A24] px-6 py-5"
: "flex-1 overflow-y-auto bg-[#F4F7FA] px-6 py-5"
}
>
{children}
</main>
<BottomStatusBar
theme={theme}
backendPort={runtime.runtimeConfig?.backendPort?.toString()}
mode={runtime.runtimeConfig?.mode}
controllerName={runtime.runtimeConfig?.controllerName}
controllerIp={runtime.runtimeConfig?.controllerIp}
/>
</div>
</div>
return (
<div
className={
isDark
? "h-screen overflow-hidden bg-[#0E1A24] text-[#EAF2FA]"
: "h-screen overflow-hidden bg-[#F4F7FA] text-[#102030]"
}
>
<div className="flex h-full overflow-hidden">
<div className="relative h-full shrink-0 overflow-hidden">
<Sidebar theme={theme} />
<div className="pointer-events-none absolute right-0 top-0 h-full w-2 bg-gradient-to-r from-[#3A5064]/6 to-transparent blur-sm" />
</div>
);
<div className="flex min-w-0 flex-1 flex-col overflow-hidden">
<TopBar
connected={telemetry.connected}
lastTimestamp={telemetry.lastTimestamp}
notificationCount={notifications.unreadCount}
userInitials={currentUser.initials}
theme={theme}
onToggleTheme={toggleTheme}
/>
<main
className={
isDark
? "custom-scrollbar min-h-0 flex-1 overflow-y-auto bg-[#0E1A24] px-6 py-5"
: "custom-scrollbar min-h-0 flex-1 overflow-y-auto bg-[#F4F7FA] px-6 py-5"
}
>
{children({
theme,
snapshots: telemetry.snapshots,
})}
</main>
<BottomStatusBar
theme={theme}
backendPort={runtime.runtimeConfig?.backendPort.toString()}
mode={runtime.runtimeConfig?.mode}
controllerName={runtime.runtimeConfig?.controllerName}
controllerIp={runtime.runtimeConfig?.controllerIp}
/>
</div>
</div>
</div>
);
}