Files
fusion/packages/dashboard/app/utils/projectStorage.ts
gsxdsm 4366a933da FN-6046: add collapsible workflow selectors
Add collapsible workflow selectors for board workflow controls and inline task creation.

- add a collapsible board workflow toolbar with persisted per-project state
- make the inline create workflow selector collapsible and store its expanded state per project
- update workflow selector styling, storage key allowlist, and regression coverage for collapse behavior

Files changed:
 packages/dashboard/app/components/Board.tsx        | 104 +++++++++++++--------
 .../dashboard/app/components/InlineCreateCard.css  |   9 ++
 .../dashboard/app/components/InlineCreateCard.tsx  |   3 +
 packages/dashboard/app/components/Lane.css         |  23 +++++
 .../dashboard/app/components/WorkflowSelector.css  |  20 +++-
 .../dashboard/app/components/WorkflowSelector.tsx  |  81 ++++++++++++++--
 .../app/components/__tests__/Board.test.tsx        | 101 ++++++++++++++++++--
 .../components/__tests__/InlineCreateCard.test.tsx |  57 ++++++++++-
 .../components/__tests__/WorkflowSelector.test.tsx |  73 ++++++++++++++-
 .../app/utils/__tests__/projectStorage.test.ts     |   4 +-
 packages/dashboard/app/utils/projectStorage.ts     |   2 +
 11 files changed, 420 insertions(+), 57 deletions(-)

Fusion-Task-Id: FN-6046

Fusion-Task-Lineage: 07cbe7a8-5740-479d-94a3-b178c72a5273
2026-06-09 02:09:31 -07:00

87 lines
2.3 KiB
TypeScript

export const GLOBAL_STORAGE_KEYS: string[] = [
"kb-dashboard-theme-mode",
"kb-dashboard-color-theme",
"kb-dashboard-view-mode",
"kb-dashboard-current-project",
"kb-dashboard-recent-projects",
"fn-agent-log-markdown",
"fn-agent-log-tool-output",
];
export const PROJECT_STORAGE_KEYS: string[] = [
"kb-dashboard-task-view",
"kb-dashboard-list-columns",
"kb-dashboard-hide-done",
"kb-dashboard-list-collapsed",
"kb-dashboard-selected-tasks",
"kb-dashboard-list-selected-task",
"kb-dashboard-list-sidebar-width",
"kb-dashboard-mailbox-sidebar-width",
"kb-dashboard-board-workflow-collapsed",
"kb-quick-entry-text",
"kb-inline-create-text",
"kb-board-workflow-selector-collapsed",
"fn-agent-view",
"kb-terminal-tabs",
"kb-planning-last-description",
"kb-subtask-last-description",
"kb-mission-last-goal",
"kb-usage-view-mode",
"kb-usage-hidden-windows",
"kb-usage-modal-size",
"kb-usage-provider-order",
"kb-chat-active-session",
"kb-dashboard-working-branch-filter",
"kb-dashboard-base-branch-filter",
"kb-capacity-risk-banner-dismissed",
"kb-files-line-numbers",
"fusion-plugin-dependency-graph:positions",
];
export function scopedKey(baseKey: string, projectId?: string): string {
if (typeof projectId !== "string" || projectId.length === 0) {
return baseKey;
}
return `kb:${projectId}:${baseKey}`;
}
export function getScopedItem(baseKey: string, projectId?: string): string | null {
if (typeof window === "undefined") {
return null;
}
const getItem = window.localStorage?.getItem;
if (typeof getItem !== "function") {
return null;
}
return getItem.call(window.localStorage, scopedKey(baseKey, projectId));
}
export function setScopedItem(baseKey: string, value: string, projectId?: string): void {
if (typeof window === "undefined") {
return;
}
const setItem = window.localStorage?.setItem;
if (typeof setItem !== "function") {
return;
}
setItem.call(window.localStorage, scopedKey(baseKey, projectId), value);
}
export function removeScopedItem(baseKey: string, projectId?: string): void {
if (typeof window === "undefined") {
return;
}
const removeItem = window.localStorage?.removeItem;
if (typeof removeItem !== "function") {
return;
}
removeItem.call(window.localStorage, scopedKey(baseKey, projectId));
}