AppDesktop.vue 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. <!-- Copyright (C) 2012-2023 Zammad Foundation, https://zammad-foundation.org/ -->
  2. <script setup lang="ts">
  3. import { useTicketOverviewsStore } from '#mobile/entities/ticket/stores/ticketOverviews.ts'
  4. import useFormKitConfig from '#shared/composables/form/useFormKitConfig.ts'
  5. import CommonNotifications from '#shared/components/CommonNotifications/CommonNotifications.vue'
  6. import useAppMaintenanceCheck from '#shared/composables/useAppMaintenanceCheck.ts'
  7. import { useAppTheme } from '#shared/stores/theme.ts'
  8. import useAuthenticationChanges from '#shared/composables/useAuthenticationUpdates.ts'
  9. import useMetaTitle from '#shared/composables/useMetaTitle.ts'
  10. import usePushMessages from '#shared/composables/usePushMessages.ts'
  11. import { useApplicationStore } from '#shared/stores/application.ts'
  12. import { useAuthenticationStore } from '#shared/stores/authentication.ts'
  13. import { useLocaleStore } from '#shared/stores/locale.ts'
  14. import { useSessionStore } from '#shared/stores/session.ts'
  15. import emitter from '#shared/utils/emitter.ts'
  16. import { onBeforeMount, watch, onBeforeUnmount } from 'vue'
  17. import { useRouter } from 'vue-router'
  18. import LayoutSidebar from './components/layout/LayoutSidebar.vue'
  19. const router = useRouter()
  20. const authentication = useAuthenticationStore()
  21. const session = useSessionStore()
  22. useMetaTitle().initializeMetaTitle()
  23. const application = useApplicationStore()
  24. onBeforeMount(() => {
  25. // If Zammad was not properly set up yet, redirect to desktop front end.
  26. if (!application.config.system_init_done) {
  27. window.location.pathname = '/'
  28. } else {
  29. application.setLoaded()
  30. }
  31. })
  32. useAppMaintenanceCheck()
  33. usePushMessages()
  34. // Add a check for authenticated changes (e.g. login/logout in a other
  35. // browser tab or maintenance mode switch).
  36. useAuthenticationChanges()
  37. // We need to trigger a manual translation update for the form related strings.
  38. const formConfig = useFormKitConfig()
  39. useLocaleStore().$subscribe(() => {
  40. formConfig.locale = 'staticLocale'
  41. })
  42. // The handling for invalid sessions. The event will be emitted, when from the server a "NotAuthorized"
  43. // response is received.
  44. emitter.on('sessionInvalid', async () => {
  45. if (authentication.authenticated) {
  46. await authentication.clearAuthentication()
  47. router.replace({
  48. name: 'Login',
  49. query: {
  50. invalidatedSession: '1',
  51. },
  52. })
  53. }
  54. })
  55. // Initialize the ticket overview store after a valid session is present on
  56. // the app level, so that the query keeps alive.
  57. watch(
  58. () => session.initialized,
  59. (newValue, oldValue) => {
  60. if (!oldValue && newValue) {
  61. useTicketOverviewsStore()
  62. }
  63. },
  64. { immediate: true },
  65. )
  66. onBeforeUnmount(() => {
  67. emitter.off('sessionInvalid')
  68. })
  69. const appTheme = useAppTheme()
  70. </script>
  71. <template>
  72. <template v-if="application.loaded">
  73. <CommonNotifications />
  74. </template>
  75. <!-- TODO: styles are placeholders -->
  76. <div v-if="application.loaded" class="flex h-full">
  77. <aside
  78. v-if="$route.meta.sidebar !== false"
  79. class="w-1/5"
  80. :aria-label="__('Sidebar')"
  81. >
  82. <LayoutSidebar />
  83. </aside>
  84. <article
  85. class="w-full h-full antialiased bg-white dark:bg-gray-500 text-gray-100 dark:text-neutral-400"
  86. >
  87. <RouterView />
  88. <div class="flex">
  89. Change Theme:
  90. <CommonIcon
  91. name="mobile-info"
  92. :class="appTheme.theme === 'dark' ? 'text-black' : 'text-yellow'"
  93. @click="appTheme.toggleTheme(false)"
  94. />
  95. </div>
  96. </article>
  97. </div>
  98. </template>