From 73a7f72426dfbf0a21209e11c43acfcca9f64641 Mon Sep 17 00:00:00 2001 From: markuczy Date: Tue, 25 Jun 2024 12:33:48 +0200 Subject: [PATCH 1/3] feat: breadcrumb service for matcher routes --- .../src/lib/services/breadcrumb.service.ts | 61 +++++++++++++------ 1 file changed, 41 insertions(+), 20 deletions(-) diff --git a/libs/angular-accelerator/src/lib/services/breadcrumb.service.ts b/libs/angular-accelerator/src/lib/services/breadcrumb.service.ts index 75c02bda..f25cb622 100644 --- a/libs/angular-accelerator/src/lib/services/breadcrumb.service.ts +++ b/libs/angular-accelerator/src/lib/services/breadcrumb.service.ts @@ -13,41 +13,62 @@ export class BreadcrumbService { itemsHandler = this.itemsSource.asObservable() constructor(private router: Router, private activeRoute: ActivatedRoute, private translateService: TranslateService) { - const breadcrumbs: MenuItem[] = [] - this.addBreadcrumb(this.activeRoute.snapshot, [], breadcrumbs) - this.generatedItemsSource.next(breadcrumbs) + this.generateBreadcrumbs(this.activeRoute.snapshot) this.router.events.pipe(filter((e) => e instanceof NavigationEnd)).subscribe(() => { const root = this.router.routerState.snapshot.root - const breadcrumbs: MenuItem[] = [] - this.addBreadcrumb(root, [], breadcrumbs) - - this.generatedItemsSource.next(breadcrumbs) + this.generateBreadcrumbs(root) }) } + private generateBreadcrumbs(route: ActivatedRouteSnapshot | null) { + if (route && route.url) { + if (route.data['mfeInfo']) { + const breadcrumbs: MenuItem[] = [ + { + label: route.data['mfeInfo'].productName, + routerLink: route.data['mfeInfo'].baseHref, + }, + ] + const baseUrl: string[] = (route.data['mfeInfo'].baseHref as string).split('/').filter((value) => value) + const parentUrl: string[] = route.url.map((url) => url.path) + if (!parentUrl.every((item) => baseUrl.includes(item))) { + this.createBreadcrumb(route, parentUrl, breadcrumbs) + } + this.addBreadcrumb(route.firstChild, parentUrl, breadcrumbs) + this.generatedItemsSource.next(breadcrumbs) + } else { + this.generateBreadcrumbs(route.firstChild) + } + } + } + private addBreadcrumb(route: ActivatedRouteSnapshot | null, parentUrl: string[], breadcrumbs: MenuItem[]) { if (route && route.url) { const routeUrl = parentUrl.concat(route.url.map((url) => url.path)) if (route.routeConfig?.path) { - if (route.data['breadcrumb']) { - const breadcrumb: MenuItem = { - label: this.getLabel(route.data, route.paramMap), - routerLink: '/' + routeUrl.join('/'), - } - breadcrumbs.push(breadcrumb) - } else { - const breadcrumb: MenuItem = { - label: 'NA', - routerLink: '/' + routeUrl.join('/'), - } - breadcrumbs.push(breadcrumb) - } + this.createBreadcrumb(route, routeUrl, breadcrumbs) } this.addBreadcrumb(route.firstChild, routeUrl, breadcrumbs) } } + private createBreadcrumb(route: ActivatedRouteSnapshot, routeUrl: string[], breadcrumbs: MenuItem[]) { + if (route.data['breadcrumb']) { + const breadcrumb: MenuItem = { + label: this.getLabel(route.data, route.paramMap), + routerLink: '/' + routeUrl.join('/'), + } + breadcrumbs.push(breadcrumb) + } else { + const breadcrumb: MenuItem = { + label: 'NA', + routerLink: '/' + routeUrl.join('/'), + } + breadcrumbs.push(breadcrumb) + } + } + private getLabel(data: Data, params: ParamMap) { if (typeof data['breadcrumbFn'] === 'function') { return data['breadcrumbFn'](data, params) From 01be280ce90e523ea7b158a9f071134dddc42f3b Mon Sep 17 00:00:00 2001 From: markuczy Date: Tue, 25 Jun 2024 16:10:28 +0200 Subject: [PATCH 2/3] feat: unsubscribe on destroy --- .../src/lib/services/breadcrumb.service.ts | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/libs/angular-accelerator/src/lib/services/breadcrumb.service.ts b/libs/angular-accelerator/src/lib/services/breadcrumb.service.ts index f25cb622..b51b4e84 100644 --- a/libs/angular-accelerator/src/lib/services/breadcrumb.service.ts +++ b/libs/angular-accelerator/src/lib/services/breadcrumb.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core' +import { Injectable, OnDestroy } from '@angular/core' import { ActivatedRoute, ActivatedRouteSnapshot, Data, NavigationEnd, ParamMap, Router } from '@angular/router' import { TranslateService } from '@ngx-translate/core' import { BehaviorSubject, filter } from 'rxjs' @@ -6,7 +6,7 @@ import { MenuItem } from 'primeng/api' import { BreadCrumbMenuItem } from '../model/breadcrumb-menu-item.model' @Injectable({ providedIn: 'any' }) -export class BreadcrumbService { +export class BreadcrumbService implements OnDestroy { private itemsSource = new BehaviorSubject([]) generatedItemsSource = new BehaviorSubject([]) @@ -19,6 +19,10 @@ export class BreadcrumbService { this.generateBreadcrumbs(root) }) } + ngOnDestroy(): void { + this.itemsSource.unsubscribe() + this.generatedItemsSource.unsubscribe() + } private generateBreadcrumbs(route: ActivatedRouteSnapshot | null) { if (route && route.url) { @@ -31,7 +35,8 @@ export class BreadcrumbService { ] const baseUrl: string[] = (route.data['mfeInfo'].baseHref as string).split('/').filter((value) => value) const parentUrl: string[] = route.url.map((url) => url.path) - if (!parentUrl.every((item) => baseUrl.includes(item))) { + const isUsingMatcher = !parentUrl.every((item) => baseUrl.includes(item)) + if (isUsingMatcher) { this.createBreadcrumb(route, parentUrl, breadcrumbs) } this.addBreadcrumb(route.firstChild, parentUrl, breadcrumbs) From e8cbd9d531c62ddca19d1e59f6a92ad5b0f00f42 Mon Sep 17 00:00:00 2001 From: markuczy Date: Thu, 27 Jun 2024 10:41:28 +0200 Subject: [PATCH 3/3] feat: backward compatibility with standard modules --- libs/angular-accelerator/package.json | 1 + .../src/lib/services/breadcrumb.service.ts | 61 ++++++++++--------- package-lock.json | 7 ++- 3 files changed, 38 insertions(+), 31 deletions(-) diff --git a/libs/angular-accelerator/package.json b/libs/angular-accelerator/package.json index 85cc66e1..b0f2a588 100644 --- a/libs/angular-accelerator/package.json +++ b/libs/angular-accelerator/package.json @@ -9,6 +9,7 @@ "@angular/platform-browser": "^15.2.7 || ^16.0.0 || ^17.0.0", "@angular/router": "^15.2.7 || ^16.0.0 || ^17.0.0", "@ngx-translate/core": "^14.0.0", + "@ngneat/until-destroy": "^9.2.2", "@onecx/integration-interface": "^4", "@onecx/angular-integration-interface": "^4", "chart.js": "^4.4.0", diff --git a/libs/angular-accelerator/src/lib/services/breadcrumb.service.ts b/libs/angular-accelerator/src/lib/services/breadcrumb.service.ts index b51b4e84..c2d17267 100644 --- a/libs/angular-accelerator/src/lib/services/breadcrumb.service.ts +++ b/libs/angular-accelerator/src/lib/services/breadcrumb.service.ts @@ -1,12 +1,14 @@ -import { Injectable, OnDestroy } from '@angular/core' +import { Injectable } from '@angular/core' import { ActivatedRoute, ActivatedRouteSnapshot, Data, NavigationEnd, ParamMap, Router } from '@angular/router' import { TranslateService } from '@ngx-translate/core' +import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy' import { BehaviorSubject, filter } from 'rxjs' import { MenuItem } from 'primeng/api' import { BreadCrumbMenuItem } from '../model/breadcrumb-menu-item.model' @Injectable({ providedIn: 'any' }) -export class BreadcrumbService implements OnDestroy { +@UntilDestroy() +export class BreadcrumbService { private itemsSource = new BehaviorSubject([]) generatedItemsSource = new BehaviorSubject([]) @@ -14,36 +16,39 @@ export class BreadcrumbService implements OnDestroy { constructor(private router: Router, private activeRoute: ActivatedRoute, private translateService: TranslateService) { this.generateBreadcrumbs(this.activeRoute.snapshot) - this.router.events.pipe(filter((e) => e instanceof NavigationEnd)).subscribe(() => { - const root = this.router.routerState.snapshot.root - this.generateBreadcrumbs(root) - }) - } - ngOnDestroy(): void { - this.itemsSource.unsubscribe() - this.generatedItemsSource.unsubscribe() + this.router.events + .pipe( + untilDestroyed(this), + filter((e) => e instanceof NavigationEnd) + ) + .subscribe(() => { + const root = this.router.routerState.snapshot.root + this.generateBreadcrumbs(root) + }) } private generateBreadcrumbs(route: ActivatedRouteSnapshot | null) { - if (route && route.url) { - if (route.data['mfeInfo']) { - const breadcrumbs: MenuItem[] = [ - { - label: route.data['mfeInfo'].productName, - routerLink: route.data['mfeInfo'].baseHref, - }, - ] - const baseUrl: string[] = (route.data['mfeInfo'].baseHref as string).split('/').filter((value) => value) - const parentUrl: string[] = route.url.map((url) => url.path) - const isUsingMatcher = !parentUrl.every((item) => baseUrl.includes(item)) - if (isUsingMatcher) { - this.createBreadcrumb(route, parentUrl, breadcrumbs) - } - this.addBreadcrumb(route.firstChild, parentUrl, breadcrumbs) - this.generatedItemsSource.next(breadcrumbs) - } else { - this.generateBreadcrumbs(route.firstChild) + if (route?.data['mfeInfo']) { + const breadcrumbs: MenuItem[] = [ + { + label: route.data['mfeInfo'].productName, + routerLink: route.data['mfeInfo'].baseHref, + }, + ] + const baseUrl: string[] = (route.data['mfeInfo'].baseHref as string).split('/').filter((value) => value) + const parentUrl: string[] = route.url.map((url) => url.path) + const isUsingMatcher = !parentUrl.every((item) => baseUrl.includes(item)) + if (isUsingMatcher) { + this.createBreadcrumb(route, parentUrl, breadcrumbs) } + this.addBreadcrumb(route.firstChild, parentUrl, breadcrumbs) + this.generatedItemsSource.next(breadcrumbs) + } else if (route?.data['breadcrumb']) { + const breadcrumbs: MenuItem[] = [] + this.addBreadcrumb(route, [], breadcrumbs) + this.generatedItemsSource.next(breadcrumbs) + } else if (route) { + this.generateBreadcrumbs(route.firstChild) } } diff --git a/package-lock.json b/package-lock.json index ea7ebadb..69295888 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@onecx/onecx-portal-ui-libs", - "version": "4.30.1", + "version": "4.33.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@onecx/onecx-portal-ui-libs", - "version": "4.30.1", + "version": "4.33.3", "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { @@ -111,7 +111,8 @@ } }, "libs/portal-layout-styles": { - "version": "4.30.1", + "name": "@onecx/portal-layout-styles", + "version": "4.33.3", "peerDependencies": { "tslib": "^2.5.0" }