init
This commit is contained in:
Generated
+6
-7
@@ -3903,9 +3903,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "1.1.3+spec-1.1.0"
|
||||
version = "1.1.4+spec-1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "53c96ecdfa941c8fc4fcaed14f99ada8ebed502eef533015095a07e3301d4c3c"
|
||||
checksum = "3aace63f4bbcdfc2c965b059de67119c89c4017a70d633be6c104910f67056f5"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"serde_core",
|
||||
@@ -3939,9 +3939,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "toml_parser"
|
||||
version = "1.1.2+spec-1.1.0"
|
||||
version = "1.1.3+spec-1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526"
|
||||
checksum = "1d38ac1cf9b95face32296c0a3ede1fdc270627c9d9c02a7274dd6d960dc4d56"
|
||||
dependencies = [
|
||||
"winnow",
|
||||
]
|
||||
@@ -4228,12 +4228,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "validator"
|
||||
version = "0.20.0"
|
||||
version = "0.21.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "43fb22e1a008ece370ce08a3e9e4447a910e92621bb49b85d6e48a45397e7cfa"
|
||||
checksum = "c3d68c6633c483df6780cc5277a417c7c2d1bceee2649d06c8ab6b0fd2dd3c81"
|
||||
dependencies = [
|
||||
"idna",
|
||||
"once_cell",
|
||||
"regex",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
|
||||
+2
-2
@@ -21,7 +21,7 @@ event_bus = { path = "event_bus" }
|
||||
parking_lot = "0.12.5"
|
||||
serde = "1.0.229"
|
||||
serde_json = "1.0.151"
|
||||
toml = "1.1.3"
|
||||
toml = "1.1.4"
|
||||
uuid = { version = "1.24.0", features = ["v4", "v7", "fast-rng", "serde"] }
|
||||
tracing = "0.1.44"
|
||||
tracing-subscriber = { version = "0.3", features = ["env-filter", "fmt", "time"] }
|
||||
@@ -35,7 +35,7 @@ jsonwebtoken = { version = "11.0.0", features = ["aws_lc_rs"] }
|
||||
tower = { version = "0.5", features = ["util"] }
|
||||
tower-http = { version = "0.7.0", features = ["catch-panic", "cors", "trace"] }
|
||||
chrono = "0.4.45"
|
||||
validator = { version = "0.20.0", features = ["derive"] }
|
||||
validator = { version = "0.21.0", features = ["derive"] }
|
||||
async-trait = "0.1.91"
|
||||
anyhow = "1.0.104"
|
||||
futures-util = "0.3"
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
<script lang="ts" setup>
|
||||
import {computed} from 'vue'
|
||||
import {useContextMenu} from '@/composables/useContextMenu'
|
||||
|
||||
const {isOpen, position, items, closeContextMenu} = useContextMenu()
|
||||
|
||||
// Cible virtuelle pour positionner Vuetify v-menu à la position X, Y exacte
|
||||
const targetPosition = computed(() => [position.value.x, position.value.y])
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<v-menu
|
||||
v-model="isOpen"
|
||||
:close-on-content-click="true"
|
||||
:target="targetPosition as any"
|
||||
location="bottom start"
|
||||
>
|
||||
<v-list class="py-1" density="compact" min-width="180">
|
||||
<v-list-item
|
||||
v-for="(item, index) in items"
|
||||
:key="index"
|
||||
:base-color="item.color"
|
||||
:disabled="item.disabled"
|
||||
@click="item.action"
|
||||
>
|
||||
<template v-if="item.icon" #prepend>
|
||||
<v-icon :icon="item.icon" size="small"/>
|
||||
</template>
|
||||
<v-list-item-title>{{ item.label }}</v-list-item-title>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</v-menu>
|
||||
</template>
|
||||
@@ -0,0 +1,36 @@
|
||||
import {ref} from 'vue'
|
||||
|
||||
export interface MenuItem {
|
||||
label: string
|
||||
icon?: string
|
||||
color?: string
|
||||
disabled?: boolean
|
||||
action: () => void
|
||||
}
|
||||
|
||||
const isOpen = ref(false)
|
||||
const position = ref({x: 0, y: 0})
|
||||
const items = ref<MenuItem[]>([])
|
||||
|
||||
export function useContextMenu() {
|
||||
function openContextMenu(event: MouseEvent, menuItems: MenuItem[]) {
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
|
||||
position.value = {x: event.clientX, y: event.clientY}
|
||||
items.value = menuItems
|
||||
isOpen.value = true
|
||||
}
|
||||
|
||||
function closeContextMenu() {
|
||||
isOpen.value = false
|
||||
}
|
||||
|
||||
return {
|
||||
isOpen,
|
||||
position,
|
||||
items,
|
||||
openContextMenu,
|
||||
closeContextMenu,
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ import {storeToRefs} from 'pinia'
|
||||
import {useServerStore} from '@/stores/server'
|
||||
import {ref} from 'vue'
|
||||
import {useRouter} from 'vue-router'
|
||||
import ContextMenu from "@/components/ContextMenu.vue";
|
||||
|
||||
const serverStore = useServerStore()
|
||||
const router = useRouter()
|
||||
@@ -74,7 +75,7 @@ const getServerColor = (str: string): string => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<v-app>
|
||||
<v-app @contextmenu.prevent>
|
||||
<!--Top bar-->
|
||||
<v-system-bar>
|
||||
|
||||
@@ -127,7 +128,8 @@ const getServerColor = (str: string): string => {
|
||||
|
||||
</v-navigation-drawer>
|
||||
<router-view/>
|
||||
|
||||
<!-- Menu contextuel global -->
|
||||
<ContextMenu/>
|
||||
<v-dialog v-model="showDialog" width="400">
|
||||
<v-card>
|
||||
<v-card-title>Create Server</v-card-title>
|
||||
|
||||
@@ -5,6 +5,7 @@ import {useCategoryStore} from '@/stores/category'
|
||||
import {ref, watch} from 'vue'
|
||||
import {useRoute} from 'vue-router'
|
||||
import CreateChannelDialog from '@/components/channel/CreateChannelDialog.vue'
|
||||
import {type MenuItem, useContextMenu} from '@/composables/useContextMenu'
|
||||
|
||||
const props = defineProps<{
|
||||
serverId: string
|
||||
@@ -16,6 +17,8 @@ const channelStore = useChannelStore()
|
||||
const categoryStore = useCategoryStore()
|
||||
const {channels} = storeToRefs(channelStore)
|
||||
const {categories} = storeToRefs(categoryStore)
|
||||
const {openContextMenu} = useContextMenu()
|
||||
|
||||
|
||||
const loadServerData = async (targetServerId: string) => {
|
||||
if (!targetServerId) return
|
||||
@@ -42,6 +45,37 @@ watch(
|
||||
)
|
||||
|
||||
const showDialog = ref(false)
|
||||
|
||||
// Right click menu
|
||||
async function openEditDialog(channel: any) {
|
||||
console.log("edit dialog clicked")
|
||||
}
|
||||
|
||||
async function deleteChannel(channelId: string) {
|
||||
console.log("delete channel clicked")
|
||||
}
|
||||
|
||||
function onChannelContextMenu(event: MouseEvent, channel: any) {
|
||||
const menuItems: MenuItem[] = [
|
||||
{
|
||||
label: 'Marquer comme lu',
|
||||
icon: 'mdi-check',
|
||||
action: () => console.log('Marqué comme lu', channel.id),
|
||||
},
|
||||
{
|
||||
label: 'Modifier le canal',
|
||||
icon: 'mdi-pencil',
|
||||
action: () => openEditDialog(channel),
|
||||
},
|
||||
{
|
||||
label: 'Supprimer le canal',
|
||||
icon: 'mdi-delete',
|
||||
color: 'error',
|
||||
action: () => deleteChannel(channel.id),
|
||||
},
|
||||
]
|
||||
openContextMenu(event, menuItems);
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -69,6 +103,7 @@ const showDialog = ref(false)
|
||||
:title="channel.name"
|
||||
:to="`/server/${serverId}/channel/${channel.id}`"
|
||||
link
|
||||
@contextmenu="onChannelContextMenu($event, channel)"
|
||||
></v-list-item>
|
||||
</v-list>
|
||||
</v-navigation-drawer>
|
||||
|
||||
Reference in New Issue
Block a user