From 1976bb998afb44e5c6a1f44a95dce5b325d9b632 Mon Sep 17 00:00:00 2001 From: "marcel.kocisek" Date: Fri, 30 May 2025 15:03:43 +0200 Subject: [PATCH 1/4] Update breadcrumps parsing to accept also function from meta.breadcrump attribute - remove support to store it in layoutStore --- web-app/packages/app/src/router.ts | 97 ++++++++++--------- .../packages/app/src/shims-vue-router.d.ts | 4 +- .../layout/components/AppBreadcrumbs.vue | 73 +++++++------- .../packages/lib/src/modules/layout/store.ts | 4 +- .../packages/lib/src/shims-vue-router.d.ts | 4 +- 5 files changed, 99 insertions(+), 83 deletions(-) diff --git a/web-app/packages/app/src/router.ts b/web-app/packages/app/src/router.ts index e8e1522d..6dbfdc22 100644 --- a/web-app/packages/app/src/router.ts +++ b/web-app/packages/app/src/router.ts @@ -194,75 +194,82 @@ export const createRouter = (pinia: Pinia) => { name: ProjectRouteName.ProjectTree, component: FileBrowserView, props: true, - meta: { public: true } + meta: { + public: true, + breadcrump: (route) => [ + { + title: route.params?.projectName, + path: `/projects/${route.params.namespace}/${route.params.projectName}/tree` + } + ] + } }, { path: 'settings', name: 'project-settings', component: ProjectSettingsView, - props: true + props: true, + meta: { + breadcrump: (route) => [ + { + title: route.params?.projectName, + path: `/projects/${route.params.namespace}/${route.params.projectName}/tree` + } + ] + } }, { path: 'history', name: 'project-versions', component: ProjectVersionsView, - props: true + props: true, + meta: { + breadcrump: (route) => [ + { + title: route.params?.projectName, + path: `/projects/${route.params.namespace}/${route.params.projectName}/tree` + } + ] + } }, { path: 'collaborators', name: ProjectRouteName.ProjectCollaborators, component: ProjectCollaboratorsView, - props: true + props: true, + meta: { + breadcrump: (route) => [ + { + title: route.params?.projectName, + path: `/projects/${route.params.namespace}/${route.params.projectName}/tree` + } + ] + } }, { path: 'history/:version_id/:path', name: 'file-version-detail', component: FileVersionDetailView, props: true, - meta: { public: true }, - // TODO: refactor to function in utils - beforeEnter(to, from, next) { - to.meta = { - ...to.meta, - breadcrump: [ - { - title: String(to.params.projectName), - path: `/projects/${to.params.namespace}/${to.params.projectName}/history` - }, - { - title: String(to.params.version_id), - path: `/projects/${to.params.namespace}/${to.params.projectName}/history/${to.params.version_id}` - }, - { - title: String(to.params.path), - path: to.fullPath - } - ] - } - next() + meta: { + public: true, + breadcrump: (route) => [ + { + title: route.params?.projectName, + path: `/projects/${route.params.namespace}/${route.params.projectName}/tree` + }, + { + title: route.params?.version_id, + path: `/projects/${route.params.namespace}/${route.params.projectName}/history/${route.params.version_id}` + }, + { + title: route.params?.path, + path: route.fullPath + } + ] } } ] - // Not apply for project version detail , which have own breadcrump - .map((child) => - child.name === 'file-version-detail' - ? child - : { - ...child, - beforeEnter: (to, from, next) => { - to.meta = { - ...to.meta, - breadcrump: [ - { - title: String(to.params.projectName), - path: to.fullPath - } - ] - } - next() - } - } - ) }, { path: '/:pathMatch(.*)*', diff --git a/web-app/packages/app/src/shims-vue-router.d.ts b/web-app/packages/app/src/shims-vue-router.d.ts index 9cbc6fc4..bce2786d 100644 --- a/web-app/packages/app/src/shims-vue-router.d.ts +++ b/web-app/packages/app/src/shims-vue-router.d.ts @@ -4,6 +4,8 @@ declare module 'vue-router' { interface RouteMeta { public?: boolean allowedForNoWorkspace?: boolean - breadcrump?: { title: string; path: string }[] + breadcrump?: + | { title: string; path: string }[] + | ((route) => { title: string; path: string }[]) } } diff --git a/web-app/packages/lib/src/modules/layout/components/AppBreadcrumbs.vue b/web-app/packages/lib/src/modules/layout/components/AppBreadcrumbs.vue index 3ef7239a..5e84fa55 100644 --- a/web-app/packages/lib/src/modules/layout/components/AppBreadcrumbs.vue +++ b/web-app/packages/lib/src/modules/layout/components/AppBreadcrumbs.vue @@ -49,44 +49,51 @@ import { MenuItem } from 'primevue/menuitem' import { computed } from 'vue' import { useRoute } from 'vue-router' -import { useLayoutStore } from '../store' - type EnhancedMenuItem = MenuItem & { path: string; active?: boolean } -const layoutStore = useLayoutStore() const route = useRoute() -// Merge all matched meta.breadcrumps with current route breadcrumps -const items = computed(() => - layoutStore.breadcrumps?.length - ? layoutStore.breadcrumps?.map((item, index, items) => ({ - label: item.title, - path: item.path, - active: index === items.length - 1 - })) - : [ - ...route.matched.reduce((acc, curr) => { - if (curr.name === route.name) return acc +function parseBreadcrump(item: { + title: string + path: string +}): EnhancedMenuItem { + return { + label: item.title, + path: item.path + } +} - return [ - ...acc, - ...(curr.meta?.breadcrump ?? []).map((item) => ({ - label: item.title, - path: item.path - })) - ] - }, []), - // adding current route wich is not in matched meta - ...(route.meta.breadcrump ?? []).map((item) => ({ - label: item.title, - path: item.path - })) - ] - // last will be active - .map((item, index, items) => ({ - ...item, - active: index === items.length - 1 - })) +const matchedBreacrumps = computed(() => { + return route.matched.reduce((acc, curr) => { + if (curr.name === route.name) return acc + const breadcrumps = + typeof curr.meta?.breadcrump === 'function' + ? curr.meta?.breadcrump(route) + : curr.meta?.breadcrump + return [...acc, ...(breadcrumps ?? []).map(parseBreadcrump)] + }, []) +}) + +const currentRouteBreacrumps = computed(() => { + const breadcrumps = + typeof route.meta?.breadcrump === 'function' + ? route.meta?.breadcrump(route) + : route.meta?.breadcrump + return (breadcrumps ?? []).map(parseBreadcrump) +}) + +// Merge all matched meta.breadcrumps with current route breadcrumps +const items = computed(() => + [ + ...matchedBreacrumps.value, + // adding current route wich is not in matched meta + ...currentRouteBreacrumps.value + ] + // last will be active + .map((item, index, items) => ({ + ...item, + active: index === items.length - 1 + })) ) diff --git a/web-app/packages/lib/src/modules/layout/store.ts b/web-app/packages/lib/src/modules/layout/store.ts index d75ef80a..2f3aef49 100644 --- a/web-app/packages/lib/src/modules/layout/store.ts +++ b/web-app/packages/lib/src/modules/layout/store.ts @@ -11,7 +11,6 @@ export interface LayoutState { isUnderOverlayBreakpoint: boolean /** Parsed closed elements from local storage and pushed back to local storage */ closedElements: string[] - breadcrumps: { title: string; path: string }[] } const CLOSED_ELEMENTS_KEY = 'mm-closed-elements' @@ -21,8 +20,7 @@ export const useLayoutStore = defineStore('layoutModule', { overlayBreakpoint: 1200, drawer: false, isUnderOverlayBreakpoint: false, - closedElements: [], - breadcrumps: [] + closedElements: [] }), getters: { /** diff --git a/web-app/packages/lib/src/shims-vue-router.d.ts b/web-app/packages/lib/src/shims-vue-router.d.ts index 9cbc6fc4..bce2786d 100644 --- a/web-app/packages/lib/src/shims-vue-router.d.ts +++ b/web-app/packages/lib/src/shims-vue-router.d.ts @@ -4,6 +4,8 @@ declare module 'vue-router' { interface RouteMeta { public?: boolean allowedForNoWorkspace?: boolean - breadcrump?: { title: string; path: string }[] + breadcrump?: + | { title: string; path: string }[] + | ((route) => { title: string; path: string }[]) } } From eeee2f035d38418f963241317af52a75d90ed92d Mon Sep 17 00:00:00 2001 From: "marcel.kocisek" Date: Fri, 30 May 2025 15:21:06 +0200 Subject: [PATCH 2/4] show profile menu button just for logged user (in case of public projects) --- .../lib/src/modules/layout/components/AppHeaderTemplate.vue | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/web-app/packages/lib/src/modules/layout/components/AppHeaderTemplate.vue b/web-app/packages/lib/src/modules/layout/components/AppHeaderTemplate.vue index b04a03c5..de50b643 100644 --- a/web-app/packages/lib/src/modules/layout/components/AppHeaderTemplate.vue +++ b/web-app/packages/lib/src/modules/layout/components/AppHeaderTemplate.vue @@ -38,6 +38,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-MerginMaps-Commercial