Add multi-diagram management

- DiagramRepository interface redesigned around multiple diagrams:
  list()/loadById()/deleteById() replace the old single-diagram
  load()/clear(). Both implementations updated to match.
- SupabaseDiagramRepository.save() now does an explicit update-or-insert
  instead of a blind upsert, so owner_id is only ever set at creation --
  an upsert would resend it on every save and let whoever saves last
  silently reassign ownership. Not reachable yet (no collaborator UI),
  but a real landmine once diagram sharing (organized-ideas.md §8) lands,
  and cheap to avoid now.
- LocalStorageDiagramRepository now stores diagrams keyed by id (was a
  single fixed key), keeping it a genuine working fallback rather than
  a stale reference implementing an old interface.
- Store: loadInitialDiagram (renamed from loadFromStorage) opens the
  last diagram you had open (tracked in localStorage -- a UI
  preference, not app data), falling back to the most recently updated
  one, falling back to a fresh empty diagram. New actions:
  refreshDiagramList, switchToDiagram, deleteDiagram. newProject and
  importProject now persist immediately (not just via the debounced
  autosave) so a new/imported diagram shows up in the list right away;
  importProject also assigns a fresh id so it can't collide with an
  existing diagram.
- New DiagramManagerModal (list/open/delete/+New), opened from a
  "Diagrams" button in TopBar that replaces the old single-diagram
  "New" button and its now-unnecessary confirmation dialog -- nothing
  is lost by creating a new diagram anymore, since the old one stays
  saved and reachable from the list.

Verified insert/list/update(-preserves-owner)/loadById/delete against
the real local stack; RLS test suite still 23/23 after a fresh reset.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017DUU6CnxECCDeqDNYJgr5x
This commit is contained in:
2026-09-07 21:19:24 -05:00
co-authored by Claude Sonnet 5
parent 027455cc7d
commit 2f1b83e0a9
7 changed files with 284 additions and 75 deletions
+15 -2
View File
@@ -1,5 +1,13 @@
import type { Project } from '../domain/types'
/** Lightweight metadata for listing diagrams without fetching each one's
* full (potentially large) data payload. */
export interface DiagramSummary {
id: string
name: string
updatedAt: string
}
/**
* Storage abstraction the rest of the app codes against. `LocalStorageDiagramRepository`
* and `SupabaseDiagramRepository` both implement it — the store/UI layers don't need to
@@ -12,7 +20,12 @@ import type { Project } from '../domain/types'
* across the whole app, tracked as its own task rather than bundled into this one.
*/
export interface DiagramRepository {
load(): Promise<Project | null>
/** Every diagram visible to the current user, most recently updated first. */
list(): Promise<DiagramSummary[]>
/** One diagram's full data by id, or null if it doesn't exist / isn't visible. */
loadById(id: string): Promise<Project | null>
/** Upsert a diagram, matched by the project's own id. */
save(project: Project): Promise<void>
clear(): Promise<void>
/** Permanently delete one diagram by id. */
deleteById(id: string): Promise<void>
}