123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135 |
- // Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
- import { keyBy } from 'lodash-es'
- import { ref, markRaw } from 'vue'
- import { useRouter } from 'vue-router'
- import {
- useNotifications,
- NotificationTypes,
- } from '#shared/components/CommonNotifications/index.ts'
- import { useConfirmation } from '#shared/composables/useConfirmation.ts'
- import { useTicketMergeMutation } from '#shared/entities/ticket/graphql/mutations/merge.api.ts'
- import { AutocompleteSearchTicketDocument } from '#shared/entities/ticket/graphql/queries/autocompleteSearchTicket.api.ts'
- import type { TicketById } from '#shared/entities/ticket/types.ts'
- import UserError from '#shared/errors/UserError.ts'
- import type { AutocompleteSearchTicketEntry } from '#shared/graphql/types.ts'
- import { MutationHandler } from '#shared/server/apollo/handler/index.ts'
- import { useDialog } from '#mobile/composables/useDialog.ts'
- import TicketMergeStatus from '../components/TicketDetailView/TicketMergeStatus.vue'
- import type { FormKitNode } from '@formkit/core'
- import type { Ref } from 'vue'
- export const useTicketsMerge = (
- sourceTicket: Ref<TicketById>,
- onSuccess?: () => void,
- ) => {
- const autocompleteRef = ref<{ node: FormKitNode }>()
- const ticketsSearchDialog = useDialog({
- name: 'tickets-search',
- prefetch: true,
- component: () =>
- import(
- '#mobile/components/Form/fields/FieldAutoComplete/FieldAutoCompleteInputDialog.vue'
- ),
- })
- const mergeHandler = new MutationHandler(useTicketMergeMutation({}))
- const { notify } = useNotifications()
- const router = useRouter()
- let localOptions: Record<string, AutocompleteSearchTicketEntry> = {}
- const { waitForConfirmation } = useConfirmation()
- const mergeTickets = async () => {
- const context = autocompleteRef.value?.node.context
- if (!context || mergeHandler.loading().value) return false
- const targetTicketId = context._value
- const targetTicketOption = localOptions[targetTicketId]
- if (!targetTicketId || !targetTicketOption) {
- notify({
- id: 'merge-ticket-error',
- type: NotificationTypes.Error,
- message: __('Please select a ticket to merge into.'),
- })
- return false
- }
- const targetTicket = targetTicketOption.ticket
- const confirmed = await waitForConfirmation(
- __('Are you sure you want to merge this ticket (#%s) into #%s?'),
- {
- textPlaceholder: [sourceTicket.value.number, targetTicket.number],
- },
- )
- if (!confirmed) return false
- try {
- const result = await mergeHandler.send({
- sourceTicketId: sourceTicket.value.id,
- targetTicketId,
- })
- if (!result) {
- return false
- }
- context.node.input(undefined)
- router.push(`/tickets/${targetTicket.internalId}`)
- return true
- } catch (errors) {
- if (errors instanceof UserError) {
- notify({
- id: 'merge-ticket-error',
- message: errors.generalErrors[0],
- type: NotificationTypes.Error,
- })
- }
- }
- return false
- }
- const mergeAndCloseModals = async () => {
- const isMerged = await mergeTickets()
- if (isMerged) {
- ticketsSearchDialog.close()
- onSuccess?.()
- }
- }
- const openMergeTicketsDialog = () => {
- const context = autocompleteRef.value?.node.context
- if (!context) return
- Object.assign(context, {
- onActionClick: mergeAndCloseModals,
- })
- ticketsSearchDialog.open({
- context,
- name: 'tickets-search',
- options: [],
- optionIconComponent: markRaw(TicketMergeStatus),
- noCloseOnSelect: true,
- onUpdateOptions(options: AutocompleteSearchTicketEntry[]) {
- localOptions = keyBy(options, 'value')
- },
- onAction() {
- mergeAndCloseModals()
- },
- })
- }
- return {
- gqlQuery: AutocompleteSearchTicketDocument,
- autocompleteRef,
- openMergeTicketsDialog,
- }
- }
|