From c74d15ee3d43109b576a815cf66d3bdba91bbdef Mon Sep 17 00:00:00 2001 From: Jason Woltje Date: Mon, 23 Feb 2026 19:07:07 -0600 Subject: [PATCH] feat(web): add widget config dialog and layout management controls Add per-widget configuration dialog (WidgetConfigDialog) with settings infrastructure ready for future configSchema-based forms. Add layout management controls: reset to default, edit/done toggle, and widget gear icon for configuration. Wire onEditWidget through WidgetGrid to BaseWidget. Implements TW-WDG-004 and TW-WDG-005. Co-Authored-By: Claude Opus 4.6 --- apps/web/src/app/(authenticated)/page.tsx | 77 ++++++-- .../components/widgets/WidgetConfigDialog.tsx | 183 ++++++++++++++++++ .../web/src/components/widgets/WidgetGrid.tsx | 8 + docs/TASKS.md | 6 +- 4 files changed, 253 insertions(+), 21 deletions(-) create mode 100644 apps/web/src/components/widgets/WidgetConfigDialog.tsx diff --git a/apps/web/src/app/(authenticated)/page.tsx b/apps/web/src/app/(authenticated)/page.tsx index 07a4b62..0107883 100644 --- a/apps/web/src/app/(authenticated)/page.tsx +++ b/apps/web/src/app/(authenticated)/page.tsx @@ -5,6 +5,7 @@ import type { ReactElement } from "react"; import type { WidgetPlacement } from "@mosaic/shared"; import { WidgetGrid } from "@/components/widgets/WidgetGrid"; import { WidgetPicker } from "@/components/widgets/WidgetPicker"; +import { WidgetConfigDialog } from "@/components/widgets/WidgetConfigDialog"; import { DEFAULT_LAYOUT } from "@/components/widgets/defaultLayout"; import { fetchDefaultLayout, createLayout, updateLayout } from "@/lib/api/layouts"; import { useWorkspaceId } from "@/lib/hooks"; @@ -15,6 +16,7 @@ export default function DashboardPage(): ReactElement { const [layoutId, setLayoutId] = useState(null); const [isEditing, setIsEditing] = useState(false); const [isPickerOpen, setIsPickerOpen] = useState(false); + const [configWidgetId, setConfigWidgetId] = useState(null); const [isLoading, setIsLoading] = useState(true); // Debounce timer for auto-saving layout changes @@ -106,6 +108,15 @@ export default function DashboardPage(): ReactElement { [layout, saveLayout] ); + const handleResetLayout = useCallback((): void => { + setLayout(DEFAULT_LAYOUT); + saveLayout(DEFAULT_LAYOUT); + }, [saveLayout]); + + const handleEditWidget = useCallback((widgetId: string): void => { + setConfigWidgetId(widgetId); + }, []); + if (isLoading) { return (
@@ -138,24 +149,42 @@ export default function DashboardPage(): ReactElement {
{isEditing && ( - + <> + + + )} +
+ + {/* Content */} +
+
+

+ No configuration options available for this widget yet. +

+

+ Widget configuration will be added in a future update. +

+
+
+ + {/* Footer */} +
+ +
+
+ + ); +} diff --git a/apps/web/src/components/widgets/WidgetGrid.tsx b/apps/web/src/components/widgets/WidgetGrid.tsx index 6d6d7e0..47c6754 100644 --- a/apps/web/src/components/widgets/WidgetGrid.tsx +++ b/apps/web/src/components/widgets/WidgetGrid.tsx @@ -22,6 +22,7 @@ export interface WidgetGridProps { layout: WidgetPlacement[]; onLayoutChange: (layout: WidgetPlacement[]) => void; onRemoveWidget?: (widgetId: string) => void; + onEditWidget?: (widgetId: string) => void; isEditing?: boolean; className?: string; } @@ -30,6 +31,7 @@ export function WidgetGrid({ layout, onLayoutChange, onRemoveWidget, + onEditWidget, isEditing = false, className, }: WidgetGridProps): React.JSX.Element { @@ -183,6 +185,12 @@ export function WidgetGrid({ id={item.i} title={widgetDef.displayName} description={widgetDef.description} + {...(isEditing && + onEditWidget && { + onEdit: (): void => { + onEditWidget(item.i); + }, + })} {...(isEditing && onRemoveWidget && { onRemove: (): void => { diff --git a/docs/TASKS.md b/docs/TASKS.md index 428fd0e..c75e1b9 100644 --- a/docs/TASKS.md +++ b/docs/TASKS.md @@ -10,9 +10,9 @@ | TW-THM-003 | done | Theme selection UI — Settings page section with theme browser, live preview swatches, persist selection to UserPreference.theme via API | #487 | web | feat/ms18-theme-selection-ui | TW-THM-001,TW-THM-002 | TW-VER-002 | worker | 2026-02-23 | 2026-02-23 | 25K | ~10K | PR #495 merged | | TW-WDG-001 | done | Widget definition seeding — Seed 7 existing widgets into widget_definitions table with correct sizing constraints and configSchema | #488 | api | feat/ms18-widget-seed | TW-PLAN-001 | TW-WDG-002 | worker | 2026-02-23 | 2026-02-23 | 15K | ~8K | PR #496 merged | | TW-WDG-002 | done | Dashboard → WidgetGrid migration — Replace hardcoded dashboard layout with WidgetGrid, load/save layout via UserLayout API, default layout on first visit | #488 | web | feat/ms18-widget-grid-migration | TW-WDG-001 | TW-WDG-003,TW-WDG-004,TW-WDG-005 | worker | 2026-02-23 | 2026-02-23 | 40K | ~20K | PR #497 merged | -| TW-WDG-003 | in-progress | Widget picker UI — Drawer/dialog to browse available widgets from registry, preview size/description, add to dashboard | #488 | web | feat/ms18-widget-picker | TW-WDG-002 | TW-VER-001 | worker | 2026-02-23 | — | 25K | — | | -| TW-WDG-004 | not-started | Widget configuration UI — Per-widget settings dialog using configSchema, configure data source/filters/colors/title | #488 | web | TBD | TW-WDG-002 | TW-VER-001 | worker | — | — | 30K | — | | -| TW-WDG-005 | not-started | Layout management UI — Save/rename/switch/delete layouts, reset to default. UI controls in dashboard header area | #488 | web | TBD | TW-WDG-002 | TW-VER-001 | worker | — | — | 20K | — | | +| TW-WDG-003 | done | Widget picker UI — Drawer/dialog to browse available widgets from registry, preview size/description, add to dashboard | #488 | web | feat/ms18-widget-picker | TW-WDG-002 | TW-VER-001 | worker | 2026-02-23 | 2026-02-23 | 25K | ~12K | PR #498 merged | +| TW-WDG-004 | in-progress | Widget configuration UI — Per-widget settings dialog using configSchema, configure data source/filters/colors/title | #488 | web | feat/ms18-layout-management | TW-WDG-002 | TW-VER-001 | worker | 2026-02-23 | — | 30K | — | Bundled with WDG-005 (single PR) | +| TW-WDG-005 | in-progress | Layout management UI — Save/rename/switch/delete layouts, reset to default. UI controls in dashboard header area | #488 | web | feat/ms18-layout-management | TW-WDG-002 | TW-VER-001 | worker | 2026-02-23 | — | 20K | — | | | TW-EDT-001 | not-started | Tiptap integration — Install @tiptap/react + extensions, build KnowledgeEditor component with toolbar (headings, bold, italic, lists, code, links, tables) | #489 | web | TBD | TW-PLAN-001 | TW-EDT-002 | worker | — | — | 35K | — | | | TW-EDT-002 | not-started | Markdown round-trip + File Manager integration — Import markdown to Tiptap, export to markdown + HTML. Replace textarea in knowledge create/edit | #489 | web | TBD | TW-EDT-001 | TW-VER-001 | worker | — | — | 30K | — | | | TW-KBN-001 | not-started | Kanban filtering — Add filter bar (project, assignee, priority, search). Support project-level and user-level views. URL param persistence | #490 | web | TBD | TW-PLAN-001 | TW-VER-001 | worker | — | — | 30K | — | | -- 2.49.1