20260623 optimize rpki explorer ui interactions
This commit is contained in:
@@ -1,9 +1,13 @@
|
||||
import { Activity, Braces, Database, FileSearch, GitBranch, Home, PackageOpen, ShieldCheck } from "lucide-react";
|
||||
import type { LucideIcon } from "lucide-react";
|
||||
import { useState } from "react";
|
||||
import { Shell } from "../components/layout/Shell";
|
||||
import { ObjectDetailPage } from "../features/object-detail/ObjectDetailPage";
|
||||
import { OverviewPage } from "../features/overview/OverviewPage";
|
||||
import { RepositoriesPage } from "../features/repositories/RepositoriesPage";
|
||||
import { createRepositoryBrowserState } from "../features/repositories/repositoryBrowserState";
|
||||
|
||||
type ViewId = "overview" | "repositories" | "publication-points" | "objects" | "validation" | "exports" | "runs" | "api";
|
||||
|
||||
const navigationItems = [
|
||||
{ id: "overview", label: "Overview", icon: Home },
|
||||
@@ -14,22 +18,86 @@ const navigationItems = [
|
||||
{ id: "exports", label: "Exports", icon: PackageOpen },
|
||||
{ id: "runs", label: "Runs", icon: Activity },
|
||||
{ id: "api", label: "API", icon: FileSearch }
|
||||
];
|
||||
] satisfies Array<{ id: ViewId; label: string; icon: LucideIcon }>;
|
||||
|
||||
const comingSoonCopy: Record<Exclude<ViewId, "overview" | "repositories" | "objects">, { title: string; description: string; alternative: string }> = {
|
||||
"publication-points": {
|
||||
title: "Publication Points",
|
||||
description: "Dedicated publication point analytics are not implemented yet.",
|
||||
alternative: "Use Repositories to drill down from repository to publication point and object rows."
|
||||
},
|
||||
validation: {
|
||||
title: "Validation",
|
||||
description: "A dedicated validation investigation workspace is planned but not available in this MVP.",
|
||||
alternative: "Use Overview for reason summaries and Object Detail for per-object validation evidence."
|
||||
},
|
||||
exports: {
|
||||
title: "Exports",
|
||||
description: "A standalone export job browser is planned but not available yet.",
|
||||
alternative: "Use Object Detail to trigger object or publication point export workflows."
|
||||
},
|
||||
runs: {
|
||||
title: "Runs",
|
||||
description: "Historical run navigation is not implemented in the current Explorer UI.",
|
||||
alternative: "The current view always uses the latest indexed run from query service."
|
||||
},
|
||||
api: {
|
||||
title: "API",
|
||||
description: "The API reference page is planned but not implemented yet.",
|
||||
alternative: "Use the project README and query service endpoints while the UI reference page is pending."
|
||||
}
|
||||
};
|
||||
|
||||
export function App() {
|
||||
const [activeView, setActiveView] = useState("overview");
|
||||
const [activeView, setActiveView] = useState<ViewId>("overview");
|
||||
const [selectedObjectInstanceId, setSelectedObjectInstanceId] = useState<string | null>(null);
|
||||
const [repositoryBrowserState, setRepositoryBrowserState] = useState(createRepositoryBrowserState);
|
||||
|
||||
const openObject = (objectInstanceId: string) => {
|
||||
setSelectedObjectInstanceId(objectInstanceId);
|
||||
setActiveView("objects");
|
||||
};
|
||||
|
||||
const renderActiveView = () => {
|
||||
if (activeView === "objects") {
|
||||
return <ObjectDetailPage initialObjectInstanceId={selectedObjectInstanceId} />;
|
||||
}
|
||||
if (activeView === "repositories") {
|
||||
return (
|
||||
<RepositoriesPage
|
||||
browserState={repositoryBrowserState}
|
||||
onBrowserStateChange={setRepositoryBrowserState}
|
||||
onOpenObject={openObject}
|
||||
/>
|
||||
);
|
||||
}
|
||||
if (activeView === "overview") {
|
||||
return <OverviewPage />;
|
||||
}
|
||||
return <ComingSoonPage {...comingSoonCopy[activeView]} />;
|
||||
};
|
||||
|
||||
return (
|
||||
<Shell activeView={activeView} navigationItems={navigationItems} onNavigate={setActiveView}>
|
||||
{activeView === "objects" ? <ObjectDetailPage initialObjectInstanceId={selectedObjectInstanceId} /> : null}
|
||||
{activeView === "repositories" ? <RepositoriesPage onOpenObject={openObject} /> : null}
|
||||
{activeView !== "objects" && activeView !== "repositories" ? <OverviewPage /> : null}
|
||||
{renderActiveView()}
|
||||
</Shell>
|
||||
);
|
||||
}
|
||||
|
||||
function ComingSoonPage({ title, description, alternative }: { title: string; description: string; alternative: string }) {
|
||||
return (
|
||||
<section className="page-stack" aria-labelledby="coming-soon-heading">
|
||||
<div className="hero-dashboard compact-hero coming-soon-panel">
|
||||
<div>
|
||||
<p className="eyebrow">Planned workspace</p>
|
||||
<h2 id="coming-soon-heading">{title}</h2>
|
||||
<p>{description}</p>
|
||||
</div>
|
||||
<div className="hero-status muted-status">
|
||||
<strong>Coming soon</strong>
|
||||
<span>{alternative}</span>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user