useTicketSubscribe.ts 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. // Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
  2. import { keyBy } from 'lodash-es'
  3. import { computed } from 'vue'
  4. import { useTicketView } from '#shared/entities/ticket/composables/useTicketView.ts'
  5. import { useMentionSubscribeMutation } from '#shared/entities/ticket/graphql/mutations/subscribe.api.ts'
  6. import { useMentionUnsubscribeMutation } from '#shared/entities/ticket/graphql/mutations/unsubscribe.api.ts'
  7. import type { TicketById } from '#shared/entities/ticket/types.ts'
  8. import type { TicketQuery } from '#shared/graphql/types.ts'
  9. import { MutationHandler } from '#shared/server/apollo/handler/index.ts'
  10. import { useSessionStore } from '#shared/stores/session.ts'
  11. import type { Ref } from 'vue'
  12. export const useTicketSubscribe = (ticket: Ref<TicketById | undefined>) => {
  13. const { isTicketAgent } = useTicketView(ticket)
  14. const canManageSubscription = computed(() => isTicketAgent.value)
  15. const session = useSessionStore()
  16. const createTicketCacheUpdater = (subscribed: boolean) => {
  17. return (previousQuery: Record<string, unknown>) => {
  18. const prev = previousQuery as TicketQuery
  19. if (!ticket.value || !prev || prev.ticket?.id !== ticket.value.id) {
  20. return prev
  21. }
  22. return {
  23. ticket: {
  24. ...prev.ticket,
  25. subscribed,
  26. },
  27. }
  28. }
  29. }
  30. const subscribeHandler = new MutationHandler(
  31. useMentionSubscribeMutation({
  32. updateQueries: {
  33. ticket: createTicketCacheUpdater(true),
  34. },
  35. }),
  36. )
  37. const unsubscribeMutation = new MutationHandler(
  38. useMentionUnsubscribeMutation({
  39. updateQueries: {
  40. ticket: createTicketCacheUpdater(false),
  41. },
  42. }),
  43. )
  44. const isSubscriptionLoading = computed(() => {
  45. return (
  46. subscribeHandler.loading().value || unsubscribeMutation.loading().value
  47. )
  48. })
  49. const subscribe = async (ticketId: string) => {
  50. const result = await subscribeHandler.send({ ticketId })
  51. return !!result?.mentionSubscribe?.success
  52. }
  53. const unsubscribe = async (ticketId: string) => {
  54. const result = await unsubscribeMutation.send({ ticketId })
  55. return !!result?.mentionUnsubscribe?.success
  56. }
  57. const toggleSubscribe = async () => {
  58. if (!ticket.value || isSubscriptionLoading.value) return false
  59. const { id, subscribed } = ticket.value
  60. if (!subscribed) {
  61. return subscribe(id)
  62. }
  63. return unsubscribe(id)
  64. }
  65. const isSubscribed = computed(() => !!ticket.value?.subscribed)
  66. const subscribers = computed(
  67. () =>
  68. ticket.value?.mentions?.edges
  69. ?.filter(({ node }) => node.user.active)
  70. .map(({ node }) => ({
  71. user: node.user,
  72. access: node.userTicketAccess,
  73. })) || [],
  74. )
  75. const subscribersWithoutMe = computed(
  76. () =>
  77. ticket.value?.mentions?.edges
  78. ?.filter(({ node }) => node.user.id !== session.userId)
  79. .map(({ node }) => node.user) || [],
  80. )
  81. const subscribersAccessLookup = computed(() =>
  82. keyBy(
  83. ticket.value?.mentions?.edges
  84. ?.filter(({ node }) => node.user.id !== session.userId)
  85. .map(({ node }) => ({
  86. userId: node.user.id,
  87. access: node.userTicketAccess,
  88. })) || [],
  89. 'userId',
  90. ),
  91. )
  92. const hasMe = computed(() => {
  93. if (!ticket.value?.mentions) return false
  94. return ticket.value.mentions.edges.some(
  95. ({ node }) => node.user.id === session.userId,
  96. )
  97. })
  98. const totalSubscribers = computed(() => {
  99. if (!ticket.value?.mentions) return 0
  100. return ticket.value.mentions.totalCount
  101. })
  102. const totalSubscribersWithoutMe = computed(() => {
  103. if (!ticket.value?.mentions) return 0
  104. // -1 for current user, who is shown as toggler
  105. return ticket.value.mentions.totalCount - (hasMe.value ? 1 : 0)
  106. })
  107. return {
  108. isSubscriptionLoading,
  109. isSubscribed,
  110. toggleSubscribe,
  111. canManageSubscription,
  112. subscribers,
  113. totalSubscribers,
  114. subscribersWithoutMe,
  115. subscribersAccessLookup,
  116. totalSubscribersWithoutMe,
  117. hasMe,
  118. }
  119. }