feat: Add canvas gallery with soft delete, snapshots and components
Replace the empty dynamic canvas placeholder with a gallery showing saved canvases, snapshots and Vue components. Users can create new canvases, restore snapshots, load components, and manage canvas toolbar/archive settings from the gallery. - Backend: soft delete (archive) instead of hard delete, status column - Frontend: CanvasGallery component with grid, search, settings popover - Show canvas name in global header when viewing a project canvas - Remove ProjectsPage (replaced by gallery), clean all references - MCP tools: project category available on canvas page, update handlers
This commit is contained in:
@@ -31,6 +31,14 @@ export const useProjectCanvasStore = defineStore('projectCanvas', () => {
|
||||
canvases.value.find(c => c.type === 'dynamic')
|
||||
)
|
||||
|
||||
const activeCanvasesList = computed(() =>
|
||||
canvases.value.filter(c => c.status !== 'archived')
|
||||
)
|
||||
|
||||
const archivedCanvases = computed(() =>
|
||||
canvases.value.filter(c => c.status === 'archived')
|
||||
)
|
||||
|
||||
const canvasCount = computed(() => canvases.value.length)
|
||||
|
||||
const hasActiveCanvas = computed(() => activeCanvas.value !== null)
|
||||
@@ -38,11 +46,12 @@ export const useProjectCanvasStore = defineStore('projectCanvas', () => {
|
||||
const hasDefaultCanvas = computed(() => defaultCanvas.value !== null)
|
||||
|
||||
// Actions
|
||||
async function fetchCanvases() {
|
||||
async function fetchCanvases(includeArchived = false) {
|
||||
loading.value = true
|
||||
error.value = null
|
||||
try {
|
||||
const res = await fetch(`${API_URL}/api/canvas`)
|
||||
const url = includeArchived ? `${API_URL}/api/canvas?include_archived=true` : `${API_URL}/api/canvas`
|
||||
const res = await fetch(url)
|
||||
if (!res.ok) throw new Error('Failed to fetch canvases')
|
||||
canvases.value = await res.json()
|
||||
} catch (e) {
|
||||
@@ -168,6 +177,10 @@ export const useProjectCanvasStore = defineStore('projectCanvas', () => {
|
||||
}
|
||||
}
|
||||
|
||||
async function restoreCanvas(id: string): Promise<boolean> {
|
||||
return updateCanvas(id, { status: 'active' } as any)
|
||||
}
|
||||
|
||||
async function cloneCanvas(id: string, newName?: string): Promise<string | null> {
|
||||
saving.value = true
|
||||
error.value = null
|
||||
@@ -304,6 +317,8 @@ export const useProjectCanvasStore = defineStore('projectCanvas', () => {
|
||||
projectCanvases,
|
||||
systemCanvases,
|
||||
dynamicCanvas,
|
||||
activeCanvasesList,
|
||||
archivedCanvases,
|
||||
canvasCount,
|
||||
hasActiveCanvas,
|
||||
hasDefaultCanvas,
|
||||
@@ -315,6 +330,7 @@ export const useProjectCanvasStore = defineStore('projectCanvas', () => {
|
||||
createCanvas,
|
||||
updateCanvas,
|
||||
deleteCanvas,
|
||||
restoreCanvas,
|
||||
cloneCanvas,
|
||||
fetchCanvasComponents,
|
||||
addComponentToCanvas,
|
||||
|
||||
Reference in New Issue
Block a user