application.ts 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. // Copyright (C) 2012-2023 Zammad Foundation, https://zammad-foundation.org/
  2. import { computed, ref } from 'vue'
  3. import { defineStore } from 'pinia'
  4. import {
  5. useNotifications,
  6. NotificationTypes,
  7. } from '@shared/components/CommonNotifications'
  8. import type { ConfigList } from '@shared/types/store'
  9. import log from '@shared/utils/log'
  10. import type {
  11. ApplicationConfigQuery,
  12. ApplicationConfigQueryVariables,
  13. } from '@shared/graphql/types'
  14. import { useConfigUpdatesSubscription } from '@shared/graphql/subscriptions/configUpdates.api'
  15. import { useApplicationConfigQuery } from '@shared/graphql/queries/applicationConfig.api'
  16. import {
  17. QueryHandler,
  18. SubscriptionHandler,
  19. } from '@shared/server/apollo/handler'
  20. import testFlags from '@shared/utils/testFlags'
  21. let configUpdatesSubscriptionInitialized = false
  22. let applicationConfigQuery: QueryHandler<
  23. ApplicationConfigQuery,
  24. ApplicationConfigQueryVariables
  25. >
  26. const getApplicationConfigQuery = () => {
  27. if (applicationConfigQuery) return applicationConfigQuery
  28. applicationConfigQuery = new QueryHandler(
  29. useApplicationConfigQuery({ fetchPolicy: 'no-cache' }),
  30. )
  31. return applicationConfigQuery
  32. }
  33. let connectionNotificationId: string
  34. // TODO: consider switching from notification to a modal dialog, and improving the message
  35. const notifications = useNotifications()
  36. export const useApplicationStore = defineStore(
  37. 'application',
  38. () => {
  39. const loaded = ref(false)
  40. const loading = computed(() => !loaded.value)
  41. const setLoaded = (): void => {
  42. const loadingAppElement: Maybe<HTMLElement> =
  43. document.getElementById('loading-app')
  44. if (notifications.hasErrors()) {
  45. loadingAppElement
  46. ?.getElementsByClassName('loading-failed')
  47. .item(0)
  48. ?.classList.add('active')
  49. return
  50. }
  51. loaded.value = true
  52. if (loadingAppElement) {
  53. loadingAppElement.remove()
  54. }
  55. testFlags.set('applicationLoaded.loaded')
  56. }
  57. const connected = ref(false)
  58. const bringConnectionUp = (): void => {
  59. if (connected.value) return
  60. log.debug('Application connection just came up.')
  61. if (connectionNotificationId) {
  62. notifications.removeNotification(connectionNotificationId)
  63. }
  64. connected.value = true
  65. }
  66. const takeConnectionDown = (): void => {
  67. if (!connected.value) return
  68. log.debug('Application connection just went down.')
  69. connectionNotificationId = notifications.notify({
  70. message: __('The connection to the server was lost.'),
  71. type: NotificationTypes.Error,
  72. persistent: true,
  73. })
  74. connected.value = false
  75. }
  76. const config = ref<ConfigList>({})
  77. const initializeConfigUpdateSubscription = (): void => {
  78. const configUpdatesSubscription = new SubscriptionHandler(
  79. useConfigUpdatesSubscription(),
  80. )
  81. configUpdatesSubscription.onResult((result) => {
  82. const updatedSetting = result.data?.configUpdates.setting
  83. if (updatedSetting) {
  84. config.value[updatedSetting.key] = updatedSetting.value
  85. } else {
  86. testFlags.set('useConfigUpdatesSubscription.subscribed')
  87. }
  88. })
  89. configUpdatesSubscriptionInitialized = true
  90. }
  91. const getConfig = async (): Promise<void> => {
  92. const configQuery = getApplicationConfigQuery()
  93. const result = await configQuery.loadedResult(true)
  94. if (result?.applicationConfig) {
  95. result.applicationConfig.forEach((item) => {
  96. config.value[item.key] = item.value
  97. })
  98. // app/assets/javascripts/app/config.coffee
  99. config.value.api_path = '/api/v1'
  100. }
  101. if (!configUpdatesSubscriptionInitialized) {
  102. initializeConfigUpdateSubscription()
  103. }
  104. }
  105. const resetAndGetConfig = async (): Promise<void> => {
  106. config.value = {}
  107. await getConfig()
  108. }
  109. const hasCustomProductBranding = computed(() =>
  110. Boolean(
  111. config.value.product_logo && config.value.product_logo !== 'logo.svg',
  112. ),
  113. )
  114. return {
  115. loaded,
  116. loading,
  117. setLoaded,
  118. connected,
  119. bringConnectionUp,
  120. takeConnectionDown,
  121. config,
  122. initializeConfigUpdateSubscription,
  123. getConfig,
  124. resetAndGetConfig,
  125. hasCustomProductBranding,
  126. }
  127. },
  128. {
  129. requiresAuth: false,
  130. },
  131. )