ticketOverviewOrder.ts 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  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 { useTicketOverviewOrderQuery } from '#shared/entities/ticket/graphql/queries/ticket/overviewOrder.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<Overview, 'name' | 'id'>
  17. export const useTicketOverviewOrderStore = defineStore(
  18. 'ticketOverviewOrder',
  19. () => {
  20. const ticketOverviewOrderHandler = new QueryHandler(
  21. useTicketOverviewOrderQuery(),
  22. )
  23. // Updates the overviews when overviews got added, updated and/or deleted.
  24. ticketOverviewOrderHandler.subscribeToMore<
  25. TicketOverviewUpdatesSubscriptionVariables,
  26. TicketOverviewUpdatesSubscription
  27. >({
  28. document: TicketOverviewUpdatesDocument,
  29. variables: {
  30. ignoreUserConditions: true,
  31. withTicketCount: false,
  32. },
  33. updateQuery(_, { subscriptionData }) {
  34. const ticketOverviews =
  35. subscriptionData.data.ticketOverviewUpdates?.ticketOverviews
  36. // if we return empty array here, the actual query will be aborted, because we have fetchPolicy "cache-and-network"
  37. // if we return existing value, it will throw an error, because "overviews" doesn't exist yet on the query result
  38. if (!ticketOverviews) {
  39. return null as unknown as TicketOverviewsQuery
  40. }
  41. return {
  42. ticketOverviews,
  43. }
  44. },
  45. })
  46. const overviewsRaw = ticketOverviewOrderHandler.result()
  47. const overviewsLoading = ticketOverviewOrderHandler.loading()
  48. const overviews = computed(() => {
  49. if (!overviewsRaw.value?.ticketOverviews) return []
  50. return overviewsRaw.value.ticketOverviews.filter(
  51. (overview) => overview?.id,
  52. )
  53. })
  54. const overviewsByKey = computed(() => keyBy(overviews.value, 'id'))
  55. const storage = getTicketOverviewStorage()
  56. const includedIds = ref(new Set<string>(storage.getOverviews()))
  57. const includedOverviews = computed(() => {
  58. return [...includedIds.value]
  59. .map((id) => overviewsByKey.value[id])
  60. .filter(Boolean)
  61. })
  62. const saveOverviews = (overviews: TicketOverview[]) => {
  63. const ids = overviews.map(({ id }) => id)
  64. storage.saveOverviews(ids)
  65. includedIds.value = new Set(ids)
  66. }
  67. const populateIncludeIds = (overviews: TicketOverview[]) => {
  68. overviews.forEach((overview) => {
  69. includedIds.value.add(overview.id)
  70. })
  71. saveOverviews(overviews)
  72. }
  73. // store overviews in local storage when loaded
  74. // force it to have something
  75. if (!includedIds.value.size) {
  76. if (!overviews.value.length) {
  77. watchOnce(overviews, populateIncludeIds)
  78. } else {
  79. populateIncludeIds(overviews.value)
  80. }
  81. }
  82. tryOnScopeDispose(() => {
  83. ticketOverviewOrderHandler.stop()
  84. })
  85. return {
  86. overviews,
  87. initializing:
  88. ticketOverviewOrderHandler.operationResult.forceDisabled.value,
  89. loading: overviewsLoading,
  90. includedOverviews,
  91. includedIds,
  92. overviewsByKey,
  93. saveOverviews,
  94. }
  95. },
  96. )