feat(demo): add reset UI and wire truthful integration status into pages

Add a "Reset demo data" action to the sidebar (Operations Manager only,
explicit confirmation, progress, error handling) -- POST /api/v1/demo/reset
already existed and was already role-gated server-side, but had no UI
trigger. Reset invalidates the acting session server-side, so the flow
signs the user out and returns them to login afterward.

Wire the new GET /api/v1/integrations/status into Automation.tsx and
Dashboard.tsx so both show the aggregate n8n state instead of the most
recent event's status, and the MCP Hub card reflects the actual
registration_enabled setting instead of a hardcoded "not configured" label.
This commit is contained in:
NuklearRabbit
2026-08-02 06:42:27 +02:00
parent 4437b8792a
commit 1867828a9d
3 changed files with 112 additions and 6 deletions
+40 -3
View File
@@ -1,7 +1,7 @@
import { useEffect, useMemo, useState } from "react";
import { Link } from "react-router-dom";
import { api } from "../api/client";
import type { Dashboard as DashboardData, KnowledgeHealth } from "../api/types";
import type { Dashboard as DashboardData, IntegrationStatus, KnowledgeHealth } from "../api/types";
import { useAuth } from "../context/AuthContext";
import { SeverityBadge, StatusBadge } from "../components/Badge";
import { Icon } from "../components/Icons";
@@ -30,6 +30,7 @@ export function Dashboard() {
const canSeeAutomation = user?.role === "operations_manager";
const [data, setData] = useState<DashboardData | null>(null);
const [knowledge, setKnowledge] = useState<KnowledgeHealth | null>(null);
const [integrationStatus, setIntegrationStatus] = useState<IntegrationStatus | null>(null);
const [error, setError] = useState<string | null>(null);
const [severity, setSeverity] = useState("all");
const [query, setQuery] = useState("");
@@ -39,6 +40,14 @@ export function Dashboard() {
api.get<KnowledgeHealth>("/api/v1/knowledge/status").then(setKnowledge).catch(() => setKnowledge(null));
}, []);
useEffect(() => {
if (!canSeeAutomation) return;
api
.get<IntegrationStatus>("/api/v1/integrations/status")
.then(setIntegrationStatus)
.catch(() => setIntegrationStatus(null));
}, [canSeeAutomation]);
const attention = useMemo(() => data?.attention_items.filter((item) => {
const matchesSeverity = severity === "all" || item.severity === severity;
const haystack = `${item.title} ${item.detail} ${item.link_ref}`.toLowerCase();
@@ -122,9 +131,37 @@ export function Dashboard() {
<section className="work-panel integration-panel" aria-labelledby="integration-heading">
<SectionHeading title="Integration pulse" description="Current evidence from connected services" action={canSeeAutomation ? <Link to="/automation">System detail <Icon name="chevron" /></Link> : undefined} />
<ul className="integration-list">
<li><IntegrationMark kind="n8n" /><div><strong>n8n delivery</strong><span>{latestRun ? `Latest event ${latestRun.aggregate_ref}` : "No workflow evidence recorded"}</span></div><StatusBadge status={n8nState.toLowerCase().replace(/ /g, "_")} /></li>
<li>
<IntegrationMark kind="n8n" />
<div>
<strong>n8n delivery</strong>
<span>
{integrationStatus
? `${integrationStatus.n8n.succeeded} succeeded · ${integrationStatus.n8n.failed} failed`
: latestRun
? `Latest event ${latestRun.aggregate_ref}`
: "No workflow evidence recorded"}
</span>
</div>
<StatusBadge
status={
integrationStatus
? integrationStatus.n8n.state === "operational"
? "available"
: integrationStatus.n8n.state
: n8nState.toLowerCase().replace(/ /g, "_")
}
/>
</li>
<li><IntegrationMark kind="rag" /><div><strong>RAGcore knowledge</strong><span>{knowledge ? `${knowledge.document_count} procedures indexed` : "Health check unavailable"}</span></div><StatusBadge status={knowledge?.available ? "available" : "unavailable"} /></li>
<li><IntegrationMark kind="mcp" /><div><strong>MCP Hub</strong><span>No active adapter in this PoC</span></div><StatusBadge status="not_configured" /></li>
<li>
<IntegrationMark kind="mcp" />
<div>
<strong>MCP Hub</strong>
<span>{integrationStatus?.mcp_hub.registration_enabled ? "Registration enabled" : "No active adapter in this PoC"}</span>
</div>
<StatusBadge status={integrationStatus?.mcp_hub.state ?? "not_configured"} />
</li>
</ul>
</section>