mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 10:04:11 +00:00
Merged in CST-12914-ldn-breadcrumbs (pull request #1115)
CST-12914 ldn breadcrumbs Approved-by: Giuseppe Digilio
This commit is contained in:
@@ -1,12 +1,12 @@
|
|||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
import {RouterModule} from '@angular/router';
|
import { RouterModule, Routes } from '@angular/router';
|
||||||
import {I18nBreadcrumbResolver} from 'src/app/core/breadcrumbs/i18n-breadcrumb.resolver';
|
|
||||||
import { LdnServicesOverviewComponent } from './ldn-services-directory/ldn-services-directory.component';
|
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';
|
import { LdnServiceFormComponent } from './ldn-service-form/ldn-service-form.component';
|
||||||
|
|
||||||
@NgModule({
|
|
||||||
imports: [
|
const moduleRoutes: Routes = [
|
||||||
RouterModule.forChild([
|
|
||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
pathMatch: 'full',
|
pathMatch: 'full',
|
||||||
@@ -16,17 +16,30 @@ import {LdnServiceFormComponent} from './ldn-service-form/ldn-service-form.compo
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'new',
|
path: 'new',
|
||||||
resolve: {breadcrumb: I18nBreadcrumbResolver},
|
resolve: {breadcrumb: NavigationBreadcrumbResolver},
|
||||||
component: LdnServiceFormComponent,
|
component: LdnServiceFormComponent,
|
||||||
data: {title: 'ldn-register-new-service.title', breadcrumbKey: 'ldn-register-new-service'}
|
data: {title: 'ldn-register-new-service.title', breadcrumbKey: 'ldn-register-new-service'}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'edit/:serviceId',
|
path: 'edit/:serviceId',
|
||||||
resolve: {breadcrumb: I18nBreadcrumbResolver},
|
resolve: {breadcrumb: NavigationBreadcrumbResolver},
|
||||||
component: LdnServiceFormComponent,
|
component: LdnServiceFormComponent,
|
||||||
data: {title: 'ldn-edit-service.title', breadcrumbKey: 'ldn-edit-service'}
|
data: {title: 'ldn-edit-service.title', breadcrumbKey: 'ldn-edit-service'}
|
||||||
},
|
},
|
||||||
]),
|
];
|
||||||
|
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
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 {
|
export class AdminLdnServicesRoutingModule {
|
||||||
|
@@ -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
src/app/core/breadcrumbs/navigation-breadcrumb.resolver.ts
Normal file
52
src/app/core/breadcrumbs/navigation-breadcrumb.resolver.ts
Normal file
@@ -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
src/app/core/breadcrumbs/navigation-breadcrumb.service.ts
Normal file
30
src/app/core/breadcrumbs/navigation-breadcrumb.service.ts
Normal file
@@ -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());
|
||||||
|
}
|
||||||
|
}
|
@@ -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() });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
Reference in New Issue
Block a user