init
This commit is contained in:
@@ -7,6 +7,7 @@ import {useRoute} from 'vue-router'
|
||||
import CreateChannelDialog from '@/components/channel/CreateChannelDialog.vue'
|
||||
import {type MenuItem, useContextMenu} from '@/composables/useContextMenu'
|
||||
import {useUserStore} from "@/stores/user.ts";
|
||||
import {useServerStore} from "@/stores/server.ts";
|
||||
|
||||
const props = defineProps<{
|
||||
serverId: string
|
||||
@@ -17,8 +18,8 @@ const route = useRoute()
|
||||
const channelStore = useChannelStore()
|
||||
const categoryStore = useCategoryStore()
|
||||
const userStore = useUserStore()
|
||||
const {channels} = storeToRefs(channelStore)
|
||||
const {categories} = storeToRefs(categoryStore)
|
||||
const serverStore = useServerStore()
|
||||
const {currentTree} = storeToRefs(serverStore)
|
||||
const {openContextMenu} = useContextMenu()
|
||||
|
||||
|
||||
@@ -29,9 +30,8 @@ const loadServerData = async (targetServerId: string) => {
|
||||
userStore.reset()
|
||||
try {
|
||||
await Promise.all([
|
||||
channelStore.fetchChannels(targetServerId),
|
||||
categoryStore.fetchCategories(targetServerId),
|
||||
userStore.fetchUsers(targetServerId)
|
||||
userStore.fetchUsers(targetServerId),
|
||||
serverStore.fetchServerTree(targetServerId)
|
||||
])
|
||||
} catch (error) {
|
||||
console.error('Failed to load server-scoped channels and categories:', error)
|
||||
@@ -50,7 +50,24 @@ watch(
|
||||
|
||||
const showDialog = ref(false)
|
||||
|
||||
// Right click menu
|
||||
// Right click menu (sidebar)
|
||||
function onSidebarContextMenu(event: MouseEvent) {
|
||||
const menuItems: MenuItem[] = [
|
||||
{
|
||||
label: 'Nouveau canal',
|
||||
icon: 'mdi-plus',
|
||||
action: () => console.log('Nouveau canal'),
|
||||
},
|
||||
{
|
||||
label: 'Nouvelle catégorie',
|
||||
icon: 'mdi-folder-plus',
|
||||
action: () => console.log('Nouvelle catégorie'),
|
||||
}
|
||||
]
|
||||
openContextMenu(event, menuItems);
|
||||
}
|
||||
|
||||
// Right click menu (channel)
|
||||
async function openEditDialog(channel: any) {
|
||||
console.log("edit dialog clicked")
|
||||
}
|
||||
@@ -80,10 +97,12 @@ function onChannelContextMenu(event: MouseEvent, channel: any) {
|
||||
]
|
||||
openContextMenu(event, menuItems);
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<v-navigation-drawer width="244">
|
||||
<v-navigation-drawer width="244" @contextmenu="onSidebarContextMenu">
|
||||
<v-sheet
|
||||
color="grey-lighten-5"
|
||||
height="128"
|
||||
@@ -100,15 +119,34 @@ function onChannelContextMenu(event: MouseEvent, channel: any) {
|
||||
New Channel
|
||||
</v-btn>
|
||||
|
||||
<v-list>
|
||||
<v-list-item
|
||||
v-for="channel in channels"
|
||||
:key="channel.id"
|
||||
:title="channel.name"
|
||||
:to="`/server/${serverId}/channel/${channel.id}`"
|
||||
link
|
||||
@contextmenu="onChannelContextMenu($event, channel)"
|
||||
></v-list-item>
|
||||
<v-list density="compact">
|
||||
<template v-for="(item, index) in currentTree" :key="index">
|
||||
<!-- Catégorie et ses canaux enfants -->
|
||||
<v-list-group v-if="'Category' in item" :value="item.Category[0].id">
|
||||
<template #activator="{ props: groupProps }">
|
||||
<v-list-item :title="item.Category[0].name" v-bind="groupProps"/>
|
||||
</template>
|
||||
|
||||
<v-list-item
|
||||
v-for="channel in item.Category[1]"
|
||||
:key="channel.id"
|
||||
:title="channel.name"
|
||||
:to="`/server/${serverId}/channel/${channel.id}`"
|
||||
link
|
||||
@contextmenu="onChannelContextMenu($event, channel)"
|
||||
/>
|
||||
</v-list-group>
|
||||
|
||||
<!-- Canal orphelin (racine) -->
|
||||
<v-list-item
|
||||
v-else-if="'Channel' in item"
|
||||
:key="item.Channel.id"
|
||||
:title="item.Channel.name"
|
||||
:to="`/server/${serverId}/channel/${item.Channel.id}`"
|
||||
link
|
||||
@contextmenu="onChannelContextMenu($event, item.Channel)"
|
||||
/>
|
||||
</template>
|
||||
</v-list>
|
||||
</v-navigation-drawer>
|
||||
|
||||
|
||||
@@ -1,9 +1,17 @@
|
||||
import {defineStore} from 'pinia'
|
||||
import {useApi} from "@/composables/useApi.ts";
|
||||
|
||||
interface Category {
|
||||
id: string
|
||||
name: string
|
||||
server_id?: string | null
|
||||
created_at: string
|
||||
updated_at: string
|
||||
}
|
||||
|
||||
export const useCategoryStore = defineStore("category", {
|
||||
state: () => ({
|
||||
categories: []
|
||||
categories: [] as Category[]
|
||||
}),
|
||||
actions: {
|
||||
async fetchCategories(serverId?: string) {
|
||||
|
||||
@@ -7,7 +7,6 @@ interface Channel {
|
||||
channel_type: string
|
||||
server_id?: string | null
|
||||
category_id?: string | null
|
||||
position: number
|
||||
created_at: string
|
||||
updated_at: string
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import {defineStore} from "pinia";
|
||||
import {useApi} from "@/composables/useApi.ts";
|
||||
import {useChannelStore} from "@/stores/channel.ts";
|
||||
import {useCategoryStore} from "@/stores/category.ts";
|
||||
|
||||
interface Server {
|
||||
id: string
|
||||
@@ -13,7 +15,8 @@ export const useServerStore = defineStore("server", {
|
||||
state: () => ({
|
||||
servers: [] as Server[],
|
||||
loading: false,
|
||||
error: null as string | null
|
||||
error: null as string | null,
|
||||
currentTree: [] as any[],
|
||||
}),
|
||||
actions: {
|
||||
async fetchServers() {
|
||||
@@ -41,6 +44,36 @@ export const useServerStore = defineStore("server", {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
async fetchServerTree(serverId: string) {
|
||||
const api = useApi();
|
||||
const channelStore = useChannelStore();
|
||||
const categoryStore = useCategoryStore();
|
||||
|
||||
const response = await api.get(`/servers/${serverId}/tree`);
|
||||
const tree = await response.json(); // { items: [...] }
|
||||
|
||||
this.currentTree = tree.items;
|
||||
|
||||
// Extraction à plat pour alimenter les stores spécialisés
|
||||
const extractedCategories: any[] = [];
|
||||
const extractedChannels: any[] = [];
|
||||
|
||||
for (const item of tree.items) {
|
||||
if ("Category" in item) {
|
||||
const [category, channels] = item.Category;
|
||||
extractedCategories.push(category);
|
||||
extractedChannels.push(...channels);
|
||||
} else if ("Channel" in item) {
|
||||
extractedChannels.push(item.Channel);
|
||||
}
|
||||
}
|
||||
|
||||
// Population / Synchro des stores individuels
|
||||
categoryStore.categories = extractedCategories;
|
||||
channelStore.channels = extractedChannels;
|
||||
|
||||
return tree.items;
|
||||
},
|
||||
reset() {
|
||||
this.servers = [];
|
||||
this.loading = false;
|
||||
|
||||
Reference in New Issue
Block a user