Skip to content

Commit a87a940

Browse files
feat: implement Docker management dashboard and frontend component architecture
1 parent 18ebe33 commit a87a940

14 files changed

Lines changed: 3922 additions & 46 deletions

frontend/src/App.tsx

Lines changed: 69 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ import QueryWorkbench from "./components/views/QueryWorkbench";
1313
import SchemaView from "./components/views/SchemaView";
1414
import DockerSidebar, { DockerContainerInfo } from "./components/DockerSidebar";
1515
import DockerDashboardView from "./components/views/DockerDashboardView";
16+
import DockerRunnerView from "./components/views/DockerRunnerView";
17+
import DockerImagesView from "./components/views/DockerImagesView";
18+
import DockerVolumesView from "./components/views/DockerVolumesView";
19+
import { AlertTriangleIcon } from "./components/Icons";
1620

1721
export type ViewMode = "table" | "documents" | "json" | "inspector";
1822
export type AppMode =
@@ -157,6 +161,24 @@ export default function App() {
157161
setStatusError(isError);
158162
}, []);
159163

164+
const refreshContainers = useCallback(async () => {
165+
try {
166+
const res = await fetch("/api/docker/containers");
167+
const data = await res.json();
168+
if (res.ok) {
169+
setContainersList(data.containers || []);
170+
showStatus("Container list refreshed");
171+
} else {
172+
showStatus(data.error || "Failed to refresh containers", true);
173+
}
174+
} catch (err: unknown) {
175+
showStatus(
176+
(err as Error).message || "Failed to refresh containers",
177+
true,
178+
);
179+
}
180+
}, [showStatus]);
181+
160182
// Load connections and initial state
161183
useEffect(() => {
162184
const init = async () => {
@@ -490,7 +512,10 @@ export default function App() {
490512
if (error) {
491513
return (
492514
<EmptyState onRetry={handleReload}>
493-
<p style={{ fontSize: "2rem" }}>⚠️</p>
515+
<AlertTriangleIcon
516+
size={40}
517+
style={{ color: "var(--warning)", marginBottom: "8px" }}
518+
/>
494519
<p className="error-msg">Failed to connect to the backend.</p>
495520
<p style={{ opacity: 0.6, fontSize: "0.85rem" }}>{error}</p>
496521
</EmptyState>
@@ -621,17 +646,29 @@ export default function App() {
621646
<DockerSidebar
622647
containers={containers}
623648
selectedContainerId={selectedContainerId}
649+
onStatusChange={showStatus}
650+
onRefreshContainers={refreshContainers}
624651
onSelectContainer={(id) => {
625652
setSelectedContainerId(id);
626-
showStatus("Loaded container details");
653+
if (id === "__runner__") {
654+
showStatus("Docker container wizard active");
655+
} else {
656+
showStatus("Loaded container details");
657+
}
627658
}}
628659
/>
629660
<div className="sidebar-resizer" onMouseDown={handleSidebarMouseDown} />
630661
<main className="main-area">
631662
<Toolbar
632663
title={
633-
containers.find((c) => c.id === selectedContainerId)?.name ||
634-
"Docker Container"
664+
selectedContainerId === "__runner__"
665+
? "Launch Containers"
666+
: selectedContainerId === "__images__"
667+
? "Local Docker Images"
668+
: selectedContainerId === "__volumes__"
669+
? "Local Docker Volumes"
670+
: containers.find((c) => c.id === selectedContainerId)
671+
?.name || "Docker Container"
635672
}
636673
dbType="Docker"
637674
theme={theme}
@@ -660,6 +697,21 @@ export default function App() {
660697
<div className="loading-pulse" />
661698
<p>Connecting to Docker...</p>
662699
</EmptyState>
700+
) : selectedContainerId === "__runner__" ? (
701+
<DockerRunnerView
702+
onRefreshSidebar={() => {
703+
fetch("/api/docker/containers")
704+
.then((res) => res.json())
705+
.then((data) => {
706+
setContainersList(data.containers || []);
707+
});
708+
}}
709+
onStatusChange={showStatus}
710+
/>
711+
) : selectedContainerId === "__images__" ? (
712+
<DockerImagesView onStatusChange={showStatus} />
713+
) : selectedContainerId === "__volumes__" ? (
714+
<DockerVolumesView onStatusChange={showStatus} />
663715
) : (
664716
<DockerDashboardView
665717
key={dockerRefreshKey}
@@ -673,6 +725,19 @@ export default function App() {
673725
setContainersList(data.containers || []);
674726
});
675727
}}
728+
onDeleted={() => {
729+
fetch("/api/docker/containers")
730+
.then((res) => res.json())
731+
.then((data) => {
732+
const list = data.containers || [];
733+
setContainersList(list);
734+
if (list.length > 0) {
735+
setSelectedContainerId(list[0].id);
736+
} else {
737+
setSelectedContainerId("");
738+
}
739+
});
740+
}}
676741
/>
677742
)}
678743
</div>

0 commit comments

Comments
 (0)