CommonDialogObjectForm.vue 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. <!-- Copyright (C) 2012-2023 Zammad Foundation, https://zammad-foundation.org/ -->
  2. <script setup lang="ts">
  3. import type { ObjectLike } from '@shared/types/utils'
  4. import {
  5. type FormSchemaNode,
  6. type FormData,
  7. useForm,
  8. } from '@shared/components/Form'
  9. import { closeDialog } from '@shared/composables/useDialog'
  10. import type {
  11. EnumFormUpdaterId,
  12. EnumObjectManagerObjects,
  13. ObjectAttributeValue,
  14. } from '@shared/graphql/types'
  15. import type {
  16. FormFieldValue,
  17. FormSchemaField,
  18. } from '@shared/components/Form/types'
  19. import type { OperationMutationFunction } from '@shared/types/server/apollo/handler'
  20. import { MutationHandler } from '@shared/server/apollo/handler'
  21. import Form from '@shared/components/Form/Form.vue'
  22. import { useObjectAttributes } from '@shared/entities/object-attributes/composables/useObjectAttributes'
  23. import { useObjectAttributeFormData } from '@shared/entities/object-attributes/composables/useObjectAttributeFormData'
  24. import CommonDialog from '@mobile/components/CommonDialog/CommonDialog.vue'
  25. import { useConfirmationDialog } from '../CommonConfirmation'
  26. export interface Props {
  27. name: string
  28. object?: ObjectLike
  29. type: EnumObjectManagerObjects
  30. formUpdaterId?: EnumFormUpdaterId
  31. formChangeFields?: Record<string, Partial<FormSchemaField>>
  32. errorNotificationMessage?: string
  33. mutation: OperationMutationFunction
  34. schema: FormSchemaNode[]
  35. keyMap?: Record<string, string | false>
  36. }
  37. const props = defineProps<Props>()
  38. const emit = defineEmits<{
  39. (e: 'success', data: unknown): void
  40. (e: 'error'): void
  41. (
  42. e: 'changedField',
  43. fieldName: string,
  44. newValue: FormFieldValue,
  45. oldValue: FormFieldValue,
  46. ): void
  47. }>()
  48. const updateMutation = new MutationHandler(props.mutation({}), {
  49. errorNotificationMessage: props.errorNotificationMessage,
  50. })
  51. const { form, isDirty, isDisabled, canSubmit } = useForm()
  52. const objectAtrributes: Record<string, string> =
  53. props.object?.objectAttributeValues?.reduce(
  54. (acc: Record<string, string>, cur: ObjectAttributeValue) => {
  55. acc[cur.attribute.name] = cur.value
  56. return acc
  57. },
  58. {},
  59. ) || {}
  60. const initialFlatObject = {
  61. ...props.object,
  62. ...objectAtrributes,
  63. }
  64. const { attributesLookup: objectAttributesLookup } = useObjectAttributes(
  65. props.type,
  66. )
  67. const { waitForConfirmation } = useConfirmationDialog()
  68. const cancelDialog = async () => {
  69. if (isDirty.value) {
  70. const confirmed = await waitForConfirmation(
  71. __('Are you sure? You have unsaved changes that will get lost.'),
  72. )
  73. if (!confirmed) return
  74. }
  75. closeDialog(props.name)
  76. }
  77. const changedFormField = (
  78. fieldName: string,
  79. newValue: FormFieldValue,
  80. oldValue: FormFieldValue,
  81. ) => {
  82. emit('changedField', fieldName, newValue, oldValue)
  83. }
  84. const saveObject = async (formData: FormData) => {
  85. const { internalObjectAttributeValues, additionalObjectAttributeValues } =
  86. useObjectAttributeFormData(
  87. objectAttributesLookup.value,
  88. formData,
  89. props.keyMap,
  90. )
  91. const result = await updateMutation.send({
  92. id: props.object?.id,
  93. input: {
  94. ...internalObjectAttributeValues,
  95. objectAttributeValues: additionalObjectAttributeValues,
  96. },
  97. })
  98. if (result) {
  99. emit('success', result)
  100. closeDialog(props.name)
  101. } else {
  102. emit('error')
  103. }
  104. }
  105. </script>
  106. <template>
  107. <CommonDialog class="w-full" no-autofocus :name="name">
  108. <template #before-label>
  109. <button
  110. class="text-white"
  111. :disabled="isDisabled"
  112. :class="{ 'opacity-50': isDisabled }"
  113. @click="cancelDialog"
  114. >
  115. {{ $t('Cancel') }}
  116. </button>
  117. </template>
  118. <template #after-label>
  119. <button
  120. :form="name"
  121. class="text-blue"
  122. :disabled="!canSubmit"
  123. :class="{ 'opacity-50': !canSubmit }"
  124. >
  125. {{ $t('Save') }}
  126. </button>
  127. </template>
  128. <Form
  129. :id="name"
  130. ref="form"
  131. class="w-full p-4"
  132. autofocus
  133. :schema="schema"
  134. :initial-entity-object="initialFlatObject"
  135. :change-fields="formChangeFields"
  136. use-object-attributes
  137. :form-updater-id="formUpdaterId"
  138. @changed="changedFormField"
  139. @submit="saveObject"
  140. />
  141. </CommonDialog>
  142. </template>