TicketDetailBottomBar.vue 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. <!-- Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/ -->
  2. <script setup lang="ts">
  3. import { computed, toRef } from 'vue'
  4. import { NotificationTypes } from '#shared/components/CommonNotifications/types.ts'
  5. import { useNotifications } from '#shared/components/CommonNotifications/useNotifications.ts'
  6. import type { FormRef } from '#shared/components/Form/types.ts'
  7. import { useMacros } from '#shared/entities/macro/composables/useMacros.ts'
  8. import type { MacroById } from '#shared/entities/macro/types.ts'
  9. import type { TicketLiveAppUser } from '#shared/entities/ticket/types.ts'
  10. import { useTicketSharedDraftZoomCreateMutation } from '#shared/entities/ticket-shared-draft-zoom/graphql/mutations/ticketSharedDraftZoomCreate.api.ts'
  11. import { MutationHandler } from '#shared/server/apollo/handler/index.ts'
  12. import CommonActionMenu from '#desktop/components/CommonActionMenu/CommonActionMenu.vue'
  13. import CommonButton from '#desktop/components/CommonButton/CommonButton.vue'
  14. import { useDialog } from '#desktop/components/CommonDialog/useDialog.ts'
  15. import TicketScreenBehavior from '#desktop/pages/ticket/components/TicketDetailView/TicketScreenBehavior/TicketScreenBehavior.vue'
  16. import { useTicketSharedDraft } from '#desktop/pages/ticket/composables/useTicketSharedDraft.ts'
  17. import TicketLiveUsers from './TicketLiveUsers.vue'
  18. import TicketSharedDraftZoom from './TicketSharedDraftZoom.vue'
  19. export interface Props {
  20. dirty: boolean
  21. disabled: boolean
  22. isTicketEditable: boolean
  23. isTicketAgent: boolean
  24. ticketId: string
  25. groupId?: string
  26. form?: FormRef
  27. hasAvailableDraft?: boolean
  28. canUseDraft?: boolean
  29. sharedDraftId?: string | null
  30. liveUserList: TicketLiveAppUser[]
  31. }
  32. const props = defineProps<Props>()
  33. const groupId = toRef(props, 'groupId')
  34. const emit = defineEmits<{
  35. submit: [MouseEvent]
  36. discard: [MouseEvent]
  37. 'execute-macro': [MacroById]
  38. }>()
  39. const { macros } = useMacros(groupId)
  40. const { notify } = useNotifications()
  41. const groupLabels = {
  42. drafts: __('Drafts'),
  43. macros: __('Macros'),
  44. }
  45. const { mapSharedDraftParams } = useTicketSharedDraft()
  46. const sharedDraftConflictDialog = useDialog({
  47. name: 'shared-draft-conflict',
  48. component: () => import('../TicketSharedDraftConflictDialog.vue'),
  49. })
  50. const actionItems = computed(() => {
  51. if (!macros.value) return null
  52. const macroMenu = macros.value.map((macro) => ({
  53. key: macro.id,
  54. label: macro.name,
  55. groupLabel: groupLabels.macros,
  56. onClick: () => emit('execute-macro', macro),
  57. }))
  58. return [
  59. {
  60. label: __('Save as draft'),
  61. groupLabel: groupLabels.drafts,
  62. icon: 'floppy',
  63. key: 'save-draft',
  64. show: () => props.canUseDraft,
  65. onClick: () => {
  66. if (props.sharedDraftId) {
  67. sharedDraftConflictDialog.open({
  68. sharedDraftId: props.sharedDraftId,
  69. sharedDraftParams: mapSharedDraftParams(props.ticketId, props.form),
  70. form: props.form,
  71. })
  72. return
  73. }
  74. const draftCreateMutation = new MutationHandler(
  75. useTicketSharedDraftZoomCreateMutation(),
  76. {
  77. errorNotificationMessage: __('Draft could not be saved.'),
  78. },
  79. )
  80. draftCreateMutation
  81. .send({ input: mapSharedDraftParams(props.ticketId, props.form) })
  82. .then(() => {
  83. notify({
  84. id: 'shared-draft-detail-view-created',
  85. type: NotificationTypes.Success,
  86. message: __('Shared draft has been created successfully.'),
  87. })
  88. })
  89. },
  90. },
  91. ...(groupId.value ? macroMenu : []),
  92. ]
  93. })
  94. </script>
  95. <template>
  96. <div class="flex gap-4 ltr:mr-auto rtl:ml-auto">
  97. <TicketLiveUsers
  98. v-if="liveUserList?.length"
  99. :live-user-list="liveUserList"
  100. />
  101. <TicketSharedDraftZoom
  102. v-if="hasAvailableDraft"
  103. :form="form"
  104. :shared-draft-id="sharedDraftId"
  105. />
  106. </div>
  107. <template v-if="isTicketEditable">
  108. <CommonButton
  109. v-if="dirty"
  110. size="large"
  111. variant="danger"
  112. :disabled="disabled"
  113. @click="$emit('discard', $event)"
  114. >{{ $t('Discard your unsaved changes') }}
  115. </CommonButton>
  116. <TicketScreenBehavior />
  117. <CommonButton
  118. size="large"
  119. variant="submit"
  120. type="button"
  121. :disabled="disabled"
  122. @click="$emit('submit', $event)"
  123. >{{ $t('Update') }}
  124. </CommonButton>
  125. <CommonActionMenu
  126. v-if="isTicketAgent && actionItems"
  127. class="flex"
  128. button-size="large"
  129. no-single-action-mode
  130. placement="arrowEnd"
  131. custom-menu-button-label="Additional ticket edit actions"
  132. :actions="actionItems"
  133. />
  134. </template>
  135. </template>