Add FastAPI backend and React frontend subprojects
Backend: - FastAPI app with 17 REST endpoints covering dashboard, monitoring, media index, file browser, and jobs - Reuses existing clients/domain/services unchanged - pydantic-settings config, dependency injection, CORS setup - Auto-generated OpenAPI docs at /docs Frontend: - Vite + React + TypeScript SPA - @tanstack/react-query for data fetching with polling - ag-grid-react for media table and file browser - recharts for monitoring charts - Tailwind CSS styling - 4 pages: Dashboard, Monitoring, Media, File Browser - Typed API client matching all backend endpoints Also: - docs/MIGRATION_PLAN.md with full architecture plan - Updated .gitignore for both subprojects - Streamlit app preserved for now (can coexist)
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
import { BrowserRouter, Routes, Route, NavLink } from "react-router-dom";
|
||||
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
||||
import { Dashboard } from "./pages/Dashboard";
|
||||
import { Monitoring } from "./pages/Monitoring";
|
||||
import { Media } from "./pages/Media";
|
||||
import { FileBrowser } from "./pages/FileBrowser";
|
||||
|
||||
const queryClient = new QueryClient({
|
||||
defaultOptions: {
|
||||
queries: {
|
||||
retry: 1,
|
||||
refetchOnWindowFocus: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const navLinks = [
|
||||
{ to: "/", label: "Dashboard" },
|
||||
{ to: "/monitoring", label: "Monitoring" },
|
||||
{ to: "/media", label: "Media" },
|
||||
{ to: "/files", label: "File Browser" },
|
||||
];
|
||||
|
||||
function NavBar() {
|
||||
return (
|
||||
<nav className="border-b px-6 py-3 flex gap-6 items-center bg-white sticky top-0 z-10">
|
||||
<span className="font-bold text-lg mr-4">Media Library Viewer</span>
|
||||
{navLinks.map((link) => (
|
||||
<NavLink
|
||||
key={link.to}
|
||||
to={link.to}
|
||||
end={link.to === "/"}
|
||||
className={({ isActive }) =>
|
||||
`text-sm px-2 py-1 rounded ${isActive ? "bg-gray-100 font-medium" : "text-gray-600 hover:text-gray-900"}`
|
||||
}
|
||||
>
|
||||
{link.label}
|
||||
</NavLink>
|
||||
))}
|
||||
</nav>
|
||||
);
|
||||
}
|
||||
|
||||
export default function App() {
|
||||
return (
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<BrowserRouter>
|
||||
<div className="min-h-screen bg-gray-50">
|
||||
<NavBar />
|
||||
<main className="max-w-screen-2xl mx-auto px-6 py-6">
|
||||
<Routes>
|
||||
<Route path="/" element={<Dashboard />} />
|
||||
<Route path="/monitoring" element={<Monitoring />} />
|
||||
<Route path="/media" element={<Media />} />
|
||||
<Route path="/files" element={<FileBrowser />} />
|
||||
</Routes>
|
||||
</main>
|
||||
</div>
|
||||
</BrowserRouter>
|
||||
</QueryClientProvider>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user