feat: Add multi-canvas system with project canvas support
- Add project_canvas and canvas_components tables for persistent canvas storage - Add ProjectCanvas store with full CRUD operations - Add ProjectCanvasPage for rendering saved canvas with components - Add ProjectsPage for managing canvas list (create, clone, delete) - Add HomePage that loads default canvas or falls back to dynamic canvas - Add toolbar support for displaying canvas as pages with custom icons - Add component usage validation to prevent deletion of components in use - Add MCP tools for canvas management (list, create, update, delete, clone) - Update router with /canvas/:id and /projects routes - Update Toolbar to show dynamic canvas pages from database
This commit is contained in:
60
frontend/src/pages/HomePage.vue
Normal file
60
frontend/src/pages/HomePage.vue
Normal file
@@ -0,0 +1,60 @@
|
||||
<script setup lang="ts">
|
||||
import { onMounted, ref } from 'vue'
|
||||
import { useProjectCanvasStore } from '../stores/projectCanvas'
|
||||
import Canvas from '../components/Canvas.vue'
|
||||
import ProjectCanvasPage from './ProjectCanvasPage.vue'
|
||||
|
||||
const projectCanvasStore = useProjectCanvasStore()
|
||||
const loading = ref(true)
|
||||
const showDefaultCanvas = ref(false)
|
||||
const defaultCanvasId = ref<string | null>(null)
|
||||
|
||||
onMounted(async () => {
|
||||
const defaultCanvas = await projectCanvasStore.fetchDefaultCanvas()
|
||||
|
||||
if (defaultCanvas) {
|
||||
showDefaultCanvas.value = true
|
||||
defaultCanvasId.value = defaultCanvas.id
|
||||
} else {
|
||||
showDefaultCanvas.value = false
|
||||
}
|
||||
|
||||
loading.value = false
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div v-if="loading" class="home-loading">
|
||||
<div class="spinner"></div>
|
||||
</div>
|
||||
|
||||
<ProjectCanvasPage
|
||||
v-else-if="showDefaultCanvas && defaultCanvasId"
|
||||
:id="defaultCanvasId"
|
||||
/>
|
||||
|
||||
<Canvas v-else />
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.home-loading {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: var(--bg-primary);
|
||||
}
|
||||
|
||||
.spinner {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border: 3px solid var(--border-color);
|
||||
border-top-color: var(--accent);
|
||||
border-radius: 50%;
|
||||
animation: spin 1s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user