diff --git a/src/app/admin/admin-ldn-services/admin-ldn-services-routing.module.ts b/src/app/admin/admin-ldn-services/admin-ldn-services-routing.module.ts index 2cbbcf7f79..50815f6a0c 100644 --- a/src/app/admin/admin-ldn-services/admin-ldn-services-routing.module.ts +++ b/src/app/admin/admin-ldn-services/admin-ldn-services-routing.module.ts @@ -3,8 +3,8 @@ import {RouterModule, Routes} from '@angular/router'; import {LdnServicesOverviewComponent} from './ldn-services-directory/ldn-services-directory.component'; import {LdnServiceNewComponent} from './ldn-service-new/ldn-service-new.component'; import {LdnServiceFormEditComponent} from './ldn-service-form-edit/ldn-service-form-edit.component'; -import {NavigationBreadcrumbResolver} from "../../core/breadcrumbs/navigation-breadcrumb.resolver"; -import {I18nBreadcrumbResolver} from "../../core/breadcrumbs/i18n-breadcrumb.resolver"; +import {NavigationBreadcrumbResolver} from '../../core/breadcrumbs/navigation-breadcrumb.resolver'; +import {I18nBreadcrumbResolver} from '../../core/breadcrumbs/i18n-breadcrumb.resolver'; const moduleRoutes: Routes = [ @@ -29,14 +29,17 @@ const moduleRoutes: Routes = [ }, ]; -const relatedRoutes = moduleRoutes.map(route => { - return {...route, data: {...route.data, parentRoute: moduleRoutes[0]}} -}) @NgModule({ imports: [ RouterModule.forChild(moduleRoutes.map(route => { - return {...route, data: {...route.data, relatedRoutes }} + return {...route, data: { + ...route.data, + relatedRoutes: moduleRoutes.filter(relatedRoute => relatedRoute.path !== route.path) + .map((relatedRoute) => { + return {path: relatedRoute.path, data: relatedRoute.data}; + }) + }}; })) ] }) diff --git a/src/app/core/breadcrumbs/navigation-breadcrumb.resolver.spec.ts b/src/app/core/breadcrumbs/navigation-breadcrumb.resolver.spec.ts new file mode 100644 index 0000000000..2c156f296d --- /dev/null +++ b/src/app/core/breadcrumbs/navigation-breadcrumb.resolver.spec.ts @@ -0,0 +1,53 @@ +import { URLCombiner } from '../url-combiner/url-combiner'; +import {NavigationBreadcrumbResolver} from "./navigation-breadcrumb.resolver"; + +describe('NavigationBreadcrumbResolver', () => { + describe('resolve', () => { + let resolver: NavigationBreadcrumbResolver; + let NavigationBreadcrumbService: any; + let i18nKey: string; + let relatedI18nKey: string; + let route: any; + let expectedPath; + let state; + beforeEach(() => { + i18nKey = 'example.key'; + relatedI18nKey = 'related.key'; + route = { + data: { + breadcrumbKey: i18nKey, + relatedRoutes: [ + { + path: '', + data: {breadcrumbKey: relatedI18nKey}, + } + ] + }, + routeConfig: { + path: 'example' + }, + parent: { + routeConfig: { + path: '' + }, + url: [{ + path: "base" + }] + } as any + }; + + state = { + url: '/base/example' + } + expectedPath = '/base/example:/base'; + NavigationBreadcrumbService = {}; + resolver = new NavigationBreadcrumbResolver(NavigationBreadcrumbService); + }); + + it('should resolve the breadcrumb config', () => { + const resolvedConfig = resolver.resolve(route, state); + const expectedConfig = { provider: NavigationBreadcrumbService, key: `${i18nKey}:${relatedI18nKey}`, url: expectedPath }; + expect(resolvedConfig).toEqual(expectedConfig); + }); + }); +}); diff --git a/src/app/core/breadcrumbs/navigation-breadcrumb.resolver.ts b/src/app/core/breadcrumbs/navigation-breadcrumb.resolver.ts index 0fc8c6d7a6..81feac5cde 100644 --- a/src/app/core/breadcrumbs/navigation-breadcrumb.resolver.ts +++ b/src/app/core/breadcrumbs/navigation-breadcrumb.resolver.ts @@ -1,21 +1,29 @@ import { BreadcrumbConfig } from '../../breadcrumbs/breadcrumb/breadcrumb-config.model'; import { Injectable } from '@angular/core'; -import {ActivatedRouteSnapshot, Resolve, RouterStateSnapshot, Routes} from '@angular/router'; -import {NavigationBreadcrumbsService} from "./navigation-breadcrumb.service"; +import {ActivatedRouteSnapshot, Resolve, RouterStateSnapshot} from '@angular/router'; +import {NavigationBreadcrumbsService} from './navigation-breadcrumb.service'; /** - * The class that resolves a BreadcrumbConfig object with an i18n key string for a route + * The class that resolves a BreadcrumbConfig object with an i18n key string for a route and related parents */ @Injectable({ providedIn: 'root' }) export class NavigationBreadcrumbResolver implements Resolve> { + + private parentRoutes: ActivatedRouteSnapshot[] = []; constructor(protected breadcrumbService: NavigationBreadcrumbsService) { } - - private getUniqueParentRoutes(routes: Routes) : Routes { - return [...new Set(routes.map(route => route.data.parentRoute))]; + /** + * Method to collect all parent routes snapshot from current route snapshot + * @param {ActivatedRouteSnapshot} route The current ActivatedRouteSnapshot + */ + private getParentRoutes(route: ActivatedRouteSnapshot): void { + if (route.parent) { + this.parentRoutes.push(route.parent); + this.getParentRoutes(route.parent); + } } /** * Method for resolving an I18n breadcrumb configuration object @@ -24,11 +32,21 @@ export class NavigationBreadcrumbResolver implements Resolve { - const path = route.routeConfig.path; - const relatedRoutes = route.data.relatedRoutes.filter(relatedRoute => relatedRoute.path !== path); - const uniqueParentRoutes = this.getUniqueParentRoutes(route.data.relatedRoutes); + this.getParentRoutes(route); + const relatedRoutes = route.data.relatedRoutes; + const parentPaths = this.parentRoutes.map(parent => parent.routeConfig?.path); + const relatedParentRoutes = relatedRoutes.filter(relatedRoute => parentPaths.includes(relatedRoute.path)); + const baseUrlSegmentPath = route.parent.url[route.parent.url.length - 1].path; + const baseUrl = state.url.substring(0, state.url.lastIndexOf(baseUrlSegmentPath) + baseUrlSegmentPath.length); - console.log(path, relatedRoutes, uniqueParentRoutes); - return {provider: this.breadcrumbService, key: "combinedBredcrumbKeys", url: ""} + + const combinedParentBreadcrumbKeys = relatedParentRoutes.reduce((previous, current) => { + return `${previous}:${current.data.breadcrumbKey}`; + }, route.data.breadcrumbKey); + const combinedUrls = relatedParentRoutes.reduce((previous, current) => { + return `${previous}:${baseUrl}${current.path}`; + }, state.url); + + return {provider: this.breadcrumbService, key: combinedParentBreadcrumbKeys, url: combinedUrls}; } } diff --git a/src/app/core/breadcrumbs/navigation-breadcrumb.service.ts b/src/app/core/breadcrumbs/navigation-breadcrumb.service.ts index 765122a85c..beebeed94e 100644 --- a/src/app/core/breadcrumbs/navigation-breadcrumb.service.ts +++ b/src/app/core/breadcrumbs/navigation-breadcrumb.service.ts @@ -22,6 +22,9 @@ export class NavigationBreadcrumbsService implements BreadcrumbsProviderService< * @param url The url to use as a link for this breadcrumb */ getBreadcrumbs(key: string, url: string): Observable { - return observableOf([new Breadcrumb(key + BREADCRUMB_MESSAGE_POSTFIX, url)]); + const keys = key.split(':'); + const urls = url.split(':'); + const breadcrumbs = keys.map((currentKey, index) => new Breadcrumb(currentKey + BREADCRUMB_MESSAGE_POSTFIX, urls[index] )); + return observableOf(breadcrumbs.reverse()); } } diff --git a/src/app/core/breadcrumbs/navigation-breadcrumbs.service.spec.ts b/src/app/core/breadcrumbs/navigation-breadcrumbs.service.spec.ts new file mode 100644 index 0000000000..e2b36feed0 --- /dev/null +++ b/src/app/core/breadcrumbs/navigation-breadcrumbs.service.spec.ts @@ -0,0 +1,43 @@ +import { TestBed, waitForAsync } from '@angular/core/testing'; +import { Breadcrumb } from '../../breadcrumbs/breadcrumb/breadcrumb.model'; +import { getTestScheduler } from 'jasmine-marbles'; +import { BREADCRUMB_MESSAGE_POSTFIX } from './i18n-breadcrumbs.service'; +import {NavigationBreadcrumbsService} from "./navigation-breadcrumb.service"; + +describe('NavigationBreadcrumbsService', () => { + let service: NavigationBreadcrumbsService; + let exampleString; + let exampleURL; + let childrenString; + let childrenUrl; + let parentString; + let parentUrl; + + function init() { + exampleString = 'example.string:parent.string'; + exampleURL = 'example.com:parent.com'; + childrenString = 'example.string'; + childrenUrl = 'example.com'; + parentString = 'parent.string'; + parentUrl = 'parent.com'; + } + + beforeEach(waitForAsync(() => { + init(); + TestBed.configureTestingModule({}).compileComponents(); + })); + + beforeEach(() => { + service = new NavigationBreadcrumbsService(); + }); + + describe('getBreadcrumbs', () => { + it('should return an array of breadcrumbs based on strings by adding the postfix', () => { + const breadcrumbs = service.getBreadcrumbs(exampleString, exampleURL); + getTestScheduler().expectObservable(breadcrumbs).toBe('(a|)', { a: [ + new Breadcrumb(childrenString + BREADCRUMB_MESSAGE_POSTFIX, childrenUrl), + new Breadcrumb(parentString + BREADCRUMB_MESSAGE_POSTFIX, parentUrl), + ].reverse() }); + }); + }); +});