feat: implement ui v1
This commit is contained in:
@@ -0,0 +1,176 @@
|
||||
import { useMutation, useQuery } from "@tanstack/react-query";
|
||||
import { useParams } from "react-router-dom";
|
||||
|
||||
import {
|
||||
exportOperationYaml,
|
||||
generateDraft,
|
||||
getOperation,
|
||||
getOperationVersion,
|
||||
listAuthProfiles,
|
||||
importOperationYaml,
|
||||
} from "../../entities/operation/api";
|
||||
import { PublishOperationPanel } from "../../features/publish-operation/panel";
|
||||
import { SampleUploadPanel } from "../../features/sample-upload/panel";
|
||||
import { SchemaViewerPanel } from "../../features/schema-viewer/panel";
|
||||
import { TestRunPanel } from "../../features/test-run/panel";
|
||||
import { PageSection } from "../../shared/ui/page-section";
|
||||
|
||||
export function OperationDetailPage() {
|
||||
const { operationId = "" } = useParams();
|
||||
const summaryQuery = useQuery({
|
||||
queryKey: ["operation-summary", operationId],
|
||||
queryFn: () => getOperation(operationId),
|
||||
enabled: operationId.length > 0,
|
||||
});
|
||||
const versionQuery = useQuery({
|
||||
queryKey: [
|
||||
"operation-version",
|
||||
operationId,
|
||||
summaryQuery.data?.current_draft_version,
|
||||
],
|
||||
queryFn: () =>
|
||||
getOperationVersion(operationId, summaryQuery.data!.current_draft_version),
|
||||
enabled:
|
||||
operationId.length > 0 &&
|
||||
summaryQuery.data !== undefined &&
|
||||
summaryQuery.data.current_draft_version > 0,
|
||||
});
|
||||
const authProfilesQuery = useQuery({
|
||||
queryKey: ["auth-profiles"],
|
||||
queryFn: listAuthProfiles,
|
||||
});
|
||||
const draftMutation = useMutation({
|
||||
mutationFn: async () => generateDraft(operationId),
|
||||
});
|
||||
const exportMutation = useMutation({
|
||||
mutationFn: async () =>
|
||||
exportOperationYaml(operationId, summaryQuery.data?.current_draft_version),
|
||||
});
|
||||
const importMutation = useMutation({
|
||||
mutationFn: async (yamlText: string) => importOperationYaml(yamlText, "upsert"),
|
||||
});
|
||||
|
||||
const currentVersion = summaryQuery.data?.current_draft_version ?? 0;
|
||||
const exportedYaml = exportMutation.data;
|
||||
|
||||
return (
|
||||
<div className="page-stack">
|
||||
<PageSection
|
||||
title={summaryQuery.data?.display_name ?? "Operation"}
|
||||
subtitle={
|
||||
summaryQuery.data
|
||||
? `${summaryQuery.data.name} · ${summaryQuery.data.protocol} · draft v${currentVersion}`
|
||||
: "Loading operation metadata..."
|
||||
}
|
||||
>
|
||||
{summaryQuery.data ? (
|
||||
<div className="summary-grid">
|
||||
<div className="summary-card">
|
||||
<span>Status</span>
|
||||
<strong>{summaryQuery.data.status}</strong>
|
||||
</div>
|
||||
<div className="summary-card">
|
||||
<span>Published version</span>
|
||||
<strong>{summaryQuery.data.latest_published_version ?? "none"}</strong>
|
||||
</div>
|
||||
<div className="summary-card">
|
||||
<span>Updated</span>
|
||||
<strong>{new Date(summaryQuery.data.updated_at).toLocaleString()}</strong>
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
</PageSection>
|
||||
|
||||
<PageSection
|
||||
title="Samples And Draft"
|
||||
subtitle="Upload input/output samples first, then generate a draft schema and mapping set."
|
||||
actions={
|
||||
<button
|
||||
className="button-primary"
|
||||
onClick={() => draftMutation.mutate()}
|
||||
type="button"
|
||||
>
|
||||
{draftMutation.isPending ? "Generating..." : "Generate draft"}
|
||||
</button>
|
||||
}
|
||||
>
|
||||
<SampleUploadPanel operationId={operationId} />
|
||||
<SchemaViewerPanel
|
||||
operationRecord={versionQuery.data}
|
||||
draftResult={draftMutation.data}
|
||||
/>
|
||||
</PageSection>
|
||||
|
||||
<PageSection
|
||||
title="Test Run"
|
||||
subtitle="Run the current draft version through the backend runtime before publishing."
|
||||
>
|
||||
<TestRunPanel operationId={operationId} version={currentVersion} />
|
||||
</PageSection>
|
||||
|
||||
<PageSection
|
||||
title="Publish"
|
||||
subtitle="Move the current draft version into the published tool set exposed by MCP."
|
||||
>
|
||||
<PublishOperationPanel operationId={operationId} version={currentVersion} />
|
||||
</PageSection>
|
||||
|
||||
<PageSection
|
||||
title="YAML Export And Reimport"
|
||||
subtitle="Export the current version, inspect the YAML, then upsert it back through the same backend contract."
|
||||
actions={
|
||||
<button
|
||||
className="button-secondary"
|
||||
type="button"
|
||||
onClick={() => exportMutation.mutate()}
|
||||
>
|
||||
{exportMutation.isPending ? "Exporting..." : "Export YAML"}
|
||||
</button>
|
||||
}
|
||||
>
|
||||
<div className="stack-layout">
|
||||
{exportedYaml ? (
|
||||
<>
|
||||
<pre className="yaml-panel">{exportedYaml}</pre>
|
||||
<div className="button-row">
|
||||
<button
|
||||
className="button-primary"
|
||||
type="button"
|
||||
onClick={() => importMutation.mutate(exportedYaml)}
|
||||
>
|
||||
{importMutation.isPending ? "Importing..." : "Upsert from YAML"}
|
||||
</button>
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
<p>Export YAML to inspect the current operation snapshot.</p>
|
||||
)}
|
||||
{importMutation.data ? (
|
||||
<div className="feedback-card feedback-success">
|
||||
Imported version {String(importMutation.data.version)} in{" "}
|
||||
{String(importMutation.data.import_mode)} mode.
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
</PageSection>
|
||||
|
||||
<PageSection
|
||||
title="Auth Profiles"
|
||||
subtitle="Currently available auth profiles exposed by the admin backend."
|
||||
>
|
||||
<div className="operation-grid">
|
||||
{(authProfilesQuery.data?.items ?? []).map((profile) => (
|
||||
<div className="operation-card" key={profile.id}>
|
||||
<div className="operation-card-top">
|
||||
<span className="protocol-pill protocol-rest">{profile.kind}</span>
|
||||
</div>
|
||||
<h3>{profile.name}</h3>
|
||||
<p className="operation-name">{profile.id}</p>
|
||||
<pre>{JSON.stringify(profile.config, null, 2)}</pre>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</PageSection>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user