@raclettejs/core 0.1.17 → 0.1.18

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 (44) hide show
  1. package/CHANGELOG.md +24 -1
  2. package/package.json +2 -2
  3. package/services/backend/package.json +2 -2
  4. package/services/backend/src/core/config/configService.ts +4 -0
  5. package/services/backend/src/corePlugins/raclette__core/backend/datatypes/composition/composition.service.ts +2 -0
  6. package/services/backend/src/corePlugins/raclette__core/backend/datatypes/composition/routes/index.ts +2 -0
  7. package/services/backend/src/corePlugins/raclette__core/backend/datatypes/composition/routes/route.composition.restore.ts +55 -0
  8. package/services/backend/src/corePlugins/raclette__core/backend/datatypes/interactionLink/interactionLink.service.ts +2 -0
  9. package/services/backend/src/corePlugins/raclette__core/backend/datatypes/interactionLink/routes/index.ts +2 -0
  10. package/services/backend/src/corePlugins/raclette__core/backend/datatypes/interactionLink/routes/route.interactionLink.restore.ts +55 -0
  11. package/services/backend/src/corePlugins/raclette__core/backend/datatypes/project/project.model.ts +17 -0
  12. package/services/backend/src/corePlugins/raclette__core/backend/datatypes/project/project.schema.ts +18 -6
  13. package/services/backend/src/corePlugins/raclette__core/backend/datatypes/project/routes/index.ts +5 -5
  14. package/services/backend/src/corePlugins/raclette__core/backend/datatypes/tag/routes/index.ts +2 -0
  15. package/services/backend/src/corePlugins/raclette__core/backend/datatypes/tag/routes/route.tag.restore.ts +55 -0
  16. package/services/backend/src/corePlugins/raclette__core/backend/datatypes/tag/tag.service.ts +2 -0
  17. package/services/backend/src/corePlugins/raclette__core/backend/datatypes/user/routes/index.ts +2 -0
  18. package/services/backend/src/corePlugins/raclette__core/backend/datatypes/user/routes/route.user.restore.ts +55 -0
  19. package/services/backend/src/corePlugins/raclette__core/backend/datatypes/user/user.service.ts +1 -0
  20. package/services/backend/src/domains/system/routes/route.user.login.ts +4 -2
  21. package/services/backend/src/shared/types/core/ProjectUpdate.types.ts +1 -0
  22. package/services/backend/src/shared/types/dataTypes/tags.ts +1 -0
  23. package/services/frontend/package.json +8 -8
  24. package/services/frontend/src/core/lib/configService.ts +1 -1
  25. package/services/frontend/src/core/lib/data/fetchDataHandler.ts +3 -23
  26. package/services/frontend/src/core/lib/data/writeDataHandler.ts +8 -13
  27. package/services/frontend/src/core/lib/dataHelper.ts +15 -0
  28. package/services/frontend/src/core/lib/eventWhitelist.ts +4 -13
  29. package/services/frontend/src/core/main.ts +7 -1
  30. package/services/frontend/src/orchestrator/LoginApp.vue +0 -1
  31. package/services/frontend/src/orchestrator/ProductOrchestrator.vue +40 -5
  32. package/services/frontend/src/orchestrator/components/composition/CompositionOverlay.vue +7 -3
  33. package/services/frontend/src/orchestrator/components/composition/WidgetsLayoutLoader.vue +12 -24
  34. package/services/frontend/src/orchestrator/components/input/SimpleSearchInput.vue +16 -4
  35. package/services/frontend/src/orchestrator/components/menu/AppBarMenu.vue +184 -0
  36. package/services/frontend/src/orchestrator/components/menu/UserMenu.vue +62 -46
  37. package/services/frontend/src/orchestrator/components/navigation/PageNavigationSidebar.vue +11 -1
  38. package/services/frontend/src/orchestrator/composables/usePageNavigation.ts +10 -1
  39. package/services/frontend/src/orchestrator/i18n/de-DE.json +1 -0
  40. package/services/frontend/src/orchestrator/i18n/en-EU.json +1 -0
  41. package/services/frontend/src/orchestrator/i18n/sk.json +1 -0
  42. package/services/frontend/src/orchestrator/router/index.ts +16 -0
  43. package/yarn.lock +4 -4
  44. package/services/frontend/src/orchestrator/setup/loginApp.ts +0 -27
@@ -31,6 +31,7 @@
31
31
  >
32
32
  </v-list-item>
33
33
  <v-divider />
34
+
34
35
  <v-list-item @click="toggleTheme">
35
36
  <template #prepend>
36
37
  <v-icon>mdi-theme-light-dark</v-icon>
@@ -43,42 +44,59 @@
43
44
  </template>
44
45
  <v-list-item-title>{{ $t("core.toggle_snow") }}</v-list-item-title>
45
46
  </v-list-item>
46
- <template v-for="item in pageNavigation.userMenuItems" :key="item.route">
47
- <v-list-item
48
- :key="locale"
49
- v-if="item.slotType !== 'inline'"
50
- :disabled="activeRouteName === item.route || !item.route"
51
- :active="activeRouteName === item.route"
52
- :value="item.route || ''"
53
- color="primary"
54
- class="nav-link"
55
- link
56
- @click="navigate(item)"
47
+ <div id="appUserMenu" ref="appUserMenu">
48
+ <template
49
+ v-for="item in pageNavigation.userMenuItems"
50
+ :key="item.route"
57
51
  >
58
- <!-- item prepend icon -->
59
- <template v-if="item.icon" #prepend>
60
- <v-icon :icon="item.icon" />
61
- </template>
62
- <v-list-item-title v-if="item.title">{{
63
- item.title
64
- }}</v-list-item-title>
65
- </v-list-item>
66
- <v-list-group v-else>
67
- <template v-slot:activator="{ props }">
68
- <v-list-item
69
- v-bind="props"
70
- :prepend-icon="item.icon"
71
- :title="item.title"
72
- ></v-list-item>
52
+ <v-list-item
53
+ :key="locale"
54
+ v-if="item.slotType !== 'inline'"
55
+ :disabled="activeRouteName === item.route || !item.route"
56
+ :active="activeRouteName === item.route"
57
+ :value="item.route || ''"
58
+ color="primary"
59
+ class="nav-link"
60
+ link
61
+ @click="navigate(item)"
62
+ >
63
+ <!-- item prepend icon -->
64
+ <template v-if="item.icon" #prepend>
65
+ <v-icon :icon="item.icon" />
66
+ </template>
67
+ <v-list-item-title v-if="item.title">{{
68
+ item.title
69
+ }}</v-list-item-title>
70
+ </v-list-item>
71
+ <template v-else>
72
+ <v-list-group v-if="item.icon || item.title">
73
+ <template v-slot:activator="{ props }">
74
+ <v-list-item
75
+ v-bind="props"
76
+ :prepend-icon="item.icon"
77
+ :title="item.title"
78
+ ></v-list-item>
79
+ </template>
80
+ <WidgetsLayoutLoader
81
+ v-if="compositions[item.compositionId]"
82
+ :widgets-layout="compositions[item.compositionId].widgetsLayout"
83
+ slot-type="inline"
84
+ :slot-layout="compositions[item.compositionId].slotLayout"
85
+ :max-height="availableComponentHeight"
86
+ />
87
+ </v-list-group>
88
+ <template v-else>
89
+ <WidgetsLayoutLoader
90
+ v-if="compositions[item.compositionId]"
91
+ :widgets-layout="compositions[item.compositionId].widgetsLayout"
92
+ slot-type="inline"
93
+ :max-height="availableComponentHeight"
94
+ :slot-layout="compositions[item.compositionId].slotLayout"
95
+ />
96
+ </template>
73
97
  </template>
74
- <WidgetsLayoutLoader
75
- v-if="compositions[item.compositionId]"
76
- :widgets-layout="compositions[item.compositionId].widgetsLayout"
77
- slot-type="inline"
78
- :slot-layout="compositions[item.compositionId].slotLayout"
79
- />
80
- </v-list-group>
81
- </template>
98
+ </template>
99
+ </div>
82
100
 
83
101
  <v-divider />
84
102
 
@@ -94,7 +112,7 @@
94
112
  </template>
95
113
  <script setup lang="ts">
96
114
  import localeFlags from "@racletteOrchestrator/assets/iconMappings/flags.json"
97
- import { computed, onMounted, ref } from "vue"
115
+ import { computed, useTemplateRef, onMounted, ref } from "vue"
98
116
  import { useRouter } from "vue-router"
99
117
  import useStateSubscriber from "@racletteOrchestrator/composables/useStateSubscriber"
100
118
  import useUiState from "@racletteOrchestrator/composables/useUiState"
@@ -112,7 +130,10 @@ import {
112
130
  import usePageNavigation, {
113
131
  type NavigationItem,
114
132
  } from "@racletteOrchestrator/composables/usePageNavigation"
115
-
133
+ const appUserMenuRef = useTemplateRef("appUserMenu")
134
+ const availableComponentHeight = computed(
135
+ () => appUserMenuRef?.value?.offsetHeight || 150,
136
+ )
116
137
  const { locales } = configService.getI18nConfig()
117
138
  const router = useRouter()
118
139
  const asteroidsDebounce = asteroidsDebounceHelper(3)
@@ -125,10 +146,6 @@ const { getCompositionLinkForSlotName } = useRouteState()
125
146
  const userLanguage = useLocalStorage<string>("user-language", null)
126
147
  const userTheme = useLocalStorage<string>("user-theme", null)
127
148
  const { state: pageNavigation } = usePageNavigation()
128
- const showDevIndicator = useLocalStorage<boolean | ("true" | "false")>(
129
- "show-dev-indicator",
130
- null,
131
- )
132
149
 
133
150
  const isOpen = ref(false)
134
151
  const canRefresh = ref(true)
@@ -164,11 +181,6 @@ const avatar = computed(() => {
164
181
 
165
182
  return nameString
166
183
  })
167
-
168
- const isInDev = computed(
169
- () => showDevIndicator.value === true || showDevIndicator.value === "true",
170
- )
171
-
172
184
  const toggleTheme = () => {
173
185
  theme.value = theme.value === "light" ? "dark" : "light"
174
186
  userTheme.value = theme.value
@@ -197,7 +209,11 @@ const navigate = (item: NavigationItem) => {
197
209
  item.navigateTo()
198
210
  }
199
211
 
200
- const openEgg = () => asteroidsDebounce(() => eggMe("asteroids"))
212
+ const openEgg = () =>
213
+ asteroidsDebounce(() => {
214
+ isOpen.value = false
215
+ eggMe("asteroids")
216
+ })
201
217
 
202
218
  onMounted(async () => {
203
219
  if (isDecember()) {
@@ -5,9 +5,10 @@
5
5
  pageNavigation?.navigationItems?.length ||
6
6
  pageNavigation?.footerItems?.length
7
7
  "
8
- id="navSideBar"
8
+ id="appPageNavSidebar"
9
9
  v-model="navigationDrawer"
10
10
  :rail="navigationRail"
11
+ :expand-on-hover="pageNavigationRail"
11
12
  permanent
12
13
  :order="-2"
13
14
  color="page-nav-bg"
@@ -33,6 +34,9 @@
33
34
  <template v-if="item.icon" #prepend>
34
35
  <v-icon :icon="item.icon" />
35
36
  </template>
37
+ <template v-if="item.title" #title>
38
+ {{ item.title }}
39
+ </template>
36
40
  </v-list-item>
37
41
  </div>
38
42
  </div>
@@ -58,6 +62,9 @@
58
62
  <template v-if="item.icon" #prepend>
59
63
  <v-icon :icon="item.icon" />
60
64
  </template>
65
+ <template v-if="item.title" #title>
66
+ {{ item.title }}
67
+ </template>
61
68
  </v-list-item>
62
69
  </div>
63
70
  </div>
@@ -73,7 +80,9 @@ import usePageNavigation, {
73
80
  } from "@racletteOrchestrator/composables/usePageNavigation"
74
81
  import useRouteState from "@racletteOrchestrator/composables/useRouteState"
75
82
  import { DEFAULT_SLOT_NAME } from "@racletteOrchestrator/router/routeParserHelper"
83
+ import useStateSubscriber from "@racletteOrchestrator/composables/useStateSubscriber"
76
84
 
85
+ const { state: projectConfig } = useStateSubscriber(["project", "config"])
77
86
  const { state: pageNavigation } = usePageNavigation()
78
87
  const { getCompositionLinkForSlotName } = useRouteState()
79
88
  const currentPageRoute = getCompositionLinkForSlotName(DEFAULT_SLOT_NAME)
@@ -81,6 +90,7 @@ const currentPageRoute = getCompositionLinkForSlotName(DEFAULT_SLOT_NAME)
81
90
  const navigationDrawer = ref(true)
82
91
  const navigationRail = ref(true)
83
92
 
93
+ const pageNavigationRail = projectConfig.value?.railPageNavigation || false
84
94
  const activeRouteName = computed(() => currentPageRoute?.value?.slotValue)
85
95
 
86
96
  const navigate = (item: NavigationItem) => item.navigateTo()
@@ -19,17 +19,23 @@ export type NavigationItem = {
19
19
 
20
20
  export default () => {
21
21
  const { locale } = useUiState()
22
- const { state } = useInteractionLinks(["page-navigation", "user-menu"])
22
+ const { state } = useInteractionLinks([
23
+ "page-navigation",
24
+ "user-menu",
25
+ "app-bar",
26
+ ])
23
27
  const { triggerInteractionLink } = useRouteState()
24
28
 
25
29
  const navigationItems = computed<{
26
30
  navigationItems: NavigationItem[]
27
31
  footerItems: NavigationItem[]
28
32
  userMenuItems: NavigationItem[]
33
+ appBarItems: NavigationItem[]
29
34
  }>(() => {
30
35
  const navigationItems: NavigationItem[] = []
31
36
  const footerItems: NavigationItem[] = []
32
37
  const userMenuItems: NavigationItem[] = []
38
+ const appBarItems: NavigationItem[] = []
33
39
  locale.value
34
40
  state.value.forEach((interactionLink) =>
35
41
  interactionLink.triggers
@@ -60,6 +66,8 @@ export default () => {
60
66
  }
61
67
  } else if (type === "user-menu") {
62
68
  userMenuItems.push(item)
69
+ } else if (type === "app-bar") {
70
+ appBarItems.push(item)
63
71
  }
64
72
  }
65
73
  }),
@@ -69,6 +77,7 @@ export default () => {
69
77
  navigationItems,
70
78
  footerItems,
71
79
  userMenuItems,
80
+ appBarItems,
72
81
  }
73
82
  })
74
83
  return {
@@ -72,6 +72,7 @@
72
72
  "noAccountYet": "Noch kein Konto?",
73
73
  "moreInformation": "Weitere Informationen"
74
74
  },
75
+ "openInFloatingWindow": "In extrafenster öffnen",
75
76
  "showDeleted": "Zeige gelöschte",
76
77
  "hideDeleted": "Verstecke gelöschte",
77
78
  "cancel": "Abbrechen",
@@ -72,6 +72,7 @@
72
72
  "noAccountYet": "Don't have an account yet?",
73
73
  "moreInformation": "More information"
74
74
  },
75
+ "openInFloatingWindow": "Open in floating window",
75
76
  "showDeleted": "Show deleted",
76
77
  "hideDeleted": "Hide deleted",
77
78
  "cancel": "Cancel",
@@ -72,6 +72,7 @@
72
72
  "noAccountYet": "Ešte nemáte účet?",
73
73
  "moreInformation": "Viac informácií"
74
74
  },
75
+ "openInFloatingWindow": "Otvoriť v plávajúcom okne",
75
76
  "showDeleted": "relácia vymazaná",
76
77
  "hideDeleted": "skryť odstránené",
77
78
  "cancel": "Zrušiť",
@@ -4,6 +4,7 @@
4
4
  import { createRouter, createWebHistory } from "vue-router"
5
5
  import { afterEach, beforeEach } from "./routerHooks"
6
6
  import routes from "./routes"
7
+ import { $eventbus } from "@racletteCore/main"
7
8
 
8
9
  // create router instance
9
10
 
@@ -15,5 +16,20 @@ const router = createRouter({
15
16
  /* Rooter hooks */
16
17
  router.beforeEach(beforeEach)
17
18
  router.afterEach(afterEach)
19
+ $eventbus.on("backend/error", (error) => {
20
+ if (error.name === "AxiosError") {
21
+ const errorResponse = error.response?.data
22
+ if (errorResponse?.code === "FST_JWT_AUTHORIZATION_TOKEN_EXPIRED") {
23
+ // Capture current route path (including query and hash)
24
+ const currentUrl = router.currentRoute.value.fullPath
25
+ // Redirect to login with the current URL as a query param
26
+ if (window.location.href !== window.location.origin + "/login") {
27
+ window.location.href =
28
+ window.location.origin + "/login?redirect=" + currentUrl
29
+ }
18
30
 
31
+ return
32
+ }
33
+ }
34
+ })
19
35
  export default router
package/yarn.lock CHANGED
@@ -295,10 +295,10 @@
295
295
  resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.2.9.tgz#d229a7b7f9dac167a156992ef23c7f023653f53b"
296
296
  integrity sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==
297
297
 
298
- "@raclettejs/types@^0.1.17":
299
- version "0.1.17"
300
- resolved "https://registry.yarnpkg.com/@raclettejs/types/-/types-0.1.17.tgz#ced377e5fa8879a5790b1c0c838f621917032690"
301
- integrity sha512-WBhi6Nf/XJPlisF1stEB0KGo5TWw+EMaTuYt39fJKc+Vtyf/SFmZqP2D3BKlssE5N/8bo2DFgf2qUeKowo0onA==
298
+ "@raclettejs/types@^0.1.18":
299
+ version "0.1.18"
300
+ resolved "https://registry.yarnpkg.com/@raclettejs/types/-/types-0.1.18.tgz#7df0eb1b86db015694fabfafa089a277e654b350"
301
+ integrity sha512-mvQI2sO48z6+QKj/s5A5JMBKnY8piE+8D8N0soctfsU7tAKg8nEwlxOiQHZiqJyR1k+gX2p+VBMRGbxHCYAGFw==
302
302
  dependencies:
303
303
  "@types/node" "24.5.2"
304
304
  fastify "5.6.0"
@@ -1,27 +0,0 @@
1
- // TODO: check if this file can be deleted
2
- export const createLoginApp = async (
3
- el: string,
4
- loginMethod: Function,
5
- noUsers: boolean,
6
- ) => {
7
- const [{ createApp }, { default: LoginApp }, { i18n }, { default: vuetify }] =
8
- await Promise.all([
9
- import("vue"),
10
- import("../LoginApp.vue"),
11
- import("./i18n"),
12
- import("./vuetify"),
13
- ])
14
-
15
- await Promise.all([
16
- import("../assets/styles/main.scss"),
17
- import("../assets/styles/tailwindStyles.css"),
18
- import("../assets/styles/vuetifyStyles.scss"),
19
- ])
20
-
21
- const app = createApp(LoginApp, { loginMethod, noUsers })
22
- app.use(i18n)
23
- app.use(vuetify)
24
- app.mount(el)
25
-
26
- return app
27
- }