x-control-panel/web-ui/vue-app/src/views/TreeDemoView.vue

237 lines
5.5 KiB
Vue

<template>
<div class="tree-demo">
<v-container fluid>
<v-row>
<v-col cols="12">
<h1>Tree View Demo</h1>
<p>This is a demonstration of the TreeView component with all required features.</p>
</v-col>
</v-row>
<v-row>
<v-col cols="12">
<v-card>
<v-card-title>Tree View Component</v-card-title>
<v-card-text>
<div class="tree-container">
<TreeView
:root-node="sampleData"
:load-function="loadChildren"
@select="handleSelect"
@delete="handleDelete"
@copy="handleCopy"
@move="handleMove"
@add="handleAdd"
/>
</div>
</v-card-text>
</v-card>
</v-col>
</v-row>
<v-row>
<v-col cols="12">
<v-card>
<v-card-title>Event Log</v-card-title>
<v-card-text>
<div class="event-log">
<div v-for="(event, index) in eventLog" :key="index" class="event-item">
<strong>{{ event.type }}:</strong> {{ event.message }}
</div>
<div v-if="eventLog.length === 0" class="no-events">
No events yet. Interact with the tree to see events here.
</div>
</div>
</v-card-text>
</v-card>
</v-col>
</v-row>
</v-container>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import TreeView from '@/components/TreeView.vue'
import type { TreeNodeData } from '@/components/TreeView.vue'
// Sample data for demonstration
const sampleData = ref<TreeNodeData[]>([
{
id: 'root',
label: 'Root',
icon: 'mdi-folder',
hasChildren: true,
expanded: false,
children: [
{
id: 'leaf1',
label: 'Leaf 1',
icon: 'mdi-file',
hasChildren: true,
expanded: false,
children: []
},
{
id: 'leaf2',
label: 'Leaf 2',
icon: 'mdi-file',
hasChildren: true,
expanded: false,
children: []
},
{
id: 'leaf3',
label: 'Leaf 3',
icon: 'mdi-file',
hasChildren: false
}
]
}
])
const eventLog = ref<Array<{ type: string; message: string }>>([])
// Simulate async loading of children
const loadChildren = async (nodeId: string): Promise<TreeNodeData[]> => {
// Simulate API delay
await new Promise((resolve) => setTimeout(resolve, 1000))
// Return mock data based on nodeId
if (nodeId === 'root') {
return [
{
id: 'leaf1',
label: 'Leaf 1',
icon: 'mdi-file',
hasChildren: true,
expanded: false,
children: []
},
{
id: 'leaf2',
label: 'Leaf 2',
icon: 'mdi-file',
hasChildren: true,
expanded: false,
children: []
},
{
id: 'leaf3',
label: 'Leaf 3',
icon: 'mdi-file',
hasChildren: false
}
]
} else if (nodeId === 'leaf1') {
return [
{
id: 'leaf1.1',
label: 'Leaf 1.1',
icon: 'mdi-file-document',
hasChildren: false
},
{
id: 'leaf1.2',
label: 'Leaf 1.2',
icon: 'mdi-file-document',
hasChildren: false
}
]
} else if (nodeId === 'leaf2') {
return [
{
id: 'leaf2.1',
label: 'Leaf 2.1',
icon: 'mdi-file-document',
hasChildren: false
}
]
}
return []
}
const addEvent = (type: string, message: string) => {
eventLog.value.unshift({ type, message })
// Keep only last 10 events
if (eventLog.value.length > 10) {
eventLog.value = eventLog.value.slice(0, 10)
}
}
const handleSelect = (items: TreeNodeData | TreeNodeData[]) => {
if (Array.isArray(items)) {
addEvent('SELECT', `Selected ${items.length} items: ${items.map((i) => i.label).join(', ')}`)
} else {
addEvent('SELECT', `Selected: ${items.label}`)
}
}
const handleDelete = (items: TreeNodeData | TreeNodeData[]) => {
if (Array.isArray(items)) {
addEvent('DELETE', `Delete ${items.length} items: ${items.map((i) => i.label).join(', ')}`)
} else {
addEvent('DELETE', `Delete: ${items.label}`)
}
}
const handleCopy = (items: TreeNodeData | TreeNodeData[]) => {
if (Array.isArray(items)) {
addEvent('COPY', `Copy ${items.length} items: ${items.map((i) => i.label).join(', ')}`)
} else {
addEvent('COPY', `Copy: ${items.label}`)
}
}
const handleMove = (items: TreeNodeData | TreeNodeData[]) => {
if (Array.isArray(items)) {
addEvent('MOVE', `Move ${items.length} items: ${items.map((i) => i.label).join(', ')}`)
} else {
addEvent('MOVE', `Move: ${items.label}`)
}
}
const handleAdd = (parentId: string) => {
addEvent('ADD', `Add new item under parent: ${parentId}`)
}
</script>
<style scoped>
.tree-demo {
padding: 20px;
}
.tree-container {
height: 500px;
border: 1px solid rgb(var(--v-theme-outline));
border-radius: 4px;
}
.event-log {
max-height: 300px;
overflow-y: auto;
border: 1px solid rgb(var(--v-theme-outline));
border-radius: 4px;
padding: 12px;
}
.event-item {
padding: 4px 0;
border-bottom: 1px solid rgb(var(--v-theme-surface-variant));
font-family: monospace;
font-size: 12px;
}
.event-item:last-child {
border-bottom: none;
}
.no-events {
color: rgb(var(--v-theme-on-surface-variant));
font-style: italic;
text-align: center;
padding: 20px;
}
</style>