@fdm-monster/client-next 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (205) hide show
  1. package/.all-contributorsrc +57 -0
  2. package/.browserslistrc +4 -0
  3. package/.editorconfig +5 -0
  4. package/.env +1 -0
  5. package/.eslintrc-auto-import.json +73 -0
  6. package/.eslintrc.js +126 -0
  7. package/.github/FUNDING.yml +3 -0
  8. package/.github/workflows/release-client.yml +94 -0
  9. package/.github/workflows/vue-publish.yml +26 -0
  10. package/.prettierignore +15 -0
  11. package/.prettierrc.cjs +7 -0
  12. package/.whitesource +12 -0
  13. package/.yarn/releases/yarn-4.5.1.cjs +934 -0
  14. package/.yarnrc.yml +3 -0
  15. package/CODE_OF_CONDUCT.md +46 -0
  16. package/README.md +93 -0
  17. package/RELEASE_NOTES.MD +11 -0
  18. package/index.html +16 -0
  19. package/package.default.json +42 -0
  20. package/package.json +26 -0
  21. package/public/favicon.ico +0 -0
  22. package/public/img/DavidZwart.jpg +0 -0
  23. package/public/img/OIG.JYDC2RaWdz7g9.jpg +0 -0
  24. package/public/img/OIG.jpg +0 -0
  25. package/public/img/icons/android-chrome-192x192.png +0 -0
  26. package/public/img/icons/android-chrome-256x256.png +0 -0
  27. package/public/img/icons/android-chrome-384x384.png +0 -0
  28. package/public/img/icons/android-chrome-512x512.png +0 -0
  29. package/public/img/icons/favicon.svg +1 -0
  30. package/public/img/logo.png +0 -0
  31. package/public/img/logo.svg +1 -0
  32. package/public/img/manifest.webmanifest +33 -0
  33. package/public/img/octoprint-tentacle.svg +144 -0
  34. package/public/img/thumbail_unknown.jpg +0 -0
  35. package/public/img/vbanner.jpg +0 -0
  36. package/public/index.html +17 -0
  37. package/public/robots.txt +2 -0
  38. package/renovate.json +30 -0
  39. package/src/App.vue +60 -0
  40. package/src/AppLoader.vue +383 -0
  41. package/src/assets/adjectives.json +1468 -0
  42. package/src/assets/android-chrome-192x192.png +0 -0
  43. package/src/assets/logo.png +0 -0
  44. package/src/assets/logo.svg +6 -0
  45. package/src/assets/nouns.json +4309 -0
  46. package/src/auto-imports.d.ts +139 -0
  47. package/src/backend/app.service.ts +39 -0
  48. package/src/backend/auth.service.ts +56 -0
  49. package/src/backend/base.service.ts +57 -0
  50. package/src/backend/batch.service.ts +37 -0
  51. package/src/backend/camera-stream.service.ts +33 -0
  52. package/src/backend/custom-gcode.service.ts +11 -0
  53. package/src/backend/dto/octoprint-settings.dto.ts +168 -0
  54. package/src/backend/first-time-setup.service.ts +17 -0
  55. package/src/backend/floor.service.ts +84 -0
  56. package/src/backend/index.ts +4 -0
  57. package/src/backend/print-completions.service.ts +11 -0
  58. package/src/backend/printer-file.service.ts +91 -0
  59. package/src/backend/printer-group.service.ts +62 -0
  60. package/src/backend/printer-job.service.ts +20 -0
  61. package/src/backend/printer-settings.service.ts +28 -0
  62. package/src/backend/printers.service.ts +136 -0
  63. package/src/backend/server-private.service.ts +55 -0
  64. package/src/backend/server.api.ts +132 -0
  65. package/src/backend/settings.service.ts +85 -0
  66. package/src/backend/user.service.ts +51 -0
  67. package/src/components/AboutHelp/AboutView.vue +164 -0
  68. package/src/components/CameraGrid/CameraGridView.vue +111 -0
  69. package/src/components/FirstTimeSetup/FirstTimeSetupView.vue +354 -0
  70. package/src/components/Generic/Actions/PrinterConnectionAction.vue +56 -0
  71. package/src/components/Generic/Actions/PrinterCreateAction.vue +22 -0
  72. package/src/components/Generic/Actions/PrinterDeleteAction.vue +29 -0
  73. package/src/components/Generic/Actions/PrinterQuickStopAction.vue +35 -0
  74. package/src/components/Generic/Actions/PrinterSettingsAction.vue +35 -0
  75. package/src/components/Generic/Actions/PrinterUrlAction.vue +24 -0
  76. package/src/components/Generic/Actions/RefreshFilesAction.vue +50 -0
  77. package/src/components/Generic/Actions/SyncPrinterNameAction.vue +36 -0
  78. package/src/components/Generic/Dialogs/AddOrUpdateCameraStreamDialog.vue +131 -0
  79. package/src/components/Generic/Dialogs/AddOrUpdateFloorDialog.vue +141 -0
  80. package/src/components/Generic/Dialogs/AddOrUpdatePrinterDialog.vue +303 -0
  81. package/src/components/Generic/Dialogs/BaseDialog.vue +81 -0
  82. package/src/components/Generic/Dialogs/BatchJsonCreateDialog.vue +109 -0
  83. package/src/components/Generic/Dialogs/BatchReprintDialog.vue +190 -0
  84. package/src/components/Generic/Dialogs/PrinterChecksPanel.vue +37 -0
  85. package/src/components/Generic/Dialogs/PrinterControlDialog.vue +202 -0
  86. package/src/components/Generic/Dialogs/PrinterMaintenanceDialog.vue +130 -0
  87. package/src/components/Generic/Dialogs/YamlImportExportDialog.vue +186 -0
  88. package/src/components/Generic/Dialogs/dialog.constants.ts +19 -0
  89. package/src/components/Generic/FileExplorerSideNav.vue +734 -0
  90. package/src/components/Generic/Loaders/GridLoader.vue +68 -0
  91. package/src/components/Generic/NavigationDrawer.vue +69 -0
  92. package/src/components/Generic/PrintJobsMenu.vue +148 -0
  93. package/src/components/Generic/Snackbars/AppErrorSnackbar.vue +64 -0
  94. package/src/components/Generic/Snackbars/AppInfoSnackbar.vue +63 -0
  95. package/src/components/Generic/Snackbars/AppProgressSnackbar.vue +158 -0
  96. package/src/components/Generic/Vuetify/TooltipButton.vue +47 -0
  97. package/src/components/HelpOverlay/HelpOverlay.vue +57 -0
  98. package/src/components/Login/LoginForm.vue +206 -0
  99. package/src/components/Login/LoginView.spec.ts +64 -0
  100. package/src/components/Login/LoginView.vue +65 -0
  101. package/src/components/Login/Logo.vue +13 -0
  102. package/src/components/Login/PermissionDenied.vue +109 -0
  103. package/src/components/Login/RegistrationForm.vue +207 -0
  104. package/src/components/Login/RegistrationView.vue +17 -0
  105. package/src/components/Login/__snapshots__/LoginView.spec.ts.snap +1051 -0
  106. package/src/components/NotFound/NotFoundView.vue +39 -0
  107. package/src/components/PrintStatistics/PrintStatistics.vue +168 -0
  108. package/src/components/PrintStatistics/PrintStatisticsView.vue +15 -0
  109. package/src/components/PrinterGrid/HomeToolbar.vue +90 -0
  110. package/src/components/PrinterGrid/PrinterGrid.vue +164 -0
  111. package/src/components/PrinterGrid/PrinterGridTile.vue +438 -0
  112. package/src/components/PrinterGrid/PrinterGridView.vue +210 -0
  113. package/src/components/PrinterList/FileControlList.vue +40 -0
  114. package/src/components/PrinterList/PrinterDetails.vue +91 -0
  115. package/src/components/PrinterList/PrintersView.vue +492 -0
  116. package/src/components/Settings/AccountSettings.vue +163 -0
  117. package/src/components/Settings/DiagnosticsSettings.vue +137 -0
  118. package/src/components/Settings/EmergencyCommands.vue +265 -0
  119. package/src/components/Settings/FloorSettings.vue +276 -0
  120. package/src/components/Settings/GridSettings.vue +127 -0
  121. package/src/components/Settings/OctoPrintSettings.vue +188 -0
  122. package/src/components/Settings/ServerProtectionSettings.vue +370 -0
  123. package/src/components/Settings/SettingsView.vue +73 -0
  124. package/src/components/Settings/SoftwareUpgradeSettings.vue +297 -0
  125. package/src/components/Settings/UserManagementSettings.vue +257 -0
  126. package/src/components/TopBar.vue +147 -0
  127. package/src/components.d.ts +70 -0
  128. package/src/directives/file-upload.directive.ts +117 -0
  129. package/src/directives/printer-drop-position.directive.ts +92 -0
  130. package/src/env.d.ts +6 -0
  131. package/src/main.ts +76 -0
  132. package/src/models/batch/reprint.dto.ts +79 -0
  133. package/src/models/batch.model.ts +11 -0
  134. package/src/models/camera-streams/camera-stream.ts +19 -0
  135. package/src/models/floors/floor.model.ts +30 -0
  136. package/src/models/octoprint/connection-options.model.ts +8 -0
  137. package/src/models/plugins/firmware-updates/prusa-firmware-release.model.ts +57 -0
  138. package/src/models/print-completions/print-completions.model.ts +49 -0
  139. package/src/models/printers/crud/create-printer.model.ts +26 -0
  140. package/src/models/printers/file-upload-commands.model.ts +4 -0
  141. package/src/models/printers/gcode/gcode-analysis.model.ts +30 -0
  142. package/src/models/printers/printer-current-job.model.ts +90 -0
  143. package/src/models/printers/printer-file.model.ts +48 -0
  144. package/src/models/printers/printer.model.ts +18 -0
  145. package/src/models/server/client-releases.model.ts +27 -0
  146. package/src/models/server/export-yaml.model.ts +11 -0
  147. package/src/models/server/features.model.ts +37 -0
  148. package/src/models/server/github-rate-limit.model.ts +21 -0
  149. package/src/models/server/version.model.ts +14 -0
  150. package/src/models/settings/printer-file-clean-settings.model.ts +5 -0
  151. package/src/models/settings/server-settings.dto.ts +19 -0
  152. package/src/models/settings/settings.model.ts +57 -0
  153. package/src/models/socketio-messages/socketio-message.model.ts +53 -0
  154. package/src/models/uploads/queued-upload.model.ts +12 -0
  155. package/src/models/user.model.ts +15 -0
  156. package/src/plugins/README.md +3 -0
  157. package/src/plugins/index.ts +17 -0
  158. package/src/plugins/vuetify.ts +53 -0
  159. package/src/router/index.ts +192 -0
  160. package/src/router/route-names.ts +14 -0
  161. package/src/router/utils.ts +23 -0
  162. package/src/shared/alert.events.ts +14 -0
  163. package/src/shared/app.constants.ts +23 -0
  164. package/src/shared/auth.constants.ts +34 -0
  165. package/src/shared/dialog.composable.ts +41 -0
  166. package/src/shared/drag.constants.ts +19 -0
  167. package/src/shared/experimental.constants.ts +1 -0
  168. package/src/shared/http-client.ts +162 -0
  169. package/src/shared/noun-adjectives.data.ts +24 -0
  170. package/src/shared/printer-grid.constants.ts +5 -0
  171. package/src/shared/printer-state.constants.ts +194 -0
  172. package/src/shared/snackbar.composable.ts +66 -0
  173. package/src/shared/socketio.service.ts +104 -0
  174. package/src/store/auth.store.ts +255 -0
  175. package/src/store/connection.store.ts +66 -0
  176. package/src/store/dialog.store.ts +114 -0
  177. package/src/store/features.store.ts +57 -0
  178. package/src/store/floor.store.ts +173 -0
  179. package/src/store/grid.store.ts +10 -0
  180. package/src/store/index.ts +4 -0
  181. package/src/store/printer-state.store.ts +246 -0
  182. package/src/store/printer.store.ts +236 -0
  183. package/src/store/profile.store.ts +25 -0
  184. package/src/store/settings.store.ts +64 -0
  185. package/src/store/test-printer.store.ts +70 -0
  186. package/src/store/uploads.store.ts +75 -0
  187. package/src/styles/README.md +3 -0
  188. package/src/styles/settings.scss +10 -0
  189. package/src/types/global.d.ts +15 -0
  190. package/src/utils/array.utils.ts +15 -0
  191. package/src/utils/date.utils.ts +5 -0
  192. package/src/utils/download-file.util.ts +25 -0
  193. package/src/utils/error.utils.ts +3 -0
  194. package/src/utils/file-size.util.ts +11 -0
  195. package/src/utils/id.type.ts +1 -0
  196. package/src/utils/sentry.util.ts +8 -0
  197. package/src/utils/test.util.ts +30 -0
  198. package/src/utils/time.utils.ts +2 -0
  199. package/src/utils/uploads-state.utils.ts +58 -0
  200. package/src/utils/validation.utils.ts +14 -0
  201. package/src/vite-env.d.ts +7 -0
  202. package/test/setup-axios-mock.ts +15 -0
  203. package/tsconfig.json +47 -0
  204. package/tsconfig.node.json +9 -0
  205. package/vite.config.mts +106 -0
@@ -0,0 +1,383 @@
1
+ <template>
2
+ <v-overlay
3
+ v-model="overlay"
4
+ opacity="0.98"
5
+ style="z-index: 7"
6
+ >
7
+ <GridLoader
8
+ v-if="loading"
9
+ :size="20"
10
+ class="ma-auto"
11
+ color="#a70015"
12
+ />
13
+ <br />
14
+
15
+ <div
16
+ v-if="errorCaught"
17
+ style="margin: 50px"
18
+ >
19
+ <h1>FDM Monster Server Error</h1>
20
+ <p>
21
+ Did not expect this answer from the server. Please check your
22
+ configuration and logs.
23
+ </p>
24
+ <v-sheet
25
+ class="pa-4 rounded"
26
+ color="grey-darken-2"
27
+ width="80%"
28
+ >
29
+ Details:
30
+ <div class="mt-2 mb-2">
31
+ {{ JSON.stringify(errorCaught, null, 4) }}
32
+ </div>
33
+ <div
34
+ v-if="errorUrl"
35
+ class="mt-2 mb-2"
36
+ >
37
+ Original URL: {{ errorUrl }}
38
+ </div>
39
+ <div
40
+ v-if="errorResponse"
41
+ class="mt-2 mb-2"
42
+ >
43
+ Response body: {{ errorResponse }}
44
+ </div>
45
+ <br />
46
+ <v-btn
47
+ class="mb-2"
48
+ color="secondary"
49
+ @click="copyError()"
50
+ >
51
+ <v-icon class="mr-2">content_copy</v-icon>
52
+ Copy error details
53
+ </v-btn>
54
+ <br />
55
+ <v-btn
56
+ color="primary mb-2"
57
+ @click="reloadPage()"
58
+ >
59
+ <v-icon class="mr-2">refresh</v-icon>
60
+ reload the page
61
+ </v-btn>
62
+ <br />
63
+ <v-btn
64
+ color="darken-2 mb-2"
65
+ href="https://docs.fdm-monster.net"
66
+ style="color: white"
67
+ target="_blank"
68
+ >
69
+ <v-icon class="mr-2">menu_book</v-icon>
70
+ view documentation
71
+ </v-btn>
72
+ <br />
73
+ <v-btn
74
+ color="purple-darken-4"
75
+ href="https://discord.gg/mwA8uP8CMc"
76
+ style="color: white"
77
+ target="_blank"
78
+ >
79
+ <v-icon class="mr-2">chat</v-icon>
80
+ join our Discord
81
+ </v-btn>
82
+ </v-sheet>
83
+
84
+ <img
85
+ class="justify-center align-center align-content-center rounded-pill mt-8 ma-4"
86
+ src="/img/OIG.JYDC2RaWdz7g9.jpg"
87
+ style="opacity: 0.9"
88
+ width="400"
89
+ />
90
+ </div>
91
+
92
+ <!-- Fade-in -->
93
+ <!-- Slow scroll fade-out vtexts -->
94
+ <div
95
+ v-if="loading"
96
+ style="animation: fadeIn 0.75s"
97
+ >
98
+ {{ overlayMessage }}
99
+ </div>
100
+ </v-overlay>
101
+ <slot v-if="!overlay" />
102
+ </template>
103
+
104
+ <script lang="ts" setup>
105
+ import { onBeforeMount, onUnmounted, ref } from 'vue'
106
+ import { useEventBus } from '@vueuse/core'
107
+ import { useRouter } from 'vue-router'
108
+ import { AxiosError } from 'axios'
109
+ import { captureException } from '@sentry/vue'
110
+ import GridLoader from './components/Generic/Loaders/GridLoader.vue'
111
+ import { useAuthStore } from './store/auth.store'
112
+ import { useSnackbar } from '@/shared/snackbar.composable'
113
+ import { useSettingsStore } from '@/store/settings.store'
114
+ import { setSentryEnabled } from '@/utils/sentry.util'
115
+ import { useFeatureStore } from '@/store/features.store'
116
+ import { useProfileStore } from '@/store/profile.store'
117
+ import { sleep } from '@/utils/time.utils'
118
+ import { RouteNames } from '@/router/route-names'
119
+ import { AppService } from '@/backend/app.service'
120
+ import {
121
+ AUTH_ERROR_REASON,
122
+ PermissionDeniedEvent
123
+ } from '@/shared/auth.constants'
124
+ import { SocketIoService } from '@/shared/socketio.service'
125
+
126
+ const authStore = useAuthStore()
127
+ const settingsStore = useSettingsStore()
128
+ const featureStore = useFeatureStore()
129
+ const profileStore = useProfileStore()
130
+ const overlay = ref(false)
131
+ const router = useRouter()
132
+ const overlayMessage = ref('')
133
+ const loading = ref(true)
134
+ const errorCaught = ref()
135
+ const errorUrl = ref()
136
+ const errorResponse = ref()
137
+ const snackbar = useSnackbar()
138
+ const socketIoClient: SocketIoService = new SocketIoService()
139
+
140
+ function reloadPage() {
141
+ window.location.reload()
142
+ }
143
+
144
+ function copyError() {
145
+ navigator.clipboard.writeText(JSON.stringify(errorCaught.value))
146
+ snackbar.openInfoMessage({
147
+ title: 'Copied',
148
+ subtitle: 'Error copied to clipboard'
149
+ })
150
+ }
151
+
152
+ function setOverlay(overlayEnabled: boolean, message: string = '') {
153
+ if (!overlayEnabled) {
154
+ overlayMessage.value = ''
155
+ } else {
156
+ overlayMessage.value = message
157
+ errorCaught.value = null
158
+ errorUrl.value = null
159
+ errorResponse.value = null
160
+ }
161
+ overlay.value = overlayEnabled
162
+ }
163
+
164
+ async function loadAppWithAuthenticationReady() {
165
+ try {
166
+ await settingsStore.loadSettings()
167
+ await featureStore.loadFeatures()
168
+ await profileStore.getProfile()
169
+
170
+ const enabled = settingsStore.serverSettings?.sentryDiagnosticsEnabled
171
+ setSentryEnabled(!!enabled)
172
+ } catch (e) {
173
+ console.log('Error when loading settings.', e)
174
+ snackbar.openErrorMessage({
175
+ title: 'Error',
176
+ subtitle: 'Error when loading settings, features and/or profile.'
177
+ })
178
+ captureException(e)
179
+ }
180
+
181
+ if (!socketIoClient.socketState().setup) {
182
+ await socketIoClient.setupSocketConnection()
183
+ } else {
184
+ socketIoClient.reconnect()
185
+ }
186
+
187
+ setOverlay(false)
188
+ }
189
+
190
+ // In use (shared/http-client.ts)
191
+ const authPermissionDeniedKey = useEventBus<PermissionDeniedEvent>(
192
+ 'auth:permission-denied'
193
+ )
194
+ authPermissionDeniedKey.on(async (event) => {
195
+ console.log('[AppLoader] Permission denied, going to permission denied page')
196
+ setOverlay(true, 'Permission denied')
197
+ await router.push({
198
+ name: RouteNames.PermissionDenied,
199
+ query: {
200
+ roles: event?.roles,
201
+ page: String(router.currentRoute.value.name),
202
+ permissions: event?.permissions,
203
+ error: event?.error,
204
+ url: event?.url
205
+ }
206
+ })
207
+ setOverlay(false)
208
+ })
209
+
210
+ // In use (shared/http-client.ts)
211
+ const authFailKey = useEventBus('auth:failure')
212
+ authFailKey.on(async (event: any) => {
213
+ console.debug(
214
+ `[AppLoader] Event received: 'auth:failure', going back to login, context: ${event}`
215
+ )
216
+ setOverlay(true, 'Authentication failed, going back to login')
217
+
218
+ if (router.currentRoute.value.name !== RouteNames.Login) {
219
+ await router.push({ name: RouteNames.Login })
220
+ }
221
+ setOverlay(false)
222
+ })
223
+
224
+ // In use (components/Login/LoginForm.vue)
225
+ const loginEventKey = useEventBus('auth:login')
226
+ loginEventKey.on(async () => {
227
+ console.debug("[AppLoader] Event received: 'auth:login', loading app")
228
+ setOverlay(true, 'Loading app')
229
+ await loadAppWithAuthenticationReady()
230
+ })
231
+
232
+ // Emitted by auth.store.ts handleAndEmitAuthenticationError
233
+ const accountNotVerifiedEventKey = useEventBus(
234
+ `auth:${AUTH_ERROR_REASON.AccountNotVerified}`
235
+ )
236
+ accountNotVerifiedEventKey.on(async () => {
237
+ console.debug(
238
+ `[AppLoader] Event received: 'auth:${AUTH_ERROR_REASON.AccountNotVerified}', going to login`
239
+ )
240
+ snackbar.error(
241
+ 'Account not verified, please ask an administrator to verify your account.'
242
+ )
243
+ setOverlay(
244
+ true,
245
+ 'Account not verified, please ask an administrator to verify your account.'
246
+ )
247
+ if (router.currentRoute.value.name !== RouteNames.Login) {
248
+ await router.push({ name: RouteNames.Login })
249
+ }
250
+ setOverlay(false)
251
+ })
252
+
253
+ // Emitted by auth.store.ts handleAndEmitAuthenticationError
254
+ const passwordChangeRequiredEventKey = useEventBus(
255
+ `auth:${AUTH_ERROR_REASON.PasswordChangeRequired}`
256
+ )
257
+ passwordChangeRequiredEventKey.on(async () => {
258
+ console.debug(
259
+ `[AppLoader] Event received: 'auth:${AUTH_ERROR_REASON.PasswordChangeRequired}', going to login`
260
+ )
261
+ snackbar.error('Password change required, please change your password.')
262
+ setOverlay(true, 'Password change required, please change your password.')
263
+ if (router.currentRoute.value.name !== RouteNames.Login) {
264
+ await router.push({ name: RouteNames.Login })
265
+ }
266
+ setOverlay(false)
267
+ })
268
+
269
+ onUnmounted(() => {
270
+ if (socketIoClient) {
271
+ socketIoClient.disconnect()
272
+ }
273
+ })
274
+
275
+ onBeforeMount(async () => {
276
+ loading.value = true
277
+ // Pick random string out of array of strings
278
+ const loadingMessages = [
279
+ 'Loading FDM Monster',
280
+ 'Loading it all',
281
+ 'Loading features',
282
+ 'Loading what needs to be loaded',
283
+ 'Farming potatoes',
284
+ 'Wiping the floor',
285
+ 'Cleaning cobwebs',
286
+ 'Loading filament.dll',
287
+ 'Loading 3D_printer.exe',
288
+ 'Loading spools'
289
+ ]
290
+
291
+ const message =
292
+ loadingMessages[Math.floor(Math.random() * loadingMessages.length)]
293
+ setOverlay(true, message)
294
+
295
+ try {
296
+ await AppService.test()
297
+ // Nice test for error handling
298
+ // throw new Error("test");
299
+ } catch (e) {
300
+ loading.value = false
301
+ errorCaught.value = e
302
+ errorUrl.value = 'api/test'
303
+ // Disable capture to sentry when it overloads
304
+ captureException(e)
305
+ return
306
+ }
307
+
308
+ // If the route is wrong about login requirements, an error will be shown
309
+ const { loginRequired, wizardState } =
310
+ await authStore.checkAuthenticationRequirements()
311
+ if (!wizardState.wizardCompleted) {
312
+ console.debug('[AppLoader] Wizard not completed, going to wizard')
313
+ await authStore.logout(false)
314
+ if (router.currentRoute.value.name !== RouteNames.FirstTimeSetup) {
315
+ await router.replace({ name: RouteNames.FirstTimeSetup })
316
+ }
317
+ setOverlay(false)
318
+ return
319
+ }
320
+
321
+ // Login is not required, load app directly
322
+ if (!loginRequired) {
323
+ console.debug('[AppLoader] Login not required, loading app')
324
+ return await loadAppWithAuthenticationReady()
325
+ }
326
+
327
+ // Router will have tackled routing already
328
+ console.debug('[AppLoader] Checking if tokens are present')
329
+ if (!authStore.hasAuthToken && !authStore.hasRefreshToken) {
330
+ console.debug(
331
+ '[AppLoader] No tokens present, hiding overlay as router will have handled it'
332
+ )
333
+ return setOverlay(false)
334
+ }
335
+
336
+ // What if refreshToken is not present or not valid?
337
+ setOverlay(true, 'Refreshing login')
338
+ console.debug('[AppLoader] Verifying or refreshing login once')
339
+ try {
340
+ const { success, handled } =
341
+ await authStore.verifyOrRefreshLoginOnceOrLogout()
342
+ if (handled) {
343
+ console.debug('[AppLoader] received handled event, hiding overlay')
344
+ return
345
+ }
346
+
347
+ if (!success) {
348
+ console.debug('[AppLoader] No success refreshing')
349
+ setOverlay(true, 'Login expired, going back to login')
350
+
351
+ await sleep(500)
352
+ if (router.currentRoute.value.name !== RouteNames.Login) {
353
+ await router.push({ name: RouteNames.Login })
354
+ }
355
+ setOverlay(false)
356
+ // Dont load app as it will be redirected to login
357
+ return
358
+ }
359
+ } catch (e) {
360
+ console.log('[AppLoader] Error when refreshing login', e)
361
+ loading.value = false
362
+ errorCaught.value = (e as AxiosError).message
363
+ errorUrl.value = (e as AxiosError).config?.url
364
+ errorResponse.value = (e as AxiosError).response?.data
365
+ captureException(e)
366
+ return
367
+ }
368
+
369
+ console.debug('[AppLoader] Loading app')
370
+ await loadAppWithAuthenticationReady()
371
+ })
372
+ </script>
373
+
374
+ <style>
375
+ @keyframes fadeIn {
376
+ 0% {
377
+ opacity: 0;
378
+ }
379
+ 100% {
380
+ opacity: 1;
381
+ }
382
+ }
383
+ </style>