refactor: create TicketDeleteDialog (#1079)

This commit is contained in:
Jonas Plum
2024-07-12 21:09:48 +02:00
committed by GitHub
parent 00b7ab585c
commit 82ad50d228
8 changed files with 83 additions and 271 deletions

View File

@@ -15,25 +15,30 @@ import { Trash2 } from 'lucide-vue-next'
import { useMutation, useQueryClient } from '@tanstack/vue-query'
import { ref } from 'vue'
import { type RouteLocationRaw, useRouter } from 'vue-router'
import { pb } from '@/lib/pocketbase'
import type { File, Ticket } from '@/lib/types'
import { handleError } from '@/lib/utils'
const queryClient = useQueryClient()
const router = useRouter()
const props = defineProps<{
ticket: Ticket
file: File
collection: string
id: string
name: string
singular: string
queryKey: string[]
to?: RouteLocationRaw
}>()
const isOpen = ref(false)
const removeFileMutation = useMutation({
mutationFn: (): Promise<boolean> => pb.collection('files').delete(props.file.id),
const deleteMutation = useMutation({
mutationFn: () => pb.collection(props.collection).delete(props.id),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['tickets', props.ticket.id] })
isOpen.value = false
queryClient.invalidateQueries({ queryKey: props.queryKey })
if (props.to) router.push(props.to)
},
onError: handleError
})
@@ -42,23 +47,27 @@ const removeFileMutation = useMutation({
<template>
<Dialog v-model:open="isOpen">
<DialogTrigger as-child>
<Button variant="ghost" size="icon">
<Trash2 class="h-4 w-4" />
<slot>
<Button variant="outline">
<Trash2 class="mr-2 h-4 w-4" />
Delete {{ props.singular }}
</Button>
</slot>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle> Delete File "{{ props.file.name }}" </DialogTitle>
<DialogDescription> Are you sure you want to delete this file? </DialogDescription>
<DialogTitle> Delete {{ props.singular }} "{{ props.name }}"</DialogTitle>
<DialogDescription>
Are you sure you want to delete this {{ props.singular }}?</DialogDescription
>
</DialogHeader>
<DialogFooter class="mt-2">
<DialogClose as-child>
<Button type="button" variant="secondary">Cancel</Button>
</DialogClose>
<Button type="button" variant="destructive" @click="removeFileMutation.mutate()">
Delete
</Button>
<Button type="button" variant="destructive" @click="deleteMutation.mutate"> Delete </Button>
</DialogFooter>
</DialogContent>
</Dialog>

View File

@@ -1,5 +1,6 @@
<script setup lang="ts">
import Icon from '@/components/Icon.vue'
import DeleteDialog from '@/components/common/DeleteDialog.vue'
import TicketCloseDialog from '@/components/ticket/TicketCloseDialog.vue'
import TicketUserSelect from '@/components/ticket/TicketUserSelect.vue'
import { Button } from '@/components/ui/button'
@@ -141,6 +142,14 @@ const closeTicketDialogOpen = ref(false)
<TooltipContent>Change User</TooltipContent>
</Tooltip>
</div>
<TicketDeleteDialog :ticket="ticket" />
<DeleteDialog
v-if="ticket"
:collection="'tickets'"
:id="ticket.id"
:name="ticket.name"
singular="Ticket"
:to="{ name: 'tickets' }"
:queryKey="['tickets']"
/>
</div>
</template>

View File

@@ -1,90 +0,0 @@
<script setup lang="ts">
import { Button } from '@/components/ui/button'
import {
Dialog,
DialogClose,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger
} from '@/components/ui/dialog'
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger
} from '@/components/ui/dropdown-menu'
import { toast } from '@/components/ui/toast'
import { MoreVertical, Trash2 } from 'lucide-vue-next'
import { useMutation, useQueryClient } from '@tanstack/vue-query'
import { ref } from 'vue'
import { useRouter } from 'vue-router'
import { pb } from '@/lib/pocketbase'
import type { Ticket } from '@/lib/types'
const queryClient = useQueryClient()
const router = useRouter()
const props = defineProps<{
ticket: Ticket
}>()
const isOpen = ref(false)
const deleteTicketMutation = useMutation({
mutationFn: (): Promise<boolean> => pb.collection('tickets').delete(props.ticket.id),
onSuccess: () => {
router.push({ name: 'tickets', params: { type: props.ticket.expand.type.id } })
queryClient.invalidateQueries({ queryKey: ['tickets'] })
isOpen.value = false
},
onError: (error) =>
toast({
title: error.name,
description: error.message,
variant: 'destructive'
})
})
</script>
<template>
<Dialog v-model:open="isOpen">
<DropdownMenu>
<DropdownMenuTrigger as-child>
<Button variant="ghost" size="icon" :disabled="!ticket">
<MoreVertical class="size-4" />
<span class="sr-only">More</span>
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
<DropdownMenuItem class="cursor-pointer" as-child>
<DialogTrigger class="w-full">
<Trash2 class="mr-2 h-4 w-4" />
Delete Ticket
</DialogTrigger>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
<DialogContent>
<DialogHeader>
<DialogTitle> Delete Ticket "{{ props.ticket.name }}"</DialogTitle>
<DialogDescription> Are you sure you want to delete this ticket?</DialogDescription>
</DialogHeader>
<DialogFooter class="mt-2">
<DialogClose as-child>
<Button type="button" variant="secondary"> Cancel</Button>
</DialogClose>
<Button type="button" variant="destructive" @click="deleteTicketMutation.mutate()">
Delete
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
</template>

View File

@@ -1,9 +1,10 @@
<script setup lang="ts">
import DeleteDialog from '@/components/common/DeleteDialog.vue'
import TicketPanel from '@/components/ticket/TicketPanel.vue'
import FileAddDialog from '@/components/ticket/file/FileAddDialog.vue'
import { Button } from '@/components/ui/button'
import { Download } from 'lucide-vue-next'
import { Download, Trash2 } from 'lucide-vue-next'
import { useQuery } from '@tanstack/vue-query'
import { ref, watch } from 'vue'
@@ -69,7 +70,18 @@ watch(config, (newConfig) => {
>
<Download class="size-4" />
</Button>
<FileRemoveDialog :ticket="ticket" :file="file" />
<DeleteDialog
v-if="file"
collection="files"
:id="file.id"
:name="file.name"
singular="File"
:queryKey="['tickets', ticket.id]"
>
<Button variant="ghost" size="icon" class="h-8 w-8">
<Trash2 class="size-4" />
</Button>
</DeleteDialog>
</div>
</TicketPanel>
</template>

View File

@@ -1,70 +0,0 @@
<script setup lang="ts">
import { Button } from '@/components/ui/button'
import {
Dialog,
DialogClose,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger
} from '@/components/ui/dialog'
import { toast } from '@/components/ui/toast'
import { Trash2 } from 'lucide-vue-next'
import { useMutation, useQueryClient } from '@tanstack/vue-query'
import { ref } from 'vue'
import { pb } from '@/lib/pocketbase'
import type { Link, Ticket } from '@/lib/types'
const queryClient = useQueryClient()
const props = defineProps<{
ticket: Ticket
link: Link
}>()
const isOpen = ref(false)
const removeLinkMutation = useMutation({
mutationFn: (): Promise<boolean> => pb.collection('links').delete(props.link.id),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['tickets', props.ticket.id] })
isOpen.value = false
},
onError: (error) =>
toast({
title: error.name,
description: error.message,
variant: 'destructive'
})
})
</script>
<template>
<Dialog v-model:open="isOpen">
<DialogTrigger as-child>
<Button variant="ghost" size="icon" class="h-8 w-8">
<Trash2 class="size-4" />
</Button>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle> Delete Link "{{ props.link.name }}" </DialogTitle>
<DialogDescription> Are you sure you want to delete this link? </DialogDescription>
</DialogHeader>
<DialogFooter class="mt-2">
<DialogClose as-child>
<Button type="button" variant="secondary"> Cancel</Button>
</DialogClose>
<Button type="button" variant="destructive" @click="removeLinkMutation.mutate()">
Delete
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
</template>

View File

@@ -1,8 +1,11 @@
<script setup lang="ts">
import DeleteDialog from '@/components/common/DeleteDialog.vue'
import PanelListElement from '@/components/common/PanelListElement.vue'
import TicketPanel from '@/components/ticket/TicketPanel.vue'
import LinkAddDialog from '@/components/ticket/link/LinkAddDialog.vue'
import LinkRemoveDialog from '@/components/ticket/link/LinkRemoveDialog.vue'
import { Button } from '@/components/ui/button'
import { Trash2 } from 'lucide-vue-next'
import { ref } from 'vue'
@@ -38,7 +41,18 @@ const dialogOpen = ref(false)
</div>
</a>
<LinkRemoveDialog :ticket="ticket" :link="link" />
<DeleteDialog
v-if="link"
collection="links"
:id="link.id"
:name="link.name"
singular="Link"
:queryKey="['tickets', ticket.id]"
>
<Button variant="ghost" size="icon" class="h-8 w-8">
<Trash2 class="size-4" />
</Button>
</DeleteDialog>
</PanelListElement>
</TicketPanel>
</template>

View File

@@ -1,70 +0,0 @@
<script setup lang="ts">
import { Button } from '@/components/ui/button'
import {
Dialog,
DialogClose,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger
} from '@/components/ui/dialog'
import { toast } from '@/components/ui/toast'
import { Trash2 } from 'lucide-vue-next'
import { useMutation, useQueryClient } from '@tanstack/vue-query'
import { ref } from 'vue'
import { pb } from '@/lib/pocketbase'
import type { Task, Ticket } from '@/lib/types'
const queryClient = useQueryClient()
const props = defineProps<{
ticket: Ticket
task: Task
}>()
const isOpen = ref(false)
const removeTaskMutation = useMutation({
mutationFn: (): Promise<boolean> => pb.collection('tasks').delete(props.task.id),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['tickets', props.ticket.id] })
isOpen.value = false
},
onError: (error) =>
toast({
title: error.name,
description: error.message,
variant: 'destructive'
})
})
</script>
<template>
<Dialog v-model:open="isOpen">
<DialogTrigger as-child>
<Button variant="ghost" size="icon" class="h-8 w-8">
<Trash2 class="size-4" />
</Button>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle> Delete Task "{{ props.task.name }}" </DialogTitle>
<DialogDescription> Are you sure you want to delete this task? </DialogDescription>
</DialogHeader>
<DialogFooter class="mt-2">
<DialogClose as-child>
<Button type="button" variant="secondary"> Cancel</Button>
</DialogClose>
<Button type="button" variant="destructive" @click="removeTaskMutation.mutate()">
Delete
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
</template>

View File

@@ -1,4 +1,5 @@
<script setup lang="ts">
import DeleteDialog from '@/components/common/DeleteDialog.vue'
import PanelListElement from '@/components/common/PanelListElement.vue'
import UserSelect from '@/components/common/UserSelect.vue'
import DynamicInput from '@/components/input/DynamicInput.vue'
@@ -8,12 +9,13 @@ import { Card } from '@/components/ui/card'
import { Checkbox } from '@/components/ui/checkbox'
import { toast } from '@/components/ui/toast'
import { User2 } from 'lucide-vue-next'
import { Trash2, User2 } from 'lucide-vue-next'
import { useMutation, useQueryClient } from '@tanstack/vue-query'
import { pb } from '@/lib/pocketbase'
import type { Task, Ticket, User } from '@/lib/types'
import { handleError } from '@/lib/utils'
const queryClient = useQueryClient()
@@ -28,12 +30,7 @@ const setTaskOwnerMutation = useMutation({
owner: update.user.id
}),
onSuccess: () => queryClient.invalidateQueries({ queryKey: ['tickets', props.ticket.id] }),
onError: (error) =>
toast({
title: error.name,
description: error.message,
variant: 'destructive'
})
onError: handleError
})
const update = (id: string, user: User) => setTaskOwnerMutation.mutate({ id, user })
@@ -44,12 +41,7 @@ const checkMutation = useMutation({
open: !task.open
}),
onSuccess: () => queryClient.invalidateQueries({ queryKey: ['tickets', props.ticket.id] }),
onError: (error) =>
toast({
title: error.name,
description: error.message,
variant: 'destructive'
})
onError: handleError
})
const check = (task: Task) => checkMutation.mutate(task)
@@ -60,12 +52,7 @@ const updateTaskNameMutation = useMutation({
name: update.name
}),
onSuccess: () => queryClient.invalidateQueries({ queryKey: ['tickets', props.ticket.id] }),
onError: (error) =>
toast({
title: error.name,
description: error.message,
variant: 'destructive'
})
onError: handleError
})
const updateTaskName = (id: string, name: string) => updateTaskNameMutation.mutate({ id, name })
@@ -104,7 +91,18 @@ const updateTaskName = (id: string, name: string) => updateTaskNameMutation.muta
{{ task.expand.owner.name }}
</Button>
</UserSelect>
<TaskRemoveDialog :ticket="ticket" :task="task" />
<DeleteDialog
v-if="task"
collection="tasks"
:id="task.id"
:name="task.name"
:singular="'Task'"
:queryKey="['tickets', ticket.id]"
>
<Button variant="ghost" size="icon" class="h-8 w-8">
<Trash2 class="size-4" />
</Button>
</DeleteDialog>
</div>
</PanelListElement>
</Card>