TicketOverviews.vue 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. <!-- Copyright (C) 2012-2025 Zammad Foundation, https://zammad-foundation.org/ -->
  2. <script setup lang="ts">
  3. import { until } from '@vueuse/core'
  4. import { computed } from 'vue'
  5. import LayoutContent from '#desktop/components/layout/LayoutContent.vue'
  6. import LayoutSidebar from '#desktop/components/layout/LayoutSidebar.vue'
  7. import TicketList from '#desktop/pages/ticket-overviews/components/TicketList.vue'
  8. import TicketOverviewsEmptyText from '#desktop/pages/ticket-overviews/components/TicketOverviewsEmptyText.vue'
  9. import TicketOverviewsSidebar from '#desktop/pages/ticket-overviews/components/TicketOverviewsSidebar.vue'
  10. import { useTicketOverviews } from '#desktop/pages/ticket-overviews/composables/useTicketOverviews.ts'
  11. interface Props {
  12. overviewLink: string
  13. }
  14. const props = defineProps<Props>()
  15. defineOptions({
  16. async beforeRouteEnter(to, _, next) {
  17. const {
  18. overviews,
  19. overviewsLoading,
  20. setPreviousTicketOverviewLink,
  21. previousTicketOverviewLink,
  22. overviewsByLink,
  23. } = useTicketOverviews()
  24. await until(() => overviewsLoading.value).toBe(false)
  25. const overviewLink = to.params.overviewLink as string
  26. if (overviewLink in overviewsByLink.value || overviews.value.length === 0) {
  27. setPreviousTicketOverviewLink(overviewLink || '')
  28. return next()
  29. }
  30. const nextOverviewLink =
  31. previousTicketOverviewLink.value || overviews.value[0].link
  32. setPreviousTicketOverviewLink(nextOverviewLink)
  33. next({
  34. name: 'TicketOverview',
  35. params: { overviewLink: nextOverviewLink },
  36. })
  37. },
  38. beforeRouteUpdate(to, _, next) {
  39. const {
  40. previousTicketOverviewLink,
  41. overviews,
  42. setPreviousTicketOverviewLink,
  43. } = useTicketOverviews()
  44. if (to.params.overviewLink) {
  45. setPreviousTicketOverviewLink(to.params.overviewLink as string)
  46. return next()
  47. }
  48. const nextOverviewLink =
  49. previousTicketOverviewLink.value || overviews.value[0].link
  50. setPreviousTicketOverviewLink(nextOverviewLink)
  51. next({
  52. name: 'TicketOverview',
  53. params: { overviewLink: nextOverviewLink },
  54. })
  55. },
  56. })
  57. const { overviewsByLink, hasOverviews, overviewsTicketCountById } =
  58. useTicketOverviews()
  59. const currentOverview = computed(
  60. () => overviewsByLink.value[props.overviewLink],
  61. )
  62. const breadcrumbItems = computed(() => [
  63. {
  64. label: __('Overviews'),
  65. route: '/tickets/view',
  66. },
  67. {
  68. label: currentOverview.value?.name,
  69. count: overviewsTicketCountById.value[currentOverview.value?.id],
  70. },
  71. ])
  72. </script>
  73. <template>
  74. <div class="h-full" :class="{ 'grid grid-cols-[260px_1fr]': hasOverviews }">
  75. <LayoutSidebar
  76. v-if="hasOverviews"
  77. id="ticket-overviews"
  78. :aria-label="$t('second level navigation sidebar')"
  79. background-variant="secondary"
  80. name="overviews"
  81. >
  82. <TicketOverviewsSidebar />
  83. </LayoutSidebar>
  84. <LayoutContent
  85. class="relative"
  86. :breadcrumb-items="currentOverview ? breadcrumbItems : undefined"
  87. no-scrollable
  88. content-padding
  89. >
  90. <!-- TODO: should we add a key to the TicketList, that we have it "fresh" for every overview => otherwise we need some watch/reset logic on switch -->
  91. <TicketList
  92. v-if="currentOverview"
  93. class="px-4 pb-4"
  94. :overview-id="currentOverview.id"
  95. :headers="currentOverview.viewColumnsRaw"
  96. :order-by="currentOverview.orderBy"
  97. :order-direction="currentOverview.orderDirection"
  98. :group-by="currentOverview.groupBy || undefined"
  99. />
  100. <TicketOverviewsEmptyText
  101. v-else
  102. :title="$t('No Overviews')"
  103. :text="
  104. $t(
  105. 'Currently, no overviews are assigned to your roles. Please contact your administrator.',
  106. )
  107. "
  108. icon="exclamation-triangle"
  109. />
  110. </LayoutContent>
  111. </div>
  112. </template>