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:
@@ -1,22 +1,15 @@
|
||||
import { useRef } from 'react'
|
||||
import { useRef, useState } from 'react'
|
||||
import { downloadProjectFile, readProjectFile, ProjectImportError } from '../../data/exportImport'
|
||||
import { supabase } from '../../data/supabaseClient'
|
||||
import { useProjectStore } from '../../state/projectStore'
|
||||
import DiagramManagerModal from './DiagramManagerModal'
|
||||
|
||||
export default function TopBar() {
|
||||
const project = useProjectStore((s) => s.project)
|
||||
const renameProject = useProjectStore((s) => s.renameProject)
|
||||
const newProject = useProjectStore((s) => s.newProject)
|
||||
const importProject = useProjectStore((s) => s.importProject)
|
||||
const fileInputRef = useRef<HTMLInputElement>(null)
|
||||
|
||||
const handleNewProject = () => {
|
||||
if (project.devices.length > 0 || project.connections.length > 0) {
|
||||
const confirmed = window.confirm('Start a new project? Unsaved changes to the current one will be lost (unless exported).')
|
||||
if (!confirmed) return
|
||||
}
|
||||
newProject()
|
||||
}
|
||||
const [diagramManagerOpen, setDiagramManagerOpen] = useState(false)
|
||||
|
||||
const handleExport = () => downloadProjectFile(project)
|
||||
|
||||
@@ -28,7 +21,7 @@ export default function TopBar() {
|
||||
if (!file) return
|
||||
try {
|
||||
const imported = await readProjectFile(file)
|
||||
importProject(imported)
|
||||
await importProject(imported)
|
||||
} catch (err) {
|
||||
const message = err instanceof ProjectImportError ? err.message : 'Could not read that file.'
|
||||
window.alert(`Import failed: ${message}`)
|
||||
@@ -46,8 +39,11 @@ export default function TopBar() {
|
||||
/>
|
||||
</div>
|
||||
<div className="flex items-center gap-1.5">
|
||||
<button onClick={handleNewProject} className="rounded px-2.5 py-1.5 text-xs text-slate-600 hover:bg-slate-100">
|
||||
New
|
||||
<button
|
||||
onClick={() => setDiagramManagerOpen(true)}
|
||||
className="rounded px-2.5 py-1.5 text-xs text-slate-600 hover:bg-slate-100"
|
||||
>
|
||||
Diagrams
|
||||
</button>
|
||||
<button onClick={handleImportClick} className="rounded px-2.5 py-1.5 text-xs text-slate-600 hover:bg-slate-100">
|
||||
Import
|
||||
@@ -66,6 +62,7 @@ export default function TopBar() {
|
||||
Sign out
|
||||
</button>
|
||||
</div>
|
||||
{diagramManagerOpen && <DiagramManagerModal onClose={() => setDiagramManagerOpen(false)} />}
|
||||
</header>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user