refactor: keep draft identity in workbench

This commit is contained in:
lda
2026-08-10 02:11:26 +07:00 Verified
parent 6b1398e9f4
commit 070cbe6d7e
4 changed files with 31 additions and 102 deletions
@@ -115,11 +115,13 @@ describe("DraftWorkbench", () => {
expect(screen.getByText("Review needs a route.")).toBeInTheDocument();
});
it("reports the controller's current canonical draft to its route owner", () => {
const onDraftChange = vi.fn();
render(<DraftWorkbench draft={workspace} onDraftChange={onDraftChange} />);
it("renders route identity from the controller's canonical draft", () => {
render(<DraftWorkbench draft={workspace} />);
expect(onDraftChange).toHaveBeenCalledWith(workspace);
const header = screen.getByRole("heading", { name: "Review workflow" }).closest("header");
if (header === null) throw new Error("Expected the workbench identity header.");
expect(within(header).getByText("Revision 2")).toBeInTheDocument();
expect(within(header).getByText("Invalid")).toBeInTheDocument();
});
it("keeps the raw draft collapsed and exposes all deferred actions without handlers", () => {
@@ -13,7 +13,6 @@ type DraftWorkbenchProps = {
readonly draft: DraftWorkspace;
readonly capabilities?: ReadonlyArray<CapabilitySummary>;
readonly initialSelection?: WorkbenchSelection;
readonly onDraftChange?: (draft: DraftWorkspace) => void;
readonly onSelectionChange?: (selection: WorkbenchSelection) => void;
readonly enableNavigationProtection?: boolean;
};
@@ -24,6 +23,12 @@ const MOBILE_BREAKPOINT = 850;
const EMPTY_CAPABILITIES: ReadonlyArray<CapabilitySummary> = [];
const titleFor = (workspace: DraftWorkspace): string =>
workspace.title?.trim() || workspace.workspaceId;
const formatStatus = (status: DraftWorkspace["status"]): string =>
status.charAt(0).toUpperCase() + status.slice(1);
const isMobileViewport = (): boolean =>
typeof window !== "undefined" && window.innerWidth <= MOBILE_BREAKPOINT;
@@ -131,7 +136,6 @@ export const DraftWorkbench = ({
draft,
capabilities = EMPTY_CAPABILITIES,
initialSelection = { kind: "canvas" },
onDraftChange,
onSelectionChange,
enableNavigationProtection = false,
}: DraftWorkbenchProps) => {
@@ -140,9 +144,6 @@ export const DraftWorkbench = ({
const [openSheet, setOpenSheet] = useState<MobileSheet | null>(null);
const paletteTriggerRef = useRef<HTMLButtonElement>(null);
const inspectorTriggerRef = useRef<HTMLButtonElement>(null);
useEffect(() => {
onDraftChange?.(controller.draft);
}, [controller.draft, onDraftChange]);
// Resolve capability details from the controller draft so a newly committed
// node can immediately render its edit form before the route-level loader refreshes.
const graph = projectAuthoringGraph(controller.draft.draft);
@@ -170,6 +171,17 @@ export const DraftWorkbench = ({
return (
<>
{enableNavigationProtection && <DirtyNavigationProtection dirty={controller.dirty} />}
<header className="draft-detail__header">
<p className="workspace-route-pending__eyebrow">Draft authoring workbench</p>
<h1>{titleFor(controller.draft)}</h1>
<p className="draft-detail__workspace-id">{controller.draft.workspaceId}</p>
<p className="draft-detail__status-line">
<span className="draft-workspaces__status" data-status={controller.draft.status}>
{formatStatus(controller.draft.status)}
</span>
<span>Revision {controller.draft.revision}</span>
</p>
</header>
<div
className="draft-workbench"
data-dirty={controller.dirty}