FieldNotificationsInput.vue 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. <!-- Copyright (C) 2012-2025 Zammad Foundation, https://zammad-foundation.org/ -->
  2. <script setup lang="ts">
  3. import { cloneDeep } from 'lodash-es'
  4. import { toRef } from 'vue'
  5. import useValue from '#shared/components/Form/composables/useValue.ts'
  6. import type { FormFieldContext } from '#shared/components/Form/types/field.ts'
  7. import CommonSimpleTable from '#desktop/components/CommonTable/CommonSimpleTable.vue'
  8. import type { TableSimpleHeader } from '#desktop/components/CommonTable/types.ts'
  9. import {
  10. NotificationMatrixColumnKey,
  11. NotificationMatrixPathKey,
  12. NotificationMatrixRowKey,
  13. } from './types.ts'
  14. const props = defineProps<{
  15. context: FormFieldContext
  16. }>()
  17. const context = toRef(props, 'context')
  18. const { localValue } = useValue(context)
  19. const tableHeaders: TableSimpleHeader[] = [
  20. {
  21. key: 'name',
  22. label: __('Name'),
  23. },
  24. {
  25. key: NotificationMatrixColumnKey.MyTickets,
  26. path: NotificationMatrixPathKey.Criteria,
  27. label: __('My tickets'),
  28. alignContent: 'center',
  29. headerClass: 'w-20',
  30. },
  31. {
  32. key: NotificationMatrixColumnKey.NotAssigned,
  33. path: NotificationMatrixPathKey.Criteria,
  34. label: __('Not assigned'),
  35. alignContent: 'center',
  36. headerClass: 'w-20',
  37. },
  38. {
  39. key: NotificationMatrixColumnKey.SubscribedTickets,
  40. path: NotificationMatrixPathKey.Criteria,
  41. label: __('Subscribed tickets'),
  42. alignContent: 'center',
  43. headerClass: 'w-20',
  44. },
  45. {
  46. key: NotificationMatrixColumnKey.AllTickets,
  47. path: NotificationMatrixPathKey.Criteria,
  48. label: __('All tickets'),
  49. alignContent: 'center',
  50. headerClass: 'w-20',
  51. columnSeparator: true,
  52. },
  53. {
  54. key: NotificationMatrixColumnKey.AlsoNotifyViaEmail,
  55. path: NotificationMatrixPathKey.Channel,
  56. label: __('Also notify via email'),
  57. alignContent: 'center',
  58. headerClass: 'w-20',
  59. },
  60. ]
  61. const tableItems = [
  62. {
  63. id: 1,
  64. key: NotificationMatrixRowKey.Create,
  65. name: __('New ticket'),
  66. },
  67. {
  68. id: 2,
  69. key: NotificationMatrixRowKey.Update,
  70. name: __('Ticket update'),
  71. },
  72. {
  73. id: 3,
  74. key: NotificationMatrixRowKey.ReminderReached,
  75. name: __('Ticket reminder reached'),
  76. },
  77. {
  78. id: 4,
  79. key: NotificationMatrixRowKey.Escalation,
  80. name: __('Ticket escalation'),
  81. },
  82. ]
  83. const valueLookup = (
  84. rowKey: NotificationMatrixRowKey,
  85. pathKey: NotificationMatrixPathKey,
  86. columnKey: NotificationMatrixColumnKey,
  87. ) => {
  88. const row = localValue.value?.[rowKey]
  89. if (!row) return undefined
  90. return row[pathKey]?.[columnKey]
  91. }
  92. const updateValue = (
  93. rowKey: NotificationMatrixRowKey,
  94. pathKey: NotificationMatrixPathKey,
  95. columnKey: NotificationMatrixColumnKey,
  96. state: boolean | undefined,
  97. ) => {
  98. const values = cloneDeep(localValue.value) || {}
  99. values[rowKey] = values[rowKey] || {}
  100. values[rowKey][pathKey] = values[rowKey][pathKey] || {}
  101. values[rowKey][pathKey][columnKey] = Boolean(state)
  102. localValue.value = values
  103. }
  104. </script>
  105. <template>
  106. <output
  107. :id="context.id"
  108. :class="context.classes.input"
  109. :name="context.node.name"
  110. :aria-disabled="context.disabled"
  111. :aria-describedby="context.describedBy"
  112. v-bind="context.attrs"
  113. >
  114. <CommonSimpleTable
  115. :caption="__('Notifications matrix')"
  116. class="mb-4 w-full"
  117. :headers="tableHeaders"
  118. :items="tableItems"
  119. >
  120. <template
  121. v-for="key in NotificationMatrixColumnKey"
  122. :key="key"
  123. #[`column-cell-${key}`]="{ item, header }"
  124. >
  125. <FormKit
  126. :id="`notifications_${item.key}_${header.path}_${header.key}`"
  127. :model-value="
  128. valueLookup(
  129. item.key as NotificationMatrixRowKey,
  130. header.path as NotificationMatrixPathKey,
  131. header.key as NotificationMatrixColumnKey,
  132. )
  133. "
  134. type="checkbox"
  135. :name="`notifications_${item.key}_${header.path}_${header.key}`"
  136. :disabled="context.disabled"
  137. :ignore="true"
  138. :label-sr-only="true"
  139. :label="`${i18n.t(item.name as string)} - ${i18n.t(header.label)}`"
  140. @update:model-value="
  141. updateValue(
  142. item.key as NotificationMatrixRowKey,
  143. header.path as NotificationMatrixPathKey,
  144. header.key as NotificationMatrixColumnKey,
  145. $event,
  146. )
  147. "
  148. @blur="context.handlers.blur"
  149. />
  150. </template>
  151. </CommonSimpleTable>
  152. </output>
  153. </template>