Files
fusion/packages/dashboard/app/utils/boardWorkflowSelection.ts
gsxdsm b36327059a FN-7234: preserve board workflow selections
Persist workflow choices across dashboard board surfaces so operators return to their selected lane reliably.

- Add project-scoped durable storage helpers for board workflow selection with stale-id validation and cleanup.
- Share the workflow selection hook across Board, List, Header, and Graph surfaces while preserving cached payloads on transient refresh failures.
- Update List quick-create/planning handoffs, cross-surface tests, and dashboard documentation for durable workflow selection behavior.
- Add patch changesets for the published Fusion package.

Files changed:
 .changeset/fn-7234-durable-board-workflow-selection.md    |   7 ++
 .changeset/workflow-selection-board-list.md               |   7 ++
 docs/dashboard-guide.md                                   |   5 +-
 .../workflow-selection-cross-surface.test.tsx             |  66 ++++++++--
 packages/dashboard/app/components/ListView.tsx            | 111 ++++-------------
 .../app/components/__tests__/Board.test.tsx               |  45 +++++++
 .../__tests__/GraphWorkflowSwitcherSlot.test.tsx          |  57 +++++++++
 .../__tests__/HeaderWorkflowSwitcherSlot.test.tsx         |  42 ++++++-
 .../app/components/__tests__/ListView.test.tsx            | 122 +++++++++++++++++++
 .../app/hooks/__tests__/useBoardWorkflows.test.ts         |  29 +++++
 packages/dashboard/app/hooks/useBoardWorkflows.ts         |  64 ++++++++-
 .../utils/__tests__/boardWorkflowSelection.test.ts        | 135 +++++++++++++++++++++
 .../app/utils/__tests__/projectStorage.test.ts            |   3 +-
 .../dashboard/app/utils/boardWorkflowSelection.ts         |  49 ++++++++
 packages/dashboard/app/utils/projectStorage.ts            |   1 +
 15 files changed, 633 insertions(+), 110 deletions(-)

Fusion-Task-Id: FN-7234
Fusion-Task-Lineage: 6ebc000c-19c3-4a8e-9303-4e18a59902ed
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-06-29 14:41:52 -07:00

50 lines
1.9 KiB
TypeScript

import { getScopedItem, removeScopedItem, setScopedItem } from "./projectStorage";
export const BOARD_WORKFLOW_SELECTION_STORAGE_KEY = "kb-dashboard-board-workflow-selection";
function isValidWorkflowSelection(value: unknown): value is string {
if (typeof value !== "string") return false;
const trimmed = value.trim();
if (trimmed.length === 0) return false;
if (trimmed.startsWith("{") || trimmed.startsWith("[")) return false;
if (/\p{C}/u.test(trimmed)) return false;
return true;
}
/**
* FNXC:BoardWorkflowSelection 2026-06-29-12:00:
* Persist only the last selected workflow id in project-scoped localStorage so Board, Header, Graph, and List selectors can restore the operator's workflow after board remounts, task state changes, respecification returns, and browser/server restarts. Storage is best-effort because private-mode, SSR, missing APIs, and quota failures must never block board rendering.
*/
export function readBoardWorkflowSelection(projectId?: string): string | null {
try {
const stored = getScopedItem(BOARD_WORKFLOW_SELECTION_STORAGE_KEY, projectId);
return isValidWorkflowSelection(stored) ? stored.trim() : null;
} catch {
return null;
}
}
export function writeBoardWorkflowSelection(projectId: string | undefined, workflowId: string): void {
try {
const trimmed = workflowId.trim();
if (!isValidWorkflowSelection(trimmed)) {
removeScopedItem(BOARD_WORKFLOW_SELECTION_STORAGE_KEY, projectId);
return;
}
setScopedItem(BOARD_WORKFLOW_SELECTION_STORAGE_KEY, trimmed, projectId);
} catch {
// Best-effort preference persistence; board rendering must continue on storage failures.
}
}
export function removeBoardWorkflowSelection(projectId?: string): void {
try {
removeScopedItem(BOARD_WORKFLOW_SELECTION_STORAGE_KEY, projectId);
} catch {
// Best-effort preference cleanup; storage failures are non-fatal.
}
}