ticketOverviews.ts 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. // Copyright (C) 2012-2025 Zammad Foundation, https://zammad-foundation.org/
  2. import { tryOnScopeDispose, watchOnce } from '@vueuse/core'
  3. import { keyBy } from 'lodash-es'
  4. import { defineStore } from 'pinia'
  5. import { ref, computed } from 'vue'
  6. import { useTicketOverviewsQuery } from '#shared/entities/ticket/graphql/queries/ticket/overviews.api.ts'
  7. import { TicketOverviewUpdatesDocument } from '#shared/entities/ticket/graphql/subscriptions/ticketOverviewUpdates.api.ts'
  8. import type {
  9. Overview,
  10. TicketOverviewsQuery,
  11. TicketOverviewUpdatesSubscription,
  12. TicketOverviewUpdatesSubscriptionVariables,
  13. } from '#shared/graphql/types.ts'
  14. import { QueryHandler } from '#shared/server/apollo/handler/index.ts'
  15. import { getTicketOverviewStorage } from '../helpers/ticketOverviewStorage.ts'
  16. export type TicketOverview = Pick<
  17. Overview,
  18. 'id' | 'name' | 'organizationShared' | 'outOfOffice'
  19. >
  20. export const useTicketOverviewsStore = defineStore('ticketOverviews', () => {
  21. const ticketOverviewHandler = new QueryHandler(
  22. useTicketOverviewsQuery({
  23. withTicketCount: true,
  24. }),
  25. )
  26. // Updates the overviews when overviews got added, updated and/or deleted.
  27. ticketOverviewHandler.subscribeToMore<
  28. TicketOverviewUpdatesSubscriptionVariables,
  29. TicketOverviewUpdatesSubscription
  30. >({
  31. document: TicketOverviewUpdatesDocument,
  32. variables: {
  33. withTicketCount: true,
  34. ignoreUserConditions: false,
  35. },
  36. updateQuery(_, { subscriptionData }) {
  37. const ticketOverviews =
  38. subscriptionData.data.ticketOverviewUpdates?.ticketOverviews
  39. // if we return empty array here, the actual query will be aborted, because we have fetchPolicy "cache-and-network"
  40. // if we return existing value, it will throw an error, because "overviews" doesn't exist yet on the query result
  41. if (!ticketOverviews) {
  42. return null as unknown as TicketOverviewsQuery
  43. }
  44. return {
  45. ticketOverviews,
  46. }
  47. },
  48. })
  49. const overviewsRaw = ticketOverviewHandler.result()
  50. const overviewsLoading = ticketOverviewHandler.loading()
  51. const overviews = computed(() => {
  52. if (!overviewsRaw.value?.ticketOverviews) return []
  53. return overviewsRaw.value.ticketOverviews.filter((overview) => overview?.id)
  54. })
  55. const overviewsByKey = computed(() => keyBy(overviews.value, 'id'))
  56. const storage = getTicketOverviewStorage()
  57. const includedIds = ref(new Set<string>(storage.getOverviews()))
  58. const includedOverviews = computed(() => {
  59. return [...includedIds.value]
  60. .map((id) => overviewsByKey.value[id])
  61. .filter(Boolean)
  62. })
  63. const populateIncludeIds = (overviews: TicketOverview[]) => {
  64. overviews.forEach((overview) => {
  65. includedIds.value.add(overview.id)
  66. })
  67. }
  68. // Do not store overviews in local storage when loaded, fallback to query response.
  69. if (!includedIds.value.size) {
  70. if (!overviews.value.length) {
  71. watchOnce(overviews, populateIncludeIds)
  72. } else {
  73. populateIncludeIds(overviews.value)
  74. }
  75. }
  76. const updateOverviews = (overviews: TicketOverview[]) => {
  77. const ids = overviews.map(({ id }) => id)
  78. includedIds.value = new Set(ids)
  79. }
  80. tryOnScopeDispose(() => {
  81. ticketOverviewHandler.stop()
  82. })
  83. return {
  84. overviews,
  85. initializing: ticketOverviewHandler.operationResult.forceDisabled.value,
  86. loading: overviewsLoading,
  87. includedOverviews,
  88. includedIds,
  89. overviewsByKey,
  90. updateOverviews,
  91. }
  92. })