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:
2026-04-30 21:40:18 +02:00
parent 1acdfbc6ba
commit 3c432473e5
63 changed files with 7778 additions and 202 deletions
+46
View File
@@ -0,0 +1,46 @@
import type { NowPlayingSession } from "../types";
interface Props {
sessions: NowPlayingSession[];
}
export function NowPlaying({ sessions }: Props) {
if (sessions.length === 0) {
return (
<p className="text-sm text-gray-500">
No active playback sessions right now.
</p>
);
}
return (
<div className="overflow-x-auto">
<table className="w-full text-sm border-collapse">
<thead>
<tr className="border-b text-left text-gray-600">
<th className="py-2 pr-4">User</th>
<th className="py-2 pr-4">Title</th>
<th className="py-2 pr-4">Type</th>
<th className="py-2 pr-4">State</th>
<th className="py-2 pr-4">Transcoding</th>
<th className="py-2 pr-4">Transcode type</th>
<th className="py-2 pr-4">Device</th>
</tr>
</thead>
<tbody>
{sessions.map((s) => (
<tr key={s.session_id} className="border-b hover:bg-gray-50">
<td className="py-2 pr-4 font-medium">{s.user}</td>
<td className="py-2 pr-4">{s.title}</td>
<td className="py-2 pr-4">{s.type}</td>
<td className="py-2 pr-4">{s.state}</td>
<td className="py-2 pr-4">{s.transcoding}</td>
<td className="py-2 pr-4">{s.transcoding_type}</td>
<td className="py-2 pr-4">{s.device}</td>
</tr>
))}
</tbody>
</table>
</div>
);
}