TicketSidebarSharedDraftStartContent.vue 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. <!-- Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/ -->
  2. <script setup lang="ts">
  3. import { createMessage, getNode } from '@formkit/core'
  4. import { computed, ref } from 'vue'
  5. import {
  6. NotificationTypes,
  7. useNotifications,
  8. } from '#shared/components/CommonNotifications/index.ts'
  9. import { useTicketSharedDraftStartCreateMutation } from '#shared/entities/ticket-shared-draft-start/graphql/mutations/ticketSharedDraftStartCreate.api.ts'
  10. import { useTicketSharedDraftStartUpdateMutation } from '#shared/entities/ticket-shared-draft-start/graphql/mutations/ticketSharedDraftStartUpdate.api.ts'
  11. import type { TicketSharedDraftStartListQuery } from '#shared/graphql/types.ts'
  12. import { convertToGraphQLId } from '#shared/graphql/utils.ts'
  13. import { MutationHandler } from '#shared/server/apollo/handler/index.ts'
  14. import { removeSignatureFromBody } from '#shared/utils/dom.ts'
  15. import CommonButton from '#desktop/components/CommonButton/CommonButton.vue'
  16. import { useTicketSharedDraft } from '#desktop/pages/ticket/composables/useTicketSharedDraft.ts'
  17. import type { TicketSidebarContentProps } from '#desktop/pages/ticket/types/sidebar.ts'
  18. import TicketSidebarContent from '../TicketSidebarContent.vue'
  19. interface Props extends TicketSidebarContentProps {
  20. sharedDraftStartList: TicketSharedDraftStartListQuery['ticketSharedDraftStartList']
  21. }
  22. const props = defineProps<Props>()
  23. const groupId = computed(() =>
  24. convertToGraphQLId('Group', Number(props.context.formValues.group_id)),
  25. )
  26. const currentSharedDraftId = computed(() =>
  27. convertToGraphQLId(
  28. 'Ticket::SharedDraftStart',
  29. Number(props.context.formValues.shared_draft_id),
  30. ),
  31. )
  32. const sharedDraftTitle = ref('')
  33. const { notify } = useNotifications()
  34. const sharedDraftStartCreateMutation = new MutationHandler(
  35. useTicketSharedDraftStartCreateMutation(),
  36. )
  37. const unsupportedFields = [
  38. 'articleSenderType',
  39. 'attachments',
  40. 'group_id',
  41. 'security',
  42. 'shared_draft_id',
  43. 'ticket_duplicate_detection',
  44. ]
  45. const supportedFields = () =>
  46. Object.fromEntries(
  47. Object.entries(props.context.formValues).filter(
  48. ([field]) => !unsupportedFields.includes(field),
  49. ),
  50. )
  51. const sharedDraftContent = () => ({
  52. ...supportedFields(),
  53. formSenderType: props.context.formValues.articleSenderType, // different key
  54. cc: ((props.context.formValues.cc as string[]) || []).join(', '),
  55. tags: ((props.context.formValues.tags as string[]) || []).join(', '),
  56. body: removeSignatureFromBody(props.context.formValues.body),
  57. })
  58. const createSharedDraft = () => {
  59. const sharedDraftTitleNode = getNode('sharedDraftTitle')
  60. if (!sharedDraftTitleNode) return
  61. // Trigger field validation.
  62. sharedDraftTitleNode.store.set(
  63. createMessage({
  64. key: 'submitted',
  65. value: true,
  66. visible: false,
  67. }),
  68. )
  69. // Check if the field passed validation.
  70. if (Object.keys(sharedDraftTitleNode.context?.messages || {}).length) return
  71. sharedDraftStartCreateMutation
  72. .send({
  73. name: sharedDraftTitle.value.trim(),
  74. input: {
  75. formId: props.context.form?.formId as string,
  76. groupId: groupId.value,
  77. content: sharedDraftContent(),
  78. },
  79. })
  80. .then(() => {
  81. sharedDraftTitleNode.reset()
  82. notify({
  83. id: 'shared-draft-created',
  84. type: NotificationTypes.Success,
  85. message: __('Shared draft has been created successfully.'),
  86. })
  87. })
  88. }
  89. const sharedDraftStartUpdateMutation = new MutationHandler(
  90. useTicketSharedDraftStartUpdateMutation(),
  91. )
  92. const updateSharedDraft = () => {
  93. if (!currentSharedDraftId.value) return
  94. sharedDraftStartUpdateMutation
  95. .send({
  96. sharedDraftId: currentSharedDraftId.value,
  97. input: {
  98. formId: props.context.form?.formId as string,
  99. groupId: groupId.value,
  100. content: sharedDraftContent(),
  101. },
  102. })
  103. .then(() => {
  104. notify({
  105. id: 'shared-draft-updated',
  106. type: NotificationTypes.Success,
  107. message: __('Shared draft has been updated successfully.'),
  108. })
  109. })
  110. }
  111. const { openSharedDraftFlyout } = useTicketSharedDraft()
  112. const openFlyout = (sharedDraftStartId: string) => {
  113. openSharedDraftFlyout('start', sharedDraftStartId, props.context.form)
  114. }
  115. </script>
  116. <template>
  117. <TicketSidebarContent :title="sidebarPlugin.title" :icon="sidebarPlugin.icon">
  118. <FormKit
  119. id="sharedDraftTitle"
  120. v-model="sharedDraftTitle"
  121. type="text"
  122. :label="__('Create a shared draft')"
  123. :placeholder="__('Name')"
  124. validation="required:trim"
  125. link="/"
  126. link-icon="plus-square-fill"
  127. :link-label="__('Create Shared Draft')"
  128. @link-click.prevent="createSharedDraft"
  129. @keypress.enter.prevent="createSharedDraft"
  130. />
  131. <div class="py-1">
  132. <div
  133. v-if="sharedDraftStartList?.length"
  134. class="flex flex-col divide-y divide-solid divide-neutral-100 dark:divide-gray-900"
  135. >
  136. <div
  137. v-for="sharedDraftStart in sharedDraftStartList"
  138. :key="sharedDraftStart.id"
  139. class="flex items-center gap-1.5 py-2.5"
  140. >
  141. <div class="flex grow flex-col">
  142. <CommonLink
  143. v-tooltip="sharedDraftStart.name"
  144. link="#"
  145. class="line-clamp-1"
  146. :aria-label="$t('Preview Shared Draft')"
  147. @click.prevent="openFlyout(sharedDraftStart.id)"
  148. >{{ sharedDraftStart.name }}</CommonLink
  149. >
  150. <CommonLabel
  151. class="line-clamp-1 text-stone-200 dark:text-neutral-500"
  152. size="small"
  153. >
  154. <CommonDateTime :date-time="sharedDraftStart.updatedAt" />
  155. <template v-if="sharedDraftStart.updatedBy">
  156. <span v-tooltip="sharedDraftStart.updatedBy.fullname">
  157. &bull; {{ sharedDraftStart.updatedBy.fullname }}
  158. </span>
  159. </template>
  160. </CommonLabel>
  161. </div>
  162. <CommonButton
  163. v-if="currentSharedDraftId === sharedDraftStart.id"
  164. v-tooltip="__('Update Shared Draft')"
  165. variant="submit"
  166. size="small"
  167. icon="arrow-repeat"
  168. @click="updateSharedDraft"
  169. />
  170. </div>
  171. </div>
  172. <CommonLabel
  173. v-else
  174. class="text-stone-200 dark:text-neutral-500"
  175. size="small"
  176. >
  177. {{ $t('No shared drafts yet') }}
  178. </CommonLabel>
  179. </div>
  180. </TicketSidebarContent>
  181. </template>