From e88aa8a58c03fea8e1f90dec8836a7daff08d7bc Mon Sep 17 00:00:00 2001 From: Austin Pickett Date: Tue, 14 Apr 2026 10:23:43 -0400 Subject: [PATCH] feat(web): re-apply dashboard UI improvements on top of i18n Re-applies changes from #9471 that were overwritten by the i18n PR: - URL-based routing via react-router-dom (NavLink, Routes, BrowserRouter) - Replace emoji icons with lucide-react in ConfigPage and SkillsPage - Sidebar layout for ConfigPage, SkillsPage, and LogsPage - Custom dropdown Select component (SelectOption) in CronPage - Remove all non-functional rounded borders across the UI - Fixed header with proper content offset Made-with: Cursor --- web/src/App.tsx | 112 ++--- web/src/components/LanguageSwitcher.tsx | 2 +- web/src/components/ModelInfoCard.tsx | 10 +- web/src/components/OAuthProvidersCard.tsx | 2 +- web/src/main.tsx | 9 +- web/src/pages/AnalyticsPage.tsx | 6 +- web/src/pages/ConfigPage.tsx | 63 ++- web/src/pages/CronPage.tsx | 14 +- web/src/pages/LogsPage.tsx | 230 +++++---- web/src/pages/SessionsPage.tsx | 4 +- web/src/pages/SkillsPage.tsx | 584 +++++++++++----------- 11 files changed, 547 insertions(+), 489 deletions(-) diff --git a/web/src/App.tsx b/web/src/App.tsx index 3d2832ccb..4bbc13fac 100644 --- a/web/src/App.tsx +++ b/web/src/App.tsx @@ -1,4 +1,4 @@ -import { useState, useEffect, useRef } from "react"; +import { Routes, Route, NavLink, Navigate } from "react-router-dom"; import { Activity, BarChart3, Clock, FileText, KeyRound, MessageSquare, Package, Settings } from "lucide-react"; import StatusPage from "@/pages/StatusPage"; import ConfigPage from "@/pages/ConfigPage"; @@ -12,89 +12,60 @@ import { LanguageSwitcher } from "@/components/LanguageSwitcher"; import { useI18n } from "@/i18n"; const NAV_ITEMS = [ - { id: "status", labelKey: "status" as const, icon: Activity }, - { id: "sessions", labelKey: "sessions" as const, icon: MessageSquare }, - { id: "analytics", labelKey: "analytics" as const, icon: BarChart3 }, - { id: "logs", labelKey: "logs" as const, icon: FileText }, - { id: "cron", labelKey: "cron" as const, icon: Clock }, - { id: "skills", labelKey: "skills" as const, icon: Package }, - { id: "config", labelKey: "config" as const, icon: Settings }, - { id: "env", labelKey: "keys" as const, icon: KeyRound }, + { path: "/", labelKey: "status" as const, icon: Activity }, + { path: "/sessions", labelKey: "sessions" as const, icon: MessageSquare }, + { path: "/analytics", labelKey: "analytics" as const, icon: BarChart3 }, + { path: "/logs", labelKey: "logs" as const, icon: FileText }, + { path: "/cron", labelKey: "cron" as const, icon: Clock }, + { path: "/skills", labelKey: "skills" as const, icon: Package }, + { path: "/config", labelKey: "config" as const, icon: Settings }, + { path: "/env", labelKey: "keys" as const, icon: KeyRound }, ] as const; -type PageId = (typeof NAV_ITEMS)[number]["id"]; - -const PAGE_COMPONENTS: Record = { - status: StatusPage, - sessions: SessionsPage, - analytics: AnalyticsPage, - logs: LogsPage, - cron: CronPage, - skills: SkillsPage, - config: ConfigPage, - env: EnvPage, -}; - export default function App() { - const [page, setPage] = useState("status"); - const [animKey, setAnimKey] = useState(0); - const initialRef = useRef(true); const { t } = useI18n(); - useEffect(() => { - // Skip the animation key bump on initial mount to avoid re-mounting - // the default page component (which causes duplicate API requests). - if (initialRef.current) { - initialRef.current = false; - return; - } - setAnimKey((k) => k + 1); - }, [page]); - - const PageComponent = PAGE_COMPONENTS[page]; - return (
- {/* Global grain + warm glow (matches landing page) */}
- {/* ---- Header with grid-border nav ---- */} -
+
- {/* Brand โ€” abbreviated on mobile */}
Hermes Agent
- {/* Nav โ€” icons only on mobile, icon+label on sm+ */} - {/* Right side: language switcher + version badge */}
@@ -104,15 +75,20 @@ export default function App() {
-
- +
+ + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> +
- {/* ---- Footer ---- */}