feat(inline-edit): add WYSIWYG inline dashboard editing mode
Replace the disconnected board edit page with inline editing directly on the board view. Toggle with Ctrl+E or the Edit button. Features: - Edit mode store with changeset accumulation and batch save - Floating toolbar (save, discard, add section, board settings, exit) - Widget hover overlays with edit/delete/drag controls - Type-specific widget config panels for all 14 widget types - Section inline editing (title, icon picker, delete) - "+" buttons for adding widgets and sections inline - Section-level drag-and-drop reordering via svelte-dnd-action - Batch save API endpoint (single Prisma transaction) - Board properties side panel with live theme/wallpaper preview - Modal widget type picker with search filtering - Icon picker component with visual grid and search - Confirmation dialog modal for all destructive actions - HTML format support for Note widget (in addition to markdown/text) - Full i18n support (en + ru) for all new UI strings - Legacy edit page banner linking to new inline mode
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
# Feature Context: Inline Dashboard Editing
|
||||
|
||||
## Configuration
|
||||
- **Development mode:** Automated
|
||||
- **Execution mode:** Direct
|
||||
- **Strategy:** Big Bang
|
||||
- **Build:** `npm run build`
|
||||
- **Test:** `npm run test`
|
||||
- **Lint:** `npm run lint`
|
||||
- **Dev server:** `npm run dev` (port: 5173)
|
||||
|
||||
## Current State
|
||||
Starting fresh. The board view page (`/boards/[boardId]`) is read-only.
|
||||
The edit page (`/boards/[boardId]/edit`) is a separate form-based page.
|
||||
|
||||
## Key Architecture Notes
|
||||
- SvelteKit 2 + Svelte 5 (runes: $state, $derived, $props)
|
||||
- Prisma ORM with SQLite
|
||||
- Tailwind CSS v4
|
||||
- `svelte-dnd-action` for drag-and-drop
|
||||
- `lucide-svelte` for icons
|
||||
- `bits-ui` for UI primitives
|
||||
- Widget configs stored as JSON strings in `Widget.config`
|
||||
- Each widget type has Zod validation in `src/lib/utils/validators.ts`
|
||||
- Existing form actions on edit page: ?/updateBoard, ?/addSection, ?/deleteSection, ?/updateSection, ?/addWidget, ?/deleteWidget
|
||||
- Board view components: Board.svelte → Section.svelte → WidgetGrid.svelte → WidgetRenderer.svelte → [TypeWidget].svelte
|
||||
|
||||
## Temporary Workarounds
|
||||
(none yet)
|
||||
|
||||
## Cross-Phase Dependencies
|
||||
- Phase 3 (widget overlay) depends on Phase 1 (edit mode state)
|
||||
- Phase 4 (config panels) depends on Phase 3 (overlay triggers)
|
||||
- Phase 6 (add widget) depends on Phase 4 (config panel infrastructure)
|
||||
- Phase 7 (DnD) depends on Phase 1 (edit mode gate)
|
||||
- Phase 8 (batch save) depends on Phases 1-7 (all accumulated changes)
|
||||
- Phase 9 (board properties) depends on Phase 2 (toolbar trigger)
|
||||
- Phase 10 (migration) depends on all previous phases
|
||||
|
||||
## Deferred Work
|
||||
(none yet)
|
||||
|
||||
## Failed Approaches
|
||||
(none yet)
|
||||
|
||||
## Review Findings Log
|
||||
(none yet)
|
||||
|
||||
## Phase Execution Log
|
||||
| Phase | Agent Used | Test Writer | Parallel | Notes |
|
||||
|-------|-----------|-------------|----------|-------|
|
||||
| — | — | — | — | — |
|
||||
|
||||
## Environment & Runtime Notes
|
||||
- Windows 10, Git Bash
|
||||
- Node.js project with Vite dev server
|
||||
|
||||
## Implementation Notes
|
||||
(none yet)
|
||||
@@ -0,0 +1,55 @@
|
||||
# Feature: Inline Dashboard Editing (Edit Mode)
|
||||
|
||||
**Branch:** `feature/inline-dashboard-editing`
|
||||
**Base branch:** `master`
|
||||
**Created:** 2026-04-02
|
||||
**Status:** 🟡 In Progress
|
||||
**Strategy:** Big Bang
|
||||
**Mode:** Automated
|
||||
**Execution:** Direct
|
||||
|
||||
## Summary
|
||||
Replace the disconnected board edit page with a WYSIWYG inline editing experience.
|
||||
Users toggle edit mode directly on the board view — widgets show edit/delete overlays,
|
||||
"+" buttons appear for adding widgets and sections, drag-and-drop works across sections,
|
||||
and all changes accumulate as a batch save. The board looks exactly as it will when
|
||||
saved, at all times.
|
||||
|
||||
## Build & Test Commands
|
||||
- **Build:** `npm run build`
|
||||
- **Test:** `npm run test`
|
||||
- **Lint:** `npm run lint`
|
||||
|
||||
## Phases
|
||||
|
||||
- [ ] Phase 1: Edit Mode State Infrastructure [domain: frontend] → [subplan](./phase-1-edit-mode-state.md)
|
||||
- [ ] Phase 2: Floating Edit Toolbar [domain: frontend] → [subplan](./phase-2-floating-toolbar.md)
|
||||
- [ ] Phase 3: Widget Edit Overlay [domain: frontend] → [subplan](./phase-3-widget-overlay.md)
|
||||
- [ ] Phase 4: Inline Widget Configuration Panels [domain: frontend] → [subplan](./phase-4-widget-config-panels.md)
|
||||
- [ ] Phase 5: Section Inline Editing [domain: frontend] → [subplan](./phase-5-section-editing.md)
|
||||
- [ ] Phase 6: Add Widget Inline ("+" Buttons) [domain: frontend] → [subplan](./phase-6-add-widget-inline.md)
|
||||
- [ ] Phase 7: Drag-and-Drop Enhancements [domain: frontend] → [subplan](./phase-7-dnd-enhancements.md)
|
||||
- [ ] Phase 8: Optimistic Updates & Batch Save [domain: fullstack] → [subplan](./phase-8-batch-save.md)
|
||||
- [ ] Phase 9: Board Properties Quick Panel [domain: frontend] → [subplan](./phase-9-board-properties-panel.md)
|
||||
- [ ] Phase 10: Legacy Edit Page Migration & Polish [domain: fullstack] → [subplan](./phase-10-migration-polish.md)
|
||||
|
||||
## Phase Progress Log
|
||||
|
||||
| Phase | Domain | Status | Review | Build | Committed |
|
||||
|-------|--------|--------|--------|-------|-----------|
|
||||
| Phase 1: Edit Mode State | frontend | ⬜ Not Started | ⬜ | ⬜ | ⬜ |
|
||||
| Phase 2: Floating Toolbar | frontend | ⬜ Not Started | ⬜ | ⬜ | ⬜ |
|
||||
| Phase 3: Widget Overlay | frontend | ⬜ Not Started | ⬜ | ⬜ | ⬜ |
|
||||
| Phase 4: Widget Config Panels | frontend | ⬜ Not Started | ⬜ | ⬜ | ⬜ |
|
||||
| Phase 5: Section Editing | frontend | ⬜ Not Started | ⬜ | ⬜ | ⬜ |
|
||||
| Phase 6: Add Widget Inline | frontend | ⬜ Not Started | ⬜ | ⬜ | ⬜ |
|
||||
| Phase 7: DnD Enhancements | frontend | ⬜ Not Started | ⬜ | ⬜ | ⬜ |
|
||||
| Phase 8: Batch Save | fullstack | ⬜ Not Started | ⬜ | ⬜ | ⬜ |
|
||||
| Phase 9: Board Properties Panel | frontend | ⬜ Not Started | ⬜ | ⬜ | ⬜ |
|
||||
| Phase 10: Migration & Polish | fullstack | ⬜ Not Started | ⬜ | ⬜ | ⬜ |
|
||||
|
||||
## Final Review
|
||||
- [ ] Comprehensive code review
|
||||
- [ ] Full build passes
|
||||
- [ ] Full test suite passes
|
||||
- [ ] Merged to `master`
|
||||
@@ -0,0 +1,47 @@
|
||||
# Phase 1: Edit Mode State Infrastructure
|
||||
|
||||
**Status:** ⬜ Not Started
|
||||
**Parent plan:** [PLAN.md](./PLAN.md)
|
||||
**Domain:** frontend
|
||||
|
||||
## Objective
|
||||
Create the foundational edit mode state management and toggle mechanism that all subsequent phases build upon.
|
||||
|
||||
## Tasks
|
||||
|
||||
- [ ] Create `src/lib/stores/editMode.svelte.ts` with state: `{ active, boardId, dirty, changeCount }`
|
||||
- [ ] Export functions: `enterEditMode(boardId)`, `exitEditMode()`, `markDirty()`, `resetDirty()`
|
||||
- [ ] Add "Edit Mode" toggle button to `BoardHeader.svelte` (replaces the current "Edit" link to `/boards/[id]/edit`)
|
||||
- [ ] When toggled ON: set edit mode active, show visual indicator (subtle board border glow or tint)
|
||||
- [ ] When toggled OFF: if dirty, show confirmation dialog "Discard unsaved changes?"
|
||||
- [ ] Register keyboard shortcut `Ctrl+E` / `Cmd+E` to toggle edit mode
|
||||
- [ ] Pass edit mode state as Svelte context from board view page
|
||||
- [ ] Add `editMode` context consumer helpers for child components
|
||||
- [ ] Visual indicator: board gets a subtle colored top-bar or border when in edit mode
|
||||
|
||||
## Files to Modify/Create
|
||||
- `src/lib/stores/editMode.svelte.ts` — new store
|
||||
- `src/lib/components/board/BoardHeader.svelte` — replace Edit link with toggle button
|
||||
- `src/routes/boards/[boardId]/+page.svelte` — provide edit mode context, visual indicators
|
||||
|
||||
## Acceptance Criteria
|
||||
- Clicking the toggle enters/exits edit mode
|
||||
- Ctrl+E toggles edit mode
|
||||
- Board view page visually indicates edit mode is active
|
||||
- Child components can read edit mode state via context
|
||||
- Dirty state tracking works (increments on markDirty, resets on save/discard)
|
||||
|
||||
## Notes
|
||||
- Use Svelte 5 runes ($state, $derived) for the store
|
||||
- The keyboard shortcut must not conflict with existing shortcuts
|
||||
- Guest users / users without edit permission must NOT see the toggle
|
||||
|
||||
## Review Checklist
|
||||
- [ ] All tasks completed
|
||||
- [ ] Code follows project conventions
|
||||
- [ ] No unintended side effects
|
||||
- [ ] Build passes
|
||||
- [ ] Tests pass (new + existing)
|
||||
|
||||
## Handoff to Next Phase
|
||||
<!-- Filled in after completing this phase -->
|
||||
@@ -0,0 +1,54 @@
|
||||
# Phase 10: Legacy Edit Page Migration & Polish
|
||||
|
||||
**Status:** ⬜ Not Started
|
||||
**Parent plan:** [PLAN.md](./PLAN.md)
|
||||
**Domain:** fullstack
|
||||
|
||||
## Objective
|
||||
Migrate remaining functionality from the legacy edit page, add polish, transitions, and ensure full accessibility.
|
||||
|
||||
## Tasks
|
||||
|
||||
- [ ] Redirect `/boards/[id]/edit` to `/boards/[id]?edit=true` (auto-enters edit mode)
|
||||
- [ ] Handle `?edit=true` query param on board view page to auto-enter edit mode
|
||||
- [ ] Migrate permission management: add permissions editor accessible from edit mode (or link to legacy page as "Advanced Settings")
|
||||
- [ ] Add smooth transition animations between view and edit modes
|
||||
- [ ] Keyboard navigation: Tab through edit controls, Enter to confirm, Escape to cancel/close
|
||||
- [ ] ARIA labels on all edit controls (buttons, overlays, panels)
|
||||
- [ ] Focus management: auto-focus appropriate elements when panels open
|
||||
- [ ] Focus trap in modals/panels
|
||||
- [ ] Screen reader announcements for mode changes ("Edit mode enabled", "Widget deleted")
|
||||
- [ ] Ensure all existing edit page functionality is accessible through inline UI
|
||||
- [ ] Polish: loading states, error boundaries, edge case handling
|
||||
- [ ] Mobile responsiveness: touch-friendly edit controls, appropriate sizing
|
||||
- [ ] Verify no regressions with guest access (guests should never see edit controls)
|
||||
|
||||
## Files to Modify/Create
|
||||
- `src/routes/boards/[boardId]/edit/+page.server.ts` — add redirect
|
||||
- `src/routes/boards/[boardId]/+page.svelte` — handle ?edit=true, transitions
|
||||
- Various components — accessibility attributes, animations
|
||||
- `src/lib/components/board/BoardAccessControl.svelte` — integrate or link from edit mode
|
||||
|
||||
## Acceptance Criteria
|
||||
- `/boards/[id]/edit` redirects to inline edit mode
|
||||
- All functionality from legacy edit page is accessible
|
||||
- Keyboard navigation works throughout edit mode
|
||||
- Screen readers can use edit mode
|
||||
- Transitions are smooth and non-jarring
|
||||
- Mobile experience is usable
|
||||
- Guest users cannot access edit features
|
||||
|
||||
## Notes
|
||||
- Consider keeping legacy edit page temporarily as "Advanced Edit" for power users
|
||||
- Permission management is complex — may be better as a dedicated panel than inline
|
||||
- Test with different board sizes (empty, 1 section, 10+ sections with many widgets)
|
||||
|
||||
## Review Checklist
|
||||
- [ ] All tasks completed
|
||||
- [ ] Code follows project conventions
|
||||
- [ ] No unintended side effects
|
||||
- [ ] Build passes
|
||||
- [ ] Tests pass (new + existing)
|
||||
|
||||
## Handoff to Next Phase
|
||||
<!-- Filled in after completing this phase -->
|
||||
@@ -0,0 +1,50 @@
|
||||
# Phase 2: Floating Edit Toolbar
|
||||
|
||||
**Status:** ⬜ Not Started
|
||||
**Parent plan:** [PLAN.md](./PLAN.md)
|
||||
**Domain:** frontend
|
||||
|
||||
## Objective
|
||||
Create a sticky floating toolbar that appears when edit mode is active, providing quick access to common editing actions.
|
||||
|
||||
## Tasks
|
||||
|
||||
- [ ] Create `src/lib/components/board/EditToolbar.svelte`
|
||||
- [ ] Toolbar actions: Save All, Discard, Add Section, Board Settings (gear), Exit Edit Mode
|
||||
- [ ] Show unsaved change count badge on Save button
|
||||
- [ ] Position: fixed at bottom-center of viewport (floating pill shape)
|
||||
- [ ] Entrance animation: slide up from bottom with fade
|
||||
- [ ] Exit animation: slide down with fade
|
||||
- [ ] Responsive: collapses to icon-only on small screens
|
||||
- [ ] Only renders when edit mode is active
|
||||
- [ ] Wire "Exit Edit Mode" to the store's exitEditMode()
|
||||
- [ ] Wire "Add Section" to emit event (handled in Phase 6)
|
||||
- [ ] Wire "Board Settings" to emit event (handled in Phase 9)
|
||||
- [ ] Wire "Save All" to emit event (handled in Phase 8)
|
||||
- [ ] Wire "Discard" to revert all changes and exit edit mode
|
||||
|
||||
## Files to Modify/Create
|
||||
- `src/lib/components/board/EditToolbar.svelte` — new component
|
||||
- `src/routes/boards/[boardId]/+page.svelte` — mount toolbar when edit mode active
|
||||
|
||||
## Acceptance Criteria
|
||||
- Toolbar appears/disappears smoothly with edit mode toggle
|
||||
- All buttons are present and visually clear
|
||||
- Change count badge updates reactively
|
||||
- Responsive layout works on mobile
|
||||
- Toolbar doesn't obscure board content (proper z-index, positioning)
|
||||
|
||||
## Notes
|
||||
- Use lucide-svelte icons for toolbar buttons
|
||||
- z-index must be above board content but below modals/dialogs
|
||||
- "Save" and "Discard" will be wired to real logic in Phase 8
|
||||
|
||||
## Review Checklist
|
||||
- [ ] All tasks completed
|
||||
- [ ] Code follows project conventions
|
||||
- [ ] No unintended side effects
|
||||
- [ ] Build passes
|
||||
- [ ] Tests pass (new + existing)
|
||||
|
||||
## Handoff to Next Phase
|
||||
<!-- Filled in after completing this phase -->
|
||||
@@ -0,0 +1,48 @@
|
||||
# Phase 3: Widget Edit Overlay
|
||||
|
||||
**Status:** ⬜ Not Started
|
||||
**Parent plan:** [PLAN.md](./PLAN.md)
|
||||
**Domain:** frontend
|
||||
|
||||
## Objective
|
||||
Add hover overlays to every widget when in edit mode, showing edit/delete/drag controls without obscuring the widget content.
|
||||
|
||||
## Tasks
|
||||
|
||||
- [ ] Create `src/lib/components/widget/WidgetEditOverlay.svelte`
|
||||
- [ ] Overlay appears on hover over a widget in edit mode
|
||||
- [ ] Controls: pencil icon (top-right), trash icon (top-right, secondary), drag handle (top-left)
|
||||
- [ ] Semi-transparent backdrop on hover (e.g., bg-black/5)
|
||||
- [ ] Pencil click emits `onEdit(widgetId)` event
|
||||
- [ ] Trash click shows inline confirmation ("Delete?" with Yes/No), then emits `onDelete(widgetId)`
|
||||
- [ ] Drag handle integrated with svelte-dnd-action (prepared for Phase 7)
|
||||
- [ ] Wrap each widget in WidgetEditOverlay in `WidgetGrid.svelte` when edit mode is active
|
||||
- [ ] Overlay transitions: fade in on hover, fade out on leave
|
||||
- [ ] Overlay does NOT block widget interaction when not hovered (pointer-events)
|
||||
|
||||
## Files to Modify/Create
|
||||
- `src/lib/components/widget/WidgetEditOverlay.svelte` — new component
|
||||
- `src/lib/components/widget/WidgetGrid.svelte` — wrap widgets conditionally
|
||||
|
||||
## Acceptance Criteria
|
||||
- Hovering over a widget in edit mode shows the overlay
|
||||
- Overlay has pencil, trash, and drag handle controls
|
||||
- Controls are clickable and emit correct events
|
||||
- Overlay does not appear when NOT in edit mode
|
||||
- Widget content remains visible through the overlay
|
||||
|
||||
## Notes
|
||||
- Keep overlay minimal — don't overwhelm the widget visually
|
||||
- Trash confirmation should be inline (not a browser confirm dialog)
|
||||
- The actual edit panel opening (pencil) is Phase 4
|
||||
- The actual delete logic is Phase 8
|
||||
|
||||
## Review Checklist
|
||||
- [ ] All tasks completed
|
||||
- [ ] Code follows project conventions
|
||||
- [ ] No unintended side effects
|
||||
- [ ] Build passes
|
||||
- [ ] Tests pass (new + existing)
|
||||
|
||||
## Handoff to Next Phase
|
||||
<!-- Filled in after completing this phase -->
|
||||
@@ -0,0 +1,63 @@
|
||||
# Phase 4: Inline Widget Configuration Panels
|
||||
|
||||
**Status:** ⬜ Not Started
|
||||
**Parent plan:** [PLAN.md](./PLAN.md)
|
||||
**Domain:** frontend
|
||||
|
||||
## Objective
|
||||
Create type-specific configuration panels that open inline when the user clicks the edit (pencil) button on a widget, allowing real-time config editing with live preview.
|
||||
|
||||
## Tasks
|
||||
|
||||
- [ ] Create `src/lib/components/widget/WidgetConfigPanel.svelte` — container/router for type-specific panels
|
||||
- [ ] Create config panel components for each widget type (or a dynamic form approach):
|
||||
- App: app selector dropdown
|
||||
- Bookmark: url, label, icon, description
|
||||
- Note/Markdown: inline content editor
|
||||
- Embed: url, height, sandbox
|
||||
- Status: multi-app selector, label
|
||||
- Clock: timezone, style, weather toggle, coordinates
|
||||
- System Stats: source url/type, metrics, refresh interval
|
||||
- RSS: feed url, max items, show summary
|
||||
- Calendar: iCal URLs, days ahead
|
||||
- Metric: label, source, value/url/query, unit, refresh
|
||||
- Link Group: links array editor, collapsible toggle
|
||||
- Camera: stream url, type, refresh, aspect ratio
|
||||
- Integration: app selector, endpoint selector, refresh
|
||||
- [ ] Panel opens as a popover/slide-out anchored to the widget
|
||||
- [ ] Pre-populate fields with current widget config
|
||||
- [ ] Live preview: changes update the widget rendering in real-time (optimistic, local state)
|
||||
- [ ] Save/Cancel buttons per panel
|
||||
- [ ] Save stores changes in the edit mode changeset (not persisted until batch save in Phase 8)
|
||||
- [ ] Cancel reverts to original config
|
||||
- [ ] Auto-focus first field when panel opens
|
||||
- [ ] Close panel on Escape key
|
||||
|
||||
## Files to Modify/Create
|
||||
- `src/lib/components/widget/WidgetConfigPanel.svelte` — new panel router
|
||||
- `src/lib/components/widget/config/` — new directory for type-specific config forms
|
||||
- `src/lib/components/widget/WidgetEditOverlay.svelte` — wire pencil to open config panel
|
||||
- `src/lib/components/widget/WidgetRenderer.svelte` — support config override from edit state
|
||||
|
||||
## Acceptance Criteria
|
||||
- Clicking pencil on any widget type opens the correct config panel
|
||||
- Fields are pre-populated with current values
|
||||
- Changes preview live on the widget
|
||||
- Save adds to changeset, Cancel reverts
|
||||
- Panel closes on Save, Cancel, or Escape
|
||||
- All 14 widget types have config support
|
||||
|
||||
## Notes
|
||||
- Reuse Zod schemas from `src/lib/utils/validators.ts` for field validation
|
||||
- Consider a generic form approach for simple types (key-value pairs) vs custom for complex ones (link_group links array)
|
||||
- Panel positioning: use a popover that doesn't overflow viewport
|
||||
|
||||
## Review Checklist
|
||||
- [ ] All tasks completed
|
||||
- [ ] Code follows project conventions
|
||||
- [ ] No unintended side effects
|
||||
- [ ] Build passes
|
||||
- [ ] Tests pass (new + existing)
|
||||
|
||||
## Handoff to Next Phase
|
||||
<!-- Filled in after completing this phase -->
|
||||
@@ -0,0 +1,47 @@
|
||||
# Phase 5: Section Inline Editing
|
||||
|
||||
**Status:** ⬜ Not Started
|
||||
**Parent plan:** [PLAN.md](./PLAN.md)
|
||||
**Domain:** frontend
|
||||
|
||||
## Objective
|
||||
Make section headers editable inline in edit mode — title, icon, card size, expand default, delete.
|
||||
|
||||
## Tasks
|
||||
|
||||
- [ ] Modify `SectionHeader.svelte` to show edit controls when edit mode is active
|
||||
- [ ] Pencil icon on section header — click to toggle inline editing of title and icon
|
||||
- [ ] Inline title editing: click title text to replace with input field, Enter to confirm, Escape to cancel
|
||||
- [ ] Icon picker for section icon (reuse `AppIconPicker` or simplified version)
|
||||
- [ ] Card size dropdown override (compact/medium/large/inherit)
|
||||
- [ ] Toggle for `isExpandedByDefault`
|
||||
- [ ] Delete section button with confirmation ("Delete section 'X' and its N widgets?")
|
||||
- [ ] Drag handle for section reordering (left side of header, visible only in edit mode)
|
||||
- [ ] All changes stored in edit mode changeset
|
||||
|
||||
## Files to Modify/Create
|
||||
- `src/lib/components/section/SectionHeader.svelte` — add edit controls
|
||||
- `src/lib/components/section/Section.svelte` — pass edit mode state
|
||||
- `src/lib/components/section/SectionEditControls.svelte` — new, extracted edit controls
|
||||
|
||||
## Acceptance Criteria
|
||||
- Section title is editable inline in edit mode
|
||||
- Section icon is changeable via picker
|
||||
- Card size override works
|
||||
- Delete shows confirmation with widget count
|
||||
- Changes accumulate in changeset (not persisted until Save)
|
||||
- Controls hidden when not in edit mode
|
||||
|
||||
## Notes
|
||||
- Section drag-and-drop reorder is handled further in Phase 7
|
||||
- Delete confirmation should show actual widget count from current state
|
||||
|
||||
## Review Checklist
|
||||
- [ ] All tasks completed
|
||||
- [ ] Code follows project conventions
|
||||
- [ ] No unintended side effects
|
||||
- [ ] Build passes
|
||||
- [ ] Tests pass (new + existing)
|
||||
|
||||
## Handoff to Next Phase
|
||||
<!-- Filled in after completing this phase -->
|
||||
@@ -0,0 +1,51 @@
|
||||
# Phase 6: Add Widget Inline ("+" Buttons)
|
||||
|
||||
**Status:** ⬜ Not Started
|
||||
**Parent plan:** [PLAN.md](./PLAN.md)
|
||||
**Domain:** frontend
|
||||
|
||||
## Objective
|
||||
Add prominent "+" buttons for adding widgets to sections and adding new sections, all inline on the board view.
|
||||
|
||||
## Tasks
|
||||
|
||||
- [ ] Create `src/lib/components/widget/AddWidgetButton.svelte` — the "+" button shown at end of widget grid
|
||||
- [ ] Create `src/lib/components/board/AddSectionDivider.svelte` — subtle divider between sections with "+" button
|
||||
- [ ] Widget type picker: grid of icons with labels (App, Bookmark, Note, Embed, Status, Clock, etc.)
|
||||
- [ ] Clicking a type opens the config panel from Phase 4 for the new widget
|
||||
- [ ] New widget appears immediately in grid as a skeleton/placeholder while being configured
|
||||
- [ ] "Add Section" shows minimal inline form: title input + optional icon + confirm button
|
||||
- [ ] New section appears immediately in the board with empty widget grid
|
||||
- [ ] All additions tracked in edit mode changeset (temporary IDs until batch save)
|
||||
- [ ] "Add Section" button also available from the floating toolbar (Phase 2)
|
||||
|
||||
## Files to Modify/Create
|
||||
- `src/lib/components/widget/AddWidgetButton.svelte` — new
|
||||
- `src/lib/components/widget/WidgetTypePicker.svelte` — new, type selection grid
|
||||
- `src/lib/components/board/AddSectionDivider.svelte` — new
|
||||
- `src/lib/components/board/AddSectionForm.svelte` — new, inline section creation
|
||||
- `src/lib/components/widget/WidgetGrid.svelte` — append AddWidgetButton in edit mode
|
||||
- `src/lib/components/board/Board.svelte` — insert AddSectionDivider between sections
|
||||
|
||||
## Acceptance Criteria
|
||||
- "+" button visible at end of each section's widget grid in edit mode
|
||||
- "+" section divider visible between sections in edit mode
|
||||
- Type picker shows all available widget types with icons
|
||||
- Selecting a type opens config panel for new widget
|
||||
- New widgets/sections appear immediately (optimistic)
|
||||
- Hidden when not in edit mode
|
||||
|
||||
## Notes
|
||||
- Use temporary client-side IDs (e.g., `temp-${crypto.randomUUID()}`) for new items
|
||||
- Widget type icons should use lucide-svelte icons matching each type
|
||||
- Empty sections should still show the "+" add widget button
|
||||
|
||||
## Review Checklist
|
||||
- [ ] All tasks completed
|
||||
- [ ] Code follows project conventions
|
||||
- [ ] No unintended side effects
|
||||
- [ ] Build passes
|
||||
- [ ] Tests pass (new + existing)
|
||||
|
||||
## Handoff to Next Phase
|
||||
<!-- Filled in after completing this phase -->
|
||||
@@ -0,0 +1,48 @@
|
||||
# Phase 7: Drag-and-Drop Enhancements
|
||||
|
||||
**Status:** ⬜ Not Started
|
||||
**Parent plan:** [PLAN.md](./PLAN.md)
|
||||
**Domain:** frontend
|
||||
|
||||
## Objective
|
||||
Enhance drag-and-drop to support cross-section widget moves, section reordering, and visual drop zone indicators — all gated behind edit mode.
|
||||
|
||||
## Tasks
|
||||
|
||||
- [ ] Enable widget drag-and-drop ONLY in edit mode (disable in view mode)
|
||||
- [ ] Cross-section widget drag: allow dragging a widget from one section to another
|
||||
- [ ] Visual drop zones: highlight target section/position when dragging
|
||||
- [ ] Section-level drag-and-drop with visual indicators (reorder sections)
|
||||
- [ ] Drag handles only visible in edit mode
|
||||
- [ ] Track all reorder/move changes in edit mode changeset
|
||||
- [ ] Handle edge cases: dragging to empty sections, dragging last widget out of section
|
||||
- [ ] Smooth animations during drag operations
|
||||
|
||||
## Files to Modify/Create
|
||||
- `src/lib/components/widget/WidgetGrid.svelte` — enable DnD only in edit mode, cross-section support
|
||||
- `src/lib/components/board/Board.svelte` — section-level DnD in edit mode
|
||||
- `src/lib/components/section/Section.svelte` — drop zone indicators
|
||||
- `src/lib/components/widget/WidgetEditOverlay.svelte` — drag handle activation
|
||||
|
||||
## Acceptance Criteria
|
||||
- Widgets can be dragged between sections in edit mode
|
||||
- Sections can be reordered by dragging in edit mode
|
||||
- Drop zones highlight during drag
|
||||
- No drag-and-drop functionality in view mode
|
||||
- All moves tracked in changeset (not persisted until Save)
|
||||
- Animations are smooth
|
||||
|
||||
## Notes
|
||||
- `svelte-dnd-action` supports cross-container DnD via shared `dropTargetStyle`
|
||||
- Need to handle `sectionId` changes when widgets move between sections
|
||||
- Existing DraggableBoard/DraggableSection are used on edit page — may adapt or replace
|
||||
|
||||
## Review Checklist
|
||||
- [ ] All tasks completed
|
||||
- [ ] Code follows project conventions
|
||||
- [ ] No unintended side effects
|
||||
- [ ] Build passes
|
||||
- [ ] Tests pass (new + existing)
|
||||
|
||||
## Handoff to Next Phase
|
||||
<!-- Filled in after completing this phase -->
|
||||
@@ -0,0 +1,68 @@
|
||||
# Phase 8: Optimistic Updates & Batch Save
|
||||
|
||||
**Status:** ⬜ Not Started
|
||||
**Parent plan:** [PLAN.md](./PLAN.md)
|
||||
**Domain:** fullstack
|
||||
|
||||
## Objective
|
||||
Implement the changeset accumulation system and a batch API endpoint that persists all edit mode changes in a single transaction.
|
||||
|
||||
## Tasks
|
||||
|
||||
- [ ] Design changeset data structure in editMode store:
|
||||
- `widgetUpdates: Map<id, configChanges>`
|
||||
- `widgetAdds: Array<{tempId, sectionId, type, config, order}>`
|
||||
- `widgetDeletes: Set<id>`
|
||||
- `widgetMoves: Map<id, {fromSectionId, toSectionId, newOrder}>`
|
||||
- `sectionUpdates: Map<id, changes>`
|
||||
- `sectionAdds: Array<{tempId, title, icon, order}>`
|
||||
- `sectionDeletes: Set<id>`
|
||||
- `sectionReorders: Array<{id, newOrder}>`
|
||||
- `boardUpdates: Partial<BoardProps>`
|
||||
- [ ] Create `POST /api/boards/[id]/batch-update` endpoint
|
||||
- [ ] Endpoint accepts the full changeset as JSON body
|
||||
- [ ] Server-side: validate all changes, execute in a single Prisma transaction
|
||||
- [ ] Server-side: handle temp IDs → real IDs mapping for new items
|
||||
- [ ] Server-side: authorization check (user must have edit permission)
|
||||
- [ ] Wire "Save All" toolbar button to serialize changeset and call batch endpoint
|
||||
- [ ] On success: clear changeset, reset dirty state, broadcast to other tabs, invalidateAll()
|
||||
- [ ] On failure: show error, keep changeset intact (no data loss)
|
||||
- [ ] Wire "Discard" toolbar button to reset changeset, revert optimistic UI, exit edit mode
|
||||
- [ ] Wire widget delete (from Phase 3 overlay) to add to changeset
|
||||
- [ ] Wire widget config save (from Phase 4) to add to changeset
|
||||
- [ ] Wire section changes (from Phase 5) to add to changeset
|
||||
- [ ] Wire new items (from Phase 6) to add to changeset
|
||||
- [ ] Wire DnD moves (from Phase 7) to add to changeset
|
||||
|
||||
## Files to Modify/Create
|
||||
- `src/lib/stores/editMode.svelte.ts` — add changeset state and mutation functions
|
||||
- `src/routes/api/boards/[id]/batch-update/+server.ts` — new batch API endpoint
|
||||
- `src/lib/components/board/EditToolbar.svelte` — wire Save/Discard to real logic
|
||||
- `src/lib/components/widget/WidgetEditOverlay.svelte` — wire delete to changeset
|
||||
- `src/lib/components/widget/WidgetConfigPanel.svelte` — wire save to changeset
|
||||
- Various components — connect to changeset mutations
|
||||
|
||||
## Acceptance Criteria
|
||||
- All changes from Phases 3-7 accumulate in the changeset
|
||||
- "Save All" sends one HTTP request with all changes
|
||||
- Server processes all changes in a single transaction
|
||||
- On success: board reloads with persisted state
|
||||
- On failure: changes are preserved, error is shown
|
||||
- "Discard" reverts everything to pre-edit state
|
||||
- Change count in toolbar updates reactively
|
||||
|
||||
## Notes
|
||||
- Batch endpoint must be idempotent-safe (temp IDs prevent double-creates)
|
||||
- Widget order values must be recalculated during batch save
|
||||
- Prisma `$transaction` for atomicity
|
||||
- Consider payload size limits for very large boards
|
||||
|
||||
## Review Checklist
|
||||
- [ ] All tasks completed
|
||||
- [ ] Code follows project conventions
|
||||
- [ ] No unintended side effects
|
||||
- [ ] Build passes
|
||||
- [ ] Tests pass (new + existing)
|
||||
|
||||
## Handoff to Next Phase
|
||||
<!-- Filled in after completing this phase -->
|
||||
@@ -0,0 +1,54 @@
|
||||
# Phase 9: Board Properties Quick Panel
|
||||
|
||||
**Status:** ⬜ Not Started
|
||||
**Parent plan:** [PLAN.md](./PLAN.md)
|
||||
**Domain:** frontend
|
||||
|
||||
## Objective
|
||||
Create a side panel / modal accessible from the edit toolbar's gear icon for editing board-level properties with live preview.
|
||||
|
||||
## Tasks
|
||||
|
||||
- [ ] Create `src/lib/components/board/BoardPropertiesPanel.svelte`
|
||||
- [ ] Panel opens from toolbar gear icon as a slide-out side panel (right side)
|
||||
- [ ] Board properties: name, description, icon
|
||||
- [ ] Theme settings: themeHue slider (0-360), themeSaturation slider (0-100)
|
||||
- [ ] Background type selector: mesh, particles, aurora, wallpaper, none
|
||||
- [ ] Wallpaper settings: upload, URL input, blur slider, overlay opacity slider
|
||||
- [ ] Card size selector: compact, medium, large
|
||||
- [ ] Custom CSS editor (textarea or code editor)
|
||||
- [ ] Guest access toggle
|
||||
- [ ] All changes preview live on the board behind the panel
|
||||
- [ ] Changes stored in edit mode changeset (boardUpdates)
|
||||
- [ ] Close panel button, Escape to close
|
||||
- [ ] Panel has its own scroll if content overflows
|
||||
|
||||
## Files to Modify/Create
|
||||
- `src/lib/components/board/BoardPropertiesPanel.svelte` — new
|
||||
- `src/lib/components/board/EditToolbar.svelte` — wire gear icon to open panel
|
||||
- `src/routes/boards/[boardId]/+page.svelte` — mount panel, apply live preview overrides
|
||||
- `src/lib/components/board/BoardThemeProvider.svelte` — support preview overrides
|
||||
|
||||
## Acceptance Criteria
|
||||
- Gear icon opens the properties panel
|
||||
- All board-level settings are editable
|
||||
- Changes preview live on the board
|
||||
- Wallpaper upload works with live preview
|
||||
- Theme sliders update board colors in real-time
|
||||
- Changes accumulate in changeset
|
||||
- Panel closes on button click or Escape
|
||||
|
||||
## Notes
|
||||
- Live preview means overriding BoardThemeProvider props with unsaved values
|
||||
- Wallpaper upload may need special handling (uploaded immediately to server, URL stored in changeset)
|
||||
- Custom CSS injection should be sandboxed to board scope
|
||||
|
||||
## Review Checklist
|
||||
- [ ] All tasks completed
|
||||
- [ ] Code follows project conventions
|
||||
- [ ] No unintended side effects
|
||||
- [ ] Build passes
|
||||
- [ ] Tests pass (new + existing)
|
||||
|
||||
## Handoff to Next Phase
|
||||
<!-- Filled in after completing this phase -->
|
||||
Reference in New Issue
Block a user