CommonDialogObjectForm.vue 4.2 KB

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