PersonalSettingOverviews.vue 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. <!-- Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/ -->
  2. <script setup lang="ts">
  3. import { storeToRefs } from 'pinia'
  4. import { ref, watch, onActivated } from 'vue'
  5. import { NotificationTypes } from '#shared/components/CommonNotifications/types.ts'
  6. import { useNotifications } from '#shared/components/CommonNotifications/useNotifications.ts'
  7. import { useConfirmation } from '#shared/composables/useConfirmation.ts'
  8. import type {
  9. UserCurrentOverviewListQuery,
  10. UserCurrentOverviewOrderingUpdatesSubscription,
  11. UserCurrentOverviewOrderingUpdatesSubscriptionVariables,
  12. } from '#shared/graphql/types.ts'
  13. import MutationHandler from '#shared/server/apollo/handler/MutationHandler.ts'
  14. import QueryHandler from '#shared/server/apollo/handler/QueryHandler.ts'
  15. import { useSessionStore } from '#shared/stores/session.ts'
  16. import CommonButton from '#desktop/components/CommonButton/CommonButton.vue'
  17. import CommonLoader from '#desktop/components/CommonLoader/CommonLoader.vue'
  18. import LayoutContent from '#desktop/components/layout/LayoutContent.vue'
  19. import PersonalSettingOverviewOrder, {
  20. type OverviewItem,
  21. } from '../components/PersonalSettingOverviewOrder.vue'
  22. import { useBreadcrumb } from '../composables/useBreadcrumb.ts'
  23. import { useUserCurrentOverviewResetOrderMutation } from '../graphql/mutations/userCurrentOverviewResetOrder.api.ts'
  24. import { useUserCurrentOverviewUpdateOrderMutation } from '../graphql/mutations/userCurrentOverviewUpdateOrder.api.ts'
  25. import { useUserCurrentOverviewListQuery } from '../graphql/queries/userCurrentOverviewList.api.ts'
  26. import { UserCurrentOverviewOrderingUpdatesDocument } from '../graphql/subscriptions/userCurrentOverviewOrderingUpdates.api.ts'
  27. const { user } = storeToRefs(useSessionStore())
  28. const { breadcrumbItems } = useBreadcrumb(__('Overviews'))
  29. const overviewList = ref<OverviewItem[]>()
  30. const overviewListQuery = new QueryHandler(useUserCurrentOverviewListQuery())
  31. const overviewListQueryLoading = overviewListQuery.loading()
  32. onActivated(() => overviewListQuery.refetch())
  33. overviewListQuery.subscribeToMore<
  34. UserCurrentOverviewOrderingUpdatesSubscriptionVariables,
  35. UserCurrentOverviewOrderingUpdatesSubscription
  36. >({
  37. document: UserCurrentOverviewOrderingUpdatesDocument,
  38. variables: {
  39. userId: user.value?.id || '',
  40. },
  41. updateQuery: (prev, { subscriptionData }) => {
  42. if (!subscriptionData.data?.userCurrentOverviewOrderingUpdates.overviews) {
  43. return null as unknown as UserCurrentOverviewListQuery
  44. }
  45. return {
  46. userCurrentOverviewList:
  47. subscriptionData.data.userCurrentOverviewOrderingUpdates.overviews,
  48. }
  49. },
  50. })
  51. watch(overviewListQuery.result(), (newValue) => {
  52. overviewList.value = newValue?.userCurrentOverviewList
  53. })
  54. const { notify } = useNotifications()
  55. const updateOverviewList = (newValue: OverviewItem[]) => {
  56. // Update the local order immediately, in order to avoid laggy UX.
  57. overviewList.value = newValue
  58. const overviewUpdateOrderMutation = new MutationHandler(
  59. useUserCurrentOverviewUpdateOrderMutation(),
  60. {
  61. errorNotificationMessage: __(
  62. 'Updating the order of your ticket overviews failed.',
  63. ),
  64. },
  65. )
  66. overviewUpdateOrderMutation
  67. .send({
  68. overviewIds: newValue.map((overview) => overview.id),
  69. })
  70. .then(() => {
  71. notify({
  72. id: 'overview-ordering-success',
  73. type: NotificationTypes.Success,
  74. message: __('The order of your ticket overviews was updated.'),
  75. })
  76. })
  77. }
  78. const { waitForVariantConfirmation } = useConfirmation()
  79. const resetOverviewOrder = () => {
  80. const userCurrentOverviewResetOrderMutation = new MutationHandler(
  81. useUserCurrentOverviewResetOrderMutation(),
  82. {
  83. errorNotificationMessage: __(
  84. 'Resetting the order of your ticket overviews failed.',
  85. ),
  86. },
  87. )
  88. userCurrentOverviewResetOrderMutation.send().then((data) => {
  89. if (data?.userCurrentOverviewResetOrder?.success) {
  90. notify({
  91. id: 'overview-ordering-delete-success',
  92. type: NotificationTypes.Success,
  93. message: __('The order of your ticket overviews was reset.'),
  94. })
  95. if (data.userCurrentOverviewResetOrder.overviews) {
  96. overviewList.value = data.userCurrentOverviewResetOrder.overviews
  97. }
  98. }
  99. })
  100. }
  101. const confirmResetOverviewOrder = async () => {
  102. const confirmed = await waitForVariantConfirmation('confirm')
  103. if (confirmed) resetOverviewOrder()
  104. }
  105. </script>
  106. <template>
  107. <LayoutContent :breadcrumb-items="breadcrumbItems" width="narrow">
  108. <CommonLoader class="mb-3 mt-5" :loading="overviewListQueryLoading">
  109. <div class="mb-4">
  110. <CommonLabel
  111. id="label-ticket-overview-order"
  112. class="!mt-0.5 mb-1 !block"
  113. >{{ $t('Order of ticket overviews') }}
  114. </CommonLabel>
  115. <PersonalSettingOverviewOrder
  116. :model-value="overviewList"
  117. aria-labelledby="label-ticket-overview-order"
  118. @update:model-value="updateOverviewList"
  119. />
  120. <div class="flex flex-col items-end">
  121. <CommonButton
  122. :aria-label="$t('Reset Overview Order')"
  123. class="mt-4"
  124. variant="danger"
  125. size="medium"
  126. @click.stop="confirmResetOverviewOrder"
  127. >
  128. {{ $t('Reset Overview Order') }}
  129. </CommonButton>
  130. </div>
  131. </div>
  132. </CommonLoader>
  133. </LayoutContent>
  134. </template>