Skip to content

Commit

Permalink
Merged in CST-12914-ldn-breadcrumbs (pull request DSpace#1115)
Browse files Browse the repository at this point in the history
CST-12914 ldn breadcrumbs

Approved-by: Giuseppe Digilio
  • Loading branch information
FrancescoMolinaro authored and atarix83 committed Dec 22, 2023
2 parents 8c6daf7 + 11bb71e commit ad723a6
Show file tree
Hide file tree
Showing 6 changed files with 224 additions and 34 deletions.
Original file line number Diff line number Diff line change
@@ -1,32 +1,45 @@
import {NgModule} from '@angular/core';
import {RouterModule} from '@angular/router';
import {I18nBreadcrumbResolver} from 'src/app/core/breadcrumbs/i18n-breadcrumb.resolver';
import {LdnServicesOverviewComponent} from './ldn-services-directory/ldn-services-directory.component';
import {LdnServiceFormComponent} from './ldn-service-form/ldn-service-form.component';
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { LdnServicesOverviewComponent } from './ldn-services-directory/ldn-services-directory.component';
import { NavigationBreadcrumbResolver } from '../../core/breadcrumbs/navigation-breadcrumb.resolver';
import { I18nBreadcrumbResolver } from '../../core/breadcrumbs/i18n-breadcrumb.resolver';
import { LdnServiceFormComponent } from './ldn-service-form/ldn-service-form.component';


const moduleRoutes: Routes = [
{
path: '',
pathMatch: 'full',
component: LdnServicesOverviewComponent,
resolve: {breadcrumb: I18nBreadcrumbResolver},
data: {title: 'ldn-registered-services.title', breadcrumbKey: 'ldn-registered-services.new'},
},
{
path: 'new',
resolve: {breadcrumb: NavigationBreadcrumbResolver},
component: LdnServiceFormComponent,
data: {title: 'ldn-register-new-service.title', breadcrumbKey: 'ldn-register-new-service'}
},
{
path: 'edit/:serviceId',
resolve: {breadcrumb: NavigationBreadcrumbResolver},
component: LdnServiceFormComponent,
data: {title: 'ldn-edit-service.title', breadcrumbKey: 'ldn-edit-service'}
},
];


@NgModule({
imports: [
RouterModule.forChild([
{
path: '',
pathMatch: 'full',
component: LdnServicesOverviewComponent,
resolve: {breadcrumb: I18nBreadcrumbResolver},
data: {title: 'ldn-registered-services.title', breadcrumbKey: 'ldn-registered-services.new'},
},
{
path: 'new',
resolve: {breadcrumb: I18nBreadcrumbResolver},
component: LdnServiceFormComponent,
data: {title: 'ldn-register-new-service.title', breadcrumbKey: 'ldn-register-new-service'}
},
{
path: 'edit/:serviceId',
resolve: {breadcrumb: I18nBreadcrumbResolver},
component: LdnServiceFormComponent,
data: {title: 'ldn-edit-service.title', breadcrumbKey: 'ldn-edit-service'}
},
]),
RouterModule.forChild(moduleRoutes.map(route => {
return {...route, data: {
...route.data,
relatedRoutes: moduleRoutes.filter(relatedRoute => relatedRoute.path !== route.path)
.map((relatedRoute) => {
return {path: relatedRoute.path, data: relatedRoute.data};
})
}};
}))
]
})
export class AdminLdnServicesRoutingModule {
Expand Down
16 changes: 8 additions & 8 deletions src/app/admin/admin-ldn-services/admin-ldn-services.module.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import {NgModule} from '@angular/core';
import {CommonModule} from '@angular/common';
import {AdminLdnServicesRoutingModule} from './admin-ldn-services-routing.module';
import {LdnServicesOverviewComponent} from './ldn-services-directory/ldn-services-directory.component';
import {SharedModule} from '../../shared/shared.module';
import {LdnServiceFormComponent} from './ldn-service-form/ldn-service-form.component';
import {FormsModule} from '@angular/forms';
import {LdnItemfiltersService} from './ldn-services-data/ldn-itemfilters-data.service';
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { AdminLdnServicesRoutingModule } from './admin-ldn-services-routing.module';
import { LdnServicesOverviewComponent } from './ldn-services-directory/ldn-services-directory.component';
import { SharedModule } from '../../shared/shared.module';
import { LdnServiceFormComponent } from './ldn-service-form/ldn-service-form.component';
import { FormsModule } from '@angular/forms';
import { LdnItemfiltersService } from './ldn-services-data/ldn-itemfilters-data.service';


@NgModule({
Expand Down
52 changes: 52 additions & 0 deletions src/app/core/breadcrumbs/navigation-breadcrumb.resolver.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
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);
});
});
});
52 changes: 52 additions & 0 deletions src/app/core/breadcrumbs/navigation-breadcrumb.resolver.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { BreadcrumbConfig } from '../../breadcrumbs/breadcrumb/breadcrumb-config.model';
import { Injectable } from '@angular/core';
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 and related parents
*/
@Injectable({
providedIn: 'root'
})
export class NavigationBreadcrumbResolver implements Resolve<BreadcrumbConfig<string>> {

private parentRoutes: ActivatedRouteSnapshot[] = [];
constructor(protected breadcrumbService: NavigationBreadcrumbsService) {
}

/**
* 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
* @param {ActivatedRouteSnapshot} route The current ActivatedRouteSnapshot
* @param {RouterStateSnapshot} state The current RouterStateSnapshot
* @returns BreadcrumbConfig object
*/
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): BreadcrumbConfig<string> {
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);


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};
}
}
30 changes: 30 additions & 0 deletions src/app/core/breadcrumbs/navigation-breadcrumb.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { Breadcrumb } from '../../breadcrumbs/breadcrumb/breadcrumb.model';
import { BreadcrumbsProviderService } from './breadcrumbsProviderService';
import { Observable, of as observableOf } from 'rxjs';
import { Injectable } from '@angular/core';

/**
* The postfix for i18n breadcrumbs
*/
export const BREADCRUMB_MESSAGE_POSTFIX = '.breadcrumbs';

/**
* Service to calculate i18n breadcrumbs for a single part of the route
*/
@Injectable({
providedIn: 'root'
})
export class NavigationBreadcrumbsService implements BreadcrumbsProviderService<string> {

/**
* Method to calculate the breadcrumbs
* @param key The key used to resolve the breadcrumb
* @param url The url to use as a link for this breadcrumb
*/
getBreadcrumbs(key: string, url: string): Observable<Breadcrumb[]> {
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());
}
}
43 changes: 43 additions & 0 deletions src/app/core/breadcrumbs/navigation-breadcrumbs.service.spec.ts
Original file line number Diff line number Diff line change
@@ -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() });
});
});
});

0 comments on commit ad723a6

Please sign in to comment.