FavoriteTicketOverviewsEdit.vue 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. <!-- Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/ -->
  2. <script setup lang="ts">
  3. import { animations } 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. dragHandle: '.handler',
  49. })
  50. const { notify } = useNotifications()
  51. const walker = useWalker()
  52. useHeader({
  53. title: __('Ticket Overview'),
  54. backUrl: '/',
  55. backAvoidHomeButton: true,
  56. actionTitle: __('Save'),
  57. onAction() {
  58. if (!includedOverviews.value.length) {
  59. notify({
  60. id: 'no-overview',
  61. message: __('Please select at least one ticket overview'),
  62. type: NotificationTypes.Error,
  63. })
  64. return
  65. }
  66. overviewStore.saveOverviews(includedOverviews.value)
  67. notify({
  68. id: 'overview-save',
  69. message: __('Ticket Overview settings are saved.'),
  70. type: NotificationTypes.Success,
  71. })
  72. walker.back('/')
  73. },
  74. })
  75. const excludedOverviews = computed(() => {
  76. return overviews.value.filter(
  77. (overview) => !includedIds.value.has(overview.id),
  78. )
  79. })
  80. const removeFromFavorites = (id: string) => {
  81. includedIds.value.delete(id)
  82. }
  83. const addToFavorites = (id: string) => {
  84. includedIds.value.add(id)
  85. }
  86. </script>
  87. <template>
  88. <div class="mx-4 mt-6">
  89. <div v-if="overviewsLoading" class="flex items-center justify-center">
  90. <CommonIcon name="loading" animation="spin" />
  91. </div>
  92. <CommonSectionMenu
  93. v-if="!overviewsLoading"
  94. :header-label="__('Included ticket overviews')"
  95. data-test-id="includedOverviews"
  96. >
  97. <div ref="dndParentRef">
  98. <TicketOverviewEditItem
  99. v-for="overview in includedOverviews"
  100. :key="overview.id"
  101. action="delete"
  102. :overview="overview"
  103. draggable
  104. @action="removeFromFavorites(overview.id)"
  105. />
  106. </div>
  107. <div
  108. v-if="!includedOverviews.length"
  109. class="ms-3 flex min-h-[54px] items-center"
  110. >
  111. <p>{{ $t('No entries') }}</p>
  112. </div>
  113. </CommonSectionMenu>
  114. <CommonSectionMenu
  115. v-if="!overviewsLoading"
  116. :header-label="__('More ticket overviews')"
  117. data-test-id="excludedOverviews"
  118. >
  119. <TicketOverviewEditItem
  120. v-for="overview of excludedOverviews"
  121. :key="overview.id"
  122. action="add"
  123. :overview="overview"
  124. @action="addToFavorites(overview.id)"
  125. />
  126. <div
  127. v-if="!excludedOverviews.length"
  128. class="ms-3 flex min-h-[54px] items-center"
  129. >
  130. <p>{{ $t('No entries') }}</p>
  131. </div>
  132. </CommonSectionMenu>
  133. </div>
  134. </template>