ticketOverviews.ts 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. // Copyright (C) 2012-2024 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 type {
  8. TicketOverviewsQuery,
  9. TicketOverviewUpdatesSubscription,
  10. TicketOverviewUpdatesSubscriptionVariables,
  11. } from '#shared/graphql/types.ts'
  12. import { QueryHandler } from '#shared/server/apollo/handler/index.ts'
  13. import type { ConfidentTake } from '#shared/types/utils.ts'
  14. import { TicketOverviewUpdatesDocument } from '../graphql/subscriptions/ticketOverviewUpdates.api.ts'
  15. import { getTicketOverviewStorage } from '../helpers/ticketOverviewStorage.ts'
  16. export type TicketOverview = ConfidentTake<
  17. TicketOverviewsQuery,
  18. 'ticketOverviews.edges.node'
  19. >
  20. export const useTicketOverviewsStore = defineStore('ticketOverviews', () => {
  21. const ticketOverviewHandler = new QueryHandler(
  22. useTicketOverviewsQuery({ withTicketCount: true }),
  23. )
  24. // Updates the overviews when overviews got added, updated and/or deleted.
  25. ticketOverviewHandler.subscribeToMore<
  26. TicketOverviewUpdatesSubscriptionVariables,
  27. TicketOverviewUpdatesSubscription
  28. >({
  29. document: TicketOverviewUpdatesDocument,
  30. variables: {
  31. withTicketCount: true,
  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 = ticketOverviewHandler.result()
  47. const overviewsLoading = ticketOverviewHandler.loading()
  48. const overviews = computed(() => {
  49. if (!overviewsRaw.value?.ticketOverviews.edges) return []
  50. return overviewsRaw.value.ticketOverviews.edges
  51. .filter((overview) => overview?.node?.id)
  52. .map((edge) => edge.node)
  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. ticketOverviewHandler.stop()
  84. })
  85. return {
  86. overviews,
  87. initializing: ticketOverviewHandler.operationResult.forceDisabled.value,
  88. loading: overviewsLoading,
  89. includedOverviews,
  90. includedIds,
  91. overviewsByKey,
  92. saveOverviews,
  93. }
  94. })