fixed dialogs behaviour
This commit is contained in:
@@ -1,40 +1,42 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { DropdownMenu, DropdownMenuItem,
|
import { ref } from 'vue'
|
||||||
DropdownMenuTrigger, DropdownMenuContent } from '@/components/ui/dropdown-menu';
|
import {
|
||||||
import { Ellipsis } from 'lucide-vue-next';
|
DropdownMenu, DropdownMenuItem,
|
||||||
import EditDeviceDialog from './EditDeviceDialog.vue';
|
DropdownMenuTrigger, DropdownMenuContent
|
||||||
import DeleteDeviceDialog from './DeleteDeviceDialog.vue';
|
} from '@/components/ui/dropdown-menu'
|
||||||
import { ref } from 'vue';
|
import EditDeviceDialog from './EditDeviceDialog.vue'
|
||||||
|
import DeleteDeviceDialog from './DeleteDeviceDialog.vue'
|
||||||
|
import { Ellipsis } from 'lucide-vue-next'
|
||||||
|
import type { Device } from '@/lib/interfaces'
|
||||||
|
// import { api } from '@/lib/api'
|
||||||
|
|
||||||
|
const props = defineProps<{ row: Device }>() // ← accept full row
|
||||||
|
|
||||||
const isEditOpen = ref(false)
|
const isEditOpen = ref(false)
|
||||||
const isDeleteOpen = ref(false)
|
const isDeleteOpen = ref(false)
|
||||||
|
|
||||||
// your actual delete logic
|
|
||||||
function onDeleteConfirmed() {
|
function onDeleteConfirmed() {
|
||||||
// e.g. await api.deleteUser(props.userId)
|
// await api.delete(`/devices/${encodeURIComponent(props.row.guid)}`)
|
||||||
isDeleteOpen.value = false
|
isDeleteOpen.value = false
|
||||||
}
|
}
|
||||||
function onEditConfirm() {
|
function onEditConfirm() {
|
||||||
isEditOpen.value = false
|
isEditOpen.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<DropdownMenu>
|
<DropdownMenu>
|
||||||
<DropdownMenuTrigger asChild>
|
<DropdownMenuTrigger asChild>
|
||||||
<button class="p-2 rounded hover:bg-muted">
|
<button class="p-2 rounded hover:bg-muted">
|
||||||
<Ellipsis/>
|
<Ellipsis />
|
||||||
</button>
|
</button>
|
||||||
</DropdownMenuTrigger>
|
</DropdownMenuTrigger>
|
||||||
<DropdownMenuContent align="end" class="w-[160px]">
|
<DropdownMenuContent align="end" class="w-[160px]">
|
||||||
<DropdownMenuItem @click.prevent="isEditOpen = true">
|
<DropdownMenuItem @click.prevent="isEditOpen = true">Rename</DropdownMenuItem>
|
||||||
Rename
|
<DropdownMenuItem @click.prevent="isDeleteOpen = true">Delete</DropdownMenuItem>
|
||||||
</DropdownMenuItem>
|
|
||||||
<DropdownMenuItem @click.prevent="isDeleteOpen = true">
|
|
||||||
Delete
|
|
||||||
</DropdownMenuItem>
|
|
||||||
</DropdownMenuContent>
|
</DropdownMenuContent>
|
||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
<EditDeviceDialog v-model:modelValue="isEditOpen"@confirm="onEditConfirm()" />
|
|
||||||
<DeleteDeviceDialog v-model:modelValue="isDeleteOpen" @confirm="onDeleteConfirmed" />
|
<EditDeviceDialog v-model:modelValue="isEditOpen" :device="props.row" @confirm="onEditConfirm" />
|
||||||
</template>
|
<DeleteDeviceDialog v-model:modelValue="isDeleteOpen" :device="props.row" @confirm="onDeleteConfirmed" />
|
||||||
|
</template>
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { ref } from 'vue'
|
||||||
import {
|
import {
|
||||||
DropdownMenu, DropdownMenuItem,
|
DropdownMenu, DropdownMenuItem,
|
||||||
DropdownMenuTrigger, DropdownMenuContent
|
DropdownMenuTrigger, DropdownMenuContent
|
||||||
} from '@/components/ui/dropdown-menu'
|
} from '@/components/ui/dropdown-menu'
|
||||||
|
|
||||||
import EditUserDialog from './EditUserDialog.vue'
|
import EditUserDialog from './EditUserDialog.vue'
|
||||||
import DeleteUserDialog from './DeleteUserDialog.vue'
|
import DeleteUserDialog from './DeleteUserDialog.vue'
|
||||||
import { Ellipsis } from 'lucide-vue-next'
|
import { Ellipsis } from 'lucide-vue-next'
|
||||||
import { ref } from 'vue'
|
import { api } from '@/lib/api'
|
||||||
import { api } from '@/lib/api' // <-- use your axios/fetch wrapper
|
import type { Users } from '@/lib/interfaces'
|
||||||
|
|
||||||
const props = defineProps<{ userId: string }>()
|
const props = defineProps<{ row: Users }>() // ← accept full row
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(e: 'deleted', id: string): void
|
(e: 'deleted', id: string): void
|
||||||
(e: 'error', err: unknown): void
|
(e: 'error', err: unknown): void
|
||||||
@@ -20,18 +20,17 @@ const isEditOpen = ref(false)
|
|||||||
const isDeleteOpen = ref(false)
|
const isDeleteOpen = ref(false)
|
||||||
const deleting = ref(false)
|
const deleting = ref(false)
|
||||||
|
|
||||||
// DELETE /users/:id
|
|
||||||
async function onDeleteConfirmed() {
|
async function onDeleteConfirmed() {
|
||||||
try {
|
try {
|
||||||
deleting.value = true
|
deleting.value = true
|
||||||
await api.delete(`/users/${encodeURIComponent(props.userId)}`)
|
await api.delete(`/users/${encodeURIComponent(String(props.row.id))}`)
|
||||||
emit('deleted', props.userId)
|
emit('deleted', String(props.row.id))
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err)
|
console.error(err)
|
||||||
emit('error', err)
|
emit('error', err)
|
||||||
} finally {
|
} finally {
|
||||||
deleting.value = false
|
deleting.value = false
|
||||||
// The dialog already closes itself on confirm; nothing else required.
|
// DeleteUserDialog closes itself after confirm
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,21 +48,13 @@ function onEditConfirm() {
|
|||||||
</DropdownMenuTrigger>
|
</DropdownMenuTrigger>
|
||||||
|
|
||||||
<DropdownMenuContent align="end" class="w-[160px]">
|
<DropdownMenuContent align="end" class="w-[160px]">
|
||||||
<DropdownMenuItem @click.prevent="isEditOpen = true">
|
<DropdownMenuItem @click.prevent="isEditOpen = true">Edit</DropdownMenuItem>
|
||||||
Edit
|
|
||||||
</DropdownMenuItem>
|
|
||||||
<DropdownMenuItem @click.prevent="isDeleteOpen = true" :disabled="deleting">
|
<DropdownMenuItem @click.prevent="isDeleteOpen = true" :disabled="deleting">
|
||||||
Delete
|
Delete
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
</DropdownMenuContent>
|
</DropdownMenuContent>
|
||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
|
|
||||||
<EditUserDialog v-model:modelValue="isEditOpen" @confirm="onEditConfirm()" />
|
<EditUserDialog v-model:modelValue="isEditOpen" @confirm="onEditConfirm" />
|
||||||
|
<DeleteUserDialog v-model:modelValue="isDeleteOpen" :loading="deleting" @confirm="onDeleteConfirmed" />
|
||||||
<!-- pass 'deleting' to disable the confirm button during request -->
|
</template>
|
||||||
<DeleteUserDialog
|
|
||||||
v-model:modelValue="isDeleteOpen"
|
|
||||||
:loading="deleting"
|
|
||||||
@confirm="onDeleteConfirmed"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
|
|||||||
@@ -96,6 +96,7 @@ const table = useVueTable({
|
|||||||
<component
|
<component
|
||||||
:is="props.dropdownComponent"
|
:is="props.dropdownComponent"
|
||||||
:row="row.original"
|
:row="row.original"
|
||||||
|
:key="row.id"
|
||||||
/>
|
/>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ const emit = defineEmits<{
|
|||||||
<template>
|
<template>
|
||||||
<AlertDialog
|
<AlertDialog
|
||||||
:open="props.modelValue"
|
:open="props.modelValue"
|
||||||
@openChange="(v: boolean) => emit('update:modelValue', v)"
|
@update:open="(v: boolean) => emit('update:modelValue', v)"
|
||||||
>
|
>
|
||||||
<AlertDialogContent>
|
<AlertDialogContent>
|
||||||
<AlertDialogHeader>
|
<AlertDialogHeader>
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ const emit = defineEmits<{
|
|||||||
<template>
|
<template>
|
||||||
<AlertDialog
|
<AlertDialog
|
||||||
:open="props.modelValue"
|
:open="props.modelValue"
|
||||||
@openChange="(v: boolean) => emit('update:modelValue', v)"
|
@update:open="(v: boolean) => emit('update:modelValue', v)"
|
||||||
>
|
>
|
||||||
<AlertDialogContent>
|
<AlertDialogContent>
|
||||||
<AlertDialogHeader>
|
<AlertDialogHeader>
|
||||||
|
|||||||
@@ -10,9 +10,10 @@ import {
|
|||||||
import { Button } from '@/components/ui/button'
|
import { Button } from '@/components/ui/button'
|
||||||
import { Input } from '@/components/ui/input'
|
import { Input } from '@/components/ui/input'
|
||||||
import { Label } from '@/components/ui/label'
|
import { Label } from '@/components/ui/label'
|
||||||
import { defineProps, defineEmits } from 'vue'
|
import { defineProps, defineEmits, ref, watch } from 'vue'
|
||||||
import type { PropType } from 'vue'
|
import type { PropType } from 'vue'
|
||||||
import AssignDevice from './AssignDevice.vue'
|
import AssignDevice from './AssignDevice.vue'
|
||||||
|
import type { Device } from '@/lib/interfaces'
|
||||||
|
|
||||||
// 1) runtime props so Vue + TS agree
|
// 1) runtime props so Vue + TS agree
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
@@ -20,6 +21,7 @@ const props = defineProps({
|
|||||||
type: Boolean as PropType<boolean>,
|
type: Boolean as PropType<boolean>,
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
|
device: { type: Object as PropType<Device>, required: false },
|
||||||
})
|
})
|
||||||
|
|
||||||
// 2) two emits: v-model and confirm
|
// 2) two emits: v-model and confirm
|
||||||
@@ -28,6 +30,16 @@ const emit = defineEmits<{
|
|||||||
(e: 'confirm'): void
|
(e: 'confirm'): void
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
|
const name = ref('')
|
||||||
|
// when device changes or dialog opens, update local value
|
||||||
|
watch(
|
||||||
|
() => props.device,
|
||||||
|
(dev) => {
|
||||||
|
name.value = dev?.devicename ?? ''
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
)
|
||||||
|
|
||||||
function onSave() {
|
function onSave() {
|
||||||
emit('confirm')
|
emit('confirm')
|
||||||
// close the dialog
|
// close the dialog
|
||||||
@@ -38,7 +50,7 @@ function onSave() {
|
|||||||
<template>
|
<template>
|
||||||
<Dialog
|
<Dialog
|
||||||
:open="props.modelValue"
|
:open="props.modelValue"
|
||||||
@openChange="(v: boolean) => emit('update:modelValue', v)"
|
@update:open="(v: boolean) => emit('update:modelValue', v)"
|
||||||
>
|
>
|
||||||
<DialogContent class="sm:max-w-[425px]">
|
<DialogContent class="sm:max-w-[425px]">
|
||||||
<DialogHeader>
|
<DialogHeader>
|
||||||
@@ -51,11 +63,11 @@ function onSave() {
|
|||||||
<div class="grid gap-4 py-4">
|
<div class="grid gap-4 py-4">
|
||||||
<div class="grid grid-cols-4 items-center gap-4">
|
<div class="grid grid-cols-4 items-center gap-4">
|
||||||
<Label for="guid" class="text-right">GUID</Label>
|
<Label for="guid" class="text-right">GUID</Label>
|
||||||
<Input id="guid" class="col-span-3" />
|
<p id="guid" class="col-span-3"> {{ props.device?.guid }}</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="grid grid-cols-4 items-center gap-4">
|
<div class="grid grid-cols-4 items-center gap-4">
|
||||||
<Label for="name" class="text-right">Name</Label>
|
<Label for="name" class="text-right">Name</Label>
|
||||||
<Input id="name" class="col-span-3" />
|
<Input id="name" class="col-span-3" v-model="name" />
|
||||||
</div>
|
</div>
|
||||||
<div class="grid grid-cols-4 items-center gap-4">
|
<div class="grid grid-cols-4 items-center gap-4">
|
||||||
<Label for="users" class="text-right">Allowed users</Label>
|
<Label for="users" class="text-right">Allowed users</Label>
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ function onSave() {
|
|||||||
<template>
|
<template>
|
||||||
<Dialog
|
<Dialog
|
||||||
:open="props.modelValue"
|
:open="props.modelValue"
|
||||||
@openChange="(v: boolean) => emit('update:modelValue', v)"
|
@update:open="(v: boolean) => emit('update:modelValue', v)"
|
||||||
>
|
>
|
||||||
<DialogContent class="sm:max-w-[425px]">
|
<DialogContent class="sm:max-w-[425px]">
|
||||||
<DialogHeader>
|
<DialogHeader>
|
||||||
|
|||||||
Reference in New Issue
Block a user