FavoriteTicketOverviewsEdit.vue 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. <!-- Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/ -->
  2. <script setup lang="ts">
  3. import { animations, updateConfig } from '@formkit/drag-and-drop'
  4. import { dragAndDrop } from '@formkit/drag-and-drop/vue'
  5. import { storeToRefs } from 'pinia'
  6. import { computed, ref, watch } from 'vue'
  7. import {
  8. NotificationTypes,
  9. useNotifications,
  10. } from '#shared/components/CommonNotifications/index.ts'
  11. import { useWalker } from '#shared/router/walker.ts'
  12. import CommonSectionMenu from '#mobile/components/CommonSectionMenu/CommonSectionMenu.vue'
  13. import { useHeader } from '#mobile/composables/useHeader.ts'
  14. import { useTicketOverviewsStore } from '#mobile/entities/ticket/stores/ticketOverviews.ts'
  15. import TicketOverviewEditItem from '../components/TicketOverviewEditItem.vue'
  16. const overviewStore = useTicketOverviewsStore()
  17. const {
  18. overviews,
  19. loading: overviewsLoading,
  20. overviewsByKey,
  21. } = storeToRefs(overviewStore)
  22. // we store local included, so they won't affect home page
  23. const includedIds = ref(new Set(overviewStore.includedIds.values()))
  24. watch(
  25. // when overviews are loaded, updated local included
  26. () => overviewStore.includedIds,
  27. (ids) => {
  28. includedIds.value = ids
  29. },
  30. )
  31. const includedOverviews = computed({
  32. get: () => {
  33. return [...includedIds.value]
  34. .map((id) => overviewsByKey.value[id])
  35. .filter(Boolean)
  36. },
  37. set: (value) => {
  38. includedIds.value = new Set(value.map((overview) => overview.id))
  39. },
  40. })
  41. const dndParentRef = ref()
  42. dragAndDrop({
  43. parent: dndParentRef,
  44. values: includedOverviews,
  45. plugins: [animations()],
  46. dropZoneClass: 'opacity-0',
  47. touchDropZoneClass: 'opacity-0',
  48. })
  49. const { notify } = useNotifications()
  50. const walker = useWalker()
  51. useHeader({
  52. title: __('Ticket Overview'),
  53. backUrl: '/',
  54. backAvoidHomeButton: true,
  55. actionTitle: __('Save'),
  56. onAction() {
  57. if (!includedOverviews.value.length) {
  58. notify({
  59. id: 'no-overview',
  60. message: __('Please select at least one ticket overview'),
  61. type: NotificationTypes.Error,
  62. })
  63. return
  64. }
  65. overviewStore.saveOverviews(includedOverviews.value)
  66. notify({
  67. id: 'overview-save',
  68. message: __('Ticket Overview settings are saved.'),
  69. type: NotificationTypes.Success,
  70. })
  71. walker.back('/')
  72. },
  73. })
  74. const excludedOverviews = computed(() => {
  75. return overviews.value.filter(
  76. (overview) => !includedIds.value.has(overview.id),
  77. )
  78. })
  79. const removeFromFavorites = (id: string) => {
  80. includedIds.value.delete(id)
  81. }
  82. const addToFavorites = (id: string) => {
  83. includedIds.value.add(id)
  84. }
  85. const updateDndDisabledConfig = (disabled: boolean) => {
  86. updateConfig(dndParentRef.value, { disabled })
  87. }
  88. </script>
  89. <template>
  90. <div class="mx-4 mt-6">
  91. <div v-if="overviewsLoading" class="flex items-center justify-center">
  92. <CommonIcon name="loading" animation="spin" />
  93. </div>
  94. <CommonSectionMenu
  95. v-if="!overviewsLoading"
  96. :header-label="__('Included ticket overviews')"
  97. data-test-id="includedOverviews"
  98. >
  99. <div ref="dndParentRef">
  100. <TicketOverviewEditItem
  101. v-for="overview in includedOverviews"
  102. :key="overview.id"
  103. action="delete"
  104. :overview="overview"
  105. draggable
  106. @action="removeFromFavorites(overview.id)"
  107. @action-active="updateDndDisabledConfig"
  108. />
  109. </div>
  110. <div
  111. v-if="!includedOverviews.length"
  112. class="ms-3 flex min-h-[54px] items-center"
  113. >
  114. <p>{{ $t('No entries') }}</p>
  115. </div>
  116. </CommonSectionMenu>
  117. <CommonSectionMenu
  118. v-if="!overviewsLoading"
  119. :header-label="__('More ticket overviews')"
  120. data-test-id="excludedOverviews"
  121. >
  122. <TicketOverviewEditItem
  123. v-for="overview of excludedOverviews"
  124. :key="overview.id"
  125. action="add"
  126. :overview="overview"
  127. @action="addToFavorites(overview.id)"
  128. />
  129. <div
  130. v-if="!excludedOverviews.length"
  131. class="ms-3 flex min-h-[54px] items-center"
  132. >
  133. <p>{{ $t('No entries') }}</p>
  134. </div>
  135. </CommonSectionMenu>
  136. </div>
  137. </template>