+
+ +
+
diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 7bc4ee1c5a..be528ccf3f 100755 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -39,6 +39,7 @@ import { DSpaceRouterStateSerializer } from './shared/ngrx/dspace-router-state-s import { NotificationComponent } from './shared/notifications/notification/notification.component'; import { NotificationsBoardComponent } from './shared/notifications/notifications-board/notifications-board.component'; import { SharedModule } from './shared/shared.module'; +import { BreadcrumbsComponent } from './breadcrumbs/breadcrumbs.component'; export function getConfig() { return ENV_CONFIG; @@ -128,6 +129,7 @@ const EXPORTS = [ ], declarations: [ ...DECLARATIONS, + BreadcrumbsComponent, ], exports: [ ...EXPORTS diff --git a/src/app/breadcrumbs/breadcrumb/breadcrumb.model.ts b/src/app/breadcrumbs/breadcrumb/breadcrumb.model.ts new file mode 100644 index 0000000000..99cf66533a --- /dev/null +++ b/src/app/breadcrumbs/breadcrumb/breadcrumb.model.ts @@ -0,0 +1,6 @@ +export class Breadcrumb { + constructor( + public text: string, + public url?: string) { + } +} diff --git a/src/app/breadcrumbs/breadcrumbs.component.html b/src/app/breadcrumbs/breadcrumbs.component.html new file mode 100644 index 0000000000..3a8730ea30 --- /dev/null +++ b/src/app/breadcrumbs/breadcrumbs.component.html @@ -0,0 +1,16 @@ + + + + + + + + + diff --git a/src/app/breadcrumbs/breadcrumbs.component.scss b/src/app/breadcrumbs/breadcrumbs.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/breadcrumbs/breadcrumbs.component.spec.ts b/src/app/breadcrumbs/breadcrumbs.component.spec.ts new file mode 100644 index 0000000000..175ef83757 --- /dev/null +++ b/src/app/breadcrumbs/breadcrumbs.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { BreadcrumbsComponent } from './breadcrumbs.component'; + +describe('BreadcrumbsComponent', () => { + let component: BreadcrumbsComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ BreadcrumbsComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(BreadcrumbsComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/breadcrumbs/breadcrumbs.component.ts b/src/app/breadcrumbs/breadcrumbs.component.ts new file mode 100644 index 0000000000..5fd0f93787 --- /dev/null +++ b/src/app/breadcrumbs/breadcrumbs.component.ts @@ -0,0 +1,53 @@ +import { Component, OnDestroy, OnInit } from '@angular/core'; +import { ActivatedRoute, NavigationEnd, Router } from '@angular/router'; +import { Breadcrumb } from './breadcrumb/breadcrumb.model'; +import { hasValue, isNotUndefined } from '../shared/empty.util'; +import { filter, map } from 'rxjs/operators'; +import { Subscription } from 'rxjs'; + +@Component({ + selector: 'ds-breadcrumbs', + templateUrl: './breadcrumbs.component.html', + styleUrls: ['./breadcrumbs.component.scss'] +}) +export class BreadcrumbsComponent implements OnDestroy { + breadcrumbs; + showBreadcrumbs; + subscription: Subscription; + + constructor( + private route: ActivatedRoute, + private router: Router + ) { + this.subscription = this.router.events.pipe( + filter((e): e is NavigationEnd => e instanceof NavigationEnd) + ).subscribe(() => { + this.reset(); + this.resolveBreadcrumb(this.route.root); + } + ) + } + + resolveBreadcrumb(route: ActivatedRoute) { + const data = route.snapshot.data; + if (hasValue(data) && hasValue(data.breadcrumb)) { + this.breadcrumbs.push(data.breadcrumb); + } + if (route.children.length > 0) { + this.resolveBreadcrumb(route.firstChild); + } else if (isNotUndefined(data.showBreadcrumbs)) { + this.showBreadcrumbs = data.showBreadcrumbs; + } + } + + ngOnDestroy(): void { + if (hasValue(this.subscription)) { + this.subscription.unsubscribe(); + } + } + + reset() { + this.breadcrumbs = []; + this.showBreadcrumbs = true; + } +} From 4ea264dd7f73d3b6c96eda942dde38d766d8d029 Mon Sep 17 00:00:00 2001 From: lotte Date: Thu, 20 Feb 2020 16:07:20 +0100 Subject: [PATCH 02/32] dso + i18n breadcrumbs with providers + resolvers --- .../breadcrumb/breadcrumb-config.model.ts | 7 ++++ src/app/breadcrumbs/breadcrumbs.component.ts | 36 ++++++++++++------- .../core/breadcrumbs/breadcrumbs.service.ts | 6 ++++ .../breadcrumbs/dso-breadcrumb.resolver.ts | 26 ++++++++++++++ .../breadcrumbs/dso-breadcrumbs.service.ts | 9 +++++ .../breadcrumbs/i18n-breadcrumb.resolver.ts | 29 +++++++++++++++ .../breadcrumbs/i18n-breadcrumbs.service.ts | 11 ++++++ 7 files changed, 111 insertions(+), 13 deletions(-) create mode 100644 src/app/breadcrumbs/breadcrumb/breadcrumb-config.model.ts create mode 100644 src/app/core/breadcrumbs/breadcrumbs.service.ts create mode 100644 src/app/core/breadcrumbs/dso-breadcrumb.resolver.ts create mode 100644 src/app/core/breadcrumbs/dso-breadcrumbs.service.ts create mode 100644 src/app/core/breadcrumbs/i18n-breadcrumb.resolver.ts create mode 100644 src/app/core/breadcrumbs/i18n-breadcrumbs.service.ts diff --git a/src/app/breadcrumbs/breadcrumb/breadcrumb-config.model.ts b/src/app/breadcrumbs/breadcrumb/breadcrumb-config.model.ts new file mode 100644 index 0000000000..cb43415d70 --- /dev/null +++ b/src/app/breadcrumbs/breadcrumb/breadcrumb-config.model.ts @@ -0,0 +1,7 @@ +import { BreadcrumbsService } from '../../core/breadcrumbs/breadcrumbs.service'; + +export interface BreadcrumbConfig { + provider: BreadcrumbsService; + key: string; + url?: string; +} diff --git a/src/app/breadcrumbs/breadcrumbs.component.ts b/src/app/breadcrumbs/breadcrumbs.component.ts index 5fd0f93787..c8ee9f5a1b 100644 --- a/src/app/breadcrumbs/breadcrumbs.component.ts +++ b/src/app/breadcrumbs/breadcrumbs.component.ts @@ -2,8 +2,9 @@ import { Component, OnDestroy, OnInit } from '@angular/core'; import { ActivatedRoute, NavigationEnd, Router } from '@angular/router'; import { Breadcrumb } from './breadcrumb/breadcrumb.model'; import { hasValue, isNotUndefined } from '../shared/empty.util'; -import { filter, map } from 'rxjs/operators'; -import { Subscription } from 'rxjs'; +import { filter, map, switchMap, tap } from 'rxjs/operators'; +import { combineLatest, Observable, Subscription } from 'rxjs'; +import { BreadcrumbConfig } from './breadcrumb/breadcrumb-config.model'; @Component({ selector: 'ds-breadcrumbs', @@ -11,8 +12,8 @@ import { Subscription } from 'rxjs'; styleUrls: ['./breadcrumbs.component.scss'] }) export class BreadcrumbsComponent implements OnDestroy { - breadcrumbs; - showBreadcrumbs; + breadcrumbs: Breadcrumb[]; + showBreadcrumbs: boolean; subscription: Subscription; constructor( @@ -20,23 +21,32 @@ export class BreadcrumbsComponent implements OnDestroy { private router: Router ) { this.subscription = this.router.events.pipe( - filter((e): e is NavigationEnd => e instanceof NavigationEnd) - ).subscribe(() => { - this.reset(); - this.resolveBreadcrumb(this.route.root); + filter((e): e is NavigationEnd => e instanceof NavigationEnd), + tap(() => this.reset()), + switchMap(() => this.resolveBreadcrumb(this.route.root)) + ).subscribe((breadcrumbs) => { + this.breadcrumbs = breadcrumbs; } ) } - resolveBreadcrumb(route: ActivatedRoute) { + resolveBreadcrumb(route: ActivatedRoute): Observable { const data = route.snapshot.data; if (hasValue(data) && hasValue(data.breadcrumb)) { - this.breadcrumbs.push(data.breadcrumb); + const { provider, key, url }: BreadcrumbConfig = data.breadcrumb; + if (route.children.length > 0) { + return combineLatest(provider.getBreadcrumbs(key, url), this.resolveBreadcrumb(route.firstChild)) + .pipe(map((crumbs) => [].concat.apply([], crumbs))); + } else { + if (isNotUndefined(data.showBreadcrumbs)) { + this.showBreadcrumbs = data.showBreadcrumbs; + } + return provider.getBreadcrumbs(key, url); + } } if (route.children.length > 0) { - this.resolveBreadcrumb(route.firstChild); - } else if (isNotUndefined(data.showBreadcrumbs)) { - this.showBreadcrumbs = data.showBreadcrumbs; + + return this.resolveBreadcrumb(route.firstChild) } } diff --git a/src/app/core/breadcrumbs/breadcrumbs.service.ts b/src/app/core/breadcrumbs/breadcrumbs.service.ts new file mode 100644 index 0000000000..8ad2ed0334 --- /dev/null +++ b/src/app/core/breadcrumbs/breadcrumbs.service.ts @@ -0,0 +1,6 @@ +import { Breadcrumb } from '../../breadcrumbs/breadcrumb/breadcrumb.model'; +import { Observable } from 'rxjs'; + +export interface BreadcrumbsService { + getBreadcrumbs(key: string, url: string): Observable; +} diff --git a/src/app/core/breadcrumbs/dso-breadcrumb.resolver.ts b/src/app/core/breadcrumbs/dso-breadcrumb.resolver.ts new file mode 100644 index 0000000000..4d8afcf1cc --- /dev/null +++ b/src/app/core/breadcrumbs/dso-breadcrumb.resolver.ts @@ -0,0 +1,26 @@ +import { BreadcrumbConfig } from '../../breadcrumbs/breadcrumb/breadcrumb-config.model'; +import { Injectable } from '@angular/core'; +import { ActivatedRouteSnapshot, Resolve, RouterStateSnapshot } from '@angular/router'; +import { DSOBreadcrumbsService } from './dso-breadcrumbs.service'; + +/** + * The class that resolve the BreadcrumbConfig object for a route + */ +@Injectable() +export class DSOBreadcrumbResolver implements Resolve { + constructor(private breadcrumbService: DSOBreadcrumbsService) { + } + + /** + * Method for resolving a site object + * @param {ActivatedRouteSnapshot} route The current ActivatedRouteSnapshot + * @param {RouterStateSnapshot} state The current RouterStateSnapshot + * @returns BreadcrumbConfig object + */ + resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): BreadcrumbConfig { + const uuid = route.params.id; + const fullPath = route.url.join(''); + const url = fullPath.substr(0, fullPath.indexOf(uuid)) + uuid; + return { provider: this.breadcrumbService, key: uuid, url: url }; + } +} diff --git a/src/app/core/breadcrumbs/dso-breadcrumbs.service.ts b/src/app/core/breadcrumbs/dso-breadcrumbs.service.ts new file mode 100644 index 0000000000..452c6c5678 --- /dev/null +++ b/src/app/core/breadcrumbs/dso-breadcrumbs.service.ts @@ -0,0 +1,9 @@ +import { Breadcrumb } from '../../breadcrumbs/breadcrumb/breadcrumb.model'; +import { BreadcrumbsService } from './breadcrumbs.service'; +import { Observable } from 'rxjs'; + +export class DSOBreadcrumbsService implements BreadcrumbsService { + getBreadcrumbs(key: string, url: string): Observable { + return undefined; + } +} diff --git a/src/app/core/breadcrumbs/i18n-breadcrumb.resolver.ts b/src/app/core/breadcrumbs/i18n-breadcrumb.resolver.ts new file mode 100644 index 0000000000..6b5d344bc6 --- /dev/null +++ b/src/app/core/breadcrumbs/i18n-breadcrumb.resolver.ts @@ -0,0 +1,29 @@ +import { BreadcrumbConfig } from '../../breadcrumbs/breadcrumb/breadcrumb-config.model'; +import { Injectable } from '@angular/core'; +import { ActivatedRouteSnapshot, Resolve, RouterStateSnapshot } from '@angular/router'; +import { I18nBreadcrumbsService } from './i18n-breadcrumbs.service'; +import { hasNoValue } from '../../shared/empty.util'; + +/** + * The class that resolve the BreadcrumbConfig object for a route + */ +@Injectable() +export class I18nBreadcrumbResolver implements Resolve { + constructor(private breadcrumbService: I18nBreadcrumbsService) { + } + + /** + * Method for resolving a site object + * @param {ActivatedRouteSnapshot} route The current ActivatedRouteSnapshot + * @param {RouterStateSnapshot} state The current RouterStateSnapshot + * @returns BreadcrumbConfig object + */ + resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): BreadcrumbConfig { + const key = route.data.breadcrumbKey; + if (hasNoValue(key)) { + throw new Error('You provided an i18nBreadcrumbResolver for url \"' + route.url + '\" but no breadcrumbKey in the route\'s data') + } + const fullPath = route.url.join(''); + return { provider: this.breadcrumbService, key: key, url: fullPath }; + } +} diff --git a/src/app/core/breadcrumbs/i18n-breadcrumbs.service.ts b/src/app/core/breadcrumbs/i18n-breadcrumbs.service.ts new file mode 100644 index 0000000000..8aefa04802 --- /dev/null +++ b/src/app/core/breadcrumbs/i18n-breadcrumbs.service.ts @@ -0,0 +1,11 @@ +import { Breadcrumb } from '../../breadcrumbs/breadcrumb/breadcrumb.model'; +import { BreadcrumbsService } from './breadcrumbs.service'; +import { Observable, of as observableOf } from 'rxjs'; + +export const BREADCRUMB_MESSAGE_PREFIX = 'breadcrumbs.'; + +export class I18nBreadcrumbsService implements BreadcrumbsService { + getBreadcrumbs(key: string, url: string): Observable { + return observableOf([new Breadcrumb(BREADCRUMB_MESSAGE_PREFIX + key, url)]); + } +} From 725f20a9d0b2182fd0c5655f1c0599fcf835216b Mon Sep 17 00:00:00 2001 From: lotte Date: Fri, 21 Feb 2020 17:06:50 +0100 Subject: [PATCH 03/32] breadcrumbs for DSOs --- .../+item-page/item-page-routing.module.ts | 12 +++++-- .../search-page-routing.module.ts | 9 +++-- src/app/app-routing.module.ts | 20 ++++++++++- .../breadcrumb/breadcrumb-config.model.ts | 6 ++-- src/app/breadcrumbs/breadcrumbs.component.ts | 20 +++++------ .../core/breadcrumbs/breadcrumbs.service.ts | 4 +-- .../collection-breadcrumb.resolver.ts | 17 +++++++++ .../community-breadcrumb.resolver.ts | 15 ++++++++ .../breadcrumbs/dso-breadcrumb.resolver.ts | 25 +++++++++---- .../breadcrumbs/dso-breadcrumbs.service.ts | 35 ++++++++++++++++--- .../breadcrumbs/i18n-breadcrumb.resolver.ts | 4 +-- .../breadcrumbs/i18n-breadcrumbs.service.ts | 4 ++- .../breadcrumbs/item-breadcrumb.resolver.ts | 15 ++++++++ src/app/core/data/remote-data.ts | 6 ++-- .../core/shared/child-hal-resource.model.ts | 5 +++ src/app/core/shared/collection.model.ts | 17 ++++++++- src/app/core/shared/community.model.ts | 15 +++++++- src/app/core/shared/item.model.ts | 7 +++- 18 files changed, 197 insertions(+), 39 deletions(-) create mode 100644 src/app/core/breadcrumbs/collection-breadcrumb.resolver.ts create mode 100644 src/app/core/breadcrumbs/community-breadcrumb.resolver.ts create mode 100644 src/app/core/breadcrumbs/item-breadcrumb.resolver.ts create mode 100644 src/app/core/shared/child-hal-resource.model.ts diff --git a/src/app/+item-page/item-page-routing.module.ts b/src/app/+item-page/item-page-routing.module.ts index ec562842aa..d2ad39d70d 100644 --- a/src/app/+item-page/item-page-routing.module.ts +++ b/src/app/+item-page/item-page-routing.module.ts @@ -7,6 +7,9 @@ import { ItemPageResolver } from './item-page.resolver'; import { URLCombiner } from '../core/url-combiner/url-combiner'; import { getItemModulePath } from '../app-routing.module'; import { AuthenticatedGuard } from '../core/auth/authenticated.guard'; +import { ItemBreadcrumbResolver } from '../core/breadcrumbs/item-breadcrumb.resolver'; +import { DSOBreadcrumbsService } from '../core/breadcrumbs/dso-breadcrumbs.service'; +import { LinkService } from '../core/cache/builders/link.service'; export function getItemPageRoute(itemId: string) { return new URLCombiner(getItemModulePath(), itemId).toString(); @@ -25,14 +28,16 @@ const ITEM_EDIT_PATH = ':id/edit'; component: ItemPageComponent, pathMatch: 'full', resolve: { - item: ItemPageResolver + item: ItemPageResolver, + breadcrumb: ItemBreadcrumbResolver } }, { path: ':id/full', component: FullItemPageComponent, resolve: { - item: ItemPageResolver + item: ItemPageResolver, + breadcrumb: ItemBreadcrumbResolver } }, { @@ -44,6 +49,9 @@ const ITEM_EDIT_PATH = ':id/edit'; ], providers: [ ItemPageResolver, + ItemBreadcrumbResolver, + DSOBreadcrumbsService, + LinkService ] }) export class ItemPageRoutingModule { diff --git a/src/app/+search-page/search-page-routing.module.ts b/src/app/+search-page/search-page-routing.module.ts index e7de31c06c..463aa8e7c4 100644 --- a/src/app/+search-page/search-page-routing.module.ts +++ b/src/app/+search-page/search-page-routing.module.ts @@ -4,14 +4,19 @@ import { RouterModule } from '@angular/router'; import { ConfigurationSearchPageGuard } from './configuration-search-page.guard'; import { ConfigurationSearchPageComponent } from './configuration-search-page.component'; import { SearchPageComponent } from './search-page.component'; -import { Breadcrumb } from '../breadcrumbs/breadcrumb/breadcrumb.model'; +import { I18nBreadcrumbResolver } from '../core/breadcrumbs/i18n-breadcrumb.resolver'; +import { I18nBreadcrumbsService } from '../core/breadcrumbs/i18n-breadcrumbs.service'; @NgModule({ imports: [ RouterModule.forChild([ - { path: '', component: SearchPageComponent, data: { title: 'search.title', breadcrumb: new Breadcrumb('Search', '/search') } }, + { path: '', component: SearchPageComponent, resolve: { breadcrumb: I18nBreadcrumbResolver }, data: { title: 'search.title', breadcrumbKey: 'Search' } }, { path: ':configuration', component: ConfigurationSearchPageComponent, canActivate: [ConfigurationSearchPageGuard] } ]) + ], + providers: [ + I18nBreadcrumbResolver, + I18nBreadcrumbsService ] }) export class SearchPageRoutingModule { diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index 471609745d..ede1879894 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -4,6 +4,13 @@ import { RouterModule } from '@angular/router'; import { PageNotFoundComponent } from './pagenotfound/pagenotfound.component'; import { AuthenticatedGuard } from './core/auth/authenticated.guard'; import { Breadcrumb } from './breadcrumbs/breadcrumb/breadcrumb.model'; +import { DSpaceObject } from './core/shared/dspace-object.model'; +import { Community } from './core/shared/community.model'; +import { getCommunityPageRoute } from './+community-page/community-page-routing.module'; +import { Collection } from './core/shared/collection.model'; +import { Item } from './core/shared/item.model'; +import { getItemPageRoute } from './+item-page/item-page-routing.module'; +import { getCollectionPageRoute } from './+collection-page/collection-page-routing.module'; const ITEM_MODULE_PATH = 'items'; @@ -29,6 +36,17 @@ export function getAdminModulePath() { return `/${ADMIN_MODULE_PATH}`; } +export function getDSOPath(dso: DSpaceObject): string { + switch ((dso as any).type) { + case Community.type.value: + return getCommunityPageRoute(dso.uuid); + case Collection.type.value: + return getCollectionPageRoute(dso.uuid); + case Item.type.value: + return getItemPageRoute(dso.uuid); + } +} + @NgModule({ imports: [ RouterModule.forRoot([ @@ -41,7 +59,7 @@ export function getAdminModulePath() { { path: COLLECTION_MODULE_PATH, loadChildren: './+collection-page/collection-page.module#CollectionPageModule' }, { path: ITEM_MODULE_PATH, loadChildren: './+item-page/item-page.module#ItemPageModule' }, { path: 'mydspace', loadChildren: './+my-dspace-page/my-dspace-page.module#MyDSpacePageModule', canActivate: [AuthenticatedGuard] }, - { path: 'search', loadChildren: './+search-page/search-page.module#SearchPageModule', data: { breadcrumb: new Breadcrumb('Search', '/search') } }, + { path: 'search', loadChildren: './+search-page/search-page.module#SearchPageModule' }, { path: 'browse', loadChildren: './+browse-by/browse-by.module#BrowseByModule' }, { path: ADMIN_MODULE_PATH, loadChildren: './+admin/admin.module#AdminModule', canActivate: [AuthenticatedGuard] }, { path: 'login', loadChildren: './+login-page/login-page.module#LoginPageModule' }, diff --git a/src/app/breadcrumbs/breadcrumb/breadcrumb-config.model.ts b/src/app/breadcrumbs/breadcrumb/breadcrumb-config.model.ts index cb43415d70..17ec96e2bd 100644 --- a/src/app/breadcrumbs/breadcrumb/breadcrumb-config.model.ts +++ b/src/app/breadcrumbs/breadcrumb/breadcrumb-config.model.ts @@ -1,7 +1,7 @@ import { BreadcrumbsService } from '../../core/breadcrumbs/breadcrumbs.service'; -export interface BreadcrumbConfig { - provider: BreadcrumbsService; - key: string; +export interface BreadcrumbConfig { + provider: BreadcrumbsService; + key: T; url?: string; } diff --git a/src/app/breadcrumbs/breadcrumbs.component.ts b/src/app/breadcrumbs/breadcrumbs.component.ts index c8ee9f5a1b..944af9b55d 100644 --- a/src/app/breadcrumbs/breadcrumbs.component.ts +++ b/src/app/breadcrumbs/breadcrumbs.component.ts @@ -3,7 +3,7 @@ import { ActivatedRoute, NavigationEnd, Router } from '@angular/router'; import { Breadcrumb } from './breadcrumb/breadcrumb.model'; import { hasValue, isNotUndefined } from '../shared/empty.util'; import { filter, map, switchMap, tap } from 'rxjs/operators'; -import { combineLatest, Observable, Subscription } from 'rxjs'; +import { combineLatest, Observable, Subscription, of as observableOf } from 'rxjs'; import { BreadcrumbConfig } from './breadcrumb/breadcrumb-config.model'; @Component({ @@ -32,22 +32,22 @@ export class BreadcrumbsComponent implements OnDestroy { resolveBreadcrumb(route: ActivatedRoute): Observable { const data = route.snapshot.data; + const last: boolean = route.children.length === 0; + + if (last && isNotUndefined(data.showBreadcrumbs)) { + this.showBreadcrumbs = data.showBreadcrumbs; + } + if (hasValue(data) && hasValue(data.breadcrumb)) { - const { provider, key, url }: BreadcrumbConfig = data.breadcrumb; - if (route.children.length > 0) { + const { provider, key, url } = data.breadcrumb; + if (!last) { return combineLatest(provider.getBreadcrumbs(key, url), this.resolveBreadcrumb(route.firstChild)) .pipe(map((crumbs) => [].concat.apply([], crumbs))); } else { - if (isNotUndefined(data.showBreadcrumbs)) { - this.showBreadcrumbs = data.showBreadcrumbs; - } return provider.getBreadcrumbs(key, url); } } - if (route.children.length > 0) { - - return this.resolveBreadcrumb(route.firstChild) - } + return !last ? this.resolveBreadcrumb(route.firstChild) : observableOf([]); } ngOnDestroy(): void { diff --git a/src/app/core/breadcrumbs/breadcrumbs.service.ts b/src/app/core/breadcrumbs/breadcrumbs.service.ts index 8ad2ed0334..30c6c44cf7 100644 --- a/src/app/core/breadcrumbs/breadcrumbs.service.ts +++ b/src/app/core/breadcrumbs/breadcrumbs.service.ts @@ -1,6 +1,6 @@ import { Breadcrumb } from '../../breadcrumbs/breadcrumb/breadcrumb.model'; import { Observable } from 'rxjs'; -export interface BreadcrumbsService { - getBreadcrumbs(key: string, url: string): Observable; +export interface BreadcrumbsService { + getBreadcrumbs(key: T, url: string): Observable; } diff --git a/src/app/core/breadcrumbs/collection-breadcrumb.resolver.ts b/src/app/core/breadcrumbs/collection-breadcrumb.resolver.ts new file mode 100644 index 0000000000..ec48e89421 --- /dev/null +++ b/src/app/core/breadcrumbs/collection-breadcrumb.resolver.ts @@ -0,0 +1,17 @@ +import { Injectable } from '@angular/core'; +import { DSOBreadcrumbsService } from './dso-breadcrumbs.service'; +import { ItemDataService } from '../data/item-data.service'; +import { Item } from '../shared/item.model'; +import { DSOBreadcrumbResolver } from './dso-breadcrumb.resolver'; +import { Collection } from '../shared/collection.model'; +import { CollectionDataService } from '../data/collection-data.service'; + +/** + * The class that resolve the BreadcrumbConfig object for a route + */ +@Injectable() +export class CollectionBreadcrumbResolver extends DSOBreadcrumbResolver { + constructor(protected breadcrumbService: DSOBreadcrumbsService, protected dataService: CollectionDataService) { + super(breadcrumbService, dataService); + } +} diff --git a/src/app/core/breadcrumbs/community-breadcrumb.resolver.ts b/src/app/core/breadcrumbs/community-breadcrumb.resolver.ts new file mode 100644 index 0000000000..3080823b97 --- /dev/null +++ b/src/app/core/breadcrumbs/community-breadcrumb.resolver.ts @@ -0,0 +1,15 @@ +import { Injectable } from '@angular/core'; +import { DSOBreadcrumbsService } from './dso-breadcrumbs.service'; +import { DSOBreadcrumbResolver } from './dso-breadcrumb.resolver'; +import { CommunityDataService } from '../data/community-data.service'; +import { Community } from '../shared/community.model'; + +/** + * The class that resolve the BreadcrumbConfig object for a route + */ +@Injectable() +export class CommunityBreadcrumbResolver extends DSOBreadcrumbResolver { + constructor(protected breadcrumbService: DSOBreadcrumbsService, protected dataService: CommunityDataService) { + super(breadcrumbService, dataService); + } +} diff --git a/src/app/core/breadcrumbs/dso-breadcrumb.resolver.ts b/src/app/core/breadcrumbs/dso-breadcrumb.resolver.ts index 4d8afcf1cc..6e90d8d123 100644 --- a/src/app/core/breadcrumbs/dso-breadcrumb.resolver.ts +++ b/src/app/core/breadcrumbs/dso-breadcrumb.resolver.ts @@ -2,13 +2,19 @@ import { BreadcrumbConfig } from '../../breadcrumbs/breadcrumb/breadcrumb-config import { Injectable } from '@angular/core'; import { ActivatedRouteSnapshot, Resolve, RouterStateSnapshot } from '@angular/router'; import { DSOBreadcrumbsService } from './dso-breadcrumbs.service'; +import { DataService } from '../data/data.service'; +import { getRemoteDataPayload, getSucceededRemoteData } from '../shared/operators'; +import { map } from 'rxjs/operators'; +import { Observable } from 'rxjs'; +import { DSpaceObject } from '../shared/dspace-object.model'; +import { ChildHALResource } from '../shared/child-hal-resource.model'; /** * The class that resolve the BreadcrumbConfig object for a route */ @Injectable() -export class DSOBreadcrumbResolver implements Resolve { - constructor(private breadcrumbService: DSOBreadcrumbsService) { +export class DSOBreadcrumbResolver implements Resolve> { + constructor(protected breadcrumbService: DSOBreadcrumbsService, protected dataService: DataService) { } /** @@ -17,10 +23,17 @@ export class DSOBreadcrumbResolver implements Resolve { * @param {RouterStateSnapshot} state The current RouterStateSnapshot * @returns BreadcrumbConfig object */ - resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): BreadcrumbConfig { + resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable> { const uuid = route.params.id; - const fullPath = route.url.join(''); - const url = fullPath.substr(0, fullPath.indexOf(uuid)) + uuid; - return { provider: this.breadcrumbService, key: uuid, url: url }; + return this.dataService.findById(uuid).pipe( + getSucceededRemoteData(), + getRemoteDataPayload(), + map((object: T) => { + const fullPath = route.url.join(''); + const url = fullPath.substr(0, fullPath.indexOf(uuid)) + uuid; + return { provider: this.breadcrumbService, key: object, url: url }; + }) + ); + } } diff --git a/src/app/core/breadcrumbs/dso-breadcrumbs.service.ts b/src/app/core/breadcrumbs/dso-breadcrumbs.service.ts index 452c6c5678..30344a3a77 100644 --- a/src/app/core/breadcrumbs/dso-breadcrumbs.service.ts +++ b/src/app/core/breadcrumbs/dso-breadcrumbs.service.ts @@ -1,9 +1,36 @@ import { Breadcrumb } from '../../breadcrumbs/breadcrumb/breadcrumb.model'; import { BreadcrumbsService } from './breadcrumbs.service'; -import { Observable } from 'rxjs'; +import { Observable, of as observableOf } from 'rxjs'; +import { ChildHALResource } from '../shared/child-hal-resource.model'; +import { LinkService } from '../cache/builders/link.service'; +import { DSpaceObject } from '../shared/dspace-object.model'; +import { followLink } from '../../shared/utils/follow-link-config.model'; +import { filter, find, map, switchMap } from 'rxjs/operators'; +import { getDSOPath } from '../../app-routing.module'; +import { RemoteData } from '../data/remote-data'; +import { hasValue } from '../../shared/empty.util'; +import { Injectable } from '@angular/core'; -export class DSOBreadcrumbsService implements BreadcrumbsService { - getBreadcrumbs(key: string, url: string): Observable { - return undefined; +@Injectable() +export class DSOBreadcrumbsService implements BreadcrumbsService { + constructor(private linkService: LinkService) { + + } + + getBreadcrumbs(key: ChildHALResource & DSpaceObject, url: string): Observable { + const crumb = new Breadcrumb(key.name, url); + const propertyName = key.getParentLinkKey(); + return this.linkService.resolveLink(key, followLink(propertyName))[propertyName].pipe( + filter((childRD: RemoteData) => childRD.isSuccessful === true && childRD.requestPending === false && childRD.responsePending === false), + switchMap((childRD: RemoteData) => { + if (hasValue(childRD.payload)) { + const child = childRD.payload; + return this.getBreadcrumbs(child, getDSOPath(child)) + } + return observableOf([]); + + }), + map((breadcrumbs: Breadcrumb[]) => [...breadcrumbs, crumb]) + ); } } diff --git a/src/app/core/breadcrumbs/i18n-breadcrumb.resolver.ts b/src/app/core/breadcrumbs/i18n-breadcrumb.resolver.ts index 6b5d344bc6..800a7b75d0 100644 --- a/src/app/core/breadcrumbs/i18n-breadcrumb.resolver.ts +++ b/src/app/core/breadcrumbs/i18n-breadcrumb.resolver.ts @@ -8,7 +8,7 @@ import { hasNoValue } from '../../shared/empty.util'; * The class that resolve the BreadcrumbConfig object for a route */ @Injectable() -export class I18nBreadcrumbResolver implements Resolve { +export class I18nBreadcrumbResolver implements Resolve> { constructor(private breadcrumbService: I18nBreadcrumbsService) { } @@ -18,7 +18,7 @@ export class I18nBreadcrumbResolver implements Resolve { * @param {RouterStateSnapshot} state The current RouterStateSnapshot * @returns BreadcrumbConfig object */ - resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): BreadcrumbConfig { + resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): BreadcrumbConfig { const key = route.data.breadcrumbKey; if (hasNoValue(key)) { throw new Error('You provided an i18nBreadcrumbResolver for url \"' + route.url + '\" but no breadcrumbKey in the route\'s data') diff --git a/src/app/core/breadcrumbs/i18n-breadcrumbs.service.ts b/src/app/core/breadcrumbs/i18n-breadcrumbs.service.ts index 8aefa04802..6a9c8916a2 100644 --- a/src/app/core/breadcrumbs/i18n-breadcrumbs.service.ts +++ b/src/app/core/breadcrumbs/i18n-breadcrumbs.service.ts @@ -1,10 +1,12 @@ import { Breadcrumb } from '../../breadcrumbs/breadcrumb/breadcrumb.model'; import { BreadcrumbsService } from './breadcrumbs.service'; import { Observable, of as observableOf } from 'rxjs'; +import { Injectable } from '@angular/core'; export const BREADCRUMB_MESSAGE_PREFIX = 'breadcrumbs.'; -export class I18nBreadcrumbsService implements BreadcrumbsService { +@Injectable() +export class I18nBreadcrumbsService implements BreadcrumbsService { getBreadcrumbs(key: string, url: string): Observable { return observableOf([new Breadcrumb(BREADCRUMB_MESSAGE_PREFIX + key, url)]); } diff --git a/src/app/core/breadcrumbs/item-breadcrumb.resolver.ts b/src/app/core/breadcrumbs/item-breadcrumb.resolver.ts new file mode 100644 index 0000000000..fdfd3c11f9 --- /dev/null +++ b/src/app/core/breadcrumbs/item-breadcrumb.resolver.ts @@ -0,0 +1,15 @@ +import { Injectable } from '@angular/core'; +import { DSOBreadcrumbsService } from './dso-breadcrumbs.service'; +import { ItemDataService } from '../data/item-data.service'; +import { Item } from '../shared/item.model'; +import { DSOBreadcrumbResolver } from './dso-breadcrumb.resolver'; + +/** + * The class that resolve the BreadcrumbConfig object for a route + */ +@Injectable() +export class ItemBreadcrumbResolver extends DSOBreadcrumbResolver { + constructor(protected breadcrumbService: DSOBreadcrumbsService, protected dataService: ItemDataService) { + super(breadcrumbService, dataService); + } +} diff --git a/src/app/core/data/remote-data.ts b/src/app/core/data/remote-data.ts index 3be9248907..4397464055 100644 --- a/src/app/core/data/remote-data.ts +++ b/src/app/core/data/remote-data.ts @@ -13,9 +13,9 @@ export enum RemoteDataState { */ export class RemoteData { constructor( - private requestPending?: boolean, - private responsePending?: boolean, - private isSuccessful?: boolean, + public requestPending?: boolean, + public responsePending?: boolean, + public isSuccessful?: boolean, public error?: RemoteDataError, public payload?: T ) { diff --git a/src/app/core/shared/child-hal-resource.model.ts b/src/app/core/shared/child-hal-resource.model.ts new file mode 100644 index 0000000000..b7682e2631 --- /dev/null +++ b/src/app/core/shared/child-hal-resource.model.ts @@ -0,0 +1,5 @@ +import { HALResource } from './hal-resource.model'; + +export interface ChildHALResource extends HALResource { + getParentLinkKey(): keyof this['_links']; +} diff --git a/src/app/core/shared/collection.model.ts b/src/app/core/shared/collection.model.ts index d5c6221428..ba2f448bba 100644 --- a/src/app/core/shared/collection.model.ts +++ b/src/app/core/shared/collection.model.ts @@ -12,10 +12,13 @@ import { License } from './license.model'; import { LICENSE } from './license.resource-type'; import { ResourcePolicy } from './resource-policy.model'; import { RESOURCE_POLICY } from './resource-policy.resource-type'; +import { COMMUNITY } from './community.resource-type'; +import { Community } from './community.model'; +import { ChildHALResource } from './child-hal-resource.model'; @typedObject @inheritSerialization(DSpaceObject) -export class Collection extends DSpaceObject { +export class Collection extends DSpaceObject implements ChildHALResource { static type = COLLECTION; /** @@ -35,6 +38,7 @@ export class Collection extends DSpaceObject { itemtemplate: HALLink; defaultAccessConditions: HALLink; logo: HALLink; + parentCommunity: HALLink; self: HALLink; }; @@ -59,6 +63,13 @@ export class Collection extends DSpaceObject { @link(RESOURCE_POLICY, true) defaultAccessConditions?: Observable>>; + /** + * The Community that is a direct parent of this Collection + * Will be undefined unless the parent community HALLink has been resolved. + */ + @link(COMMUNITY, false) + parentCommunity?: Observable>; + /** * The introductory text of this Collection * Corresponds to the metadata field dc.description @@ -98,4 +109,8 @@ export class Collection extends DSpaceObject { get sidebarText(): string { return this.firstMetadataValue('dc.description.tableofcontents'); } + + getParentLinkKey(): keyof this['_links'] { + return 'parentCommunity'; + } } diff --git a/src/app/core/shared/community.model.ts b/src/app/core/shared/community.model.ts index 703c4b3eef..e18ec743e8 100644 --- a/src/app/core/shared/community.model.ts +++ b/src/app/core/shared/community.model.ts @@ -10,10 +10,11 @@ import { COLLECTION } from './collection.resource-type'; import { COMMUNITY } from './community.resource-type'; import { DSpaceObject } from './dspace-object.model'; import { HALLink } from './hal-link.model'; +import { ChildHALResource } from './child-hal-resource.model'; @typedObject @inheritSerialization(DSpaceObject) -export class Community extends DSpaceObject { +export class Community extends DSpaceObject implements ChildHALResource { static type = COMMUNITY; /** @@ -30,6 +31,7 @@ export class Community extends DSpaceObject { collections: HALLink; logo: HALLink; subcommunities: HALLink; + parentCommunity: HALLink; self: HALLink; }; @@ -54,6 +56,13 @@ export class Community extends DSpaceObject { @link(COMMUNITY, true) subcommunities?: Observable>>; + /** + * The Community that is a direct parent of this Community + * Will be undefined unless the parent community HALLink has been resolved. + */ + @link(COMMUNITY, false) + parentCommunity?: Observable>; + /** * The introductory text of this Community * Corresponds to the metadata field dc.description @@ -85,4 +94,8 @@ export class Community extends DSpaceObject { get sidebarText(): string { return this.firstMetadataValue('dc.description.tableofcontents'); } + + getParentLinkKey(): keyof this['_links'] { + return 'parentCommunity'; + } } diff --git a/src/app/core/shared/item.model.ts b/src/app/core/shared/item.model.ts index 3fd35280da..e7f0ae9e10 100644 --- a/src/app/core/shared/item.model.ts +++ b/src/app/core/shared/item.model.ts @@ -17,13 +17,14 @@ import { HALLink } from './hal-link.model'; import { Relationship } from './item-relationships/relationship.model'; import { RELATIONSHIP } from './item-relationships/relationship.resource-type'; import { ITEM } from './item.resource-type'; +import { ChildHALResource } from './child-hal-resource.model'; /** * Class representing a DSpace Item */ @typedObject @inheritSerialization(DSpaceObject) -export class Item extends DSpaceObject { +export class Item extends DSpaceObject implements ChildHALResource { static type = ITEM; /** @@ -100,4 +101,8 @@ export class Item extends DSpaceObject { } return [entityType, ...super.getRenderTypes()]; } + + getParentLinkKey(): keyof this['_links'] { + return 'owningCollection'; + } } From f67387ed65984ff93783bd72b0632ec4aafa1416 Mon Sep 17 00:00:00 2001 From: lotte Date: Mon, 24 Feb 2020 16:06:12 +0100 Subject: [PATCH 04/32] first draft breadcrumbs --- .../collection-item-mapper.component.ts | 2 +- .../collection-page-routing.module.ts | 70 +++++---- .../collection-page.component.ts | 2 +- .../edit-collection-page.routing.module.ts | 7 - .../community-page-routing.module.ts | 55 ++++--- .../community-page.component.ts | 2 +- .../edit-community-page.routing.module.ts | 6 - .../edit-item-page.routing.module.ts | 141 ++++++++---------- .../+item-page/item-page-routing.module.ts | 41 ++--- .../+login-page/login-page-routing.module.ts | 6 +- .../search-page-routing.module.ts | 13 +- .../breadcrumbs/breadcrumbs.component.html | 7 +- src/app/breadcrumbs/breadcrumbs.component.ts | 8 +- .../breadcrumbs/dso-breadcrumb.resolver.ts | 2 +- .../breadcrumbs/dso-breadcrumbs.service.ts | 2 +- .../builders/remote-data-build.service.ts | 15 +- src/app/core/data/remote-data.ts | 9 +- 17 files changed, 197 insertions(+), 191 deletions(-) diff --git a/src/app/+collection-page/collection-item-mapper/collection-item-mapper.component.ts b/src/app/+collection-page/collection-item-mapper/collection-item-mapper.component.ts index ec384df641..64ad426584 100644 --- a/src/app/+collection-page/collection-item-mapper/collection-item-mapper.component.ts +++ b/src/app/+collection-page/collection-item-mapper/collection-item-mapper.component.ts @@ -102,7 +102,7 @@ export class CollectionItemMapperComponent implements OnInit { } ngOnInit(): void { - this.collectionRD$ = this.route.data.pipe(map((data) => data.collection)).pipe(getSucceededRemoteData()) as Observable>; + this.collectionRD$ = this.route.data.pipe(map((data) => data.dso)).pipe(getSucceededRemoteData()) as Observable>; this.searchOptions$ = this.searchConfigService.paginatedSearchOptions; this.loadItemLists(); } diff --git a/src/app/+collection-page/collection-page-routing.module.ts b/src/app/+collection-page/collection-page-routing.module.ts index 2df7997e1e..4bd23f4f95 100644 --- a/src/app/+collection-page/collection-page-routing.module.ts +++ b/src/app/+collection-page/collection-page-routing.module.ts @@ -10,6 +10,9 @@ import { DeleteCollectionPageComponent } from './delete-collection-page/delete-c import { URLCombiner } from '../core/url-combiner/url-combiner'; import { getCollectionModulePath } from '../app-routing.module'; import { CollectionItemMapperComponent } from './collection-item-mapper/collection-item-mapper.component'; +import { CollectionBreadcrumbResolver } from '../core/breadcrumbs/collection-breadcrumb.resolver'; +import { DSOBreadcrumbsService } from '../core/breadcrumbs/dso-breadcrumbs.service'; +import { LinkService } from '../core/cache/builders/link.service'; export const COLLECTION_PARENT_PARAMETER = 'parent'; @@ -26,51 +29,54 @@ export function getCollectionCreatePath() { } const COLLECTION_CREATE_PATH = 'create'; -const COLLECTION_EDIT_PATH = ':id/edit'; +const COLLECTION_EDIT_PATH = 'edit'; @NgModule({ imports: [ RouterModule.forChild([ + { + path: ':id', + resolve: { + dso: CollectionPageResolver, + breadcrumb: CollectionBreadcrumbResolver + }, + children: [ + { + path: COLLECTION_EDIT_PATH, + loadChildren: './edit-collection-page/edit-collection-page.module#EditCollectionPageModule', + canActivate: [AuthenticatedGuard] + }, + { + path: 'delete', + pathMatch: 'full', + component: DeleteCollectionPageComponent, + canActivate: [AuthenticatedGuard], + }, + { + path: '', + component: CollectionPageComponent, + pathMatch: 'full', + }, + { + path: '/edit/mapper', + component: CollectionItemMapperComponent, + pathMatch: 'full', + canActivate: [AuthenticatedGuard] + } + ] + }, { path: COLLECTION_CREATE_PATH, component: CreateCollectionPageComponent, canActivate: [AuthenticatedGuard, CreateCollectionPageGuard] }, - { - path: COLLECTION_EDIT_PATH, - loadChildren: './edit-collection-page/edit-collection-page.module#EditCollectionPageModule', - canActivate: [AuthenticatedGuard] - }, - { - path: ':id/delete', - pathMatch: 'full', - component: DeleteCollectionPageComponent, - canActivate: [AuthenticatedGuard], - resolve: { - dso: CollectionPageResolver - } - }, - { - path: ':id', - component: CollectionPageComponent, - pathMatch: 'full', - resolve: { - collection: CollectionPageResolver - } - }, - { - path: ':id/edit/mapper', - component: CollectionItemMapperComponent, - pathMatch: 'full', - resolve: { - collection: CollectionPageResolver - }, - canActivate: [AuthenticatedGuard] - } ]) ], providers: [ CollectionPageResolver, + CollectionBreadcrumbResolver, + DSOBreadcrumbsService, + LinkService, CreateCollectionPageGuard ] }) diff --git a/src/app/+collection-page/collection-page.component.ts b/src/app/+collection-page/collection-page.component.ts index 4866cf3b60..7f54e0f9d7 100644 --- a/src/app/+collection-page/collection-page.component.ts +++ b/src/app/+collection-page/collection-page.component.ts @@ -62,7 +62,7 @@ export class CollectionPageComponent implements OnInit { ngOnInit(): void { this.collectionRD$ = this.route.data.pipe( - map((data) => data.collection as RemoteData), + map((data) => data.dso as RemoteData), redirectToPageNotFoundOn404(this.router), take(1) ); diff --git a/src/app/+collection-page/edit-collection-page/edit-collection-page.routing.module.ts b/src/app/+collection-page/edit-collection-page/edit-collection-page.routing.module.ts index fcfced9d81..4498198e8d 100644 --- a/src/app/+collection-page/edit-collection-page/edit-collection-page.routing.module.ts +++ b/src/app/+collection-page/edit-collection-page/edit-collection-page.routing.module.ts @@ -1,7 +1,6 @@ import { RouterModule } from '@angular/router'; import { NgModule } from '@angular/core'; import { EditCollectionPageComponent } from './edit-collection-page.component'; -import { CollectionPageResolver } from '../collection-page.resolver'; import { CollectionMetadataComponent } from './collection-metadata/collection-metadata.component'; import { CollectionRolesComponent } from './collection-roles/collection-roles.component'; import { CollectionSourceComponent } from './collection-source/collection-source.component'; @@ -16,9 +15,6 @@ import { CollectionCurateComponent } from './collection-curate/collection-curate { path: '', component: EditCollectionPageComponent, - resolve: { - dso: CollectionPageResolver - }, children: [ { path: '', @@ -51,9 +47,6 @@ import { CollectionCurateComponent } from './collection-curate/collection-curate ] } ]) - ], - providers: [ - CollectionPageResolver, ] }) export class EditCollectionPageRoutingModule { diff --git a/src/app/+community-page/community-page-routing.module.ts b/src/app/+community-page/community-page-routing.module.ts index df548e0617..7ee71034a6 100644 --- a/src/app/+community-page/community-page-routing.module.ts +++ b/src/app/+community-page/community-page-routing.module.ts @@ -9,6 +9,9 @@ import { CreateCommunityPageGuard } from './create-community-page/create-communi import { DeleteCommunityPageComponent } from './delete-community-page/delete-community-page.component'; import { URLCombiner } from '../core/url-combiner/url-combiner'; import { getCommunityModulePath } from '../app-routing.module'; +import { CommunityBreadcrumbResolver } from '../core/breadcrumbs/community-breadcrumb.resolver'; +import { DSOBreadcrumbsService } from '../core/breadcrumbs/dso-breadcrumbs.service'; +import { LinkService } from '../core/cache/builders/link.service'; export const COMMUNITY_PARENT_PARAMETER = 'parent'; @@ -25,42 +28,48 @@ export function getCommunityCreatePath() { } const COMMUNITY_CREATE_PATH = 'create'; -const COMMUNITY_EDIT_PATH = ':id/edit'; +const COMMUNITY_EDIT_PATH = 'edit'; @NgModule({ imports: [ RouterModule.forChild([ + { + path: ':id', + resolve: { + dso: CommunityPageResolver, + breadcrumb: CommunityBreadcrumbResolver + }, + children: [ + { + path: COMMUNITY_EDIT_PATH, + loadChildren: './edit-community-page/edit-community-page.module#EditCommunityPageModule', + canActivate: [AuthenticatedGuard] + }, + { + path: 'delete', + pathMatch: 'full', + component: DeleteCommunityPageComponent, + canActivate: [AuthenticatedGuard], + }, + { + path: '', + component: CommunityPageComponent, + pathMatch: 'full', + } + ] + }, { path: COMMUNITY_CREATE_PATH, component: CreateCommunityPageComponent, canActivate: [AuthenticatedGuard, CreateCommunityPageGuard] }, - { - path: COMMUNITY_EDIT_PATH, - loadChildren: './edit-community-page/edit-community-page.module#EditCommunityPageModule', - canActivate: [AuthenticatedGuard] - }, - { - path: ':id/delete', - pathMatch: 'full', - component: DeleteCommunityPageComponent, - canActivate: [AuthenticatedGuard], - resolve: { - dso: CommunityPageResolver - } - }, - { - path: ':id', - component: CommunityPageComponent, - pathMatch: 'full', - resolve: { - community: CommunityPageResolver - } - } ]) ], providers: [ CommunityPageResolver, + CommunityBreadcrumbResolver, + DSOBreadcrumbsService, + LinkService, CreateCommunityPageGuard ] }) diff --git a/src/app/+community-page/community-page.component.ts b/src/app/+community-page/community-page.component.ts index f337d70250..3621829927 100644 --- a/src/app/+community-page/community-page.component.ts +++ b/src/app/+community-page/community-page.component.ts @@ -46,7 +46,7 @@ export class CommunityPageComponent implements OnInit { ngOnInit(): void { this.communityRD$ = this.route.data.pipe( - map((data) => data.community as RemoteData), + map((data) => data.dso as RemoteData), redirectToPageNotFoundOn404(this.router) ); this.logoRD$ = this.communityRD$.pipe( diff --git a/src/app/+community-page/edit-community-page/edit-community-page.routing.module.ts b/src/app/+community-page/edit-community-page/edit-community-page.routing.module.ts index 1182db2de1..721a404f84 100644 --- a/src/app/+community-page/edit-community-page/edit-community-page.routing.module.ts +++ b/src/app/+community-page/edit-community-page/edit-community-page.routing.module.ts @@ -15,9 +15,6 @@ import { CommunityCurateComponent } from './community-curate/community-curate.co { path: '', component: EditCommunityPageComponent, - resolve: { - dso: CommunityPageResolver - }, children: [ { path: '', @@ -46,9 +43,6 @@ import { CommunityCurateComponent } from './community-curate/community-curate.co } ]) ], - providers: [ - CommunityPageResolver, - ] }) export class EditCommunityPageRoutingModule { diff --git a/src/app/+item-page/edit-item-page/edit-item-page.routing.module.ts b/src/app/+item-page/edit-item-page/edit-item-page.routing.module.ts index 1b386440c0..71d8f65568 100644 --- a/src/app/+item-page/edit-item-page/edit-item-page.routing.module.ts +++ b/src/app/+item-page/edit-item-page/edit-item-page.routing.module.ts @@ -13,6 +13,7 @@ import { ItemBitstreamsComponent } from './item-bitstreams/item-bitstreams.compo import { ItemCollectionMapperComponent } from './item-collection-mapper/item-collection-mapper.component'; import { ItemMoveComponent } from './item-move/item-move.component'; import { ItemRelationshipsComponent } from './item-relationships/item-relationships.component'; +import { I18nBreadcrumbResolver } from '../../core/breadcrumbs/i18n-breadcrumb.resolver'; const ITEM_EDIT_WITHDRAW_PATH = 'withdraw'; const ITEM_EDIT_REINSTATE_PATH = 'reinstate'; @@ -29,104 +30,88 @@ const ITEM_EDIT_MOVE_PATH = 'move'; RouterModule.forChild([ { path: '', - component: EditItemPageComponent, resolve: { - item: ItemPageResolver + breadcrumb: I18nBreadcrumbResolver }, + data: { breadcrumbKey: 'edit.item' }, children: [ { path: '', - redirectTo: 'status', - pathMatch: 'full' + component: EditItemPageComponent, + children: [ + { + path: '', + redirectTo: 'status', + pathMatch: 'full' + }, + { + path: 'status', + component: ItemStatusComponent, + data: { title: 'item.edit.tabs.status.title' } + }, + { + path: 'bitstreams', + component: ItemBitstreamsComponent, + data: { title: 'item.edit.tabs.bitstreams.title' } + }, + { + path: 'metadata', + component: ItemMetadataComponent, + data: { title: 'item.edit.tabs.metadata.title' } + }, + { + path: 'relationships', + component: ItemRelationshipsComponent, + data: { title: 'item.edit.tabs.relationships.title' } + }, + { + path: 'view', + /* TODO - change when view page exists */ + component: ItemBitstreamsComponent, + data: { title: 'item.edit.tabs.view.title' } + }, + { + path: 'curate', + /* TODO - change when curate page exists */ + component: ItemBitstreamsComponent, + data: { title: 'item.edit.tabs.curate.title' } + } + ] }, { - path: 'status', - component: ItemStatusComponent, - data: { title: 'item.edit.tabs.status.title' } + path: 'mapper', + component: ItemCollectionMapperComponent, }, { - path: 'bitstreams', - component: ItemBitstreamsComponent, - data: { title: 'item.edit.tabs.bitstreams.title' } + path: ITEM_EDIT_WITHDRAW_PATH, + component: ItemWithdrawComponent, }, { - path: 'metadata', - component: ItemMetadataComponent, - data: { title: 'item.edit.tabs.metadata.title' } + path: ITEM_EDIT_REINSTATE_PATH, + component: ItemReinstateComponent, }, { - path: 'relationships', - component: ItemRelationshipsComponent, - data: { title: 'item.edit.tabs.relationships.title' } + path: ITEM_EDIT_PRIVATE_PATH, + component: ItemPrivateComponent, }, { - path: 'view', - /* TODO - change when view page exists */ - component: ItemBitstreamsComponent, - data: { title: 'item.edit.tabs.view.title' } + path: ITEM_EDIT_PUBLIC_PATH, + component: ItemPublicComponent, }, { - path: 'curate', - /* TODO - change when curate page exists */ - component: ItemBitstreamsComponent, - data: { title: 'item.edit.tabs.curate.title' } + path: ITEM_EDIT_DELETE_PATH, + component: ItemDeleteComponent, }, + { + path: ITEM_EDIT_MOVE_PATH, + component: ItemMoveComponent, + data: { title: 'item.edit.move.title' }, + } ] - }, - { - path: 'mapper', - component: ItemCollectionMapperComponent, - resolve: { - item: ItemPageResolver - } - }, - { - path: ITEM_EDIT_WITHDRAW_PATH, - component: ItemWithdrawComponent, - resolve: { - item: ItemPageResolver - } - }, - { - path: ITEM_EDIT_REINSTATE_PATH, - component: ItemReinstateComponent, - resolve: { - item: ItemPageResolver - } - }, - { - path: ITEM_EDIT_PRIVATE_PATH, - component: ItemPrivateComponent, - resolve: { - item: ItemPageResolver - } - }, - { - path: ITEM_EDIT_PUBLIC_PATH, - component: ItemPublicComponent, - resolve: { - item: ItemPageResolver - } - }, - { - path: ITEM_EDIT_DELETE_PATH, - component: ItemDeleteComponent, - resolve: { - item: ItemPageResolver - } - }, - { - path: ITEM_EDIT_MOVE_PATH, - component: ItemMoveComponent, - data: { title: 'item.edit.move.title' }, - resolve: { - item: ItemPageResolver - } - }]) + } + ]) ], - providers: [ - ItemPageResolver, - ] + providers: [] }) export class EditItemPageRoutingModule { diff --git a/src/app/+item-page/item-page-routing.module.ts b/src/app/+item-page/item-page-routing.module.ts index d2ad39d70d..4ceece59d0 100644 --- a/src/app/+item-page/item-page-routing.module.ts +++ b/src/app/+item-page/item-page-routing.module.ts @@ -14,37 +14,39 @@ import { LinkService } from '../core/cache/builders/link.service'; export function getItemPageRoute(itemId: string) { return new URLCombiner(getItemModulePath(), itemId).toString(); } + export function getItemEditPath(id: string) { - return new URLCombiner(getItemModulePath(),ITEM_EDIT_PATH.replace(/:id/, id)).toString() + return new URLCombiner(getItemModulePath(), ITEM_EDIT_PATH.replace(/:id/, id)).toString() } -const ITEM_EDIT_PATH = ':id/edit'; +const ITEM_EDIT_PATH = 'edit'; @NgModule({ imports: [ RouterModule.forChild([ { path: ':id', - component: ItemPageComponent, - pathMatch: 'full', resolve: { item: ItemPageResolver, breadcrumb: ItemBreadcrumbResolver - } - }, - { - path: ':id/full', - component: FullItemPageComponent, - resolve: { - item: ItemPageResolver, - breadcrumb: ItemBreadcrumbResolver - } - }, - { - path: ITEM_EDIT_PATH, - loadChildren: './edit-item-page/edit-item-page.module#EditItemPageModule', - canActivate: [AuthenticatedGuard] - }, + }, + children: [ + { + path: '', + component: ItemPageComponent, + pathMatch: 'full', + }, + { + path: 'full', + component: FullItemPageComponent, + }, + { + path: ITEM_EDIT_PATH, + loadChildren: './edit-item-page/edit-item-page.module#EditItemPageModule', + canActivate: [AuthenticatedGuard] + } + ], + } ]) ], providers: [ @@ -53,6 +55,7 @@ const ITEM_EDIT_PATH = ':id/edit'; DSOBreadcrumbsService, LinkService ] + }) export class ItemPageRoutingModule { diff --git a/src/app/+login-page/login-page-routing.module.ts b/src/app/+login-page/login-page-routing.module.ts index d3c6425dd3..950ac44d8c 100644 --- a/src/app/+login-page/login-page-routing.module.ts +++ b/src/app/+login-page/login-page-routing.module.ts @@ -2,12 +2,14 @@ import { NgModule } from '@angular/core'; import { RouterModule } from '@angular/router'; import { LoginPageComponent } from './login-page.component'; +import { I18nBreadcrumbResolver } from '../core/breadcrumbs/i18n-breadcrumb.resolver'; @NgModule({ imports: [ RouterModule.forChild([ - { path: '', pathMatch: 'full', component: LoginPageComponent, data: { title: 'login.title' } } + { path: '', pathMatch: 'full', component: LoginPageComponent, resolve: { breadcrumb: I18nBreadcrumbResolver }, data: { breadcrumbKey: 'Search', title: 'login.title' } } ]) ] }) -export class LoginPageRoutingModule { } +export class LoginPageRoutingModule { +} diff --git a/src/app/+search-page/search-page-routing.module.ts b/src/app/+search-page/search-page-routing.module.ts index 463aa8e7c4..c76207da9b 100644 --- a/src/app/+search-page/search-page-routing.module.ts +++ b/src/app/+search-page/search-page-routing.module.ts @@ -9,10 +9,15 @@ import { I18nBreadcrumbsService } from '../core/breadcrumbs/i18n-breadcrumbs.ser @NgModule({ imports: [ - RouterModule.forChild([ - { path: '', component: SearchPageComponent, resolve: { breadcrumb: I18nBreadcrumbResolver }, data: { title: 'search.title', breadcrumbKey: 'Search' } }, - { path: ':configuration', component: ConfigurationSearchPageComponent, canActivate: [ConfigurationSearchPageGuard] } - ]) + RouterModule.forChild([{ + path: '', + resolve: { breadcrumb: I18nBreadcrumbResolver }, data: { title: 'search.title', breadcrumbKey: 'Search' }, + children: [ + { path: '', component: SearchPageComponent }, + { path: ':configuration', component: ConfigurationSearchPageComponent, canActivate: [ConfigurationSearchPageGuard] } + ] + }] + ) ], providers: [ I18nBreadcrumbResolver, diff --git a/src/app/breadcrumbs/breadcrumbs.component.html b/src/app/breadcrumbs/breadcrumbs.component.html index 3a8730ea30..b773964d1e 100644 --- a/src/app/breadcrumbs/breadcrumbs.component.html +++ b/src/app/breadcrumbs/breadcrumbs.component.html @@ -1,16 +1,17 @@ - + - + + diff --git a/src/app/breadcrumbs/breadcrumbs.component.ts b/src/app/breadcrumbs/breadcrumbs.component.ts index 944af9b55d..fc3527a241 100644 --- a/src/app/breadcrumbs/breadcrumbs.component.ts +++ b/src/app/breadcrumbs/breadcrumbs.component.ts @@ -32,13 +32,17 @@ export class BreadcrumbsComponent implements OnDestroy { resolveBreadcrumb(route: ActivatedRoute): Observable { const data = route.snapshot.data; - const last: boolean = route.children.length === 0; + const routeConfig = route.snapshot.routeConfig; + const last: boolean = route.children.length === 0; if (last && isNotUndefined(data.showBreadcrumbs)) { this.showBreadcrumbs = data.showBreadcrumbs; } - if (hasValue(data) && hasValue(data.breadcrumb)) { + if ( + hasValue(data) && hasValue(data.breadcrumb) && + hasValue(routeConfig) && hasValue(routeConfig.resolve) && hasValue(routeConfig.resolve.breadcrumb) + ) { const { provider, key, url } = data.breadcrumb; if (!last) { return combineLatest(provider.getBreadcrumbs(key, url), this.resolveBreadcrumb(route.firstChild)) diff --git a/src/app/core/breadcrumbs/dso-breadcrumb.resolver.ts b/src/app/core/breadcrumbs/dso-breadcrumb.resolver.ts index 6e90d8d123..2f4138d144 100644 --- a/src/app/core/breadcrumbs/dso-breadcrumb.resolver.ts +++ b/src/app/core/breadcrumbs/dso-breadcrumb.resolver.ts @@ -29,7 +29,7 @@ export class DSOBreadcrumbResolver im getSucceededRemoteData(), getRemoteDataPayload(), map((object: T) => { - const fullPath = route.url.join(''); + const fullPath = state.url; const url = fullPath.substr(0, fullPath.indexOf(uuid)) + uuid; return { provider: this.breadcrumbService, key: object, url: url }; }) diff --git a/src/app/core/breadcrumbs/dso-breadcrumbs.service.ts b/src/app/core/breadcrumbs/dso-breadcrumbs.service.ts index 30344a3a77..0e6af2291b 100644 --- a/src/app/core/breadcrumbs/dso-breadcrumbs.service.ts +++ b/src/app/core/breadcrumbs/dso-breadcrumbs.service.ts @@ -21,7 +21,7 @@ export class DSOBreadcrumbsService implements BreadcrumbsService) => childRD.isSuccessful === true && childRD.requestPending === false && childRD.responsePending === false), + find((childRD: RemoteData) => childRD.hasSucceeded || childRD.statusCode === 204), switchMap((childRD: RemoteData) => { if (hasValue(childRD.payload)) { const child = childRD.payload; diff --git a/src/app/core/cache/builders/remote-data-build.service.ts b/src/app/core/cache/builders/remote-data-build.service.ts index 94c660d672..df895e11a2 100644 --- a/src/app/core/cache/builders/remote-data-build.service.ts +++ b/src/app/core/cache/builders/remote-data-build.service.ts @@ -96,13 +96,14 @@ export class RemoteDataBuildService { const responsePending = hasValue(reqEntry) && hasValue(reqEntry.responsePending) ? reqEntry.responsePending : false; let isSuccessful: boolean; let error: RemoteDataError; - if (hasValue(reqEntry) && hasValue(reqEntry.response)) { - isSuccessful = reqEntry.response.isSuccessful; - const errorMessage = isSuccessful === false ? (reqEntry.response as ErrorResponse).errorMessage : undefined; + const response = reqEntry ? reqEntry.response : undefined; + if (hasValue(response)) { + isSuccessful = response.isSuccessful; + const errorMessage = isSuccessful === false ? (response as ErrorResponse).errorMessage : undefined; if (hasValue(errorMessage)) { error = new RemoteDataError( - (reqEntry.response as ErrorResponse).statusCode, - (reqEntry.response as ErrorResponse).statusText, + response.statusCode, + response.statusText, errorMessage ); } @@ -112,7 +113,9 @@ export class RemoteDataBuildService { responsePending, isSuccessful, error, - payload + payload, + hasValue(response) ? response.statusCode : undefined + ); }) ); diff --git a/src/app/core/data/remote-data.ts b/src/app/core/data/remote-data.ts index 4397464055..8502c8ba1d 100644 --- a/src/app/core/data/remote-data.ts +++ b/src/app/core/data/remote-data.ts @@ -13,11 +13,12 @@ export enum RemoteDataState { */ export class RemoteData { constructor( - public requestPending?: boolean, - public responsePending?: boolean, - public isSuccessful?: boolean, + private requestPending?: boolean, + private responsePending?: boolean, + private isSuccessful?: boolean, public error?: RemoteDataError, - public payload?: T + public payload?: T, + public statusCode?: number, ) { } From 5b326aea92590c47cb1c2c80cf0bc407a235274f Mon Sep 17 00:00:00 2001 From: Art Lowel Date: Wed, 26 Feb 2020 13:58:09 +0100 Subject: [PATCH 05/32] add DSONameService --- .../breadcrumbs/dso-breadcrumbs.service.ts | 11 +- .../core/breadcrumbs/dso-name.service.spec.ts | 116 ++++++++++++++++++ src/app/core/breadcrumbs/dso-name.service.ts | 53 ++++++++ src/app/core/cache/builders/link.service.ts | 20 +-- src/app/core/metadata/metadata.service.ts | 4 +- src/app/core/shared/dspace-object.model.ts | 1 + 6 files changed, 193 insertions(+), 12 deletions(-) create mode 100644 src/app/core/breadcrumbs/dso-name.service.spec.ts create mode 100644 src/app/core/breadcrumbs/dso-name.service.ts diff --git a/src/app/core/breadcrumbs/dso-breadcrumbs.service.ts b/src/app/core/breadcrumbs/dso-breadcrumbs.service.ts index 0e6af2291b..eaf1fed759 100644 --- a/src/app/core/breadcrumbs/dso-breadcrumbs.service.ts +++ b/src/app/core/breadcrumbs/dso-breadcrumbs.service.ts @@ -1,11 +1,12 @@ import { Breadcrumb } from '../../breadcrumbs/breadcrumb/breadcrumb.model'; import { BreadcrumbsService } from './breadcrumbs.service'; +import { DSONameService } from './dso-name.service'; import { Observable, of as observableOf } from 'rxjs'; import { ChildHALResource } from '../shared/child-hal-resource.model'; import { LinkService } from '../cache/builders/link.service'; import { DSpaceObject } from '../shared/dspace-object.model'; import { followLink } from '../../shared/utils/follow-link-config.model'; -import { filter, find, map, switchMap } from 'rxjs/operators'; +import { find, map, switchMap } from 'rxjs/operators'; import { getDSOPath } from '../../app-routing.module'; import { RemoteData } from '../data/remote-data'; import { hasValue } from '../../shared/empty.util'; @@ -13,12 +14,16 @@ import { Injectable } from '@angular/core'; @Injectable() export class DSOBreadcrumbsService implements BreadcrumbsService { - constructor(private linkService: LinkService) { + constructor( + private linkService: LinkService, + private dsoNameService: DSONameService + ) { } getBreadcrumbs(key: ChildHALResource & DSpaceObject, url: string): Observable { - const crumb = new Breadcrumb(key.name, url); + const label = this.dsoNameService.getName(key); + const crumb = new Breadcrumb(label, url); const propertyName = key.getParentLinkKey(); return this.linkService.resolveLink(key, followLink(propertyName))[propertyName].pipe( find((childRD: RemoteData) => childRD.hasSucceeded || childRD.statusCode === 204), diff --git a/src/app/core/breadcrumbs/dso-name.service.spec.ts b/src/app/core/breadcrumbs/dso-name.service.spec.ts new file mode 100644 index 0000000000..aa06116ed5 --- /dev/null +++ b/src/app/core/breadcrumbs/dso-name.service.spec.ts @@ -0,0 +1,116 @@ +import { ListableObject } from '../../shared/object-collection/shared/listable-object.model'; +import { DSpaceObject } from '../shared/dspace-object.model'; +import { GenericConstructor } from '../shared/generic-constructor'; +import { Item } from '../shared/item.model'; +import { MetadataValueFilter } from '../shared/metadata.models'; +import { DSONameService } from './dso-name.service'; + +describe(`DSONameService`, () => { + let service: DSONameService; + let mockPersonName: string; + let mockPerson: DSpaceObject; + let mockOrgUnitName: string; + let mockOrgUnit: DSpaceObject; + let mockDSOName: string; + let mockDSO: DSpaceObject; + + beforeEach(() => { + mockPersonName = 'Doe, John'; + mockPerson = Object.assign(new DSpaceObject(), { + firstMetadataValue(keyOrKeys: string | string[], valueFilter?: MetadataValueFilter): string { + return mockPersonName + }, + getRenderTypes(): Array> { + return ['Person', Item, DSpaceObject]; + } + }); + + mockOrgUnitName = 'Molecular Spectroscopy'; + mockOrgUnit = Object.assign(new DSpaceObject(), { + firstMetadataValue(keyOrKeys: string | string[], valueFilter?: MetadataValueFilter): string { + return mockOrgUnitName + }, + getRenderTypes(): Array> { + return ['OrgUnit', Item, DSpaceObject]; + } + }); + + mockDSOName = 'Lorem Ipsum'; + mockDSO = Object.assign(new DSpaceObject(), { + firstMetadataValue(keyOrKeys: string | string[], valueFilter?: MetadataValueFilter): string { + return mockDSOName + }, + getRenderTypes(): Array> { + return [DSpaceObject]; + } + }); + + service = new DSONameService(); + }); + + describe(`getName`, () => { + it(`should use the Person factory for Person entities`, () => { + spyOn((service as any).factories, 'Person').and.returnValue('Bingo!'); + + const result = service.getName(mockPerson); + + expect((service as any).factories.Person).toHaveBeenCalledWith(mockPerson); + expect(result).toBe('Bingo!'); + }); + + it(`should use the OrgUnit factory for OrgUnit entities`, () => { + spyOn((service as any).factories, 'OrgUnit').and.returnValue('Bingo!'); + + const result = service.getName(mockOrgUnit); + + expect((service as any).factories.OrgUnit).toHaveBeenCalledWith(mockOrgUnit); + expect(result).toBe('Bingo!'); + }); + + it(`should use the Default factory for regular DSpaceObjects`, () => { + spyOn((service as any).factories, 'Default').and.returnValue('Bingo!'); + + const result = service.getName(mockDSO); + + expect((service as any).factories.Default).toHaveBeenCalledWith(mockDSO); + expect(result).toBe('Bingo!'); + }); + }); + + describe(`factories.Person`, () => { + beforeEach(() => { + spyOn(mockPerson, 'firstMetadataValue').and.returnValues(...mockPersonName.split(', ')); + }); + + it(`should return 'person.familyName, person.givenName'`, () => { + const result = (service as any).factories.Person(mockPerson); + expect(result).toBe(mockPersonName); + expect(mockPerson.firstMetadataValue).toHaveBeenCalledWith('person.familyName'); + expect(mockPerson.firstMetadataValue).toHaveBeenCalledWith('person.givenName'); + }); + }); + + describe(`factories.OrgUnit`, () => { + beforeEach(() => { + spyOn(mockOrgUnit, 'firstMetadataValue').and.callThrough(); + }); + + it(`should return 'organization.legalName'`, () => { + const result = (service as any).factories.OrgUnit(mockOrgUnit); + expect(result).toBe(mockOrgUnitName); + expect(mockOrgUnit.firstMetadataValue).toHaveBeenCalledWith('organization.legalName'); + }); + }); + + describe(`factories.Default`, () => { + beforeEach(() => { + spyOn(mockDSO, 'firstMetadataValue').and.callThrough(); + }); + + it(`should return 'dc.title'`, () => { + const result = (service as any).factories.Default(mockDSO); + expect(result).toBe(mockDSOName); + expect(mockDSO.firstMetadataValue).toHaveBeenCalledWith('dc.title'); + }); + }); +}); diff --git a/src/app/core/breadcrumbs/dso-name.service.ts b/src/app/core/breadcrumbs/dso-name.service.ts new file mode 100644 index 0000000000..161c4f7254 --- /dev/null +++ b/src/app/core/breadcrumbs/dso-name.service.ts @@ -0,0 +1,53 @@ +import { Injectable } from '@angular/core'; +import { hasValue } from '../../shared/empty.util'; +import { DSpaceObject } from '../shared/dspace-object.model'; + +/** + * Returns a name for a {@link DSpaceObject} based + * on its render types. + */ +@Injectable({ + providedIn: 'root' +}) +export class DSONameService { + + /** + * Functions to generate the specific names. + * + * If this list ever expands it will probably be worth it to + * refactor this using decorators for specific entity types, + * or perhaps by using a dedicated model for each entity type + * + * With only two exceptions those solutions seem overkill for now. + */ + private factories = { + Person: (dso: DSpaceObject): string => { + return `${dso.firstMetadataValue('person.familyName')}, ${dso.firstMetadataValue('person.givenName')}`; + }, + OrgUnit: (dso: DSpaceObject): string => { + return dso.firstMetadataValue('organization.legalName'); + }, + Default: (dso: DSpaceObject): string => { + return dso.firstMetadataValue('dc.title'); + } + }; + + /** + * Get the name for the given {@link DSpaceObject} + * + * @param dso The {@link DSpaceObject} you want a name for + */ + getName(dso: DSpaceObject): string { + const types = dso.getRenderTypes(); + const match = types + .filter((type) => typeof type === 'string') + .find((type: string) => Object.keys(this.factories).includes(type)) as string; + + if (hasValue(match)) { + return this.factories[match](dso); + } else { + return this.factories.Default(dso); + } + } + +} diff --git a/src/app/core/cache/builders/link.service.ts b/src/app/core/cache/builders/link.service.ts index c41a5484a1..e57adaa598 100644 --- a/src/app/core/cache/builders/link.service.ts +++ b/src/app/core/cache/builders/link.service.ts @@ -55,16 +55,20 @@ export class LinkService { parent: this.parentInjector }).get(provider); - const href = model._links[matchingLinkDef.linkName].href; + const link = model._links[matchingLinkDef.linkName]; - try { - if (matchingLinkDef.isList) { - model[linkToFollow.name] = service.findAllByHref(href, linkToFollow.findListOptions, ...linkToFollow.linksToFollow); - } else { - model[linkToFollow.name] = service.findByHref(href, ...linkToFollow.linksToFollow); + if (hasValue(link)) { + const href = link.href; + + try { + if (matchingLinkDef.isList) { + model[linkToFollow.name] = service.findAllByHref(href, linkToFollow.findListOptions, ...linkToFollow.linksToFollow); + } else { + model[linkToFollow.name] = service.findByHref(href, ...linkToFollow.linksToFollow); + } + } catch (e) { + throw new Error(`Something went wrong when using @dataService(${matchingLinkDef.resourceType.value}) ${hasValue(service) ? '' : '(undefined) '}to resolve link ${linkToFollow.name} from ${href}`); } - } catch (e) { - throw new Error(`Something went wrong when using @dataService(${matchingLinkDef.resourceType.value}) ${hasValue(service) ? '' : '(undefined) '}to resolve link ${linkToFollow.name} from ${href}`); } } return model; diff --git a/src/app/core/metadata/metadata.service.ts b/src/app/core/metadata/metadata.service.ts index 1417005b9d..dbba9d83f6 100644 --- a/src/app/core/metadata/metadata.service.ts +++ b/src/app/core/metadata/metadata.service.ts @@ -10,6 +10,7 @@ import { catchError, distinctUntilKeyChanged, filter, first, map, take } from 'r import { GLOBAL_CONFIG, GlobalConfig } from '../../../config'; import { hasValue, isNotEmpty } from '../../shared/empty.util'; +import { DSONameService } from '../breadcrumbs/dso-name.service'; import { CacheableObject } from '../cache/object-cache.reducer'; import { BitstreamDataService } from '../data/bitstream-data.service'; import { BitstreamFormatDataService } from '../data/bitstream-format-data.service'; @@ -35,6 +36,7 @@ export class MetadataService { private translate: TranslateService, private meta: Meta, private title: Title, + private dsoNameService: DSONameService, private bitstreamDataService: BitstreamDataService, private bitstreamFormatDataService: BitstreamFormatDataService, @Inject(GLOBAL_CONFIG) private envConfig: GlobalConfig @@ -154,7 +156,7 @@ export class MetadataService { * Add to the */ private setTitleTag(): void { - const value = this.getMetaTagValue('dc.title'); + const value = this.dsoNameService.getName(this.currentObject.getValue()); this.addMetaTag('title', value); this.title.setTitle(value); } diff --git a/src/app/core/shared/dspace-object.model.ts b/src/app/core/shared/dspace-object.model.ts index 2e1afe9c8a..60a1160d3e 100644 --- a/src/app/core/shared/dspace-object.model.ts +++ b/src/app/core/shared/dspace-object.model.ts @@ -69,6 +69,7 @@ export class DSpaceObject extends ListableObject implements CacheableObject { /** * The name for this DSpaceObject + * @deprecated use {@link DSONameService} instead */ get name(): string { return (isUndefined(this._name)) ? this.firstMetadataValue('dc.title') : this._name; From b4a63fccf4501eae550403215122f01fd378a29f Mon Sep 17 00:00:00 2001 From: Art Lowel Date: Wed, 26 Feb 2020 14:17:27 +0100 Subject: [PATCH 06/32] rollback debug change --- src/app/core/cache/builders/link.service.ts | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/src/app/core/cache/builders/link.service.ts b/src/app/core/cache/builders/link.service.ts index e57adaa598..c41a5484a1 100644 --- a/src/app/core/cache/builders/link.service.ts +++ b/src/app/core/cache/builders/link.service.ts @@ -55,20 +55,16 @@ export class LinkService { parent: this.parentInjector }).get(provider); - const link = model._links[matchingLinkDef.linkName]; + const href = model._links[matchingLinkDef.linkName].href; - if (hasValue(link)) { - const href = link.href; - - try { - if (matchingLinkDef.isList) { - model[linkToFollow.name] = service.findAllByHref(href, linkToFollow.findListOptions, ...linkToFollow.linksToFollow); - } else { - model[linkToFollow.name] = service.findByHref(href, ...linkToFollow.linksToFollow); - } - } catch (e) { - throw new Error(`Something went wrong when using @dataService(${matchingLinkDef.resourceType.value}) ${hasValue(service) ? '' : '(undefined) '}to resolve link ${linkToFollow.name} from ${href}`); + try { + if (matchingLinkDef.isList) { + model[linkToFollow.name] = service.findAllByHref(href, linkToFollow.findListOptions, ...linkToFollow.linksToFollow); + } else { + model[linkToFollow.name] = service.findByHref(href, ...linkToFollow.linksToFollow); } + } catch (e) { + throw new Error(`Something went wrong when using @dataService(${matchingLinkDef.resourceType.value}) ${hasValue(service) ? '' : '(undefined) '}to resolve link ${linkToFollow.name} from ${href}`); } } return model; From 4ae8997ada3eb09929f04ab5825187694abf19cb Mon Sep 17 00:00:00 2001 From: lotte Date: Wed, 26 Feb 2020 14:44:34 +0100 Subject: [PATCH 07/32] added tests for breadcrumbs service and component --- resources/i18n/en.json5 | 8 ++ .../collection-page-routing.module.ts | 2 +- .../edit-collection-page.routing.module.ts | 5 + .../community-page-routing.module.ts | 2 +- .../edit-community-page.routing.module.ts | 5 + .../edit-item-page.routing.module.ts | 2 +- .../+item-page/item-page-routing.module.ts | 2 +- .../+login-page/login-page-routing.module.ts | 2 +- .../search-page-routing.module.ts | 2 +- .../breadcrumbs/breadcrumbs.component.spec.ts | 90 +++++++++++++- src/app/breadcrumbs/breadcrumbs.component.ts | 18 +-- .../collection-breadcrumb.resolver.ts | 2 - .../dso-breadcrumbs.service.spec.ts | 117 ++++++++++++++++++ .../breadcrumbs/dso-breadcrumbs.service.ts | 10 +- .../i18n-breadcrumbs.service.spec.ts | 31 +++++ .../breadcrumbs/i18n-breadcrumbs.service.ts | 4 +- .../comcol-page-browse-by.component.ts | 7 +- 17 files changed, 280 insertions(+), 29 deletions(-) create mode 100644 src/app/core/breadcrumbs/dso-breadcrumbs.service.spec.ts create mode 100644 src/app/core/breadcrumbs/i18n-breadcrumbs.service.spec.ts diff --git a/resources/i18n/en.json5 b/resources/i18n/en.json5 index 8d956d1a0e..044cf216b8 100644 --- a/resources/i18n/en.json5 +++ b/resources/i18n/en.json5 @@ -266,6 +266,8 @@ "collection.edit.head": "Edit Collection", + "collection.edit.breadcrumbs": "Edit Collection", + "collection.edit.item-mapper.cancel": "Cancel", @@ -450,6 +452,7 @@ "community.edit.head": "Edit Community", + "community.edit.breadcrumbs": "Edit Community", "community.edit.logo.label": "Community logo", @@ -657,6 +660,8 @@ "item.edit.head": "Edit Item", + "item.edit.breadcrumbs": "Edit Item", + "item.edit.item-mapper.buttons.add": "Map item to selected collections", @@ -1077,6 +1082,8 @@ "login.title": "Login", + "login.breadcrumbs": "Login", + "logout.form.header": "Log out from DSpace", @@ -1473,6 +1480,7 @@ "search.title": "DSpace Angular :: Search", + "search.breadcrumbs": "Search", "search.filters.applied.f.author": "Author", diff --git a/src/app/+collection-page/collection-page-routing.module.ts b/src/app/+collection-page/collection-page-routing.module.ts index 4bd23f4f95..61cfda0d9e 100644 --- a/src/app/+collection-page/collection-page-routing.module.ts +++ b/src/app/+collection-page/collection-page-routing.module.ts @@ -21,7 +21,7 @@ export function getCollectionPageRoute(collectionId: string) { } export function getCollectionEditPath(id: string) { - return new URLCombiner(getCollectionModulePath(), COLLECTION_EDIT_PATH.replace(/:id/, id)).toString() + return new URLCombiner(getCollectionModulePath(), id, COLLECTION_EDIT_PATH).toString() } export function getCollectionCreatePath() { diff --git a/src/app/+collection-page/edit-collection-page/edit-collection-page.routing.module.ts b/src/app/+collection-page/edit-collection-page/edit-collection-page.routing.module.ts index 4498198e8d..e3d5749472 100644 --- a/src/app/+collection-page/edit-collection-page/edit-collection-page.routing.module.ts +++ b/src/app/+collection-page/edit-collection-page/edit-collection-page.routing.module.ts @@ -5,6 +5,7 @@ import { CollectionMetadataComponent } from './collection-metadata/collection-me import { CollectionRolesComponent } from './collection-roles/collection-roles.component'; import { CollectionSourceComponent } from './collection-source/collection-source.component'; import { CollectionCurateComponent } from './collection-curate/collection-curate.component'; +import { I18nBreadcrumbResolver } from '../../core/breadcrumbs/i18n-breadcrumb.resolver'; /** * Routing module that handles the routing for the Edit Collection page administrator functionality @@ -14,6 +15,10 @@ import { CollectionCurateComponent } from './collection-curate/collection-curate RouterModule.forChild([ { path: '', + resolve: { + breadcrumb: I18nBreadcrumbResolver + }, + data: { breadcrumbKey: 'collection.edit' }, component: EditCollectionPageComponent, children: [ { diff --git a/src/app/+community-page/community-page-routing.module.ts b/src/app/+community-page/community-page-routing.module.ts index 7ee71034a6..976a4ad0fe 100644 --- a/src/app/+community-page/community-page-routing.module.ts +++ b/src/app/+community-page/community-page-routing.module.ts @@ -20,7 +20,7 @@ export function getCommunityPageRoute(communityId: string) { } export function getCommunityEditPath(id: string) { - return new URLCombiner(getCommunityModulePath(), COMMUNITY_EDIT_PATH.replace(/:id/, id)).toString() + return new URLCombiner(getCommunityModulePath(), id, COMMUNITY_EDIT_PATH).toString() } export function getCommunityCreatePath() { diff --git a/src/app/+community-page/edit-community-page/edit-community-page.routing.module.ts b/src/app/+community-page/edit-community-page/edit-community-page.routing.module.ts index 721a404f84..f0a7813bac 100644 --- a/src/app/+community-page/edit-community-page/edit-community-page.routing.module.ts +++ b/src/app/+community-page/edit-community-page/edit-community-page.routing.module.ts @@ -5,6 +5,7 @@ import { NgModule } from '@angular/core'; import { CommunityMetadataComponent } from './community-metadata/community-metadata.component'; import { CommunityRolesComponent } from './community-roles/community-roles.component'; import { CommunityCurateComponent } from './community-curate/community-curate.component'; +import { I18nBreadcrumbResolver } from '../../core/breadcrumbs/i18n-breadcrumb.resolver'; /** * Routing module that handles the routing for the Edit Community page administrator functionality @@ -14,6 +15,10 @@ import { CommunityCurateComponent } from './community-curate/community-curate.co RouterModule.forChild([ { path: '', + resolve: { + breadcrumb: I18nBreadcrumbResolver + }, + data: { breadcrumbKey: 'community.edit' }, component: EditCommunityPageComponent, children: [ { diff --git a/src/app/+item-page/edit-item-page/edit-item-page.routing.module.ts b/src/app/+item-page/edit-item-page/edit-item-page.routing.module.ts index 71d8f65568..af78eeea6f 100644 --- a/src/app/+item-page/edit-item-page/edit-item-page.routing.module.ts +++ b/src/app/+item-page/edit-item-page/edit-item-page.routing.module.ts @@ -33,7 +33,7 @@ const ITEM_EDIT_MOVE_PATH = 'move'; resolve: { breadcrumb: I18nBreadcrumbResolver }, - data: { breadcrumbKey: 'edit.item' }, + data: { breadcrumbKey: 'item.edit' }, children: [ { path: '', diff --git a/src/app/+item-page/item-page-routing.module.ts b/src/app/+item-page/item-page-routing.module.ts index 4ceece59d0..686c5ff2fc 100644 --- a/src/app/+item-page/item-page-routing.module.ts +++ b/src/app/+item-page/item-page-routing.module.ts @@ -16,7 +16,7 @@ export function getItemPageRoute(itemId: string) { } export function getItemEditPath(id: string) { - return new URLCombiner(getItemModulePath(), ITEM_EDIT_PATH.replace(/:id/, id)).toString() + return new URLCombiner(getItemModulePath(), id, ITEM_EDIT_PATH).toString() } const ITEM_EDIT_PATH = 'edit'; diff --git a/src/app/+login-page/login-page-routing.module.ts b/src/app/+login-page/login-page-routing.module.ts index 950ac44d8c..cd023da55c 100644 --- a/src/app/+login-page/login-page-routing.module.ts +++ b/src/app/+login-page/login-page-routing.module.ts @@ -7,7 +7,7 @@ import { I18nBreadcrumbResolver } from '../core/breadcrumbs/i18n-breadcrumb.reso @NgModule({ imports: [ RouterModule.forChild([ - { path: '', pathMatch: 'full', component: LoginPageComponent, resolve: { breadcrumb: I18nBreadcrumbResolver }, data: { breadcrumbKey: 'Search', title: 'login.title' } } + { path: '', pathMatch: 'full', component: LoginPageComponent, resolve: { breadcrumb: I18nBreadcrumbResolver }, data: { breadcrumbKey: 'login', title: 'login.title' } } ]) ] }) diff --git a/src/app/+search-page/search-page-routing.module.ts b/src/app/+search-page/search-page-routing.module.ts index c76207da9b..6e36883394 100644 --- a/src/app/+search-page/search-page-routing.module.ts +++ b/src/app/+search-page/search-page-routing.module.ts @@ -11,7 +11,7 @@ import { I18nBreadcrumbsService } from '../core/breadcrumbs/i18n-breadcrumbs.ser imports: [ RouterModule.forChild([{ path: '', - resolve: { breadcrumb: I18nBreadcrumbResolver }, data: { title: 'search.title', breadcrumbKey: 'Search' }, + resolve: { breadcrumb: I18nBreadcrumbResolver }, data: { title: 'search.title', breadcrumbKey: 'search' }, children: [ { path: '', component: SearchPageComponent }, { path: ':configuration', component: ConfigurationSearchPageComponent, canActivate: [ConfigurationSearchPageGuard] } diff --git a/src/app/breadcrumbs/breadcrumbs.component.spec.ts b/src/app/breadcrumbs/breadcrumbs.component.spec.ts index 175ef83757..0ab1fed208 100644 --- a/src/app/breadcrumbs/breadcrumbs.component.spec.ts +++ b/src/app/breadcrumbs/breadcrumbs.component.spec.ts @@ -1,25 +1,111 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { BreadcrumbsComponent } from './breadcrumbs.component'; +import { ActivatedRoute, NavigationEnd, Router } from '@angular/router'; +import { Observable, of as observableOf } from 'rxjs'; +import { RouterTestingModule } from '@angular/router/testing'; +import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; +import { MockTranslateLoader } from '../shared/testing/mock-translate-loader'; +import { BreadcrumbConfig } from './breadcrumb/breadcrumb-config.model'; +import { BreadcrumbsService } from '../core/breadcrumbs/breadcrumbs.service'; +import { Breadcrumb } from './breadcrumb/breadcrumb.model'; +import { getTestScheduler } from 'jasmine-marbles'; + +class TestBreadcrumbsService implements BreadcrumbsService { + getBreadcrumbs(key: string, url: string): Observable { + return observableOf([new Breadcrumb(key, url)]); + } +} describe('BreadcrumbsComponent', () => { let component: BreadcrumbsComponent; let fixture: ComponentFixture; + let router: any; + let route: any; + let breadcrumbProvider; + let breadcrumbConfigA: BreadcrumbConfig; + let breadcrumbConfigB: BreadcrumbConfig; + let expectedBreadcrumbs; + + function init() { + breadcrumbProvider = new TestBreadcrumbsService(); + + breadcrumbConfigA = { provider: breadcrumbProvider, key: 'example.path', url: 'example.com' }; + breadcrumbConfigB = { provider: breadcrumbProvider, key: 'another.path', url: 'another.com' }; + + route = { + root: { + snapshot: { + data: { breadcrumb: breadcrumbConfigA }, + routeConfig: { resolve: { breadcrumb: {} } } + }, + firstChild: { + snapshot: { + // Example without resolver should be ignored + data: { breadcrumb: breadcrumbConfigA }, + }, + firstChild: { + snapshot: { + data: { breadcrumb: breadcrumbConfigB }, + routeConfig: { resolve: { breadcrumb: {} } } + } + } + } + } + }; + + expectedBreadcrumbs = [ + new Breadcrumb(breadcrumbConfigA.key, breadcrumbConfigA.url), + new Breadcrumb(breadcrumbConfigB.key, breadcrumbConfigB.url) + ] + + } beforeEach(async(() => { + init(); TestBed.configureTestingModule({ - declarations: [ BreadcrumbsComponent ] + declarations: [BreadcrumbsComponent], + imports: [RouterTestingModule.withRoutes([]), TranslateModule.forRoot({ + loader: { + provide: TranslateLoader, + useClass: MockTranslateLoader + } + })], + providers: [ + { provide: ActivatedRoute, useValue: route } + + ] }) - .compileComponents(); + .compileComponents(); })); beforeEach(() => { fixture = TestBed.createComponent(BreadcrumbsComponent); component = fixture.componentInstance; + router = TestBed.get(Router); fixture.detectChanges(); }); it('should create', () => { expect(component).toBeTruthy(); }); + + describe('ngOnInit', () => { + beforeEach(() => { + spyOn(component, 'resolveBreadcrumbs').and.returnValue(observableOf([])) + }); + + it('should call resolveBreadcrumb on init', () => { + router.events = observableOf(new NavigationEnd(0, '', '')); + component.ngOnInit(); + expect(component.resolveBreadcrumbs).toHaveBeenCalledWith(route.root); + }) + }); + + describe('resolveBreadcrumbs', () => { + it('should return the correct breadcrumbs', () => { + const breadcrumbs = component.resolveBreadcrumbs(route.root); + getTestScheduler().expectObservable(breadcrumbs).toBe('(a|)', { a: expectedBreadcrumbs }) + }) + }) }); diff --git a/src/app/breadcrumbs/breadcrumbs.component.ts b/src/app/breadcrumbs/breadcrumbs.component.ts index fc3527a241..19b77fe59c 100644 --- a/src/app/breadcrumbs/breadcrumbs.component.ts +++ b/src/app/breadcrumbs/breadcrumbs.component.ts @@ -1,17 +1,16 @@ import { Component, OnDestroy, OnInit } from '@angular/core'; import { ActivatedRoute, NavigationEnd, Router } from '@angular/router'; import { Breadcrumb } from './breadcrumb/breadcrumb.model'; -import { hasValue, isNotUndefined } from '../shared/empty.util'; +import { hasNoValue, hasValue, isNotUndefined } from '../shared/empty.util'; import { filter, map, switchMap, tap } from 'rxjs/operators'; import { combineLatest, Observable, Subscription, of as observableOf } from 'rxjs'; -import { BreadcrumbConfig } from './breadcrumb/breadcrumb-config.model'; @Component({ selector: 'ds-breadcrumbs', templateUrl: './breadcrumbs.component.html', styleUrls: ['./breadcrumbs.component.scss'] }) -export class BreadcrumbsComponent implements OnDestroy { +export class BreadcrumbsComponent implements OnInit, OnDestroy { breadcrumbs: Breadcrumb[]; showBreadcrumbs: boolean; subscription: Subscription; @@ -20,21 +19,24 @@ export class BreadcrumbsComponent implements OnDestroy { private route: ActivatedRoute, private router: Router ) { + } + + ngOnInit(): void { this.subscription = this.router.events.pipe( filter((e): e is NavigationEnd => e instanceof NavigationEnd), tap(() => this.reset()), - switchMap(() => this.resolveBreadcrumb(this.route.root)) + switchMap(() => this.resolveBreadcrumbs(this.route.root)) ).subscribe((breadcrumbs) => { this.breadcrumbs = breadcrumbs; } ) } - resolveBreadcrumb(route: ActivatedRoute): Observable { + resolveBreadcrumbs(route: ActivatedRoute): Observable { const data = route.snapshot.data; const routeConfig = route.snapshot.routeConfig; - const last: boolean = route.children.length === 0; + const last: boolean = hasNoValue(route.firstChild); if (last && isNotUndefined(data.showBreadcrumbs)) { this.showBreadcrumbs = data.showBreadcrumbs; } @@ -45,13 +47,13 @@ export class BreadcrumbsComponent implements OnDestroy { ) { const { provider, key, url } = data.breadcrumb; if (!last) { - return combineLatest(provider.getBreadcrumbs(key, url), this.resolveBreadcrumb(route.firstChild)) + return combineLatest(provider.getBreadcrumbs(key, url), this.resolveBreadcrumbs(route.firstChild)) .pipe(map((crumbs) => [].concat.apply([], crumbs))); } else { return provider.getBreadcrumbs(key, url); } } - return !last ? this.resolveBreadcrumb(route.firstChild) : observableOf([]); + return !last ? this.resolveBreadcrumbs(route.firstChild) : observableOf([]); } ngOnDestroy(): void { diff --git a/src/app/core/breadcrumbs/collection-breadcrumb.resolver.ts b/src/app/core/breadcrumbs/collection-breadcrumb.resolver.ts index ec48e89421..78f90f149a 100644 --- a/src/app/core/breadcrumbs/collection-breadcrumb.resolver.ts +++ b/src/app/core/breadcrumbs/collection-breadcrumb.resolver.ts @@ -1,7 +1,5 @@ import { Injectable } from '@angular/core'; import { DSOBreadcrumbsService } from './dso-breadcrumbs.service'; -import { ItemDataService } from '../data/item-data.service'; -import { Item } from '../shared/item.model'; import { DSOBreadcrumbResolver } from './dso-breadcrumb.resolver'; import { Collection } from '../shared/collection.model'; import { CollectionDataService } from '../data/collection-data.service'; diff --git a/src/app/core/breadcrumbs/dso-breadcrumbs.service.spec.ts b/src/app/core/breadcrumbs/dso-breadcrumbs.service.spec.ts new file mode 100644 index 0000000000..dc6195071a --- /dev/null +++ b/src/app/core/breadcrumbs/dso-breadcrumbs.service.spec.ts @@ -0,0 +1,117 @@ +import { async, TestBed } from '@angular/core/testing'; +import { DSOBreadcrumbsService } from './dso-breadcrumbs.service'; +import { getMockLinkService } from '../../shared/mocks/mock-link-service'; +import { LinkService } from '../cache/builders/link.service'; +import { Item } from '../shared/item.model'; +import { createSuccessfulRemoteDataObject, createSuccessfulRemoteDataObject$ } from '../../shared/testing/utils'; +import { DSpaceObject } from '../shared/dspace-object.model'; +import { map } from 'rxjs/operators'; +import { of as observableOf } from 'rxjs'; +import { RemoteData } from '../data/remote-data'; +import { hasValue } from '../../shared/empty.util'; +import { Community } from '../shared/community.model'; +import { Collection } from '../shared/collection.model'; +import { Breadcrumb } from '../../breadcrumbs/breadcrumb/breadcrumb.model'; +import { getItemPageRoute } from '../../+item-page/item-page-routing.module'; +import { getCommunityPageRoute } from '../../+community-page/community-page-routing.module'; +import { getCollectionPageRoute } from '../../+collection-page/collection-page-routing.module'; +import { cold, getTestScheduler } from 'jasmine-marbles'; +import { getDSOPath } from '../../app-routing.module'; + +fdescribe('DSOBreadcrumbsService', () => { + let service: DSOBreadcrumbsService; + let linkService: any; + let testItem; + let testCollection; + let testCommunity; + + let itemPath; + let collectionPath; + let communityPath; + + let itemUUID; + let collectionUUID; + let communityUUID; + + let objects: DSpaceObject[]; + + function init() { + itemPath = '/items/'; + collectionPath = '/collection/'; + communityPath = '/community/'; + + itemUUID = '04dd18fc-03f9-4b9a-9304-ed7c313686d3'; + collectionUUID = '91dfa5b5-5440-4fb4-b869-02610342f886'; + communityUUID = '6c0bfa6b-ce82-4bf4-a2a8-fd7682c567e8'; + + testCommunity = Object.assign(new Community(), + { + type: 'community', + name: 'community', + uuid: communityUUID, + parentCommunity: observableOf(Object.assign(createSuccessfulRemoteDataObject(undefined), { statusCode: 204 })), + + _links: { + parentCommunity: 'site', + self: communityPath + communityUUID + } + } + ); + + testCollection = Object.assign(new Collection(), + { + type: 'collection', + name: 'collection', + uuid: collectionUUID, + parentCommunity: createSuccessfulRemoteDataObject$(testCommunity), + _links: { + parentCommunity: communityPath + communityUUID, + self: communityPath + collectionUUID + } + } + ); + + testItem = Object.assign(new Item(), + { + type: 'item', + name: 'item', + uuid: itemUUID, + owningCollection: createSuccessfulRemoteDataObject$(testCollection), + _links: { + owningCollection: collectionPath + collectionUUID, + self: itemPath + itemUUID + } + } + ); + + objects = [testItem, testCollection, testCommunity]; + + } + + beforeEach(async(() => { + init(); + TestBed.configureTestingModule({ + providers: [ + { provide: LinkService, useValue: getMockLinkService() } + ] + }).compileComponents(); + })); + + beforeEach(() => { + linkService = TestBed.get(LinkService); + linkService.resolveLink.and.callFake((object, link) => object); + service = new DSOBreadcrumbsService(linkService); + }); + + describe('getBreadcrumbs', () => { + it('should return the breadcrumbs based on an Item', () => { + const breadcrumbs = service.getBreadcrumbs(testItem, testItem._links.self); + const expectedCrumbs = [ + new Breadcrumb(testCommunity.name, getDSOPath(testCommunity)), + new Breadcrumb(testCollection.name, getDSOPath(testCollection)), + new Breadcrumb(testItem.name, getDSOPath(testItem)), + ]; + getTestScheduler().expectObservable(breadcrumbs).toBe('(a|)', { a: expectedCrumbs }); + }) + }); +}); diff --git a/src/app/core/breadcrumbs/dso-breadcrumbs.service.ts b/src/app/core/breadcrumbs/dso-breadcrumbs.service.ts index eaf1fed759..e4a22f1bf5 100644 --- a/src/app/core/breadcrumbs/dso-breadcrumbs.service.ts +++ b/src/app/core/breadcrumbs/dso-breadcrumbs.service.ts @@ -26,11 +26,11 @@ export class DSOBreadcrumbsService implements BreadcrumbsService) => childRD.hasSucceeded || childRD.statusCode === 204), - switchMap((childRD: RemoteData) => { - if (hasValue(childRD.payload)) { - const child = childRD.payload; - return this.getBreadcrumbs(child, getDSOPath(child)) + find((parentRD: RemoteData) => parentRD.hasSucceeded || parentRD.statusCode === 204), + switchMap((parentRD: RemoteData) => { + if (hasValue(parentRD.payload)) { + const parent = parentRD.payload; + return this.getBreadcrumbs(parent, getDSOPath(parent)) } return observableOf([]); diff --git a/src/app/core/breadcrumbs/i18n-breadcrumbs.service.spec.ts b/src/app/core/breadcrumbs/i18n-breadcrumbs.service.spec.ts new file mode 100644 index 0000000000..f29907312b --- /dev/null +++ b/src/app/core/breadcrumbs/i18n-breadcrumbs.service.spec.ts @@ -0,0 +1,31 @@ +import { async, TestBed } from '@angular/core/testing'; +import { Breadcrumb } from '../../breadcrumbs/breadcrumb/breadcrumb.model'; +import { getTestScheduler } from 'jasmine-marbles'; +import { BREADCRUMB_MESSAGE_POSTFIX, I18nBreadcrumbsService } from './i18n-breadcrumbs.service'; + +fdescribe('I18nBreadcrumbsService', () => { + let service: I18nBreadcrumbsService; + let exampleString; + let exampleURL; + + function init() { + exampleString = 'example.string'; + exampleURL = 'example.com'; + } + + beforeEach(async(() => { + init(); + TestBed.configureTestingModule({}).compileComponents(); + })); + + beforeEach(() => { + service = new I18nBreadcrumbsService(); + }); + + describe('getBreadcrumbs', () => { + it('should return a breadcrumb based on a string by adding the postfix', () => { + const breadcrumbs = service.getBreadcrumbs(exampleString, exampleURL); + getTestScheduler().expectObservable(breadcrumbs).toBe('(a|)', { a: [new Breadcrumb(exampleString + BREADCRUMB_MESSAGE_POSTFIX, exampleURL)] }); + }) + }); +}); diff --git a/src/app/core/breadcrumbs/i18n-breadcrumbs.service.ts b/src/app/core/breadcrumbs/i18n-breadcrumbs.service.ts index 6a9c8916a2..97ff89479a 100644 --- a/src/app/core/breadcrumbs/i18n-breadcrumbs.service.ts +++ b/src/app/core/breadcrumbs/i18n-breadcrumbs.service.ts @@ -3,11 +3,11 @@ import { BreadcrumbsService } from './breadcrumbs.service'; import { Observable, of as observableOf } from 'rxjs'; import { Injectable } from '@angular/core'; -export const BREADCRUMB_MESSAGE_PREFIX = 'breadcrumbs.'; +export const BREADCRUMB_MESSAGE_POSTFIX = '.breadcrumbs'; @Injectable() export class I18nBreadcrumbsService implements BreadcrumbsService { getBreadcrumbs(key: string, url: string): Observable { - return observableOf([new Breadcrumb(BREADCRUMB_MESSAGE_PREFIX + key, url)]); + return observableOf([new Breadcrumb(key + BREADCRUMB_MESSAGE_POSTFIX, url)]); } } diff --git a/src/app/shared/comcol-page-browse-by/comcol-page-browse-by.component.ts b/src/app/shared/comcol-page-browse-by/comcol-page-browse-by.component.ts index 1bc83d74a5..091e02723f 100644 --- a/src/app/shared/comcol-page-browse-by/comcol-page-browse-by.component.ts +++ b/src/app/shared/comcol-page-browse-by/comcol-page-browse-by.component.ts @@ -12,7 +12,7 @@ import { filter, map, startWith, tap } from 'rxjs/operators'; import { getCollectionPageRoute } from '../../+collection-page/collection-page-routing.module'; import { getCommunityPageRoute } from '../../+community-page/community-page-routing.module'; import { GLOBAL_CONFIG, GlobalConfig } from '../../../config'; -import { Router, ActivatedRoute, RouterModule, UrlSegment } from '@angular/router'; +import { Router, ActivatedRoute, RouterModule, UrlSegment, Params } from '@angular/router'; import { BrowseByTypeConfig } from '../../../config/browse-by-type-config.interface'; import { hasValue } from '../empty.util'; @@ -76,9 +76,8 @@ export class ComcolPageBrowseByComponent implements OnInit { }, ...this.allOptions ]; } - this.currentOptionId$ = this.route.url.pipe( - filter((urlSegments: UrlSegment[]) => hasValue(urlSegments)), - map((urlSegments: UrlSegment[]) => urlSegments[urlSegments.length - 1].path) + this.currentOptionId$ = this.route.params.pipe( + map((params: Params) => params.id) ); } From b554d40e9ca7514a35fb53aeef0bbd5602eb7829 Mon Sep 17 00:00:00 2001 From: lotte Date: Wed, 26 Feb 2020 16:53:10 +0100 Subject: [PATCH 08/32] added tests and docs --- .../collection-item-mapper.component.spec.ts | 2 +- src/app/breadcrumbs/breadcrumbs.component.ts | 27 ++++++++++++ .../core/breadcrumbs/breadcrumbs.service.ts | 9 ++++ .../collection-breadcrumb.resolver.ts | 2 +- .../community-breadcrumb.resolver.ts | 2 +- .../dso-breadcrumb.resolver.spec.ts | 34 +++++++++++++++ .../breadcrumbs/dso-breadcrumb.resolver.ts | 4 +- .../dso-breadcrumbs.service.spec.ts | 43 +++++++++++-------- .../breadcrumbs/dso-breadcrumbs.service.ts | 9 ++++ .../i18n-breadcrumb.resolver.spec.ts | 28 ++++++++++++ .../breadcrumbs/i18n-breadcrumb.resolver.ts | 2 +- .../i18n-breadcrumbs.service.spec.ts | 2 +- .../breadcrumbs/i18n-breadcrumbs.service.ts | 12 ++++++ .../breadcrumbs/item-breadcrumb.resolver.ts | 2 +- ...em-metadata-list-element.component.spec.ts | 2 +- 15 files changed, 152 insertions(+), 28 deletions(-) create mode 100644 src/app/core/breadcrumbs/dso-breadcrumb.resolver.spec.ts create mode 100644 src/app/core/breadcrumbs/i18n-breadcrumb.resolver.spec.ts diff --git a/src/app/+collection-page/collection-item-mapper/collection-item-mapper.component.spec.ts b/src/app/+collection-page/collection-item-mapper/collection-item-mapper.component.spec.ts index 8a07f5d235..19bdd2951e 100644 --- a/src/app/+collection-page/collection-item-mapper/collection-item-mapper.component.spec.ts +++ b/src/app/+collection-page/collection-item-mapper/collection-item-mapper.component.spec.ts @@ -83,7 +83,7 @@ describe('CollectionItemMapperComponent', () => { const itemDataServiceStub = { mapToCollection: () => of(new RestResponse(true, 200, 'OK')) }; - const activatedRouteStub = new ActivatedRouteStub({}, { collection: mockCollectionRD }); + const activatedRouteStub = new ActivatedRouteStub({}, { dso: mockCollectionRD }); const translateServiceStub = { get: () => of('test-message of collection ' + mockCollection.name), onLangChange: new EventEmitter(), diff --git a/src/app/breadcrumbs/breadcrumbs.component.ts b/src/app/breadcrumbs/breadcrumbs.component.ts index 19b77fe59c..861fda844b 100644 --- a/src/app/breadcrumbs/breadcrumbs.component.ts +++ b/src/app/breadcrumbs/breadcrumbs.component.ts @@ -5,14 +5,28 @@ import { hasNoValue, hasValue, isNotUndefined } from '../shared/empty.util'; import { filter, map, switchMap, tap } from 'rxjs/operators'; import { combineLatest, Observable, Subscription, of as observableOf } from 'rxjs'; +/** + * Component representing the breadcrumbs of a page + */ @Component({ selector: 'ds-breadcrumbs', templateUrl: './breadcrumbs.component.html', styleUrls: ['./breadcrumbs.component.scss'] }) export class BreadcrumbsComponent implements OnInit, OnDestroy { + /** + * List of breadcrumbs for this page + */ breadcrumbs: Breadcrumb[]; + + /** + * Whether or not to show breadcrumbs on this page + */ showBreadcrumbs: boolean; + + /** + * Subscription to unsubscribe from on destroy + */ subscription: Subscription; constructor( @@ -21,6 +35,9 @@ export class BreadcrumbsComponent implements OnInit, OnDestroy { ) { } + /** + * Sets the breadcrumbs on init for this page + */ ngOnInit(): void { this.subscription = this.router.events.pipe( filter((e): e is NavigationEnd => e instanceof NavigationEnd), @@ -32,6 +49,10 @@ export class BreadcrumbsComponent implements OnInit, OnDestroy { ) } + /** + * Method that recursively resolves breadcrumbs + * @param route The route to get the breadcrumb from + */ resolveBreadcrumbs(route: ActivatedRoute): Observable { const data = route.snapshot.data; const routeConfig = route.snapshot.routeConfig; @@ -56,12 +77,18 @@ export class BreadcrumbsComponent implements OnInit, OnDestroy { return !last ? this.resolveBreadcrumbs(route.firstChild) : observableOf([]); } + /** + * Unsubscribe from subscription + */ ngOnDestroy(): void { if (hasValue(this.subscription)) { this.subscription.unsubscribe(); } } + /** + * Resets the state of the breadcrumbs + */ reset() { this.breadcrumbs = []; this.showBreadcrumbs = true; diff --git a/src/app/core/breadcrumbs/breadcrumbs.service.ts b/src/app/core/breadcrumbs/breadcrumbs.service.ts index 30c6c44cf7..f274485d5d 100644 --- a/src/app/core/breadcrumbs/breadcrumbs.service.ts +++ b/src/app/core/breadcrumbs/breadcrumbs.service.ts @@ -1,6 +1,15 @@ import { Breadcrumb } from '../../breadcrumbs/breadcrumb/breadcrumb.model'; import { Observable } from 'rxjs'; +/** + * Service to calculate breadcrumbs for a single part of the route + */ export interface BreadcrumbsService { + + /** + * Method to calculate the breadcrumbs for a part of the route + * @param key The key used to resolve the breadcrumb + * @param url The url to use as a link for this breadcrumb + */ getBreadcrumbs(key: T, url: string): Observable; } diff --git a/src/app/core/breadcrumbs/collection-breadcrumb.resolver.ts b/src/app/core/breadcrumbs/collection-breadcrumb.resolver.ts index 78f90f149a..c662ead129 100644 --- a/src/app/core/breadcrumbs/collection-breadcrumb.resolver.ts +++ b/src/app/core/breadcrumbs/collection-breadcrumb.resolver.ts @@ -5,7 +5,7 @@ import { Collection } from '../shared/collection.model'; import { CollectionDataService } from '../data/collection-data.service'; /** - * The class that resolve the BreadcrumbConfig object for a route + * The class that resolves the BreadcrumbConfig object for a Collection */ @Injectable() export class CollectionBreadcrumbResolver extends DSOBreadcrumbResolver { diff --git a/src/app/core/breadcrumbs/community-breadcrumb.resolver.ts b/src/app/core/breadcrumbs/community-breadcrumb.resolver.ts index 3080823b97..1e4959f9e5 100644 --- a/src/app/core/breadcrumbs/community-breadcrumb.resolver.ts +++ b/src/app/core/breadcrumbs/community-breadcrumb.resolver.ts @@ -5,7 +5,7 @@ import { CommunityDataService } from '../data/community-data.service'; import { Community } from '../shared/community.model'; /** - * The class that resolve the BreadcrumbConfig object for a route + * The class that resolves the BreadcrumbConfig object for a Community */ @Injectable() export class CommunityBreadcrumbResolver extends DSOBreadcrumbResolver { diff --git a/src/app/core/breadcrumbs/dso-breadcrumb.resolver.spec.ts b/src/app/core/breadcrumbs/dso-breadcrumb.resolver.spec.ts new file mode 100644 index 0000000000..774fcd04d5 --- /dev/null +++ b/src/app/core/breadcrumbs/dso-breadcrumb.resolver.spec.ts @@ -0,0 +1,34 @@ +import { DSOBreadcrumbResolver } from './dso-breadcrumb.resolver'; +import { Collection } from '../shared/collection.model'; +import { createSuccessfulRemoteDataObject$ } from '../../shared/testing/utils'; +import { getTestScheduler } from 'jasmine-marbles'; + +describe('DSOBreadcrumbResolver', () => { + describe('resolve', () => { + let resolver: DSOBreadcrumbResolver; + let collectionService: any; + let dsoBreadcrumbService: any; + let testCollection: Collection; + let uuid; + let breadcrumbUrl; + let currentUrl; + + beforeEach(() => { + uuid = '1234-65487-12354-1235'; + breadcrumbUrl = '/collections/' + uuid; + currentUrl = breadcrumbUrl + '/edit'; + testCollection = Object.assign(new Collection(), { uuid }); + dsoBreadcrumbService = {}; + collectionService = { + findById: (id: string) => createSuccessfulRemoteDataObject$(testCollection) + }; + resolver = new DSOBreadcrumbResolver(dsoBreadcrumbService, collectionService); + }); + + it('should resolve a breadcrumb config for the correct DSO', () => { + const resolvedConfig = resolver.resolve({ params: { id: uuid } } as any, { url: currentUrl } as any); + const expectedConfig = { provider: dsoBreadcrumbService, key: testCollection, url: breadcrumbUrl }; + getTestScheduler().expectObservable(resolvedConfig).toBe('(a|)', { a: expectedConfig}) + }); + }); +}); diff --git a/src/app/core/breadcrumbs/dso-breadcrumb.resolver.ts b/src/app/core/breadcrumbs/dso-breadcrumb.resolver.ts index 2f4138d144..78ba349a5c 100644 --- a/src/app/core/breadcrumbs/dso-breadcrumb.resolver.ts +++ b/src/app/core/breadcrumbs/dso-breadcrumb.resolver.ts @@ -10,7 +10,7 @@ import { DSpaceObject } from '../shared/dspace-object.model'; import { ChildHALResource } from '../shared/child-hal-resource.model'; /** - * The class that resolve the BreadcrumbConfig object for a route + * The class that resolves the BreadcrumbConfig object for a DSpaceObject */ @Injectable() export class DSOBreadcrumbResolver implements Resolve> { @@ -18,7 +18,7 @@ export class DSOBreadcrumbResolver im } /** - * Method for resolving a site object + * Method for resolving a breadcrumb config object * @param {ActivatedRouteSnapshot} route The current ActivatedRouteSnapshot * @param {RouterStateSnapshot} state The current RouterStateSnapshot * @returns BreadcrumbConfig object diff --git a/src/app/core/breadcrumbs/dso-breadcrumbs.service.spec.ts b/src/app/core/breadcrumbs/dso-breadcrumbs.service.spec.ts index dc6195071a..101545cb14 100644 --- a/src/app/core/breadcrumbs/dso-breadcrumbs.service.spec.ts +++ b/src/app/core/breadcrumbs/dso-breadcrumbs.service.spec.ts @@ -5,20 +5,15 @@ import { LinkService } from '../cache/builders/link.service'; import { Item } from '../shared/item.model'; import { createSuccessfulRemoteDataObject, createSuccessfulRemoteDataObject$ } from '../../shared/testing/utils'; import { DSpaceObject } from '../shared/dspace-object.model'; -import { map } from 'rxjs/operators'; import { of as observableOf } from 'rxjs'; -import { RemoteData } from '../data/remote-data'; -import { hasValue } from '../../shared/empty.util'; import { Community } from '../shared/community.model'; import { Collection } from '../shared/collection.model'; import { Breadcrumb } from '../../breadcrumbs/breadcrumb/breadcrumb.model'; -import { getItemPageRoute } from '../../+item-page/item-page-routing.module'; -import { getCommunityPageRoute } from '../../+community-page/community-page-routing.module'; -import { getCollectionPageRoute } from '../../+collection-page/collection-page-routing.module'; -import { cold, getTestScheduler } from 'jasmine-marbles'; +import { getTestScheduler } from 'jasmine-marbles'; import { getDSOPath } from '../../app-routing.module'; +import { DSONameService } from './dso-name.service'; -fdescribe('DSOBreadcrumbsService', () => { +describe('DSOBreadcrumbsService', () => { let service: DSOBreadcrumbsService; let linkService: any; let testItem; @@ -33,7 +28,7 @@ fdescribe('DSOBreadcrumbsService', () => { let collectionUUID; let communityUUID; - let objects: DSpaceObject[]; + let dsoNameService; function init() { itemPath = '/items/'; @@ -47,7 +42,9 @@ fdescribe('DSOBreadcrumbsService', () => { testCommunity = Object.assign(new Community(), { type: 'community', - name: 'community', + metadata: { + 'dc.title': [{value: 'community'}] + }, uuid: communityUUID, parentCommunity: observableOf(Object.assign(createSuccessfulRemoteDataObject(undefined), { statusCode: 204 })), @@ -61,7 +58,9 @@ fdescribe('DSOBreadcrumbsService', () => { testCollection = Object.assign(new Collection(), { type: 'collection', - name: 'collection', + metadata: { + 'dc.title': [{value: 'collection'}] + }, uuid: collectionUUID, parentCommunity: createSuccessfulRemoteDataObject$(testCommunity), _links: { @@ -74,7 +73,9 @@ fdescribe('DSOBreadcrumbsService', () => { testItem = Object.assign(new Item(), { type: 'item', - name: 'item', + metadata: { + 'dc.title': [{value: 'item'}] + }, uuid: itemUUID, owningCollection: createSuccessfulRemoteDataObject$(testCollection), _links: { @@ -84,15 +85,15 @@ fdescribe('DSOBreadcrumbsService', () => { } ); - objects = [testItem, testCollection, testCommunity]; - + dsoNameService = { getName: (dso) => getName(dso) } } beforeEach(async(() => { init(); TestBed.configureTestingModule({ providers: [ - { provide: LinkService, useValue: getMockLinkService() } + { provide: LinkService, useValue: getMockLinkService() }, + { provide: DSONameService, useValue: dsoNameService } ] }).compileComponents(); })); @@ -100,18 +101,22 @@ fdescribe('DSOBreadcrumbsService', () => { beforeEach(() => { linkService = TestBed.get(LinkService); linkService.resolveLink.and.callFake((object, link) => object); - service = new DSOBreadcrumbsService(linkService); + service = new DSOBreadcrumbsService(linkService, dsoNameService); }); describe('getBreadcrumbs', () => { it('should return the breadcrumbs based on an Item', () => { const breadcrumbs = service.getBreadcrumbs(testItem, testItem._links.self); const expectedCrumbs = [ - new Breadcrumb(testCommunity.name, getDSOPath(testCommunity)), - new Breadcrumb(testCollection.name, getDSOPath(testCollection)), - new Breadcrumb(testItem.name, getDSOPath(testItem)), + new Breadcrumb(getName(testCommunity), getDSOPath(testCommunity)), + new Breadcrumb(getName(testCollection), getDSOPath(testCollection)), + new Breadcrumb(getName(testItem), getDSOPath(testItem)), ]; getTestScheduler().expectObservable(breadcrumbs).toBe('(a|)', { a: expectedCrumbs }); }) }); + + function getName(dso: DSpaceObject): string { + return dso.metadata['dc.title'][0].value + } }); diff --git a/src/app/core/breadcrumbs/dso-breadcrumbs.service.ts b/src/app/core/breadcrumbs/dso-breadcrumbs.service.ts index e4a22f1bf5..3cb73be876 100644 --- a/src/app/core/breadcrumbs/dso-breadcrumbs.service.ts +++ b/src/app/core/breadcrumbs/dso-breadcrumbs.service.ts @@ -12,6 +12,9 @@ import { RemoteData } from '../data/remote-data'; import { hasValue } from '../../shared/empty.util'; import { Injectable } from '@angular/core'; +/** + * Service to calculate DSpaceObject breadcrumbs for a single part of the route + */ @Injectable() export class DSOBreadcrumbsService implements BreadcrumbsService { constructor( @@ -21,6 +24,12 @@ export class DSOBreadcrumbsService implements BreadcrumbsService { const label = this.dsoNameService.getName(key); const crumb = new Breadcrumb(label, url); diff --git a/src/app/core/breadcrumbs/i18n-breadcrumb.resolver.spec.ts b/src/app/core/breadcrumbs/i18n-breadcrumb.resolver.spec.ts new file mode 100644 index 0000000000..d34d6d8a9b --- /dev/null +++ b/src/app/core/breadcrumbs/i18n-breadcrumb.resolver.spec.ts @@ -0,0 +1,28 @@ +import { I18nBreadcrumbResolver } from './i18n-breadcrumb.resolver'; + +describe('I18nBreadcrumbResolver', () => { + describe('resolve', () => { + let resolver: I18nBreadcrumbResolver; + let i18nBreadcrumbService: any; + let i18nKey: string; + let path: string; + beforeEach(() => { + i18nKey = 'example.key'; + path = 'rest.com/path/to/breadcrumb'; + i18nBreadcrumbService = {}; + resolver = new I18nBreadcrumbResolver(i18nBreadcrumbService); + }); + + it('should resolve the breadcrumb config', () => { + const resolvedConfig = resolver.resolve({ data: { breadcrumbKey: i18nKey }, url: [path] } as any, {} as any); + const expectedConfig = { provider: i18nBreadcrumbService, key: i18nKey, url: path }; + expect(resolvedConfig).toEqual(expectedConfig); + }); + + it('should resolve throw an error when no breadcrumbKey is defined', () => { + expect(() => { + resolver.resolve({ data: {} } as any, undefined) + }).toThrow(); + }); + }); +}); diff --git a/src/app/core/breadcrumbs/i18n-breadcrumb.resolver.ts b/src/app/core/breadcrumbs/i18n-breadcrumb.resolver.ts index 800a7b75d0..0978648ba3 100644 --- a/src/app/core/breadcrumbs/i18n-breadcrumb.resolver.ts +++ b/src/app/core/breadcrumbs/i18n-breadcrumb.resolver.ts @@ -5,7 +5,7 @@ import { I18nBreadcrumbsService } from './i18n-breadcrumbs.service'; import { hasNoValue } from '../../shared/empty.util'; /** - * The class that resolve the BreadcrumbConfig object for a route + * The class that resolves a BreadcrumbConfig object with an i18n key string for a route */ @Injectable() export class I18nBreadcrumbResolver implements Resolve> { diff --git a/src/app/core/breadcrumbs/i18n-breadcrumbs.service.spec.ts b/src/app/core/breadcrumbs/i18n-breadcrumbs.service.spec.ts index f29907312b..274389db3b 100644 --- a/src/app/core/breadcrumbs/i18n-breadcrumbs.service.spec.ts +++ b/src/app/core/breadcrumbs/i18n-breadcrumbs.service.spec.ts @@ -3,7 +3,7 @@ import { Breadcrumb } from '../../breadcrumbs/breadcrumb/breadcrumb.model'; import { getTestScheduler } from 'jasmine-marbles'; import { BREADCRUMB_MESSAGE_POSTFIX, I18nBreadcrumbsService } from './i18n-breadcrumbs.service'; -fdescribe('I18nBreadcrumbsService', () => { +describe('I18nBreadcrumbsService', () => { let service: I18nBreadcrumbsService; let exampleString; let exampleURL; diff --git a/src/app/core/breadcrumbs/i18n-breadcrumbs.service.ts b/src/app/core/breadcrumbs/i18n-breadcrumbs.service.ts index 97ff89479a..e07d9ed541 100644 --- a/src/app/core/breadcrumbs/i18n-breadcrumbs.service.ts +++ b/src/app/core/breadcrumbs/i18n-breadcrumbs.service.ts @@ -3,10 +3,22 @@ import { BreadcrumbsService } from './breadcrumbs.service'; 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() export class I18nBreadcrumbsService implements BreadcrumbsService { + + /** + * 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 { return observableOf([new Breadcrumb(key + BREADCRUMB_MESSAGE_POSTFIX, url)]); } diff --git a/src/app/core/breadcrumbs/item-breadcrumb.resolver.ts b/src/app/core/breadcrumbs/item-breadcrumb.resolver.ts index fdfd3c11f9..c447f7de2a 100644 --- a/src/app/core/breadcrumbs/item-breadcrumb.resolver.ts +++ b/src/app/core/breadcrumbs/item-breadcrumb.resolver.ts @@ -5,7 +5,7 @@ import { Item } from '../shared/item.model'; import { DSOBreadcrumbResolver } from './dso-breadcrumb.resolver'; /** - * The class that resolve the BreadcrumbConfig object for a route + * The class that resolves the BreadcrumbConfig object for an Item */ @Injectable() export class ItemBreadcrumbResolver extends DSOBreadcrumbResolver { diff --git a/src/app/entity-groups/research-entities/metadata-representations/org-unit/org-unit-item-metadata-list-element.component.spec.ts b/src/app/entity-groups/research-entities/metadata-representations/org-unit/org-unit-item-metadata-list-element.component.spec.ts index 37cbe47c72..0354469372 100644 --- a/src/app/entity-groups/research-entities/metadata-representations/org-unit/org-unit-item-metadata-list-element.component.spec.ts +++ b/src/app/entity-groups/research-entities/metadata-representations/org-unit/org-unit-item-metadata-list-element.component.spec.ts @@ -13,7 +13,7 @@ const mockItem = Object.assign(new Item(), { metadata: { 'dc.description': [{ va const virtMD = Object.assign(new MetadataValue(), { value: organisation }); const mockItemMetadataRepresentation = Object.assign(new ItemMetadataRepresentation(virtMD), mockItem); -describe('OrgUnitItemMetadataListElementComponent', () => { +fdescribe('OrgUnitItemMetadataListElementComponent', () => { let comp: OrgUnitItemMetadataListElementComponent; let fixture: ComponentFixture; From d2fe506299240b41f6742c5f582e40374838a811 Mon Sep 17 00:00:00 2001 From: lotte Date: Wed, 26 Feb 2020 17:08:59 +0100 Subject: [PATCH 09/32] fixed time out --- .../org-unit-item-metadata-list-element.component.spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/entity-groups/research-entities/metadata-representations/org-unit/org-unit-item-metadata-list-element.component.spec.ts b/src/app/entity-groups/research-entities/metadata-representations/org-unit/org-unit-item-metadata-list-element.component.spec.ts index 0354469372..7d27b605ec 100644 --- a/src/app/entity-groups/research-entities/metadata-representations/org-unit/org-unit-item-metadata-list-element.component.spec.ts +++ b/src/app/entity-groups/research-entities/metadata-representations/org-unit/org-unit-item-metadata-list-element.component.spec.ts @@ -13,7 +13,7 @@ const mockItem = Object.assign(new Item(), { metadata: { 'dc.description': [{ va const virtMD = Object.assign(new MetadataValue(), { value: organisation }); const mockItemMetadataRepresentation = Object.assign(new ItemMetadataRepresentation(virtMD), mockItem); -fdescribe('OrgUnitItemMetadataListElementComponent', () => { +describe('OrgUnitItemMetadataListElementComponent', () => { let comp: OrgUnitItemMetadataListElementComponent; let fixture: ComponentFixture; @@ -23,7 +23,7 @@ fdescribe('OrgUnitItemMetadataListElementComponent', () => { declarations: [OrgUnitItemMetadataListElementComponent], schemas: [NO_ERRORS_SCHEMA] }).overrideComponent(OrgUnitItemMetadataListElementComponent, { - // set: { changeDetection: ChangeDetectionStrategy.Default } + set: { changeDetection: ChangeDetectionStrategy.Default } }).compileComponents(); })); From e1f940668a909c21ce1494719df8e61fec0e8149 Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Wed, 26 Feb 2020 17:50:44 +0100 Subject: [PATCH 10/32] 69115: MyDSpace ClaimedTask proper link resolving --- .../+my-dspace-page/my-dspace-page.component.ts | 7 ++++++- src/app/core/eperson/group-data.service.ts | 3 +++ src/app/core/shared/search/search.service.ts | 12 +++++++----- .../tasks/models/claimed-task-object.model.ts | 6 +++--- src/app/core/tasks/models/task-object.model.ts | 7 ++++--- ...item-metadata-list-element.component.spec.ts | 4 ++-- ...ed-search-result-list-element.component.html | 14 ++++++++------ ...search-result-list-element.component.spec.ts | 10 +++++++--- ...imed-search-result-list-element.component.ts | 17 ++--------------- 9 files changed, 42 insertions(+), 38 deletions(-) diff --git a/src/app/+my-dspace-page/my-dspace-page.component.ts b/src/app/+my-dspace-page/my-dspace-page.component.ts index 6556eaaf1f..592984d250 100644 --- a/src/app/+my-dspace-page/my-dspace-page.component.ts +++ b/src/app/+my-dspace-page/my-dspace-page.component.ts @@ -29,6 +29,8 @@ import { ViewMode } from '../core/shared/view-mode.model'; import { MyDSpaceRequest } from '../core/data/request.models'; import { SearchResult } from '../shared/search/search-result.model'; import { Context } from '../core/shared/context.model'; +import { followLink } from '../shared/utils/follow-link-config.model'; +import { ClaimedTask } from '../core/tasks/models/claimed-task-object.model'; export const MYDSPACE_ROUTE = '/mydspace'; export const SEARCH_CONFIG_SERVICE: InjectionToken = new InjectionToken('searchConfigurationService'); @@ -126,7 +128,10 @@ export class MyDSpacePageComponent implements OnInit { this.searchOptions$ = this.searchConfigService.paginatedSearchOptions; this.sub = this.searchOptions$.pipe( tap(() => this.resultsRD$.next(null)), - switchMap((options: PaginatedSearchOptions) => this.service.search(options).pipe(getSucceededRemoteData()))) + switchMap((options: PaginatedSearchOptions) => + this.service.search(options, undefined, + followLink('workflowitem', undefined, followLink('item'), followLink('submitter')), + followLink('owner')).pipe(getSucceededRemoteData()))) .subscribe((results) => { this.resultsRD$.next(results); }); diff --git a/src/app/core/eperson/group-data.service.ts b/src/app/core/eperson/group-data.service.ts index 2beeb588a9..532f42323a 100644 --- a/src/app/core/eperson/group-data.service.ts +++ b/src/app/core/eperson/group-data.service.ts @@ -18,6 +18,8 @@ import { RemoteData } from '../data/remote-data'; import { PaginatedList } from '../data/paginated-list'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { DSOChangeAnalyzer } from '../data/dso-change-analyzer.service'; +import { dataService } from '../cache/builders/build-decorators'; +import { GROUP } from './models/group.resource-type'; /** * Provides methods to retrieve eperson group resources. @@ -25,6 +27,7 @@ import { DSOChangeAnalyzer } from '../data/dso-change-analyzer.service'; @Injectable({ providedIn: 'root' }) +@dataService(GROUP) export class GroupDataService extends DataService { protected linkPath = 'groups'; protected browseEndpoint = ''; diff --git a/src/app/core/shared/search/search.service.ts b/src/app/core/shared/search/search.service.ts index 1a016e64f8..06dfd6dba0 100644 --- a/src/app/core/shared/search/search.service.ts +++ b/src/app/core/shared/search/search.service.ts @@ -2,7 +2,7 @@ import { combineLatest as observableCombineLatest, Observable, of as observableO import { Injectable, OnDestroy } from '@angular/core'; import { NavigationExtras, Router } from '@angular/router'; import { first, map, switchMap, tap } from 'rxjs/operators'; -import { followLink } from '../../../shared/utils/follow-link-config.model'; +import { followLink, FollowLinkConfig } from '../../../shared/utils/follow-link-config.model'; import { LinkService } from '../../cache/builders/link.service'; import { FacetConfigSuccessResponse, FacetValueSuccessResponse, SearchSuccessResponse } from '../../cache/response.models'; import { PaginatedList } from '../../data/paginated-list'; @@ -107,10 +107,11 @@ export class SearchService implements OnDestroy { * Method to retrieve a paginated list of search results from the server * @param {PaginatedSearchOptions} searchOptions The configuration necessary to perform this search * @param responseMsToLive The amount of milliseconds for the response to live in cache + * @param linksToFollow List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved * @returns {Observable>>>} Emits a paginated list with all search results found */ - search(searchOptions?: PaginatedSearchOptions, responseMsToLive?: number): Observable>>> { - return this.getPaginatedResults(this.searchEntries(searchOptions)); + search(searchOptions?: PaginatedSearchOptions, responseMsToLive?: number, ...linksToFollow: Array>): Observable>>> { + return this.getPaginatedResults(this.searchEntries(searchOptions), ...linksToFollow); } /** @@ -151,9 +152,10 @@ export class SearchService implements OnDestroy { /** * Method to convert the parsed responses into a paginated list of search results * @param searchEntries: The request entries from the search method + * @param linksToFollow List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved * @returns {Observable>>>} Emits a paginated list with all search results found */ - getPaginatedResults(searchEntries: Observable<{ searchOptions: PaginatedSearchOptions, requestEntry: RequestEntry }>): Observable>>> { + getPaginatedResults(searchEntries: Observable<{ searchOptions: PaginatedSearchOptions, requestEntry: RequestEntry }>, ...linksToFollow: Array>): Observable>>> { const requestEntryObs: Observable = searchEntries.pipe( map((entry) => entry.requestEntry), ); @@ -174,7 +176,7 @@ export class SearchService implements OnDestroy { }), // Send a request for each item to ensure fresh cache tap((reqs: RestRequest[]) => reqs.forEach((req: RestRequest) => this.requestService.configure(req))), - map((reqs: RestRequest[]) => reqs.map((req: RestRequest) => this.rdb.buildSingle(req.href))), + map((reqs: RestRequest[]) => reqs.map((req: RestRequest) => this.rdb.buildSingle(req.href, ...linksToFollow))), switchMap((input: Array>>) => this.rdb.aggregate(input)), ); diff --git a/src/app/core/tasks/models/claimed-task-object.model.ts b/src/app/core/tasks/models/claimed-task-object.model.ts index 9ec28bc2e0..3ea78595f2 100644 --- a/src/app/core/tasks/models/claimed-task-object.model.ts +++ b/src/app/core/tasks/models/claimed-task-object.model.ts @@ -1,6 +1,5 @@ import { inheritSerialization } from 'cerialize'; -import { typedObject } from '../../cache/builders/build-decorators'; -import { DSpaceObject } from '../../shared/dspace-object.model'; +import { inheritLinkAnnotations, typedObject } from '../../cache/builders/build-decorators'; import { CLAIMED_TASK } from './claimed-task-object.resource-type'; import { TaskObject } from './task-object.model'; @@ -8,7 +7,8 @@ import { TaskObject } from './task-object.model'; * A model class for a ClaimedTask. */ @typedObject -@inheritSerialization(DSpaceObject) +@inheritSerialization(TaskObject) +@inheritLinkAnnotations(TaskObject) export class ClaimedTask extends TaskObject { static type = CLAIMED_TASK; } diff --git a/src/app/core/tasks/models/task-object.model.ts b/src/app/core/tasks/models/task-object.model.ts index ac659ca9e5..b56cec3a7e 100644 --- a/src/app/core/tasks/models/task-object.model.ts +++ b/src/app/core/tasks/models/task-object.model.ts @@ -12,6 +12,7 @@ import { DSpaceObject } from '../../shared/dspace-object.model'; import { HALLink } from '../../shared/hal-link.model'; import { WorkflowItem } from '../../submission/models/workflowitem.model'; import { TASK_OBJECT } from './task-object.resource-type'; +import { WORKFLOWITEM } from '../../eperson/models/workflowitem.resource-type'; /** * An abstract model class for a TaskObject. @@ -45,7 +46,7 @@ export class TaskObject extends DSpaceObject implements CacheableObject { @deserialize _links: { self: HALLink; - eperson: HALLink; + owner: HALLink; group: HALLink; workflowitem: HALLink; }; @@ -54,7 +55,7 @@ export class TaskObject extends DSpaceObject implements CacheableObject { * The EPerson for this task * Will be undefined unless the eperson {@link HALLink} has been resolved. */ - @link(EPERSON) + @link(EPERSON, false, 'owner') eperson?: Observable>; /** @@ -68,7 +69,7 @@ export class TaskObject extends DSpaceObject implements CacheableObject { * The WorkflowItem for this task * Will be undefined unless the workflowitem {@link HALLink} has been resolved. */ - @link(WorkflowItem.type) + @link(WORKFLOWITEM) workflowitem?: Observable> | WorkflowItem; } diff --git a/src/app/entity-groups/research-entities/metadata-representations/org-unit/org-unit-item-metadata-list-element.component.spec.ts b/src/app/entity-groups/research-entities/metadata-representations/org-unit/org-unit-item-metadata-list-element.component.spec.ts index 37cbe47c72..4f899edaa8 100644 --- a/src/app/entity-groups/research-entities/metadata-representations/org-unit/org-unit-item-metadata-list-element.component.spec.ts +++ b/src/app/entity-groups/research-entities/metadata-representations/org-unit/org-unit-item-metadata-list-element.component.spec.ts @@ -27,12 +27,12 @@ describe('OrgUnitItemMetadataListElementComponent', () => { }).compileComponents(); })); - beforeEach(async(() => { + beforeEach(() => { fixture = TestBed.createComponent(OrgUnitItemMetadataListElementComponent); comp = fixture.componentInstance; comp.metadataRepresentation = mockItemMetadataRepresentation; fixture.detectChanges(); - })); + }); it('should show the name of the organisation as a link', () => { const linkText = fixture.debugElement.query(By.css('a')).nativeElement.textContent; diff --git a/src/app/shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-search-result-list-element.component.html b/src/app/shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-search-result-list-element.component.html index 5ec4c9a5b5..5e988a5b7e 100644 --- a/src/app/shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-search-result-list-element.component.html +++ b/src/app/shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-search-result-list-element.component.html @@ -1,7 +1,9 @@ - + + - + + diff --git a/src/app/shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-search-result-list-element.component.spec.ts b/src/app/shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-search-result-list-element.component.spec.ts index cce134f806..24b8adb5b4 100644 --- a/src/app/shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-search-result-list-element.component.spec.ts +++ b/src/app/shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-search-result-list-element.component.spec.ts @@ -12,6 +12,7 @@ import { WorkflowItem } from '../../../../core/submission/models/workflowitem.mo import { createSuccessfulRemoteDataObject } from '../../../testing/utils'; import { ClaimedTaskSearchResult } from '../../../object-collection/shared/claimed-task-search-result.model'; import { TruncatableService } from '../../../truncatable/truncatable.service'; +import { VarDirective } from '../../../utils/var.directive'; let component: ClaimedSearchResultListElementComponent; let fixture: ComponentFixture; @@ -59,7 +60,7 @@ describe('ClaimedSearchResultListElementComponent', () => { beforeEach(async(() => { TestBed.configureTestingModule({ imports: [NoopAnimationsModule], - declarations: [ClaimedSearchResultListElementComponent], + declarations: [ClaimedSearchResultListElementComponent, VarDirective], providers: [ { provide: TruncatableService, useValue: {} }, ], @@ -79,8 +80,11 @@ describe('ClaimedSearchResultListElementComponent', () => { fixture.detectChanges(); }); - it('should init item properly', () => { - expect(component.workflowitem).toEqual(workflowitem); + it('should init item properly', (done) => { + component.workflowitemRD$.subscribe((workflowitemRD) => { + expect(workflowitemRD.payload).toEqual(workflowitem); + done(); + }); }); it('should have properly status', () => { diff --git a/src/app/shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-search-result-list-element.component.ts b/src/app/shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-search-result-list-element.component.ts index 35371f40aa..ea8bf30f04 100644 --- a/src/app/shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-search-result-list-element.component.ts +++ b/src/app/shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-search-result-list-element.component.ts @@ -2,11 +2,9 @@ import { Component } from '@angular/core'; import { Location, LocationStrategy, PathLocationStrategy } from '@angular/common'; import { Observable } from 'rxjs'; -import { find } from 'rxjs/operators'; import { ViewMode } from '../../../../core/shared/view-mode.model'; import { RemoteData } from '../../../../core/data/remote-data'; -import { isNotUndefined } from '../../../empty.util'; import { WorkflowItem } from '../../../../core/submission/models/workflowitem.model'; import { ClaimedTask } from '../../../../core/tasks/models/claimed-task-object.model'; import { MyDspaceItemStatusType } from '../../../object-collection/shared/mydspace-item-status/my-dspace-item-status-type'; @@ -40,24 +38,13 @@ export class ClaimedSearchResultListElementComponent extends SearchResultListEle /** * The workflowitem object that belonging to the result object */ - public workflowitem: WorkflowItem; + public workflowitemRD$: Observable>; /** * Initialize all instance variables */ ngOnInit() { super.ngOnInit(); - this.initWorkflowItem(this.dso.workflowitem as Observable>); - } - - /** - * Retrieve workflowitem from result object - */ - initWorkflowItem(wfi$: Observable>) { - wfi$.pipe( - find((rd: RemoteData) => (rd.hasSucceeded && isNotUndefined(rd.payload))) - ).subscribe((rd: RemoteData) => { - this.workflowitem = rd.payload; - }); + this.workflowitemRD$ = this.dso.workflowitem as Observable>; } } From 802498e27ea6bccef32c31a80eeb2c3738acf64e Mon Sep 17 00:00:00 2001 From: muiltje Date: Tue, 7 Jan 2020 12:54:16 +0100 Subject: [PATCH 11/32] First batch of Dutch translations --- resources/i18n/nl.json5 | 2217 ++++++++++++++++++--------------------- 1 file changed, 1046 insertions(+), 1171 deletions(-) diff --git a/resources/i18n/nl.json5 b/resources/i18n/nl.json5 index 3eb7b7c7c3..410b3e6a8b 100644 --- a/resources/i18n/nl.json5 +++ b/resources/i18n/nl.json5 @@ -1,3087 +1,2962 @@ { - + // "404.help": "We can't find the page you're looking for. The page may have been moved or deleted. You can use the button below to get back to the home page. ", "404.help": "De pagina die u zoekt kan niet gevonden worden. De pagina werd mogelijk verplaatst of verwijderd. U kan onderstaande knop gebruiken om terug naar de homepagina te gaan. ", - + // "404.link.home-page": "Take me to the home page", "404.link.home-page": "Terug naar de homepagina", - + // "404.page-not-found": "page not found", "404.page-not-found": "Pagina niet gevonden", - - - + + + // "admin.registries.bitstream-formats.create.failure.content": "An error occurred while creating the new bitstream format.", // TODO New key - Add a translation "admin.registries.bitstream-formats.create.failure.content": "An error occurred while creating the new bitstream format.", - + // "admin.registries.bitstream-formats.create.failure.head": "Failure", - // TODO New key - Add a translation - "admin.registries.bitstream-formats.create.failure.head": "Failure", - + "admin.registries.bitstream-formats.create.failure.head": "Gefaald", + // "admin.registries.bitstream-formats.create.head": "Create Bitstream format", - // TODO New key - Add a translation - "admin.registries.bitstream-formats.create.head": "Create Bitstream format", - + "admin.registries.bitstream-formats.create.head": "Maak een Bitstream formaat aan", + // "admin.registries.bitstream-formats.create.new": "Add a new bitstream format", - // TODO New key - Add a translation - "admin.registries.bitstream-formats.create.new": "Add a new bitstream format", - + "admin.registries.bitstream-formats.create.new": "Voeg een nieuw Bitstream formaat toe", + // "admin.registries.bitstream-formats.create.success.content": "The new bitstream format was successfully created.", - // TODO New key - Add a translation - "admin.registries.bitstream-formats.create.success.content": "The new bitstream format was successfully created.", - + "admin.registries.bitstream-formats.create.success.content": "Het nieuwe Bitstream formaat is aangemaakt.", + // "admin.registries.bitstream-formats.create.success.head": "Success", "admin.registries.bitstream-formats.create.success.head": "Succes", - + // "admin.registries.bitstream-formats.delete.failure.amount": "Failed to remove {{ amount }} format(s)", - // TODO New key - Add a translation - "admin.registries.bitstream-formats.delete.failure.amount": "Failed to remove {{ amount }} format(s)", - + "admin.registries.bitstream-formats.delete.failure.amount": "Het verwijderen van {{ amount }} forma(a)t(en) is mislukt.", + // "admin.registries.bitstream-formats.delete.failure.head": "Failure", "admin.registries.bitstream-formats.delete.failure.head": "Gefaald", - + // "admin.registries.bitstream-formats.delete.success.amount": "Successfully removed {{ amount }} format(s)", - // TODO New key - Add a translation - "admin.registries.bitstream-formats.delete.success.amount": "Successfully removed {{ amount }} format(s)", - + "admin.registries.bitstream-formats.delete.success.amount": "Het verwijderen van {{ amount }} forma(a)t(en) is gelukt.", + // "admin.registries.bitstream-formats.delete.success.head": "Success", "admin.registries.bitstream-formats.delete.success.head": "Succes", - + // "admin.registries.bitstream-formats.description": "This list of bitstream formats provides information about known formats and their support level.", "admin.registries.bitstream-formats.description": "Deze lijst van Bitstream formaten biedt informatie over de formaten die in deze repository zijn toegelaten en op welke manier ze ondersteund worden. De term Bitstream wordt in DSpace gebruikt om een bestand aan te duiden dat samen met metadata onderdeel uitmaakt van een item. De naam bitstream duidt op het feit dat het bestand achterliggend wordt opgeslaan zonder bestandsextensie.", - + // "admin.registries.bitstream-formats.edit.description.hint": "", // TODO New key - Add a translation "admin.registries.bitstream-formats.edit.description.hint": "", - + // "admin.registries.bitstream-formats.edit.description.label": "Description", - // TODO New key - Add a translation - "admin.registries.bitstream-formats.edit.description.label": "Description", - + "admin.registries.bitstream-formats.edit.description.label": "Beschrijving", + // "admin.registries.bitstream-formats.edit.extensions.hint": "Extensions are file extensions that are used to automatically identify the format of uploaded files. You can enter several extensions for each format.", // TODO New key - Add a translation "admin.registries.bitstream-formats.edit.extensions.hint": "Extensions are file extensions that are used to automatically identify the format of uploaded files. You can enter several extensions for each format.", - + // "admin.registries.bitstream-formats.edit.extensions.label": "File extensions", // TODO New key - Add a translation "admin.registries.bitstream-formats.edit.extensions.label": "File extensions", - + // "admin.registries.bitstream-formats.edit.extensions.placeholder": "Enter a file extenstion without the dot", // TODO New key - Add a translation "admin.registries.bitstream-formats.edit.extensions.placeholder": "Enter a file extenstion without the dot", - + // "admin.registries.bitstream-formats.edit.failure.content": "An error occurred while editing the bitstream format.", // TODO New key - Add a translation "admin.registries.bitstream-formats.edit.failure.content": "An error occurred while editing the bitstream format.", - + // "admin.registries.bitstream-formats.edit.failure.head": "Failure", // TODO New key - Add a translation "admin.registries.bitstream-formats.edit.failure.head": "Failure", - + // "admin.registries.bitstream-formats.edit.head": "Bitstream format: {{ format }}", - // TODO New key - Add a translation - "admin.registries.bitstream-formats.edit.head": "Bitstream format: {{ format }}", - + "admin.registries.bitstream-formats.edit.head": "Bitstream formaat: {{ format }}", + // "admin.registries.bitstream-formats.edit.internal.hint": "Formats marked as internal are hidden from the user, and used for administrative purposes.", // TODO New key - Add a translation "admin.registries.bitstream-formats.edit.internal.hint": "Formats marked as internal are hidden from the user, and used for administrative purposes.", - + // "admin.registries.bitstream-formats.edit.internal.label": "Internal", - // TODO New key - Add a translation - "admin.registries.bitstream-formats.edit.internal.label": "Internal", - + "admin.registries.bitstream-formats.edit.internal.label": "Intern", + // "admin.registries.bitstream-formats.edit.mimetype.hint": "The MIME type associated with this format, does not have to be unique.", // TODO New key - Add a translation "admin.registries.bitstream-formats.edit.mimetype.hint": "The MIME type associated with this format, does not have to be unique.", - + // "admin.registries.bitstream-formats.edit.mimetype.label": "MIME Type", - // TODO New key - Add a translation - "admin.registries.bitstream-formats.edit.mimetype.label": "MIME Type", - + "admin.registries.bitstream-formats.edit.mimetype.label": "MIME Type", + // "admin.registries.bitstream-formats.edit.shortDescription.hint": "A unique name for this format, (e.g. Microsoft Word XP or Microsoft Word 2000)", // TODO New key - Add a translation "admin.registries.bitstream-formats.edit.shortDescription.hint": "A unique name for this format, (e.g. Microsoft Word XP or Microsoft Word 2000)", - + // "admin.registries.bitstream-formats.edit.shortDescription.label": "Name", - // TODO New key - Add a translation - "admin.registries.bitstream-formats.edit.shortDescription.label": "Name", - + "admin.registries.bitstream-formats.edit.shortDescription.label": "Naam", + // "admin.registries.bitstream-formats.edit.success.content": "The bitstream format was successfully edited.", // TODO New key - Add a translation "admin.registries.bitstream-formats.edit.success.content": "The bitstream format was successfully edited.", - + // "admin.registries.bitstream-formats.edit.success.head": "Success", - // TODO New key - Add a translation - "admin.registries.bitstream-formats.edit.success.head": "Success", - + "admin.registries.bitstream-formats.edit.success.head": "Succes", + // "admin.registries.bitstream-formats.edit.supportLevel.hint": "The level of support your institution pledges for this format.", // TODO New key - Add a translation "admin.registries.bitstream-formats.edit.supportLevel.hint": "The level of support your institution pledges for this format.", - + // "admin.registries.bitstream-formats.edit.supportLevel.label": "Support level", // TODO New key - Add a translation "admin.registries.bitstream-formats.edit.supportLevel.label": "Support level", - + // "admin.registries.bitstream-formats.head": "Bitstream Format Registry", "admin.registries.bitstream-formats.head": "Bitstream Formaat Register", - + // "admin.registries.bitstream-formats.no-items": "No bitstream formats to show.", // TODO New key - Add a translation "admin.registries.bitstream-formats.no-items": "No bitstream formats to show.", - + // "admin.registries.bitstream-formats.table.delete": "Delete selected", // TODO New key - Add a translation "admin.registries.bitstream-formats.table.delete": "Delete selected", - + // "admin.registries.bitstream-formats.table.deselect-all": "Deselect all", // TODO New key - Add a translation "admin.registries.bitstream-formats.table.deselect-all": "Deselect all", - + // "admin.registries.bitstream-formats.table.internal": "internal", - // TODO New key - Add a translation - "admin.registries.bitstream-formats.table.internal": "internal", - + "admin.registries.bitstream-formats.table.internal": "intern", + // "admin.registries.bitstream-formats.table.mimetype": "MIME Type", - // TODO New key - Add a translation "admin.registries.bitstream-formats.table.mimetype": "MIME Type", - + // "admin.registries.bitstream-formats.table.name": "Name", - // TODO New key - Add a translation - "admin.registries.bitstream-formats.table.name": "Name", - + "admin.registries.bitstream-formats.table.name": "Naam", + // "admin.registries.bitstream-formats.table.return": "Return", - // TODO New key - Add a translation - "admin.registries.bitstream-formats.table.return": "Return", - + "admin.registries.bitstream-formats.table.return": "Terug", + // "admin.registries.bitstream-formats.table.supportLevel.KNOWN": "Known", - // TODO New key - Add a translation - "admin.registries.bitstream-formats.table.supportLevel.KNOWN": "Known", - + "admin.registries.bitstream-formats.table.supportLevel.KNOWN": "Bekend", + // "admin.registries.bitstream-formats.table.supportLevel.SUPPORTED": "Supported", - // TODO New key - Add a translation - "admin.registries.bitstream-formats.table.supportLevel.SUPPORTED": "Supported", - + "admin.registries.bitstream-formats.table.supportLevel.SUPPORTED": "Ondersteund", + // "admin.registries.bitstream-formats.table.supportLevel.UNKNOWN": "Unknown", - // TODO New key - Add a translation - "admin.registries.bitstream-formats.table.supportLevel.UNKNOWN": "Unknown", - + "admin.registries.bitstream-formats.table.supportLevel.UNKNOWN": "Onbekend", + // "admin.registries.bitstream-formats.table.supportLevel.head": "Support Level", - // TODO New key - Add a translation - "admin.registries.bitstream-formats.table.supportLevel.head": "Support Level", - + "admin.registries.bitstream-formats.table.supportLevel.head": "Ondersteuningsniveau", + // "admin.registries.bitstream-formats.title": "DSpace Angular :: Bitstream Format Registry", "admin.registries.bitstream-formats.title": "DSpace Angular :: Bitstream Formaat Register", - - - + + + // "admin.registries.metadata.description": "The metadata registry maintains a list of all metadata fields available in the repository. These fields may be divided amongst multiple schemas. However, DSpace requires the qualified Dublin Core schema.", "admin.registries.metadata.description": "Het metadataregister omvat de lijst van alle metadatavelden die beschikbaar zijn in het systeem. Deze velden kunnen verspreid zijn over verschillende metadataschema's. Het qualified Dublin Core schema (dc) is een verplicht schema en kan niet worden verwijderd.", - + // "admin.registries.metadata.form.create": "Create metadata schema", - // TODO New key - Add a translation - "admin.registries.metadata.form.create": "Create metadata schema", - + "admin.registries.metadata.form.create": "Maak een metadata schema aan", + // "admin.registries.metadata.form.edit": "Edit metadata schema", - // TODO New key - Add a translation - "admin.registries.metadata.form.edit": "Edit metadata schema", - + "admin.registries.metadata.form.edit": "Bewerk een metadata schema", + // "admin.registries.metadata.form.name": "Name", - // TODO New key - Add a translation - "admin.registries.metadata.form.name": "Name", - + "admin.registries.metadata.form.name": "Naam", + // "admin.registries.metadata.form.namespace": "Namespace", - // TODO New key - Add a translation "admin.registries.metadata.form.namespace": "Namespace", - + // "admin.registries.metadata.head": "Metadata Registry", "admin.registries.metadata.head": "Metadata Register", - + // "admin.registries.metadata.schemas.no-items": "No metadata schemas to show.", "admin.registries.metadata.schemas.no-items": "Er kunnen geen metadataschema's getoond worden.", - + // "admin.registries.metadata.schemas.table.delete": "Delete selected", // TODO New key - Add a translation "admin.registries.metadata.schemas.table.delete": "Delete selected", - + // "admin.registries.metadata.schemas.table.id": "ID", "admin.registries.metadata.schemas.table.id": "ID", - + // "admin.registries.metadata.schemas.table.name": "Name", "admin.registries.metadata.schemas.table.name": "Naam", - + // "admin.registries.metadata.schemas.table.namespace": "Namespace", - "admin.registries.metadata.schemas.table.namespace": "Naamruimte", - + "admin.registries.metadata.schemas.table.namespace": "Namespace", + // "admin.registries.metadata.title": "DSpace Angular :: Metadata Registry", "admin.registries.metadata.title": "DSpace Angular :: Metadata Register", - - - + + + // "admin.registries.schema.description": "This is the metadata schema for \"{{namespace}}\".", "admin.registries.schema.description": "Dit is het metadataschema voor \"{{namespace}}\".", - + // "admin.registries.schema.fields.head": "Schema metadata fields", "admin.registries.schema.fields.head": "Schema metadatavelden", - + // "admin.registries.schema.fields.no-items": "No metadata fields to show.", "admin.registries.schema.fields.no-items": "Er kunnen geen metadatavelden getoond worden.", - + // "admin.registries.schema.fields.table.delete": "Delete selected", // TODO New key - Add a translation "admin.registries.schema.fields.table.delete": "Delete selected", - + // "admin.registries.schema.fields.table.field": "Field", "admin.registries.schema.fields.table.field": "Veld", - + // "admin.registries.schema.fields.table.scopenote": "Scope Note", "admin.registries.schema.fields.table.scopenote": "Opmerking over bereik", - + // "admin.registries.schema.form.create": "Create metadata field", - // TODO New key - Add a translation - "admin.registries.schema.form.create": "Create metadata field", - + "admin.registries.schema.form.create": "Maak een metadataveld aan", + // "admin.registries.schema.form.edit": "Edit metadata field", - // TODO New key - Add a translation - "admin.registries.schema.form.edit": "Edit metadata field", - + "admin.registries.schema.form.edit": "Bewerk metadataveld", + // "admin.registries.schema.form.element": "Element", // TODO New key - Add a translation "admin.registries.schema.form.element": "Element", - + // "admin.registries.schema.form.qualifier": "Qualifier", // TODO New key - Add a translation "admin.registries.schema.form.qualifier": "Qualifier", - + // "admin.registries.schema.form.scopenote": "Scope Note", // TODO New key - Add a translation "admin.registries.schema.form.scopenote": "Scope Note", - + // "admin.registries.schema.head": "Metadata Schema", "admin.registries.schema.head": "Metadata Schema", - + // "admin.registries.schema.notification.created": "Successfully created metadata schema \"{{prefix}}\"", // TODO New key - Add a translation "admin.registries.schema.notification.created": "Successfully created metadata schema \"{{prefix}}\"", - + // "admin.registries.schema.notification.deleted.failure": "Failed to delete {{amount}} metadata schemas", // TODO New key - Add a translation "admin.registries.schema.notification.deleted.failure": "Failed to delete {{amount}} metadata schemas", - + // "admin.registries.schema.notification.deleted.success": "Successfully deleted {{amount}} metadata schemas", // TODO New key - Add a translation "admin.registries.schema.notification.deleted.success": "Successfully deleted {{amount}} metadata schemas", - + // "admin.registries.schema.notification.edited": "Successfully edited metadata schema \"{{prefix}}\"", // TODO New key - Add a translation "admin.registries.schema.notification.edited": "Successfully edited metadata schema \"{{prefix}}\"", - + // "admin.registries.schema.notification.failure": "Error", // TODO New key - Add a translation "admin.registries.schema.notification.failure": "Error", - + // "admin.registries.schema.notification.field.created": "Successfully created metadata field \"{{field}}\"", // TODO New key - Add a translation "admin.registries.schema.notification.field.created": "Successfully created metadata field \"{{field}}\"", - + // "admin.registries.schema.notification.field.deleted.failure": "Failed to delete {{amount}} metadata fields", // TODO New key - Add a translation "admin.registries.schema.notification.field.deleted.failure": "Failed to delete {{amount}} metadata fields", - + // "admin.registries.schema.notification.field.deleted.success": "Successfully deleted {{amount}} metadata fields", // TODO New key - Add a translation "admin.registries.schema.notification.field.deleted.success": "Successfully deleted {{amount}} metadata fields", - + // "admin.registries.schema.notification.field.edited": "Successfully edited metadata field \"{{field}}\"", // TODO New key - Add a translation "admin.registries.schema.notification.field.edited": "Successfully edited metadata field \"{{field}}\"", - + // "admin.registries.schema.notification.success": "Success", - // TODO New key - Add a translation - "admin.registries.schema.notification.success": "Success", - + "admin.registries.schema.notification.success": "Succes", + // "admin.registries.schema.return": "Return", - // TODO New key - Add a translation - "admin.registries.schema.return": "Return", - + "admin.registries.schema.return": "Terug", + // "admin.registries.schema.title": "DSpace Angular :: Metadata Schema Registry", "admin.registries.schema.title": "DSpace Angular :: Metadata Schema Register", - - - + + + // "auth.errors.invalid-user": "Invalid email address or password.", "auth.errors.invalid-user": "Ongeldig e-mailadres of wachtwoord.", - + // "auth.messages.expired": "Your session has expired. Please log in again.", "auth.messages.expired": "Uw sessie is vervallen. Gelieve opnieuw aan te melden.", - - - + + + // "browse.comcol.by.author": "By Author", - // TODO New key - Add a translation - "browse.comcol.by.author": "By Author", - + "browse.comcol.by.author": "Op auteur", + // "browse.comcol.by.dateissued": "By Issue Date", - // TODO New key - Add a translation - "browse.comcol.by.dateissued": "By Issue Date", - + "browse.comcol.by.dateissued": "Op datum van uitgave", + // "browse.comcol.by.subject": "By Subject", - // TODO New key - Add a translation - "browse.comcol.by.subject": "By Subject", - + "browse.comcol.by.subject": "Op onderwerp", + // "browse.comcol.by.title": "By Title", - // TODO New key - Add a translation - "browse.comcol.by.title": "By Title", - + "browse.comcol.by.title": "Op titel", + // "browse.comcol.head": "Browse", - // TODO New key - Add a translation - "browse.comcol.head": "Browse", - + "browse.comcol.head": "Blader", + // "browse.empty": "No items to show.", - // TODO New key - Add a translation - "browse.empty": "No items to show.", - + "browse.empty": "Geen items om te tonen.", + // "browse.metadata.author": "Author", - // TODO New key - Add a translation - "browse.metadata.author": "Author", - + "browse.metadata.author": "Auteur", + // "browse.metadata.dateissued": "Issue Date", - // TODO New key - Add a translation - "browse.metadata.dateissued": "Issue Date", - + "browse.metadata.dateissued": "Datum van uitgave", + // "browse.metadata.subject": "Subject", - // TODO New key - Add a translation - "browse.metadata.subject": "Subject", - + "browse.metadata.subject": "Onderwerp", + // "browse.metadata.title": "Title", - // TODO New key - Add a translation - "browse.metadata.title": "Title", - + "browse.metadata.title": "Titel", + // "browse.startsWith.choose_start": "(Choose start)", - // TODO New key - Add a translation - "browse.startsWith.choose_start": "(Choose start)", - + "browse.startsWith.choose_start": "(Kies begin)", + // "browse.startsWith.choose_year": "(Choose year)", - // TODO New key - Add a translation - "browse.startsWith.choose_year": "(Choose year)", - + "browse.startsWith.choose_year": "(Kies jaar)", + // "browse.startsWith.jump": "Jump to a point in the index:", - // TODO New key - Add a translation - "browse.startsWith.jump": "Jump to a point in the index:", - + "browse.startsWith.jump": "Ga naar een plaats in de index:", + // "browse.startsWith.months.april": "April", - // TODO New key - Add a translation "browse.startsWith.months.april": "April", - + // "browse.startsWith.months.august": "August", - // TODO New key - Add a translation - "browse.startsWith.months.august": "August", - + "browse.startsWith.months.august": "Augustus", + // "browse.startsWith.months.december": "December", - // TODO New key - Add a translation "browse.startsWith.months.december": "December", - + // "browse.startsWith.months.february": "February", - // TODO New key - Add a translation - "browse.startsWith.months.february": "February", - + "browse.startsWith.months.february": "Februari", + // "browse.startsWith.months.january": "January", - // TODO New key - Add a translation - "browse.startsWith.months.january": "January", - + "browse.startsWith.months.january": "Januari", + // "browse.startsWith.months.july": "July", - // TODO New key - Add a translation - "browse.startsWith.months.july": "July", - + "browse.startsWith.months.july": "Juli", + // "browse.startsWith.months.june": "June", - // TODO New key - Add a translation - "browse.startsWith.months.june": "June", - + "browse.startsWith.months.june": "Juni", + // "browse.startsWith.months.march": "March", - // TODO New key - Add a translation - "browse.startsWith.months.march": "March", - + "browse.startsWith.months.march": "Maart", + // "browse.startsWith.months.may": "May", - // TODO New key - Add a translation - "browse.startsWith.months.may": "May", - + "browse.startsWith.months.may": "Mei", + // "browse.startsWith.months.none": "(Choose month)", - // TODO New key - Add a translation - "browse.startsWith.months.none": "(Choose month)", - + "browse.startsWith.months.none": "(Kies maand)", + // "browse.startsWith.months.november": "November", - // TODO New key - Add a translation "browse.startsWith.months.november": "November", - + // "browse.startsWith.months.october": "October", - // TODO New key - Add a translation - "browse.startsWith.months.october": "October", - + "browse.startsWith.months.october": "Oktober", + // "browse.startsWith.months.september": "September", - // TODO New key - Add a translation "browse.startsWith.months.september": "September", - + // "browse.startsWith.submit": "Go", - // TODO New key - Add a translation - "browse.startsWith.submit": "Go", - + "browse.startsWith.submit": "Ga", + // "browse.startsWith.type_date": "Or type in a date (year-month):", - // TODO New key - Add a translation - "browse.startsWith.type_date": "Or type in a date (year-month):", - + "browse.startsWith.type_date": "Of type een datum (jaar-maand):", + // "browse.startsWith.type_text": "Or enter first few letters:", - // TODO New key - Add a translation - "browse.startsWith.type_text": "Or enter first few letters:", - + "browse.startsWith.type_text": "Or vul de eerste paar letters in:", + // "browse.title": "Browsing {{ collection }} by {{ field }} {{ value }}", "browse.title": "Verken {{ collection }} volgens {{ field }} {{ value }}", - - - + + + // "chips.remove": "Remove chip", - // TODO New key - Add a translation - "chips.remove": "Remove chip", - - - + "chips.remove": "Verwijder chip", + + + // "collection.create.head": "Create a Collection", - // TODO New key - Add a translation - "collection.create.head": "Create a Collection", - + "collection.create.head": "Maak een collectie aan", + // "collection.create.sub-head": "Create a Collection for Community {{ parent }}", - // TODO New key - Add a translation - "collection.create.sub-head": "Create a Collection for Community {{ parent }}", - + "collection.create.sub-head": "Maak een collectie voor de community {{ parent }}", + // "collection.delete.cancel": "Cancel", - // TODO New key - Add a translation - "collection.delete.cancel": "Cancel", - + "collection.delete.cancel": "Annuleer", + // "collection.delete.confirm": "Confirm", - // TODO New key - Add a translation - "collection.delete.confirm": "Confirm", - + "collection.delete.confirm": "Bevestig", + // "collection.delete.head": "Delete Collection", - // TODO New key - Add a translation - "collection.delete.head": "Delete Collection", - + "collection.delete.head": "Verwijder Collectie", + // "collection.delete.notification.fail": "Collection could not be deleted", - // TODO New key - Add a translation - "collection.delete.notification.fail": "Collection could not be deleted", - + "collection.delete.notification.fail": "De collectie kon niet verwijderd worden", + // "collection.delete.notification.success": "Successfully deleted collection", - // TODO New key - Add a translation - "collection.delete.notification.success": "Successfully deleted collection", - + "collection.delete.notification.success": "De collectie is verwijderd", + // "collection.delete.text": "Are you sure you want to delete collection \"{{ dso }}\"", - // TODO New key - Add a translation - "collection.delete.text": "Are you sure you want to delete collection \"{{ dso }}\"", - - - + "collection.delete.text": "Weet u zeker dat u de collectie \"{{ dso }}\" wilt verwijderen?", + // "collection.edit.delete": "Delete this collection", - // TODO New key - Add a translation - "collection.edit.delete": "Delete this collection", - + "collection.edit.delete": "Verwijder deze collectie", + // "collection.edit.head": "Edit Collection", - // TODO New key - Add a translation - "collection.edit.head": "Edit Collection", - - - + "collection.edit.head": "Bewerk de collectie", + + + // "collection.edit.item-mapper.cancel": "Cancel", - // TODO New key - Add a translation - "collection.edit.item-mapper.cancel": "Cancel", - + "collection.edit.item-mapper.cancel": "Annuleer", + // "collection.edit.item-mapper.collection": "Collection: \"{{name}}\"", - // TODO New key - Add a translation - "collection.edit.item-mapper.collection": "Collection: \"{{name}}\"", - + "collection.edit.item-mapper.collection": "Collectie: \"{{name}}\"", + // "collection.edit.item-mapper.confirm": "Map selected items", - // TODO New key - Add a translation - "collection.edit.item-mapper.confirm": "Map selected items", - + "collection.edit.item-mapper.confirm": "Map de geselecteerde items", + // "collection.edit.item-mapper.description": "This is the item mapper tool that allows collection administrators to map items from other collections into this collection. You can search for items from other collections and map them, or browse the list of currently mapped items.", // TODO New key - Add a translation "collection.edit.item-mapper.description": "This is the item mapper tool that allows collection administrators to map items from other collections into this collection. You can search for items from other collections and map them, or browse the list of currently mapped items.", - + // "collection.edit.item-mapper.head": "Item Mapper - Map Items from Other Collections", // TODO New key - Add a translation "collection.edit.item-mapper.head": "Item Mapper - Map Items from Other Collections", - + // "collection.edit.item-mapper.no-search": "Please enter a query to search", // TODO New key - Add a translation "collection.edit.item-mapper.no-search": "Please enter a query to search", - + // "collection.edit.item-mapper.notifications.map.error.content": "Errors occurred for mapping of {{amount}} items.", // TODO New key - Add a translation "collection.edit.item-mapper.notifications.map.error.content": "Errors occurred for mapping of {{amount}} items.", - + // "collection.edit.item-mapper.notifications.map.error.head": "Mapping errors", // TODO New key - Add a translation "collection.edit.item-mapper.notifications.map.error.head": "Mapping errors", - + // "collection.edit.item-mapper.notifications.map.success.content": "Successfully mapped {{amount}} items.", // TODO New key - Add a translation "collection.edit.item-mapper.notifications.map.success.content": "Successfully mapped {{amount}} items.", - + // "collection.edit.item-mapper.notifications.map.success.head": "Mapping completed", // TODO New key - Add a translation "collection.edit.item-mapper.notifications.map.success.head": "Mapping completed", - + // "collection.edit.item-mapper.notifications.unmap.error.content": "Errors occurred for removing the mappings of {{amount}} items.", // TODO New key - Add a translation "collection.edit.item-mapper.notifications.unmap.error.content": "Errors occurred for removing the mappings of {{amount}} items.", - + // "collection.edit.item-mapper.notifications.unmap.error.head": "Remove mapping errors", // TODO New key - Add a translation "collection.edit.item-mapper.notifications.unmap.error.head": "Remove mapping errors", - + // "collection.edit.item-mapper.notifications.unmap.success.content": "Successfully removed the mappings of {{amount}} items.", // TODO New key - Add a translation "collection.edit.item-mapper.notifications.unmap.success.content": "Successfully removed the mappings of {{amount}} items.", - + // "collection.edit.item-mapper.notifications.unmap.success.head": "Remove mapping completed", // TODO New key - Add a translation "collection.edit.item-mapper.notifications.unmap.success.head": "Remove mapping completed", - + // "collection.edit.item-mapper.remove": "Remove selected item mappings", // TODO New key - Add a translation "collection.edit.item-mapper.remove": "Remove selected item mappings", - + // "collection.edit.item-mapper.tabs.browse": "Browse mapped items", // TODO New key - Add a translation "collection.edit.item-mapper.tabs.browse": "Browse mapped items", - + // "collection.edit.item-mapper.tabs.map": "Map new items", // TODO New key - Add a translation "collection.edit.item-mapper.tabs.map": "Map new items", - - - + + + // "collection.form.abstract": "Short Description", - // TODO New key - Add a translation - "collection.form.abstract": "Short Description", - + "collection.form.abstract": "Korte beschrijving", + // "collection.form.description": "Introductory text (HTML)", - // TODO New key - Add a translation - "collection.form.description": "Introductory text (HTML)", - + "collection.form.description": "Inleidende tekst (HTML)", + // "collection.form.errors.title.required": "Please enter a collection name", - // TODO New key - Add a translation - "collection.form.errors.title.required": "Please enter a collection name", - + "collection.form.errors.title.required": "Vul alstublieft een collectienaam in", + // "collection.form.license": "License", - // TODO New key - Add a translation - "collection.form.license": "License", - + "collection.form.license": "Licentie", + // "collection.form.provenance": "Provenance", - // TODO New key - Add a translation - "collection.form.provenance": "Provenance", - + "collection.form.provenance": "Herkomst", + // "collection.form.rights": "Copyright text (HTML)", - // TODO New key - Add a translation - "collection.form.rights": "Copyright text (HTML)", - + "collection.form.rights": "Auteursrechten-tekst (HTML)", + // "collection.form.tableofcontents": "News (HTML)", - // TODO New key - Add a translation - "collection.form.tableofcontents": "News (HTML)", - + "collection.form.tableofcontents": "Nieuws (HTML)", + // "collection.form.title": "Name", - // TODO New key - Add a translation - "collection.form.title": "Name", - - - + "collection.form.title": "Naam", + + + // "collection.page.browse.recent.head": "Recent Submissions", "collection.page.browse.recent.head": "Recent toegevoegd", - + // "collection.page.browse.recent.empty": "No items to show", - // TODO New key - Add a translation - "collection.page.browse.recent.empty": "No items to show", - + "collection.page.browse.recent.empty": "Geen items om te tonen", + // "collection.page.handle": "Permanent URI for this collection", - // TODO New key - Add a translation - "collection.page.handle": "Permanent URI for this collection", - + "collection.page.handle": "Permanente URI voor deze collectie", + // "collection.page.license": "License", "collection.page.license": "Licentie", - + // "collection.page.news": "News", "collection.page.news": "Nieuws", - - - + + + // "collection.select.confirm": "Confirm selected", - // TODO New key - Add a translation - "collection.select.confirm": "Confirm selected", - + "collection.select.confirm": "Bevestig uw keuze", + // "collection.select.empty": "No collections to show", - // TODO New key - Add a translation - "collection.select.empty": "No collections to show", - + "collection.select.empty": "Geen collecties om te tonen", + // "collection.select.table.title": "Title", - // TODO New key - Add a translation - "collection.select.table.title": "Title", - - - + "collection.select.table.title": "Titel", + + + // "community.create.head": "Create a Community", - // TODO New key - Add a translation - "community.create.head": "Create a Community", - + "community.create.head": "Maak een community aan", + // "community.create.sub-head": "Create a Sub-Community for Community {{ parent }}", - // TODO New key - Add a translation - "community.create.sub-head": "Create a Sub-Community for Community {{ parent }}", - + "community.create.sub-head": "Maak een sub-community voor community {{ parent }}", + // "community.delete.cancel": "Cancel", - // TODO New key - Add a translation - "community.delete.cancel": "Cancel", - + "community.delete.cancel": "Annuleer", + // "community.delete.confirm": "Confirm", - // TODO New key - Add a translation - "community.delete.confirm": "Confirm", - + "community.delete.confirm": "Bevestig", + // "community.delete.head": "Delete Community", - // TODO New key - Add a translation - "community.delete.head": "Delete Community", - + "community.delete.head": "Verwijder community", + // "community.delete.notification.fail": "Community could not be deleted", - // TODO New key - Add a translation - "community.delete.notification.fail": "Community could not be deleted", - + "community.delete.notification.fail": "De community kon niet verwijderd worden", + // "community.delete.notification.success": "Successfully deleted community", - // TODO New key - Add a translation - "community.delete.notification.success": "Successfully deleted community", - + "community.delete.notification.success": "Community succesvol verwijderd", + // "community.delete.text": "Are you sure you want to delete community \"{{ dso }}\"", - // TODO New key - Add a translation - "community.delete.text": "Are you sure you want to delete community \"{{ dso }}\"", - + "community.delete.text": "Weet u zeker dat u community \"{{ dso }}\" wilt verwijderen?", + // "community.edit.delete": "Delete this community", - // TODO New key - Add a translation - "community.edit.delete": "Delete this community", - + "community.edit.delete": "Verwijder deze community", + // "community.edit.head": "Edit Community", - // TODO New key - Add a translation - "community.edit.head": "Edit Community", - + "community.edit.head": "Bewerk community", + // "community.form.abstract": "Short Description", - // TODO New key - Add a translation - "community.form.abstract": "Short Description", - + "community.form.abstract": "Korte beschrijving", + // "community.form.description": "Introductory text (HTML)", - // TODO New key - Add a translation - "community.form.description": "Introductory text (HTML)", - + "community.form.description": "Inleidende tekst (HTML)", + // "community.form.errors.title.required": "Please enter a community name", - // TODO New key - Add a translation - "community.form.errors.title.required": "Please enter a community name", - + "community.form.errors.title.required": "Vul alstublieft een communitynaam in", + // "community.form.rights": "Copyright text (HTML)", - // TODO New key - Add a translation - "community.form.rights": "Copyright text (HTML)", - + "community.form.rights": "Auteursrechten-tekst (HTML)", + // "community.form.tableofcontents": "News (HTML)", - // TODO New key - Add a translation - "community.form.tableofcontents": "News (HTML)", - + "community.form.tableofcontents": "Nieuws (HTML)", + // "community.form.title": "Name", - // TODO New key - Add a translation - "community.form.title": "Name", - + "community.form.title": "Naam", + // "community.page.handle": "Permanent URI for this community", - // TODO New key - Add a translation - "community.page.handle": "Permanent URI for this community", - + "community.page.handle": "Permanente URI voor deze community", + // "community.page.license": "License", "community.page.license": "Licentie", - + // "community.page.news": "News", "community.page.news": "Nieuws", - + // "community.all-lists.head": "Subcommunities and Collections", - // TODO New key - Add a translation - "community.all-lists.head": "Subcommunities and Collections", - + "community.all-lists.head": "Subcommunities en collecties", + // "community.sub-collection-list.head": "Collections of this Community", - "community.sub-collection-list.head": "Collecties in deze Community", - + "community.sub-collection-list.head": "Collecties in deze community", + // "community.sub-community-list.head": "Communities of this Community", - // TODO New key - Add a translation - "community.sub-community-list.head": "Communities of this Community", - - - + "community.sub-community-list.head": "Communities in deze community", + + + // "dso-selector.create.collection.head": "New collection", // TODO New key - Add a translation "dso-selector.create.collection.head": "New collection", - + // "dso-selector.create.community.head": "New community", // TODO New key - Add a translation "dso-selector.create.community.head": "New community", - + // "dso-selector.create.community.sub-level": "Create a new community in", // TODO New key - Add a translation "dso-selector.create.community.sub-level": "Create a new community in", - + // "dso-selector.create.community.top-level": "Create a new top-level community", // TODO New key - Add a translation "dso-selector.create.community.top-level": "Create a new top-level community", - + // "dso-selector.create.item.head": "New item", // TODO New key - Add a translation "dso-selector.create.item.head": "New item", - + // "dso-selector.edit.collection.head": "Edit collection", // TODO New key - Add a translation "dso-selector.edit.collection.head": "Edit collection", - + // "dso-selector.edit.community.head": "Edit community", // TODO New key - Add a translation "dso-selector.edit.community.head": "Edit community", - + // "dso-selector.edit.item.head": "Edit item", // TODO New key - Add a translation "dso-selector.edit.item.head": "Edit item", - + // "dso-selector.no-results": "No {{ type }} found", // TODO New key - Add a translation "dso-selector.no-results": "No {{ type }} found", - + // "dso-selector.placeholder": "Search for a {{ type }}", // TODO New key - Add a translation "dso-selector.placeholder": "Search for a {{ type }}", - - - + + + // "error.browse-by": "Error fetching items", "error.browse-by": "Fout bij het ophalen van items", - + // "error.collection": "Error fetching collection", "error.collection": "Fout bij het ophalen van een collectie", - + // "error.collections": "Error fetching collections", - // TODO New key - Add a translation - "error.collections": "Error fetching collections", - + "error.collections": "Fout bij het ophalen van de collecties", + // "error.community": "Error fetching community", "error.community": "Fout bij het ophalen van een community", + // "error.identifier": "No item found for the identifier", - // TODO New key - Add a translation - "error.identifier": "No item found for the identifier", - + "error.identifier": "Geen item gevonden voor deze identifier", + // "error.identifier": "No item found for the identifier", - // TODO New key - Add a translation - "error.identifier": "No item found for the identifier", - + "error.identifier": "Geen item gevonden voor deze identifier", + // "error.default": "Error", "error.default": "Fout", - + // "error.item": "Error fetching item", - "error.item": "Fout bij het ophalen van items", - + "error.item": "Fout bij het ophalen van het item", + // "error.items": "Error fetching items", - // TODO New key - Add a translation - "error.items": "Error fetching items", - + "error.items": "Fout bij het ophalen van items", + // "error.objects": "Error fetching objects", "error.objects": "Fout bij het ophalen van objecten", - + // "error.recent-submissions": "Error fetching recent submissions", "error.recent-submissions": "Fout bij het ophalen van recent toegevoegde items", - + // "error.search-results": "Error fetching search results", "error.search-results": "Fout bij het ophalen van zoekresultaten", - + // "error.sub-collections": "Error fetching sub-collections", "error.sub-collections": "Fout bij het ophalen van sub-collecties", - + // "error.sub-communities": "Error fetching sub-communities", - // TODO New key - Add a translation - "error.sub-communities": "Error fetching sub-communities", - + "error.sub-communities": "Fout bij het ophalen van sub-communities", + // "error.submission.sections.init-form-error": "An error occurred during section initialize, please check your input-form configuration. Details are below :

", // TODO New key - Add a translation "error.submission.sections.init-form-error": "An error occurred during section initialize, please check your input-form configuration. Details are below :

", - + // "error.top-level-communities": "Error fetching top-level communities", "error.top-level-communities": "Fout bij het inladen van communities op het hoogste niveau", - + // "error.validation.license.notgranted": "You must grant this license to complete your submission. If you are unable to grant this license at this time you may save your work and return later or remove the submission.", "error.validation.license.notgranted": "U moet de invoerlicentie goedkeuren om de invoer af te werken. Indien u deze licentie momenteel niet kan of mag goedkeuren, kan u uw werk opslaan en de invoer later afwerken. U kunt dit nieuwe item ook verwijderen indien u niet voldoet aan de vereisten van de invoerlicentie.", - + // "error.validation.pattern": "This input is restricted by the current pattern: {{ pattern }}.", // TODO New key - Add a translation "error.validation.pattern": "This input is restricted by the current pattern: {{ pattern }}.", - - - + + + // "footer.copyright": "copyright © 2002-{{ year }}", "footer.copyright": "copyright © 2002-{{ year }}", - + // "footer.link.dspace": "DSpace software", "footer.link.dspace": "DSpace software", - + // "footer.link.duraspace": "DuraSpace", "footer.link.duraspace": "DuraSpace", - - - + + + // "form.cancel": "Cancel", "form.cancel": "Annuleer", - + // "form.clear": "Clear", - // TODO New key - Add a translation - "form.clear": "Clear", - + "form.clear": "Maak leeg", + // "form.clear-help": "Click here to remove the selected value", - // TODO New key - Add a translation - "form.clear-help": "Click here to remove the selected value", - + "form.clear-help": "Klik hier om de geselecteerde waarde the verwijderen", + // "form.edit": "Edit", - // TODO New key - Add a translation - "form.edit": "Edit", - + "form.edit": "Bewerk", + // "form.edit-help": "Click here to edit the selected value", - // TODO New key - Add a translation - "form.edit-help": "Click here to edit the selected value", - + "form.edit-help": "Klik hier om de geselecteerde waarde te bewerken", + // "form.first-name": "First name", "form.first-name": "Voornaam", - + // "form.group-collapse": "Collapse", "form.group-collapse": "Inklappen", - + // "form.group-collapse-help": "Click here to collapse", "form.group-collapse-help": "Klik hier op in te klappen", - + // "form.group-expand": "Expand", "form.group-expand": "Uitklappen", - + // "form.group-expand-help": "Click here to expand and add more elements", "form.group-expand-help": "Klik hier om uit te klappen en om meer onderdelen toe te voegen", - + // "form.last-name": "Last name", "form.last-name": "Achternaam", - + // "form.loading": "Loading...", "form.loading": "Inladen...", - + // "form.no-results": "No results found", "form.no-results": "Geen resultaten gevonden", - + // "form.no-value": "No value entered", "form.no-value": "Geen waarde ingevoerd", - + // "form.other-information": {}, // TODO New key - Add a translation "form.other-information": {}, - + // "form.remove": "Remove", "form.remove": "Verwijder", - + // "form.save": "Save", - // TODO New key - Add a translation - "form.save": "Save", - + "form.save": "Bewaar", + // "form.save-help": "Save changes", - // TODO New key - Add a translation - "form.save-help": "Save changes", - + "form.save-help": "Veranderingen opslaan", + // "form.search": "Search", "form.search": "Zoek", - + // "form.search-help": "Click here to looking for an existing correspondence", // TODO New key - Add a translation "form.search-help": "Click here to looking for an existing correspondence", - + // "form.submit": "Submit", "form.submit": "Verstuur", - - - + + + // "home.description": "", "home.description": "", - + // "home.title": "DSpace Angular :: Home", "home.title": "DSpace Angular :: Home", - + // "home.top-level-communities.head": "Communities in DSpace", "home.top-level-communities.head": "Communities in DSpace", - + // "home.top-level-communities.help": "Select a community to browse its collections.", "home.top-level-communities.help": "Selecteer een community om diens collecties te verkennen.", - - - + + + // "item.edit.delete.cancel": "Cancel", - // TODO New key - Add a translation - "item.edit.delete.cancel": "Cancel", - + "item.edit.delete.cancel": "Annuleer", + // "item.edit.delete.confirm": "Delete", - // TODO New key - Add a translation - "item.edit.delete.confirm": "Delete", - + "item.edit.delete.confirm": "Verwijder", + // "item.edit.delete.description": "Are you sure this item should be completely deleted? Caution: At present, no tombstone would be left.", - // TODO New key - Add a translation - "item.edit.delete.description": "Are you sure this item should be completely deleted? Caution: At present, no tombstone would be left.", - + "item.edit.delete.description": "Weet u zeker dat dit item geheel verwijderd moet worden? Pas op: er zal geen tombstone overblijven.", + // "item.edit.delete.error": "An error occurred while deleting the item", - // TODO New key - Add a translation - "item.edit.delete.error": "An error occurred while deleting the item", - + "item.edit.delete.error": "Er is een fout opgetreden bij het verwijderen van het item", + // "item.edit.delete.header": "Delete item: {{ id }}", - // TODO New key - Add a translation - "item.edit.delete.header": "Delete item: {{ id }}", - + "item.edit.delete.header": "Verwijder item: {{ id }}", + // "item.edit.delete.success": "The item has been deleted", - // TODO New key - Add a translation - "item.edit.delete.success": "The item has been deleted", - + "item.edit.delete.success": "Het item is verwijderd", + // "item.edit.head": "Edit Item", - // TODO New key - Add a translation - "item.edit.head": "Edit Item", - - - + "item.edit.head": "Bewerk item", + + + // "item.edit.item-mapper.buttons.add": "Map item to selected collections", // TODO New key - Add a translation "item.edit.item-mapper.buttons.add": "Map item to selected collections", - + // "item.edit.item-mapper.buttons.remove": "Remove item's mapping for selected collections", // TODO New key - Add a translation "item.edit.item-mapper.buttons.remove": "Remove item's mapping for selected collections", - + // "item.edit.item-mapper.cancel": "Cancel", // TODO New key - Add a translation "item.edit.item-mapper.cancel": "Cancel", - + // "item.edit.item-mapper.description": "This is the item mapper tool that allows administrators to map this item to other collections. You can search for collections and map them, or browse the list of collections the item is currently mapped to.", // TODO New key - Add a translation "item.edit.item-mapper.description": "This is the item mapper tool that allows administrators to map this item to other collections. You can search for collections and map them, or browse the list of collections the item is currently mapped to.", - + // "item.edit.item-mapper.head": "Item Mapper - Map Item to Collections", // TODO New key - Add a translation "item.edit.item-mapper.head": "Item Mapper - Map Item to Collections", - + // "item.edit.item-mapper.item": "Item: \"{{name}}\"", // TODO New key - Add a translation "item.edit.item-mapper.item": "Item: \"{{name}}\"", - + // "item.edit.item-mapper.no-search": "Please enter a query to search", // TODO New key - Add a translation "item.edit.item-mapper.no-search": "Please enter a query to search", - + // "item.edit.item-mapper.notifications.add.error.content": "Errors occurred for mapping of item to {{amount}} collections.", // TODO New key - Add a translation "item.edit.item-mapper.notifications.add.error.content": "Errors occurred for mapping of item to {{amount}} collections.", - + // "item.edit.item-mapper.notifications.add.error.head": "Mapping errors", // TODO New key - Add a translation "item.edit.item-mapper.notifications.add.error.head": "Mapping errors", - + // "item.edit.item-mapper.notifications.add.success.content": "Successfully mapped item to {{amount}} collections.", // TODO New key - Add a translation "item.edit.item-mapper.notifications.add.success.content": "Successfully mapped item to {{amount}} collections.", - + // "item.edit.item-mapper.notifications.add.success.head": "Mapping completed", // TODO New key - Add a translation "item.edit.item-mapper.notifications.add.success.head": "Mapping completed", - + // "item.edit.item-mapper.notifications.remove.error.content": "Errors occurred for the removal of the mapping to {{amount}} collections.", // TODO New key - Add a translation "item.edit.item-mapper.notifications.remove.error.content": "Errors occurred for the removal of the mapping to {{amount}} collections.", - + // "item.edit.item-mapper.notifications.remove.error.head": "Removal of mapping errors", // TODO New key - Add a translation "item.edit.item-mapper.notifications.remove.error.head": "Removal of mapping errors", - + // "item.edit.item-mapper.notifications.remove.success.content": "Successfully removed mapping of item to {{amount}} collections.", // TODO New key - Add a translation "item.edit.item-mapper.notifications.remove.success.content": "Successfully removed mapping of item to {{amount}} collections.", - + // "item.edit.item-mapper.notifications.remove.success.head": "Removal of mapping completed", // TODO New key - Add a translation "item.edit.item-mapper.notifications.remove.success.head": "Removal of mapping completed", - + // "item.edit.item-mapper.tabs.browse": "Browse mapped collections", // TODO New key - Add a translation "item.edit.item-mapper.tabs.browse": "Browse mapped collections", - + // "item.edit.item-mapper.tabs.map": "Map new collections", // TODO New key - Add a translation "item.edit.item-mapper.tabs.map": "Map new collections", - - - + + + // "item.edit.metadata.add-button": "Add", // TODO New key - Add a translation "item.edit.metadata.add-button": "Add", - + // "item.edit.metadata.discard-button": "Discard", // TODO New key - Add a translation "item.edit.metadata.discard-button": "Discard", - + // "item.edit.metadata.edit.buttons.edit": "Edit", // TODO New key - Add a translation "item.edit.metadata.edit.buttons.edit": "Edit", - + // "item.edit.metadata.edit.buttons.remove": "Remove", // TODO New key - Add a translation "item.edit.metadata.edit.buttons.remove": "Remove", - + // "item.edit.metadata.edit.buttons.undo": "Undo changes", // TODO New key - Add a translation "item.edit.metadata.edit.buttons.undo": "Undo changes", - + // "item.edit.metadata.edit.buttons.unedit": "Stop editing", // TODO New key - Add a translation "item.edit.metadata.edit.buttons.unedit": "Stop editing", - + // "item.edit.metadata.headers.edit": "Edit", // TODO New key - Add a translation "item.edit.metadata.headers.edit": "Edit", - + // "item.edit.metadata.headers.field": "Field", // TODO New key - Add a translation "item.edit.metadata.headers.field": "Field", - + // "item.edit.metadata.headers.language": "Lang", // TODO New key - Add a translation "item.edit.metadata.headers.language": "Lang", - + // "item.edit.metadata.headers.value": "Value", // TODO New key - Add a translation "item.edit.metadata.headers.value": "Value", - + // "item.edit.metadata.metadatafield.invalid": "Please choose a valid metadata field", // TODO New key - Add a translation "item.edit.metadata.metadatafield.invalid": "Please choose a valid metadata field", - + // "item.edit.metadata.notifications.discarded.content": "Your changes were discarded. To reinstate your changes click the 'Undo' button", // TODO New key - Add a translation "item.edit.metadata.notifications.discarded.content": "Your changes were discarded. To reinstate your changes click the 'Undo' button", - + // "item.edit.metadata.notifications.discarded.title": "Changed discarded", // TODO New key - Add a translation "item.edit.metadata.notifications.discarded.title": "Changed discarded", - + // "item.edit.metadata.notifications.invalid.content": "Your changes were not saved. Please make sure all fields are valid before you save.", // TODO New key - Add a translation "item.edit.metadata.notifications.invalid.content": "Your changes were not saved. Please make sure all fields are valid before you save.", - + // "item.edit.metadata.notifications.invalid.title": "Metadata invalid", // TODO New key - Add a translation "item.edit.metadata.notifications.invalid.title": "Metadata invalid", - + // "item.edit.metadata.notifications.outdated.content": "The item you're currently working on has been changed by another user. Your current changes are discarded to prevent conflicts", // TODO New key - Add a translation "item.edit.metadata.notifications.outdated.content": "The item you're currently working on has been changed by another user. Your current changes are discarded to prevent conflicts", - + // "item.edit.metadata.notifications.outdated.title": "Changed outdated", // TODO New key - Add a translation "item.edit.metadata.notifications.outdated.title": "Changed outdated", - + // "item.edit.metadata.notifications.saved.content": "Your changes to this item's metadata were saved.", // TODO New key - Add a translation "item.edit.metadata.notifications.saved.content": "Your changes to this item's metadata were saved.", - + // "item.edit.metadata.notifications.saved.title": "Metadata saved", // TODO New key - Add a translation "item.edit.metadata.notifications.saved.title": "Metadata saved", - + // "item.edit.metadata.reinstate-button": "Undo", // TODO New key - Add a translation "item.edit.metadata.reinstate-button": "Undo", - + // "item.edit.metadata.save-button": "Save", // TODO New key - Add a translation "item.edit.metadata.save-button": "Save", - - - + + + // "item.edit.modify.overview.field": "Field", // TODO New key - Add a translation "item.edit.modify.overview.field": "Field", - + // "item.edit.modify.overview.language": "Language", // TODO New key - Add a translation "item.edit.modify.overview.language": "Language", - + // "item.edit.modify.overview.value": "Value", // TODO New key - Add a translation "item.edit.modify.overview.value": "Value", - - - + + + // "item.edit.move.cancel": "Cancel", // TODO New key - Add a translation "item.edit.move.cancel": "Cancel", - + // "item.edit.move.description": "Select the collection you wish to move this item to. To narrow down the list of displayed collections, you can enter a search query in the box.", // TODO New key - Add a translation "item.edit.move.description": "Select the collection you wish to move this item to. To narrow down the list of displayed collections, you can enter a search query in the box.", - + // "item.edit.move.error": "An error occurred when attempting to move the item", // TODO New key - Add a translation "item.edit.move.error": "An error occurred when attempting to move the item", - + // "item.edit.move.head": "Move item: {{id}}", // TODO New key - Add a translation "item.edit.move.head": "Move item: {{id}}", - + // "item.edit.move.inheritpolicies.checkbox": "Inherit policies", // TODO New key - Add a translation "item.edit.move.inheritpolicies.checkbox": "Inherit policies", - + // "item.edit.move.inheritpolicies.description": "Inherit the default policies of the destination collection", // TODO New key - Add a translation "item.edit.move.inheritpolicies.description": "Inherit the default policies of the destination collection", - + // "item.edit.move.move": "Move", // TODO New key - Add a translation "item.edit.move.move": "Move", - + // "item.edit.move.processing": "Moving...", // TODO New key - Add a translation "item.edit.move.processing": "Moving...", - + // "item.edit.move.search.placeholder": "Enter a search query to look for collections", // TODO New key - Add a translation "item.edit.move.search.placeholder": "Enter a search query to look for collections", - + // "item.edit.move.success": "The item has been moved successfully", // TODO New key - Add a translation "item.edit.move.success": "The item has been moved successfully", - + // "item.edit.move.title": "Move item", // TODO New key - Add a translation "item.edit.move.title": "Move item", - - - + + + // "item.edit.private.cancel": "Cancel", // TODO New key - Add a translation "item.edit.private.cancel": "Cancel", - + // "item.edit.private.confirm": "Make it Private", // TODO New key - Add a translation "item.edit.private.confirm": "Make it Private", - + // "item.edit.private.description": "Are you sure this item should be made private in the archive?", // TODO New key - Add a translation "item.edit.private.description": "Are you sure this item should be made private in the archive?", - + // "item.edit.private.error": "An error occurred while making the item private", // TODO New key - Add a translation "item.edit.private.error": "An error occurred while making the item private", - + // "item.edit.private.header": "Make item private: {{ id }}", // TODO New key - Add a translation "item.edit.private.header": "Make item private: {{ id }}", - + // "item.edit.private.success": "The item is now private", // TODO New key - Add a translation "item.edit.private.success": "The item is now private", - - - + + + // "item.edit.public.cancel": "Cancel", // TODO New key - Add a translation "item.edit.public.cancel": "Cancel", - + // "item.edit.public.confirm": "Make it Public", // TODO New key - Add a translation "item.edit.public.confirm": "Make it Public", - + // "item.edit.public.description": "Are you sure this item should be made public in the archive?", // TODO New key - Add a translation "item.edit.public.description": "Are you sure this item should be made public in the archive?", - + // "item.edit.public.error": "An error occurred while making the item public", // TODO New key - Add a translation "item.edit.public.error": "An error occurred while making the item public", - + // "item.edit.public.header": "Make item public: {{ id }}", // TODO New key - Add a translation "item.edit.public.header": "Make item public: {{ id }}", - + // "item.edit.public.success": "The item is now public", // TODO New key - Add a translation "item.edit.public.success": "The item is now public", - - - + + + // "item.edit.reinstate.cancel": "Cancel", // TODO New key - Add a translation "item.edit.reinstate.cancel": "Cancel", - + // "item.edit.reinstate.confirm": "Reinstate", // TODO New key - Add a translation "item.edit.reinstate.confirm": "Reinstate", - + // "item.edit.reinstate.description": "Are you sure this item should be reinstated to the archive?", // TODO New key - Add a translation "item.edit.reinstate.description": "Are you sure this item should be reinstated to the archive?", - + // "item.edit.reinstate.error": "An error occurred while reinstating the item", // TODO New key - Add a translation "item.edit.reinstate.error": "An error occurred while reinstating the item", - + // "item.edit.reinstate.header": "Reinstate item: {{ id }}", // TODO New key - Add a translation "item.edit.reinstate.header": "Reinstate item: {{ id }}", - + // "item.edit.reinstate.success": "The item was reinstated successfully", // TODO New key - Add a translation "item.edit.reinstate.success": "The item was reinstated successfully", - - - + + + // "item.edit.relationships.discard-button": "Discard", // TODO New key - Add a translation "item.edit.relationships.discard-button": "Discard", - + // "item.edit.relationships.edit.buttons.remove": "Remove", // TODO New key - Add a translation "item.edit.relationships.edit.buttons.remove": "Remove", - + // "item.edit.relationships.edit.buttons.undo": "Undo changes", // TODO New key - Add a translation "item.edit.relationships.edit.buttons.undo": "Undo changes", - + // "item.edit.relationships.notifications.discarded.content": "Your changes were discarded. To reinstate your changes click the 'Undo' button", // TODO New key - Add a translation "item.edit.relationships.notifications.discarded.content": "Your changes were discarded. To reinstate your changes click the 'Undo' button", - + // "item.edit.relationships.notifications.discarded.title": "Changes discarded", // TODO New key - Add a translation "item.edit.relationships.notifications.discarded.title": "Changes discarded", - + // "item.edit.relationships.notifications.failed.title": "Error deleting relationship", // TODO New key - Add a translation "item.edit.relationships.notifications.failed.title": "Error deleting relationship", - + // "item.edit.relationships.notifications.outdated.content": "The item you're currently working on has been changed by another user. Your current changes are discarded to prevent conflicts", // TODO New key - Add a translation "item.edit.relationships.notifications.outdated.content": "The item you're currently working on has been changed by another user. Your current changes are discarded to prevent conflicts", - + // "item.edit.relationships.notifications.outdated.title": "Changes outdated", // TODO New key - Add a translation "item.edit.relationships.notifications.outdated.title": "Changes outdated", - + // "item.edit.relationships.notifications.saved.content": "Your changes to this item's relationships were saved.", // TODO New key - Add a translation "item.edit.relationships.notifications.saved.content": "Your changes to this item's relationships were saved.", - + // "item.edit.relationships.notifications.saved.title": "Relationships saved", // TODO New key - Add a translation "item.edit.relationships.notifications.saved.title": "Relationships saved", - + // "item.edit.relationships.reinstate-button": "Undo", // TODO New key - Add a translation "item.edit.relationships.reinstate-button": "Undo", - + // "item.edit.relationships.save-button": "Save", // TODO New key - Add a translation "item.edit.relationships.save-button": "Save", - - - + + + // "item.edit.tabs.bitstreams.head": "Item Bitstreams", // TODO New key - Add a translation "item.edit.tabs.bitstreams.head": "Item Bitstreams", - + // "item.edit.tabs.bitstreams.title": "Item Edit - Bitstreams", // TODO New key - Add a translation "item.edit.tabs.bitstreams.title": "Item Edit - Bitstreams", - + // "item.edit.tabs.curate.head": "Curate", // TODO New key - Add a translation "item.edit.tabs.curate.head": "Curate", - + // "item.edit.tabs.curate.title": "Item Edit - Curate", // TODO New key - Add a translation "item.edit.tabs.curate.title": "Item Edit - Curate", - + // "item.edit.tabs.metadata.head": "Item Metadata", // TODO New key - Add a translation "item.edit.tabs.metadata.head": "Item Metadata", - + // "item.edit.tabs.metadata.title": "Item Edit - Metadata", // TODO New key - Add a translation "item.edit.tabs.metadata.title": "Item Edit - Metadata", - + // "item.edit.tabs.relationships.head": "Item Relationships", // TODO New key - Add a translation "item.edit.tabs.relationships.head": "Item Relationships", - + // "item.edit.tabs.relationships.title": "Item Edit - Relationships", // TODO New key - Add a translation "item.edit.tabs.relationships.title": "Item Edit - Relationships", - + // "item.edit.tabs.status.buttons.authorizations.button": "Authorizations...", // TODO New key - Add a translation "item.edit.tabs.status.buttons.authorizations.button": "Authorizations...", - + // "item.edit.tabs.status.buttons.authorizations.label": "Edit item's authorization policies", // TODO New key - Add a translation "item.edit.tabs.status.buttons.authorizations.label": "Edit item's authorization policies", - + // "item.edit.tabs.status.buttons.delete.button": "Permanently delete", // TODO New key - Add a translation "item.edit.tabs.status.buttons.delete.button": "Permanently delete", - + // "item.edit.tabs.status.buttons.delete.label": "Completely expunge item", // TODO New key - Add a translation "item.edit.tabs.status.buttons.delete.label": "Completely expunge item", - + // "item.edit.tabs.status.buttons.mappedCollections.button": "Mapped collections", // TODO New key - Add a translation "item.edit.tabs.status.buttons.mappedCollections.button": "Mapped collections", - + // "item.edit.tabs.status.buttons.mappedCollections.label": "Manage mapped collections", // TODO New key - Add a translation "item.edit.tabs.status.buttons.mappedCollections.label": "Manage mapped collections", - + // "item.edit.tabs.status.buttons.move.button": "Move...", // TODO New key - Add a translation "item.edit.tabs.status.buttons.move.button": "Move...", - + // "item.edit.tabs.status.buttons.move.label": "Move item to another collection", // TODO New key - Add a translation "item.edit.tabs.status.buttons.move.label": "Move item to another collection", - + // "item.edit.tabs.status.buttons.private.button": "Make it private...", // TODO New key - Add a translation "item.edit.tabs.status.buttons.private.button": "Make it private...", - + // "item.edit.tabs.status.buttons.private.label": "Make item private", // TODO New key - Add a translation "item.edit.tabs.status.buttons.private.label": "Make item private", - + // "item.edit.tabs.status.buttons.public.button": "Make it public...", // TODO New key - Add a translation "item.edit.tabs.status.buttons.public.button": "Make it public...", - + // "item.edit.tabs.status.buttons.public.label": "Make item public", // TODO New key - Add a translation "item.edit.tabs.status.buttons.public.label": "Make item public", - + // "item.edit.tabs.status.buttons.reinstate.button": "Reinstate...", // TODO New key - Add a translation "item.edit.tabs.status.buttons.reinstate.button": "Reinstate...", - + // "item.edit.tabs.status.buttons.reinstate.label": "Reinstate item into the repository", // TODO New key - Add a translation "item.edit.tabs.status.buttons.reinstate.label": "Reinstate item into the repository", - + // "item.edit.tabs.status.buttons.withdraw.button": "Withdraw...", // TODO New key - Add a translation "item.edit.tabs.status.buttons.withdraw.button": "Withdraw...", - + // "item.edit.tabs.status.buttons.withdraw.label": "Withdraw item from the repository", // TODO New key - Add a translation "item.edit.tabs.status.buttons.withdraw.label": "Withdraw item from the repository", - + // "item.edit.tabs.status.description": "Welcome to the item management page. From here you can withdraw, reinstate, move or delete the item. You may also update or add new metadata / bitstreams on the other tabs.", // TODO New key - Add a translation "item.edit.tabs.status.description": "Welcome to the item management page. From here you can withdraw, reinstate, move or delete the item. You may also update or add new metadata / bitstreams on the other tabs.", - + // "item.edit.tabs.status.head": "Item Status", // TODO New key - Add a translation "item.edit.tabs.status.head": "Item Status", - + // "item.edit.tabs.status.labels.handle": "Handle", // TODO New key - Add a translation "item.edit.tabs.status.labels.handle": "Handle", - + // "item.edit.tabs.status.labels.id": "Item Internal ID", // TODO New key - Add a translation "item.edit.tabs.status.labels.id": "Item Internal ID", - + // "item.edit.tabs.status.labels.itemPage": "Item Page", // TODO New key - Add a translation "item.edit.tabs.status.labels.itemPage": "Item Page", - + // "item.edit.tabs.status.labels.lastModified": "Last Modified", // TODO New key - Add a translation "item.edit.tabs.status.labels.lastModified": "Last Modified", - + // "item.edit.tabs.status.title": "Item Edit - Status", // TODO New key - Add a translation "item.edit.tabs.status.title": "Item Edit - Status", - + // "item.edit.tabs.view.head": "View Item", // TODO New key - Add a translation "item.edit.tabs.view.head": "View Item", - + // "item.edit.tabs.view.title": "Item Edit - View", // TODO New key - Add a translation "item.edit.tabs.view.title": "Item Edit - View", - - - + + + // "item.edit.withdraw.cancel": "Cancel", // TODO New key - Add a translation "item.edit.withdraw.cancel": "Cancel", - + // "item.edit.withdraw.confirm": "Withdraw", // TODO New key - Add a translation "item.edit.withdraw.confirm": "Withdraw", - + // "item.edit.withdraw.description": "Are you sure this item should be withdrawn from the archive?", // TODO New key - Add a translation "item.edit.withdraw.description": "Are you sure this item should be withdrawn from the archive?", - + // "item.edit.withdraw.error": "An error occurred while withdrawing the item", // TODO New key - Add a translation "item.edit.withdraw.error": "An error occurred while withdrawing the item", - + // "item.edit.withdraw.header": "Withdraw item: {{ id }}", // TODO New key - Add a translation "item.edit.withdraw.header": "Withdraw item: {{ id }}", - + // "item.edit.withdraw.success": "The item was withdrawn successfully", // TODO New key - Add a translation "item.edit.withdraw.success": "The item was withdrawn successfully", - - - + + + // "item.page.abstract": "Abstract", "item.page.abstract": "Abstract", - + // "item.page.author": "Authors", "item.page.author": "Auteur", - + // "item.page.citation": "Citation", // TODO New key - Add a translation "item.page.citation": "Citation", - + // "item.page.collections": "Collections", "item.page.collections": "Collecties", - + // "item.page.date": "Date", "item.page.date": "Datum", - + // "item.page.files": "Files", "item.page.files": "Bestanden", - + // "item.page.filesection.description": "Description:", // TODO New key - Add a translation "item.page.filesection.description": "Description:", - + // "item.page.filesection.download": "Download", "item.page.filesection.download": "Download", - + // "item.page.filesection.format": "Format:", // TODO New key - Add a translation "item.page.filesection.format": "Format:", - + // "item.page.filesection.name": "Name:", // TODO New key - Add a translation "item.page.filesection.name": "Name:", - + // "item.page.filesection.size": "Size:", // TODO New key - Add a translation "item.page.filesection.size": "Size:", - + // "item.page.journal.search.title": "Articles in this journal", // TODO New key - Add a translation "item.page.journal.search.title": "Articles in this journal", - + // "item.page.link.full": "Full item page", "item.page.link.full": "Volledige itemweergave", - + // "item.page.link.simple": "Simple item page", "item.page.link.simple": "Eenvoudige itemweergave", - + // "item.page.person.search.title": "Articles by this author", // TODO New key - Add a translation "item.page.person.search.title": "Articles by this author", - + // "item.page.related-items.view-more": "View more", // TODO New key - Add a translation "item.page.related-items.view-more": "View more", - + // "item.page.related-items.view-less": "View less", // TODO New key - Add a translation "item.page.related-items.view-less": "View less", - + // "item.page.subject": "Keywords", // TODO New key - Add a translation "item.page.subject": "Keywords", - + // "item.page.uri": "URI", "item.page.uri": "URI", - - - + + + // "item.select.confirm": "Confirm selected", // TODO New key - Add a translation "item.select.confirm": "Confirm selected", - + // "item.select.empty": "No items to show", // TODO New key - Add a translation "item.select.empty": "No items to show", - + // "item.select.table.author": "Author", // TODO New key - Add a translation "item.select.table.author": "Author", - + // "item.select.table.collection": "Collection", // TODO New key - Add a translation "item.select.table.collection": "Collection", - + // "item.select.table.title": "Title", // TODO New key - Add a translation "item.select.table.title": "Title", - - - + + + // "journal.listelement.badge": "Journal", // TODO New key - Add a translation "journal.listelement.badge": "Journal", - + // "journal.page.description": "Description", // TODO New key - Add a translation "journal.page.description": "Description", - + // "journal.page.editor": "Editor-in-Chief", // TODO New key - Add a translation "journal.page.editor": "Editor-in-Chief", - + // "journal.page.issn": "ISSN", // TODO New key - Add a translation "journal.page.issn": "ISSN", - + // "journal.page.publisher": "Publisher", // TODO New key - Add a translation "journal.page.publisher": "Publisher", - + // "journal.page.titleprefix": "Journal: ", // TODO New key - Add a translation "journal.page.titleprefix": "Journal: ", - + // "journal.search.results.head": "Journal Search Results", // TODO New key - Add a translation "journal.search.results.head": "Journal Search Results", - + // "journal.search.title": "DSpace Angular :: Journal Search", // TODO New key - Add a translation "journal.search.title": "DSpace Angular :: Journal Search", - - - + + + // "journalissue.listelement.badge": "Journal Issue", // TODO New key - Add a translation "journalissue.listelement.badge": "Journal Issue", - + // "journalissue.page.description": "Description", // TODO New key - Add a translation "journalissue.page.description": "Description", - + // "journalissue.page.issuedate": "Issue Date", // TODO New key - Add a translation "journalissue.page.issuedate": "Issue Date", - + // "journalissue.page.journal-issn": "Journal ISSN", // TODO New key - Add a translation "journalissue.page.journal-issn": "Journal ISSN", - + // "journalissue.page.journal-title": "Journal Title", // TODO New key - Add a translation "journalissue.page.journal-title": "Journal Title", - + // "journalissue.page.keyword": "Keywords", // TODO New key - Add a translation "journalissue.page.keyword": "Keywords", - + // "journalissue.page.number": "Number", // TODO New key - Add a translation "journalissue.page.number": "Number", - + // "journalissue.page.titleprefix": "Journal Issue: ", // TODO New key - Add a translation "journalissue.page.titleprefix": "Journal Issue: ", - - - + + + // "journalvolume.listelement.badge": "Journal Volume", // TODO New key - Add a translation "journalvolume.listelement.badge": "Journal Volume", - + // "journalvolume.page.description": "Description", // TODO New key - Add a translation "journalvolume.page.description": "Description", - + // "journalvolume.page.issuedate": "Issue Date", // TODO New key - Add a translation "journalvolume.page.issuedate": "Issue Date", - + // "journalvolume.page.titleprefix": "Journal Volume: ", // TODO New key - Add a translation "journalvolume.page.titleprefix": "Journal Volume: ", - + // "journalvolume.page.volume": "Volume", // TODO New key - Add a translation "journalvolume.page.volume": "Volume", - - - + + + // "loading.browse-by": "Loading items...", "loading.browse-by": "Items worden ingeladen...", - + // "loading.browse-by-page": "Loading page...", // TODO New key - Add a translation "loading.browse-by-page": "Loading page...", - + // "loading.collection": "Loading collection...", "loading.collection": "Collectie wordt ingeladen...", - + // "loading.collections": "Loading collections...", // TODO New key - Add a translation "loading.collections": "Loading collections...", - + // "loading.community": "Loading community...", "loading.community": "Community wordt ingeladen...", - + // "loading.default": "Loading...", "loading.default": "Laden...", - + // "loading.item": "Loading item...", "loading.item": "Item wordt ingeladen...", - + // "loading.items": "Loading items...", // TODO New key - Add a translation "loading.items": "Loading items...", - + // "loading.mydspace-results": "Loading items...", // TODO New key - Add a translation "loading.mydspace-results": "Loading items...", - + // "loading.objects": "Loading...", "loading.objects": "Laden...", - + // "loading.recent-submissions": "Loading recent submissions...", "loading.recent-submissions": "Recent toegevoegde items worden ingeladen...", - + // "loading.search-results": "Loading search results...", "loading.search-results": "Zoekresultaten worden ingeladen...", - + // "loading.sub-collections": "Loading sub-collections...", "loading.sub-collections": "De sub-collecties worden ingeladen...", - + // "loading.sub-communities": "Loading sub-communities...", // TODO New key - Add a translation "loading.sub-communities": "Loading sub-communities...", - + // "loading.top-level-communities": "Loading top-level communities...", "loading.top-level-communities": "Inladen van de Communities op het hoogste niveau...", - - - + + + // "login.form.email": "Email address", "login.form.email": "Email adres", - + // "login.form.forgot-password": "Have you forgotten your password?", "login.form.forgot-password": "Bent u uw wachtwoord vergeten?", - + // "login.form.header": "Please log in to DSpace", "login.form.header": "Gelieve in te loggen in DSpace", - + // "login.form.new-user": "New user? Click here to register.", "login.form.new-user": "Nieuwe gebruiker? Gelieve u hier te registreren", - + // "login.form.password": "Password", "login.form.password": "Wachtwoord", - + // "login.form.submit": "Log in", "login.form.submit": "Aanmelden", - + // "login.title": "Login", "login.title": "Aanmelden", - - - + + + // "logout.form.header": "Log out from DSpace", "logout.form.header": "Afmelden in DSpace", - + // "logout.form.submit": "Log out", "logout.form.submit": "Afmelden", - + // "logout.title": "Logout", "logout.title": "Afmelden", - - - + + + // "menu.header.admin": "Admin", // TODO New key - Add a translation "menu.header.admin": "Admin", - + // "menu.header.image.logo": "Repository logo", // TODO New key - Add a translation "menu.header.image.logo": "Repository logo", - - - + + + // "menu.section.access_control": "Access Control", // TODO New key - Add a translation "menu.section.access_control": "Access Control", - + // "menu.section.access_control_authorizations": "Authorizations", // TODO New key - Add a translation "menu.section.access_control_authorizations": "Authorizations", - + // "menu.section.access_control_groups": "Groups", // TODO New key - Add a translation "menu.section.access_control_groups": "Groups", - + // "menu.section.access_control_people": "People", // TODO New key - Add a translation "menu.section.access_control_people": "People", - - - + + + // "menu.section.browse_community": "This Community", // TODO New key - Add a translation "menu.section.browse_community": "This Community", - + // "menu.section.browse_community_by_author": "By Author", // TODO New key - Add a translation "menu.section.browse_community_by_author": "By Author", - + // "menu.section.browse_community_by_issue_date": "By Issue Date", // TODO New key - Add a translation "menu.section.browse_community_by_issue_date": "By Issue Date", - + // "menu.section.browse_community_by_title": "By Title", // TODO New key - Add a translation "menu.section.browse_community_by_title": "By Title", - + // "menu.section.browse_global": "All of DSpace", // TODO New key - Add a translation "menu.section.browse_global": "All of DSpace", - + // "menu.section.browse_global_by_author": "By Author", // TODO New key - Add a translation "menu.section.browse_global_by_author": "By Author", - + // "menu.section.browse_global_by_dateissued": "By Issue Date", // TODO New key - Add a translation "menu.section.browse_global_by_dateissued": "By Issue Date", - + // "menu.section.browse_global_by_subject": "By Subject", // TODO New key - Add a translation "menu.section.browse_global_by_subject": "By Subject", - + // "menu.section.browse_global_by_title": "By Title", // TODO New key - Add a translation "menu.section.browse_global_by_title": "By Title", - + // "menu.section.browse_global_communities_and_collections": "Communities & Collections", // TODO New key - Add a translation "menu.section.browse_global_communities_and_collections": "Communities & Collections", - - - + + + // "menu.section.control_panel": "Control Panel", // TODO New key - Add a translation "menu.section.control_panel": "Control Panel", - + // "menu.section.curation_task": "Curation Task", // TODO New key - Add a translation "menu.section.curation_task": "Curation Task", - - - + + + // "menu.section.edit": "Edit", // TODO New key - Add a translation "menu.section.edit": "Edit", - + // "menu.section.edit_collection": "Collection", // TODO New key - Add a translation "menu.section.edit_collection": "Collection", - + // "menu.section.edit_community": "Community", // TODO New key - Add a translation "menu.section.edit_community": "Community", - + // "menu.section.edit_item": "Item", // TODO New key - Add a translation "menu.section.edit_item": "Item", - - - + + + // "menu.section.export": "Export", // TODO New key - Add a translation "menu.section.export": "Export", - + // "menu.section.export_collection": "Collection", // TODO New key - Add a translation "menu.section.export_collection": "Collection", - + // "menu.section.export_community": "Community", // TODO New key - Add a translation "menu.section.export_community": "Community", - + // "menu.section.export_item": "Item", // TODO New key - Add a translation "menu.section.export_item": "Item", - + // "menu.section.export_metadata": "Metadata", // TODO New key - Add a translation "menu.section.export_metadata": "Metadata", - - - + + + // "menu.section.find": "Find", // TODO New key - Add a translation "menu.section.find": "Find", - + // "menu.section.find_items": "Items", // TODO New key - Add a translation "menu.section.find_items": "Items", - + // "menu.section.find_private_items": "Private Items", // TODO New key - Add a translation "menu.section.find_private_items": "Private Items", - + // "menu.section.find_withdrawn_items": "Withdrawn Items", // TODO New key - Add a translation "menu.section.find_withdrawn_items": "Withdrawn Items", - - - + + + // "menu.section.icon.access_control": "Access Control menu section", // TODO New key - Add a translation "menu.section.icon.access_control": "Access Control menu section", - + // "menu.section.icon.control_panel": "Control Panel menu section", // TODO New key - Add a translation "menu.section.icon.control_panel": "Control Panel menu section", - + // "menu.section.icon.curation_task": "Curation Task menu section", // TODO New key - Add a translation "menu.section.icon.curation_task": "Curation Task menu section", - + // "menu.section.icon.edit": "Edit menu section", // TODO New key - Add a translation "menu.section.icon.edit": "Edit menu section", - + // "menu.section.icon.export": "Export menu section", // TODO New key - Add a translation "menu.section.icon.export": "Export menu section", - + // "menu.section.icon.find": "Find menu section", // TODO New key - Add a translation "menu.section.icon.find": "Find menu section", - + // "menu.section.icon.import": "Import menu section", // TODO New key - Add a translation "menu.section.icon.import": "Import menu section", - + // "menu.section.icon.new": "New menu section", // TODO New key - Add a translation "menu.section.icon.new": "New menu section", - + // "menu.section.icon.pin": "Pin sidebar", // TODO New key - Add a translation "menu.section.icon.pin": "Pin sidebar", - + // "menu.section.icon.registries": "Registries menu section", // TODO New key - Add a translation "menu.section.icon.registries": "Registries menu section", - + // "menu.section.icon.statistics_task": "Statistics Task menu section", // TODO New key - Add a translation "menu.section.icon.statistics_task": "Statistics Task menu section", - + // "menu.section.icon.unpin": "Unpin sidebar", // TODO New key - Add a translation "menu.section.icon.unpin": "Unpin sidebar", - - - + + + // "menu.section.import": "Import", // TODO New key - Add a translation "menu.section.import": "Import", - + // "menu.section.import_batch": "Batch Import (ZIP)", // TODO New key - Add a translation "menu.section.import_batch": "Batch Import (ZIP)", - + // "menu.section.import_metadata": "Metadata", // TODO New key - Add a translation "menu.section.import_metadata": "Metadata", - - - + + + // "menu.section.new": "New", // TODO New key - Add a translation "menu.section.new": "New", - + // "menu.section.new_collection": "Collection", // TODO New key - Add a translation "menu.section.new_collection": "Collection", - + // "menu.section.new_community": "Community", // TODO New key - Add a translation "menu.section.new_community": "Community", - + // "menu.section.new_item": "Item", // TODO New key - Add a translation "menu.section.new_item": "Item", - + // "menu.section.new_item_version": "Item Version", // TODO New key - Add a translation "menu.section.new_item_version": "Item Version", - - - + + + // "menu.section.pin": "Pin sidebar", // TODO New key - Add a translation "menu.section.pin": "Pin sidebar", - + // "menu.section.unpin": "Unpin sidebar", // TODO New key - Add a translation "menu.section.unpin": "Unpin sidebar", - - - + + + // "menu.section.registries": "Registries", // TODO New key - Add a translation "menu.section.registries": "Registries", - + // "menu.section.registries_format": "Format", // TODO New key - Add a translation "menu.section.registries_format": "Format", - + // "menu.section.registries_metadata": "Metadata", // TODO New key - Add a translation "menu.section.registries_metadata": "Metadata", - - - + + + // "menu.section.statistics": "Statistics", // TODO New key - Add a translation "menu.section.statistics": "Statistics", - + // "menu.section.statistics_task": "Statistics Task", // TODO New key - Add a translation "menu.section.statistics_task": "Statistics Task", - - - + + + // "menu.section.toggle.access_control": "Toggle Access Control section", // TODO New key - Add a translation "menu.section.toggle.access_control": "Toggle Access Control section", - + // "menu.section.toggle.control_panel": "Toggle Control Panel section", // TODO New key - Add a translation "menu.section.toggle.control_panel": "Toggle Control Panel section", - + // "menu.section.toggle.curation_task": "Toggle Curation Task section", // TODO New key - Add a translation "menu.section.toggle.curation_task": "Toggle Curation Task section", - + // "menu.section.toggle.edit": "Toggle Edit section", // TODO New key - Add a translation "menu.section.toggle.edit": "Toggle Edit section", - + // "menu.section.toggle.export": "Toggle Export section", // TODO New key - Add a translation "menu.section.toggle.export": "Toggle Export section", - + // "menu.section.toggle.find": "Toggle Find section", // TODO New key - Add a translation "menu.section.toggle.find": "Toggle Find section", - + // "menu.section.toggle.import": "Toggle Import section", // TODO New key - Add a translation "menu.section.toggle.import": "Toggle Import section", - + // "menu.section.toggle.new": "Toggle New section", // TODO New key - Add a translation "menu.section.toggle.new": "Toggle New section", - + // "menu.section.toggle.registries": "Toggle Registries section", // TODO New key - Add a translation "menu.section.toggle.registries": "Toggle Registries section", - + // "menu.section.toggle.statistics_task": "Toggle Statistics Task section", // TODO New key - Add a translation "menu.section.toggle.statistics_task": "Toggle Statistics Task section", - - - + + + // "mydspace.description": "", // TODO New key - Add a translation "mydspace.description": "", - + // "mydspace.general.text-here": "HERE", // TODO New key - Add a translation "mydspace.general.text-here": "HERE", - + // "mydspace.messages.controller-help": "Select this option to send a message to item's submitter.", // TODO New key - Add a translation "mydspace.messages.controller-help": "Select this option to send a message to item's submitter.", - + // "mydspace.messages.description-placeholder": "Insert your message here...", // TODO New key - Add a translation "mydspace.messages.description-placeholder": "Insert your message here...", - + // "mydspace.messages.hide-msg": "Hide message", // TODO New key - Add a translation "mydspace.messages.hide-msg": "Hide message", - + // "mydspace.messages.mark-as-read": "Mark as read", // TODO New key - Add a translation "mydspace.messages.mark-as-read": "Mark as read", - + // "mydspace.messages.mark-as-unread": "Mark as unread", // TODO New key - Add a translation "mydspace.messages.mark-as-unread": "Mark as unread", - + // "mydspace.messages.no-content": "No content.", // TODO New key - Add a translation "mydspace.messages.no-content": "No content.", - + // "mydspace.messages.no-messages": "No messages yet.", // TODO New key - Add a translation "mydspace.messages.no-messages": "No messages yet.", - + // "mydspace.messages.send-btn": "Send", // TODO New key - Add a translation "mydspace.messages.send-btn": "Send", - + // "mydspace.messages.show-msg": "Show message", // TODO New key - Add a translation "mydspace.messages.show-msg": "Show message", - + // "mydspace.messages.subject-placeholder": "Subject...", // TODO New key - Add a translation "mydspace.messages.subject-placeholder": "Subject...", - + // "mydspace.messages.submitter-help": "Select this option to send a message to controller.", // TODO New key - Add a translation "mydspace.messages.submitter-help": "Select this option to send a message to controller.", - + // "mydspace.messages.title": "Messages", // TODO New key - Add a translation "mydspace.messages.title": "Messages", - + // "mydspace.messages.to": "To", // TODO New key - Add a translation "mydspace.messages.to": "To", - + // "mydspace.new-submission": "New submission", // TODO New key - Add a translation "mydspace.new-submission": "New submission", - + // "mydspace.results.head": "Your submissions", // TODO New key - Add a translation "mydspace.results.head": "Your submissions", - + // "mydspace.results.no-abstract": "No Abstract", // TODO New key - Add a translation "mydspace.results.no-abstract": "No Abstract", - + // "mydspace.results.no-authors": "No Authors", // TODO New key - Add a translation "mydspace.results.no-authors": "No Authors", - + // "mydspace.results.no-collections": "No Collections", // TODO New key - Add a translation "mydspace.results.no-collections": "No Collections", - + // "mydspace.results.no-date": "No Date", // TODO New key - Add a translation "mydspace.results.no-date": "No Date", - + // "mydspace.results.no-files": "No Files", // TODO New key - Add a translation "mydspace.results.no-files": "No Files", - + // "mydspace.results.no-results": "There were no items to show", // TODO New key - Add a translation "mydspace.results.no-results": "There were no items to show", - + // "mydspace.results.no-title": "No title", // TODO New key - Add a translation "mydspace.results.no-title": "No title", - + // "mydspace.results.no-uri": "No Uri", // TODO New key - Add a translation "mydspace.results.no-uri": "No Uri", - + // "mydspace.show.workflow": "All tasks", // TODO New key - Add a translation "mydspace.show.workflow": "All tasks", - + // "mydspace.show.workspace": "Your Submissions", // TODO New key - Add a translation "mydspace.show.workspace": "Your Submissions", - + // "mydspace.status.archived": "Archived", // TODO New key - Add a translation "mydspace.status.archived": "Archived", - + // "mydspace.status.validation": "Validation", // TODO New key - Add a translation "mydspace.status.validation": "Validation", - + // "mydspace.status.waiting-for-controller": "Waiting for controller", // TODO New key - Add a translation "mydspace.status.waiting-for-controller": "Waiting for controller", - + // "mydspace.status.workflow": "Workflow", // TODO New key - Add a translation "mydspace.status.workflow": "Workflow", - + // "mydspace.status.workspace": "Workspace", // TODO New key - Add a translation "mydspace.status.workspace": "Workspace", - + // "mydspace.title": "MyDSpace", // TODO New key - Add a translation "mydspace.title": "MyDSpace", - + // "mydspace.upload.upload-failed": "Error creating new workspace. Please verify the content uploaded before retry.", // TODO New key - Add a translation "mydspace.upload.upload-failed": "Error creating new workspace. Please verify the content uploaded before retry.", - + // "mydspace.upload.upload-multiple-successful": "{{qty}} new workspace items created.", // TODO New key - Add a translation "mydspace.upload.upload-multiple-successful": "{{qty}} new workspace items created.", - + // "mydspace.upload.upload-successful": "New workspace item created. Click {{here}} for edit it.", // TODO New key - Add a translation "mydspace.upload.upload-successful": "New workspace item created. Click {{here}} for edit it.", - + // "mydspace.view-btn": "View", // TODO New key - Add a translation "mydspace.view-btn": "View", - - - + + + // "nav.browse.header": "All of DSpace", // TODO New key - Add a translation "nav.browse.header": "All of DSpace", - + // "nav.community-browse.header": "By Community", // TODO New key - Add a translation "nav.community-browse.header": "By Community", - + // "nav.language": "Language switch", // TODO New key - Add a translation "nav.language": "Language switch", - + // "nav.login": "Log In", "nav.login": "Log In", - + // "nav.logout": "Log Out", "nav.logout": "Log Uit", - + // "nav.mydspace": "MyDSpace", // TODO New key - Add a translation "nav.mydspace": "MyDSpace", - + // "nav.search": "Search", // TODO New key - Add a translation "nav.search": "Search", - + // "nav.statistics.header": "Statistics", // TODO New key - Add a translation "nav.statistics.header": "Statistics", - - - + + + // "orgunit.listelement.badge": "Organizational Unit", // TODO New key - Add a translation "orgunit.listelement.badge": "Organizational Unit", - + // "orgunit.page.city": "City", // TODO New key - Add a translation "orgunit.page.city": "City", - + // "orgunit.page.country": "Country", // TODO New key - Add a translation "orgunit.page.country": "Country", - + // "orgunit.page.dateestablished": "Date established", // TODO New key - Add a translation "orgunit.page.dateestablished": "Date established", - + // "orgunit.page.description": "Description", // TODO New key - Add a translation "orgunit.page.description": "Description", - + // "orgunit.page.id": "ID", // TODO New key - Add a translation "orgunit.page.id": "ID", - + // "orgunit.page.titleprefix": "Organizational Unit: ", // TODO New key - Add a translation "orgunit.page.titleprefix": "Organizational Unit: ", - - - + + + // "pagination.results-per-page": "Results Per Page", "pagination.results-per-page": "Resultaten per pagina", - + // "pagination.showing.detail": "{{ range }} of {{ total }}", "pagination.showing.detail": "{{ range }} van {{ total }}", - + // "pagination.showing.label": "Now showing ", "pagination.showing.label": "Resultaten ", - + // "pagination.sort-direction": "Sort Options", "pagination.sort-direction": "Sorteermogelijkheden", - - - + + + // "person.listelement.badge": "Person", // TODO New key - Add a translation "person.listelement.badge": "Person", - + // "person.page.birthdate": "Birth Date", // TODO New key - Add a translation "person.page.birthdate": "Birth Date", - + // "person.page.email": "Email Address", // TODO New key - Add a translation "person.page.email": "Email Address", - + // "person.page.firstname": "First Name", // TODO New key - Add a translation "person.page.firstname": "First Name", - + // "person.page.jobtitle": "Job Title", // TODO New key - Add a translation "person.page.jobtitle": "Job Title", - + // "person.page.lastname": "Last Name", // TODO New key - Add a translation "person.page.lastname": "Last Name", - + // "person.page.link.full": "Show all metadata", // TODO New key - Add a translation "person.page.link.full": "Show all metadata", - + // "person.page.orcid": "ORCID", // TODO New key - Add a translation "person.page.orcid": "ORCID", - + // "person.page.staffid": "Staff ID", // TODO New key - Add a translation "person.page.staffid": "Staff ID", - + // "person.page.titleprefix": "Person: ", // TODO New key - Add a translation "person.page.titleprefix": "Person: ", - + // "person.search.results.head": "Person Search Results", // TODO New key - Add a translation "person.search.results.head": "Person Search Results", - + // "person.search.title": "DSpace Angular :: Person Search", // TODO New key - Add a translation "person.search.title": "DSpace Angular :: Person Search", - - - + + + // "project.listelement.badge": "Research Project", // TODO New key - Add a translation "project.listelement.badge": "Research Project", - + // "project.page.contributor": "Contributors", // TODO New key - Add a translation "project.page.contributor": "Contributors", - + // "project.page.description": "Description", // TODO New key - Add a translation "project.page.description": "Description", - + // "project.page.expectedcompletion": "Expected Completion", // TODO New key - Add a translation "project.page.expectedcompletion": "Expected Completion", - + // "project.page.funder": "Funders", // TODO New key - Add a translation "project.page.funder": "Funders", - + // "project.page.id": "ID", // TODO New key - Add a translation "project.page.id": "ID", - + // "project.page.keyword": "Keywords", // TODO New key - Add a translation "project.page.keyword": "Keywords", - + // "project.page.status": "Status", // TODO New key - Add a translation "project.page.status": "Status", - + // "project.page.titleprefix": "Research Project: ", // TODO New key - Add a translation "project.page.titleprefix": "Research Project: ", - - - + + + // "publication.listelement.badge": "Publication", // TODO New key - Add a translation "publication.listelement.badge": "Publication", - + // "publication.page.description": "Description", // TODO New key - Add a translation "publication.page.description": "Description", - + // "publication.page.journal-issn": "Journal ISSN", // TODO New key - Add a translation "publication.page.journal-issn": "Journal ISSN", - + // "publication.page.journal-title": "Journal Title", // TODO New key - Add a translation "publication.page.journal-title": "Journal Title", - + // "publication.page.publisher": "Publisher", // TODO New key - Add a translation "publication.page.publisher": "Publisher", - + // "publication.page.titleprefix": "Publication: ", // TODO New key - Add a translation "publication.page.titleprefix": "Publication: ", - + // "publication.page.volume-title": "Volume Title", // TODO New key - Add a translation "publication.page.volume-title": "Volume Title", - + // "publication.search.results.head": "Publication Search Results", // TODO New key - Add a translation "publication.search.results.head": "Publication Search Results", - + // "publication.search.title": "DSpace Angular :: Publication Search", // TODO New key - Add a translation "publication.search.title": "DSpace Angular :: Publication Search", - - - + + + // "relationships.isAuthorOf": "Authors", // TODO New key - Add a translation "relationships.isAuthorOf": "Authors", - + // "relationships.isIssueOf": "Journal Issues", // TODO New key - Add a translation "relationships.isIssueOf": "Journal Issues", - + // "relationships.isJournalIssueOf": "Journal Issue", // TODO New key - Add a translation "relationships.isJournalIssueOf": "Journal Issue", - + // "relationships.isJournalOf": "Journals", // TODO New key - Add a translation "relationships.isJournalOf": "Journals", - + // "relationships.isOrgUnitOf": "Organizational Units", // TODO New key - Add a translation "relationships.isOrgUnitOf": "Organizational Units", - + // "relationships.isPersonOf": "Authors", // TODO New key - Add a translation "relationships.isPersonOf": "Authors", - + // "relationships.isProjectOf": "Research Projects", // TODO New key - Add a translation "relationships.isProjectOf": "Research Projects", - + // "relationships.isPublicationOf": "Publications", // TODO New key - Add a translation "relationships.isPublicationOf": "Publications", - + // "relationships.isPublicationOfJournalIssue": "Articles", // TODO New key - Add a translation "relationships.isPublicationOfJournalIssue": "Articles", - + // "relationships.isSingleJournalOf": "Journal", // TODO New key - Add a translation "relationships.isSingleJournalOf": "Journal", - + // "relationships.isSingleVolumeOf": "Journal Volume", // TODO New key - Add a translation "relationships.isSingleVolumeOf": "Journal Volume", - + // "relationships.isVolumeOf": "Journal Volumes", // TODO New key - Add a translation "relationships.isVolumeOf": "Journal Volumes", - - - + + + // "search.description": "", "search.description": "", - + // "search.switch-configuration.title": "Show", // TODO New key - Add a translation "search.switch-configuration.title": "Show", - + // "search.title": "DSpace Angular :: Search", "search.title": "DSpace Angular :: Zoek", - - - + + + // "search.filters.applied.f.author": "Author", "search.filters.applied.f.author": "Auteur", - + // "search.filters.applied.f.dateIssued.max": "End date", "search.filters.applied.f.dateIssued.max": "Einddatum", - + // "search.filters.applied.f.dateIssued.min": "Start date", "search.filters.applied.f.dateIssued.min": "Startdatum", - + // "search.filters.applied.f.dateSubmitted": "Date submitted", // TODO New key - Add a translation "search.filters.applied.f.dateSubmitted": "Date submitted", - + // "search.filters.applied.f.entityType": "Item Type", // TODO New key - Add a translation "search.filters.applied.f.entityType": "Item Type", - + // "search.filters.applied.f.has_content_in_original_bundle": "Has files", "search.filters.applied.f.has_content_in_original_bundle": "Heeft bestanden", - + // "search.filters.applied.f.itemtype": "Type", // TODO New key - Add a translation "search.filters.applied.f.itemtype": "Type", - + // "search.filters.applied.f.namedresourcetype": "Status", // TODO New key - Add a translation "search.filters.applied.f.namedresourcetype": "Status", - + // "search.filters.applied.f.subject": "Subject", "search.filters.applied.f.subject": "Sleutelwoord", - + // "search.filters.applied.f.submitter": "Submitter", // TODO New key - Add a translation "search.filters.applied.f.submitter": "Submitter", - - - + + + // "search.filters.filter.author.head": "Author", "search.filters.filter.author.head": "Auteur", - + // "search.filters.filter.author.placeholder": "Author name", "search.filters.filter.author.placeholder": "Auteursnaam", - + // "search.filters.filter.birthDate.head": "Birth Date", // TODO New key - Add a translation "search.filters.filter.birthDate.head": "Birth Date", - + // "search.filters.filter.birthDate.placeholder": "Birth Date", // TODO New key - Add a translation "search.filters.filter.birthDate.placeholder": "Birth Date", - + // "search.filters.filter.creativeDatePublished.head": "Date Published", // TODO New key - Add a translation "search.filters.filter.creativeDatePublished.head": "Date Published", - + // "search.filters.filter.creativeDatePublished.placeholder": "Date Published", // TODO New key - Add a translation "search.filters.filter.creativeDatePublished.placeholder": "Date Published", - + // "search.filters.filter.creativeWorkEditor.head": "Editor", // TODO New key - Add a translation "search.filters.filter.creativeWorkEditor.head": "Editor", - + // "search.filters.filter.creativeWorkEditor.placeholder": "Editor", // TODO New key - Add a translation "search.filters.filter.creativeWorkEditor.placeholder": "Editor", - + // "search.filters.filter.creativeWorkKeywords.head": "Subject", // TODO New key - Add a translation "search.filters.filter.creativeWorkKeywords.head": "Subject", - + // "search.filters.filter.creativeWorkKeywords.placeholder": "Subject", // TODO New key - Add a translation "search.filters.filter.creativeWorkKeywords.placeholder": "Subject", - + // "search.filters.filter.creativeWorkPublisher.head": "Publisher", // TODO New key - Add a translation "search.filters.filter.creativeWorkPublisher.head": "Publisher", - + // "search.filters.filter.creativeWorkPublisher.placeholder": "Publisher", // TODO New key - Add a translation "search.filters.filter.creativeWorkPublisher.placeholder": "Publisher", - + // "search.filters.filter.dateIssued.head": "Date", "search.filters.filter.dateIssued.head": "Datum", - + // "search.filters.filter.dateIssued.max.placeholder": "Minimum Date", "search.filters.filter.dateIssued.max.placeholder": "Vroegste Datum", - + // "search.filters.filter.dateIssued.min.placeholder": "Maximum Date", "search.filters.filter.dateIssued.min.placeholder": "Laatste Datum", - + // "search.filters.filter.dateSubmitted.head": "Date submitted", // TODO New key - Add a translation "search.filters.filter.dateSubmitted.head": "Date submitted", - + // "search.filters.filter.dateSubmitted.placeholder": "Date submitted", // TODO New key - Add a translation "search.filters.filter.dateSubmitted.placeholder": "Date submitted", - + // "search.filters.filter.entityType.head": "Item Type", // TODO New key - Add a translation "search.filters.filter.entityType.head": "Item Type", - + // "search.filters.filter.entityType.placeholder": "Item Type", // TODO New key - Add a translation "search.filters.filter.entityType.placeholder": "Item Type", - + // "search.filters.filter.has_content_in_original_bundle.head": "Has files", "search.filters.filter.has_content_in_original_bundle.head": "Heeft bestanden", - + // "search.filters.filter.itemtype.head": "Type", // TODO New key - Add a translation "search.filters.filter.itemtype.head": "Type", - + // "search.filters.filter.itemtype.placeholder": "Type", // TODO New key - Add a translation "search.filters.filter.itemtype.placeholder": "Type", - + // "search.filters.filter.jobTitle.head": "Job Title", // TODO New key - Add a translation "search.filters.filter.jobTitle.head": "Job Title", - + // "search.filters.filter.jobTitle.placeholder": "Job Title", // TODO New key - Add a translation "search.filters.filter.jobTitle.placeholder": "Job Title", - + // "search.filters.filter.knowsLanguage.head": "Known language", // TODO New key - Add a translation "search.filters.filter.knowsLanguage.head": "Known language", - + // "search.filters.filter.knowsLanguage.placeholder": "Known language", // TODO New key - Add a translation "search.filters.filter.knowsLanguage.placeholder": "Known language", - + // "search.filters.filter.namedresourcetype.head": "Status", // TODO New key - Add a translation "search.filters.filter.namedresourcetype.head": "Status", - + // "search.filters.filter.namedresourcetype.placeholder": "Status", // TODO New key - Add a translation "search.filters.filter.namedresourcetype.placeholder": "Status", - + // "search.filters.filter.objectpeople.head": "People", // TODO New key - Add a translation "search.filters.filter.objectpeople.head": "People", - + // "search.filters.filter.objectpeople.placeholder": "People", // TODO New key - Add a translation "search.filters.filter.objectpeople.placeholder": "People", - + // "search.filters.filter.organizationAddressCountry.head": "Country", // TODO New key - Add a translation "search.filters.filter.organizationAddressCountry.head": "Country", - + // "search.filters.filter.organizationAddressCountry.placeholder": "Country", // TODO New key - Add a translation "search.filters.filter.organizationAddressCountry.placeholder": "Country", - + // "search.filters.filter.organizationAddressLocality.head": "City", // TODO New key - Add a translation "search.filters.filter.organizationAddressLocality.head": "City", - + // "search.filters.filter.organizationAddressLocality.placeholder": "City", // TODO New key - Add a translation "search.filters.filter.organizationAddressLocality.placeholder": "City", - + // "search.filters.filter.organizationFoundingDate.head": "Date Founded", // TODO New key - Add a translation "search.filters.filter.organizationFoundingDate.head": "Date Founded", - + // "search.filters.filter.organizationFoundingDate.placeholder": "Date Founded", // TODO New key - Add a translation "search.filters.filter.organizationFoundingDate.placeholder": "Date Founded", - + // "search.filters.filter.scope.head": "Scope", "search.filters.filter.scope.head": "Bereik", - + // "search.filters.filter.scope.placeholder": "Scope filter", "search.filters.filter.scope.placeholder": "Bereikfilter", - + // "search.filters.filter.show-less": "Collapse", "search.filters.filter.show-less": "Inklappen", - + // "search.filters.filter.show-more": "Show more", "search.filters.filter.show-more": "Toon meer", - + // "search.filters.filter.subject.head": "Subject", "search.filters.filter.subject.head": "Onderwerp", - + // "search.filters.filter.subject.placeholder": "Subject", "search.filters.filter.subject.placeholder": "Onderwerp", - + // "search.filters.filter.submitter.head": "Submitter", // TODO New key - Add a translation "search.filters.filter.submitter.head": "Submitter", - + // "search.filters.filter.submitter.placeholder": "Submitter", // TODO New key - Add a translation "search.filters.filter.submitter.placeholder": "Submitter", - - - + + + // "search.filters.head": "Filters", "search.filters.head": "Filters", - + // "search.filters.reset": "Reset filters", "search.filters.reset": "Filters verwijderen", - - - + + + // "search.form.search": "Search", "search.form.search": "Zoek", - + // "search.form.search_dspace": "Search DSpace", "search.form.search_dspace": "Zoek in DSpace", - + // "search.form.search_mydspace": "Search MyDSpace", - // TODO New key - Add a translation - "search.form.search_mydspace": "Search MyDSpace", - - - + "search.form.search_mydspace": "Zoek in MyDSpace", + + + // "search.results.head": "Search Results", "search.results.head": "Zoekresultaten", - + // "search.results.no-results": "Your search returned no results. Having trouble finding what you're looking for? Try putting", - "search.results.no-results": "Er waren geen resultaten voor deze zoekopdracht", - + "search.results.no-results": "Er waren geen resultaten voor deze zoekopdracht. Kunt u niet vinden wat u zoekt? Probeer het met ", + // "search.results.no-results-link": "quotes around it", - // TODO New key - Add a translation - "search.results.no-results-link": "quotes around it", - - - + "search.results.no-results-link": "aanhalingstekens om uw zoekterm", + + + // "search.sidebar.close": "Back to results", "search.sidebar.close": "Terug naar de resultaten", - + // "search.sidebar.filters.title": "Filters", "search.sidebar.filters.title": "Filters", - + // "search.sidebar.open": "Search Tools", "search.sidebar.open": "Zoek Tools", - + // "search.sidebar.results": "results", "search.sidebar.results": "resultaten", - + // "search.sidebar.settings.rpp": "Results per page", "search.sidebar.settings.rpp": "Resultaten per pagina", - + // "search.sidebar.settings.sort-by": "Sort By", "search.sidebar.settings.sort-by": "Sorteer volgens", - + // "search.sidebar.settings.title": "Settings", "search.sidebar.settings.title": "Instellingen", - - - + + + // "search.view-switch.show-detail": "Show detail", - // TODO New key - Add a translation - "search.view-switch.show-detail": "Show detail", - + "search.view-switch.show-detail": "Toon detail", + // "search.view-switch.show-grid": "Show as grid", "search.view-switch.show-grid": "Toon in raster", - + // "search.view-switch.show-list": "Show as list", "search.view-switch.show-list": "Toon als lijst", - - - + + + // "sorting.dc.title.ASC": "Title Ascending", "sorting.dc.title.ASC": "Oplopend op titel", - + // "sorting.dc.title.DESC": "Title Descending", "sorting.dc.title.DESC": "Aflopend op titel", - + // "sorting.score.DESC": "Relevance", "sorting.score.DESC": "Relevantie", - - - + + + // "submission.edit.title": "Edit Submission", // TODO New key - Add a translation "submission.edit.title": "Edit Submission", - + // "submission.general.cannot_submit": "You have not the privilege to make a new submission.", // TODO New key - Add a translation "submission.general.cannot_submit": "You have not the privilege to make a new submission.", - + // "submission.general.deposit": "Deposit", // TODO New key - Add a translation "submission.general.deposit": "Deposit", - + // "submission.general.discard.confirm.cancel": "Cancel", // TODO New key - Add a translation "submission.general.discard.confirm.cancel": "Cancel", - + // "submission.general.discard.confirm.info": "This operation can't be undone. Are you sure?", // TODO New key - Add a translation "submission.general.discard.confirm.info": "This operation can't be undone. Are you sure?", - + // "submission.general.discard.confirm.submit": "Yes, I'm sure", // TODO New key - Add a translation "submission.general.discard.confirm.submit": "Yes, I'm sure", - + // "submission.general.discard.confirm.title": "Discard submission", // TODO New key - Add a translation "submission.general.discard.confirm.title": "Discard submission", - + // "submission.general.discard.submit": "Discard", // TODO New key - Add a translation "submission.general.discard.submit": "Discard", - + // "submission.general.save": "Save", // TODO New key - Add a translation "submission.general.save": "Save", - + // "submission.general.save-later": "Save for later", // TODO New key - Add a translation "submission.general.save-later": "Save for later", - - - + + + // "submission.sections.general.add-more": "Add more", // TODO New key - Add a translation "submission.sections.general.add-more": "Add more", - + // "submission.sections.general.collection": "Collection", // TODO New key - Add a translation "submission.sections.general.collection": "Collection", - + // "submission.sections.general.deposit_error_notice": "There was an issue when submitting the item, please try again later.", // TODO New key - Add a translation "submission.sections.general.deposit_error_notice": "There was an issue when submitting the item, please try again later.", - + // "submission.sections.general.deposit_success_notice": "Submission deposited successfully.", // TODO New key - Add a translation "submission.sections.general.deposit_success_notice": "Submission deposited successfully.", - + // "submission.sections.general.discard_error_notice": "There was an issue when discarding the item, please try again later.", // TODO New key - Add a translation "submission.sections.general.discard_error_notice": "There was an issue when discarding the item, please try again later.", - + // "submission.sections.general.discard_success_notice": "Submission discarded successfully.", // TODO New key - Add a translation "submission.sections.general.discard_success_notice": "Submission discarded successfully.", - + // "submission.sections.general.metadata-extracted": "New metadata have been extracted and added to the {{sectionId}} section.", // TODO New key - Add a translation "submission.sections.general.metadata-extracted": "New metadata have been extracted and added to the {{sectionId}} section.", - + // "submission.sections.general.metadata-extracted-new-section": "New {{sectionId}} section has been added to submission.", // TODO New key - Add a translation "submission.sections.general.metadata-extracted-new-section": "New {{sectionId}} section has been added to submission.", - + // "submission.sections.general.no-collection": "No collection found", // TODO New key - Add a translation "submission.sections.general.no-collection": "No collection found", - + // "submission.sections.general.no-sections": "No options available", // TODO New key - Add a translation "submission.sections.general.no-sections": "No options available", - + // "submission.sections.general.save_error_notice": "There was an issue when saving the item, please try again later.", // TODO New key - Add a translation "submission.sections.general.save_error_notice": "There was an issue when saving the item, please try again later.", - + // "submission.sections.general.save_success_notice": "Submission saved successfully.", // TODO New key - Add a translation "submission.sections.general.save_success_notice": "Submission saved successfully.", - + // "submission.sections.general.search-collection": "Search for a collection", // TODO New key - Add a translation "submission.sections.general.search-collection": "Search for a collection", - + // "submission.sections.general.sections_not_valid": "There are incomplete sections.", // TODO New key - Add a translation "submission.sections.general.sections_not_valid": "There are incomplete sections.", - - - + + + // "submission.sections.submit.progressbar.cclicense": "Creative commons license", // TODO New key - Add a translation "submission.sections.submit.progressbar.cclicense": "Creative commons license", - + // "submission.sections.submit.progressbar.describe.recycle": "Recycle", // TODO New key - Add a translation "submission.sections.submit.progressbar.describe.recycle": "Recycle", - + // "submission.sections.submit.progressbar.describe.stepcustom": "Describe", // TODO New key - Add a translation "submission.sections.submit.progressbar.describe.stepcustom": "Describe", - + // "submission.sections.submit.progressbar.describe.stepone": "Describe", // TODO New key - Add a translation "submission.sections.submit.progressbar.describe.stepone": "Describe", - + // "submission.sections.submit.progressbar.describe.steptwo": "Describe", // TODO New key - Add a translation "submission.sections.submit.progressbar.describe.steptwo": "Describe", - + // "submission.sections.submit.progressbar.detect-duplicate": "Potential duplicates", // TODO New key - Add a translation "submission.sections.submit.progressbar.detect-duplicate": "Potential duplicates", - + // "submission.sections.submit.progressbar.license": "Deposit license", // TODO New key - Add a translation "submission.sections.submit.progressbar.license": "Deposit license", - + // "submission.sections.submit.progressbar.upload": "Upload files", // TODO New key - Add a translation "submission.sections.submit.progressbar.upload": "Upload files", - - - + + + // "submission.sections.upload.delete.confirm.cancel": "Cancel", // TODO New key - Add a translation "submission.sections.upload.delete.confirm.cancel": "Cancel", - + // "submission.sections.upload.delete.confirm.info": "This operation can't be undone. Are you sure?", // TODO New key - Add a translation "submission.sections.upload.delete.confirm.info": "This operation can't be undone. Are you sure?", - + // "submission.sections.upload.delete.confirm.submit": "Yes, I'm sure", // TODO New key - Add a translation "submission.sections.upload.delete.confirm.submit": "Yes, I'm sure", - + // "submission.sections.upload.delete.confirm.title": "Delete bitstream", // TODO New key - Add a translation "submission.sections.upload.delete.confirm.title": "Delete bitstream", - + // "submission.sections.upload.delete.submit": "Delete", // TODO New key - Add a translation "submission.sections.upload.delete.submit": "Delete", - + // "submission.sections.upload.drop-message": "Drop files to attach them to the item", // TODO New key - Add a translation "submission.sections.upload.drop-message": "Drop files to attach them to the item", - + // "submission.sections.upload.form.access-condition-label": "Access condition type", // TODO New key - Add a translation "submission.sections.upload.form.access-condition-label": "Access condition type", - + // "submission.sections.upload.form.date-required": "Date is required.", // TODO New key - Add a translation "submission.sections.upload.form.date-required": "Date is required.", - + // "submission.sections.upload.form.from-label": "Access grant from", // TODO New key - Add a translation "submission.sections.upload.form.from-label": "Access grant from", - + // "submission.sections.upload.form.from-placeholder": "From", // TODO New key - Add a translation "submission.sections.upload.form.from-placeholder": "From", - + // "submission.sections.upload.form.group-label": "Group", // TODO New key - Add a translation "submission.sections.upload.form.group-label": "Group", - + // "submission.sections.upload.form.group-required": "Group is required.", // TODO New key - Add a translation "submission.sections.upload.form.group-required": "Group is required.", - + // "submission.sections.upload.form.until-label": "Access grant until", // TODO New key - Add a translation "submission.sections.upload.form.until-label": "Access grant until", - + // "submission.sections.upload.form.until-placeholder": "Until", // TODO New key - Add a translation "submission.sections.upload.form.until-placeholder": "Until", - + // "submission.sections.upload.header.policy.default.nolist": "Uploaded files in the {{collectionName}} collection will be accessible according to the following group(s):", // TODO New key - Add a translation "submission.sections.upload.header.policy.default.nolist": "Uploaded files in the {{collectionName}} collection will be accessible according to the following group(s):", - + // "submission.sections.upload.header.policy.default.withlist": "Please note that uploaded files in the {{collectionName}} collection will be accessible, in addition to what is explicitly decided for the single file, with the following group(s):", // TODO New key - Add a translation "submission.sections.upload.header.policy.default.withlist": "Please note that uploaded files in the {{collectionName}} collection will be accessible, in addition to what is explicitly decided for the single file, with the following group(s):", - + // "submission.sections.upload.info": "Here you will find all the files currently in the item. You can update the file metadata and access conditions or upload additional files just dragging & dropping them everywhere in the page", // TODO New key - Add a translation "submission.sections.upload.info": "Here you will find all the files currently in the item. You can update the file metadata and access conditions or upload additional files just dragging & dropping them everywhere in the page", - + // "submission.sections.upload.no-entry": "No", // TODO New key - Add a translation "submission.sections.upload.no-entry": "No", - + // "submission.sections.upload.no-file-uploaded": "No file uploaded yet.", // TODO New key - Add a translation "submission.sections.upload.no-file-uploaded": "No file uploaded yet.", - + // "submission.sections.upload.save-metadata": "Save metadata", // TODO New key - Add a translation "submission.sections.upload.save-metadata": "Save metadata", - + // "submission.sections.upload.undo": "Cancel", // TODO New key - Add a translation "submission.sections.upload.undo": "Cancel", - + // "submission.sections.upload.upload-failed": "Upload failed", // TODO New key - Add a translation "submission.sections.upload.upload-failed": "Upload failed", - + // "submission.sections.upload.upload-successful": "Upload successful", // TODO New key - Add a translation "submission.sections.upload.upload-successful": "Upload successful", - - - + + + // "submission.submit.title": "Submission", // TODO New key - Add a translation "submission.submit.title": "Submission", - - - + + + // "submission.workflow.generic.delete": "Delete", // TODO New key - Add a translation "submission.workflow.generic.delete": "Delete", - + // "submission.workflow.generic.delete-help": "If you would to discard this item, select \"Delete\". You will then be asked to confirm it.", // TODO New key - Add a translation "submission.workflow.generic.delete-help": "If you would to discard this item, select \"Delete\". You will then be asked to confirm it.", - + // "submission.workflow.generic.edit": "Edit", // TODO New key - Add a translation "submission.workflow.generic.edit": "Edit", - + // "submission.workflow.generic.edit-help": "Select this option to change the item's metadata.", // TODO New key - Add a translation "submission.workflow.generic.edit-help": "Select this option to change the item's metadata.", - + // "submission.workflow.generic.view": "View", // TODO New key - Add a translation "submission.workflow.generic.view": "View", - + // "submission.workflow.generic.view-help": "Select this option to view the item's metadata.", // TODO New key - Add a translation "submission.workflow.generic.view-help": "Select this option to view the item's metadata.", - - - + + + // "submission.workflow.tasks.claimed.approve": "Approve", // TODO New key - Add a translation "submission.workflow.tasks.claimed.approve": "Approve", - + // "submission.workflow.tasks.claimed.approve_help": "If you have reviewed the item and it is suitable for inclusion in the collection, select \"Approve\".", // TODO New key - Add a translation "submission.workflow.tasks.claimed.approve_help": "If you have reviewed the item and it is suitable for inclusion in the collection, select \"Approve\".", - + // "submission.workflow.tasks.claimed.edit": "Edit", // TODO New key - Add a translation "submission.workflow.tasks.claimed.edit": "Edit", - + // "submission.workflow.tasks.claimed.edit_help": "Select this option to change the item's metadata.", // TODO New key - Add a translation "submission.workflow.tasks.claimed.edit_help": "Select this option to change the item's metadata.", - + // "submission.workflow.tasks.claimed.reject.reason.info": "Please enter your reason for rejecting the submission into the box below, indicating whether the submitter may fix a problem and resubmit.", // TODO New key - Add a translation "submission.workflow.tasks.claimed.reject.reason.info": "Please enter your reason for rejecting the submission into the box below, indicating whether the submitter may fix a problem and resubmit.", - + // "submission.workflow.tasks.claimed.reject.reason.placeholder": "Describe the reason of reject", // TODO New key - Add a translation "submission.workflow.tasks.claimed.reject.reason.placeholder": "Describe the reason of reject", - + // "submission.workflow.tasks.claimed.reject.reason.submit": "Reject item", // TODO New key - Add a translation "submission.workflow.tasks.claimed.reject.reason.submit": "Reject item", - + // "submission.workflow.tasks.claimed.reject.reason.title": "Reason", // TODO New key - Add a translation "submission.workflow.tasks.claimed.reject.reason.title": "Reason", - + // "submission.workflow.tasks.claimed.reject.submit": "Reject", // TODO New key - Add a translation "submission.workflow.tasks.claimed.reject.submit": "Reject", - + // "submission.workflow.tasks.claimed.reject_help": "If you have reviewed the item and found it is not suitable for inclusion in the collection, select \"Reject\". You will then be asked to enter a message indicating why the item is unsuitable, and whether the submitter should change something and resubmit.", // TODO New key - Add a translation "submission.workflow.tasks.claimed.reject_help": "If you have reviewed the item and found it is not suitable for inclusion in the collection, select \"Reject\". You will then be asked to enter a message indicating why the item is unsuitable, and whether the submitter should change something and resubmit.", - + // "submission.workflow.tasks.claimed.return": "Return to pool", // TODO New key - Add a translation "submission.workflow.tasks.claimed.return": "Return to pool", - + // "submission.workflow.tasks.claimed.return_help": "Return the task to the pool so that another user may perform the task.", // TODO New key - Add a translation "submission.workflow.tasks.claimed.return_help": "Return the task to the pool so that another user may perform the task.", - - - + + + // "submission.workflow.tasks.generic.error": "Error occurred during operation...", // TODO New key - Add a translation "submission.workflow.tasks.generic.error": "Error occurred during operation...", - + // "submission.workflow.tasks.generic.processing": "Processing...", // TODO New key - Add a translation "submission.workflow.tasks.generic.processing": "Processing...", - + // "submission.workflow.tasks.generic.submitter": "Submitter", // TODO New key - Add a translation "submission.workflow.tasks.generic.submitter": "Submitter", - + // "submission.workflow.tasks.generic.success": "Operation successful", // TODO New key - Add a translation "submission.workflow.tasks.generic.success": "Operation successful", - - - + + + // "submission.workflow.tasks.pool.claim": "Claim", // TODO New key - Add a translation "submission.workflow.tasks.pool.claim": "Claim", - + // "submission.workflow.tasks.pool.claim_help": "Assign this task to yourself.", // TODO New key - Add a translation "submission.workflow.tasks.pool.claim_help": "Assign this task to yourself.", - + // "submission.workflow.tasks.pool.hide-detail": "Hide detail", // TODO New key - Add a translation "submission.workflow.tasks.pool.hide-detail": "Hide detail", - + // "submission.workflow.tasks.pool.show-detail": "Show detail", // TODO New key - Add a translation "submission.workflow.tasks.pool.show-detail": "Show detail", - - - + + + // "title": "DSpace", "title": "DSpace", - - - + + + // "uploader.browse": "browse", // TODO New key - Add a translation "uploader.browse": "browse", - + // "uploader.drag-message": "Drag & Drop your files here", // TODO New key - Add a translation "uploader.drag-message": "Drag & Drop your files here", - + // "uploader.or": ", or", // TODO New key - Add a translation "uploader.or": ", or", - + // "uploader.processing": "Processing", // TODO New key - Add a translation "uploader.processing": "Processing", - + // "uploader.queue-length": "Queue length", // TODO New key - Add a translation "uploader.queue-length": "Queue length", - - - + + + } From 9d988022c7e33b66798c3b3e7ca3f1853f865422 Mon Sep 17 00:00:00 2001 From: muiltje Date: Tue, 7 Jan 2020 17:11:53 +0100 Subject: [PATCH 12/32] First batch of Dutch translations --- resources/i18n/nl.json5 | 363 ++++++++++++++-------------------------- 1 file changed, 122 insertions(+), 241 deletions(-) diff --git a/resources/i18n/nl.json5 b/resources/i18n/nl.json5 index 410b3e6a8b..973a045af8 100644 --- a/resources/i18n/nl.json5 +++ b/resources/i18n/nl.json5 @@ -12,20 +12,19 @@ // "admin.registries.bitstream-formats.create.failure.content": "An error occurred while creating the new bitstream format.", - // TODO New key - Add a translation - "admin.registries.bitstream-formats.create.failure.content": "An error occurred while creating the new bitstream format.", + "admin.registries.bitstream-formats.create.failure.content": "Er is een fout opgetreden bij het maken van het nieuwe bitstream-formaat.", // "admin.registries.bitstream-formats.create.failure.head": "Failure", "admin.registries.bitstream-formats.create.failure.head": "Gefaald", // "admin.registries.bitstream-formats.create.head": "Create Bitstream format", - "admin.registries.bitstream-formats.create.head": "Maak een Bitstream formaat aan", + "admin.registries.bitstream-formats.create.head": "Maak een bitstream-formaat aan", // "admin.registries.bitstream-formats.create.new": "Add a new bitstream format", - "admin.registries.bitstream-formats.create.new": "Voeg een nieuw Bitstream formaat toe", + "admin.registries.bitstream-formats.create.new": "Voeg een nieuw bitstream-formaat toe", // "admin.registries.bitstream-formats.create.success.content": "The new bitstream format was successfully created.", - "admin.registries.bitstream-formats.create.success.content": "Het nieuwe Bitstream formaat is aangemaakt.", + "admin.registries.bitstream-formats.create.success.content": "Het nieuwe bitstream-formaat is aangemaakt.", // "admin.registries.bitstream-formats.create.success.head": "Success", "admin.registries.bitstream-formats.create.success.head": "Succes", @@ -37,94 +36,79 @@ "admin.registries.bitstream-formats.delete.failure.head": "Gefaald", // "admin.registries.bitstream-formats.delete.success.amount": "Successfully removed {{ amount }} format(s)", - "admin.registries.bitstream-formats.delete.success.amount": "Het verwijderen van {{ amount }} forma(a)t(en) is gelukt.", + "admin.registries.bitstream-formats.delete.success.amount": "{{ amount }} Forma(a)t(en) zijn succesvol verwijderd.", // "admin.registries.bitstream-formats.delete.success.head": "Success", "admin.registries.bitstream-formats.delete.success.head": "Succes", // "admin.registries.bitstream-formats.description": "This list of bitstream formats provides information about known formats and their support level.", - "admin.registries.bitstream-formats.description": "Deze lijst van Bitstream formaten biedt informatie over de formaten die in deze repository zijn toegelaten en op welke manier ze ondersteund worden. De term Bitstream wordt in DSpace gebruikt om een bestand aan te duiden dat samen met metadata onderdeel uitmaakt van een item. De naam bitstream duidt op het feit dat het bestand achterliggend wordt opgeslaan zonder bestandsextensie.", + "admin.registries.bitstream-formats.description": "Deze lijst van bitstream-formaten biedt informatie over de formaten die in deze repository zijn toegelaten en op welke manier ze ondersteund worden. De term Bitstream wordt in DSpace gebruikt om een bestand aan te duiden dat samen met metadata onderdeel uitmaakt van een item. De naam bitstream duidt op het feit dat het bestand achterliggend wordt opgeslaan zonder bestandsextensie.", // "admin.registries.bitstream-formats.edit.description.hint": "", - // TODO New key - Add a translation "admin.registries.bitstream-formats.edit.description.hint": "", // "admin.registries.bitstream-formats.edit.description.label": "Description", "admin.registries.bitstream-formats.edit.description.label": "Beschrijving", // "admin.registries.bitstream-formats.edit.extensions.hint": "Extensions are file extensions that are used to automatically identify the format of uploaded files. You can enter several extensions for each format.", - // TODO New key - Add a translation - "admin.registries.bitstream-formats.edit.extensions.hint": "Extensions are file extensions that are used to automatically identify the format of uploaded files. You can enter several extensions for each format.", + "admin.registries.bitstream-formats.edit.extensions.hint": "Extensies zijn bestandsextensies die worden gebruikt om automatisch het formaat van geuploade bestanden te bepalen. U kunt meerdere extensies voor een formaat invullen.", // "admin.registries.bitstream-formats.edit.extensions.label": "File extensions", - // TODO New key - Add a translation - "admin.registries.bitstream-formats.edit.extensions.label": "File extensions", + "admin.registries.bitstream-formats.edit.extensions.label": "Bestandsextensies", // "admin.registries.bitstream-formats.edit.extensions.placeholder": "Enter a file extenstion without the dot", - // TODO New key - Add a translation - "admin.registries.bitstream-formats.edit.extensions.placeholder": "Enter a file extenstion without the dot", + "admin.registries.bitstream-formats.edit.extensions.placeholder": "Vul een bestandsextensie toe zonder de punt", // "admin.registries.bitstream-formats.edit.failure.content": "An error occurred while editing the bitstream format.", - // TODO New key - Add a translation - "admin.registries.bitstream-formats.edit.failure.content": "An error occurred while editing the bitstream format.", + "admin.registries.bitstream-formats.edit.failure.content": "Er is een fout opgetreden bij het bewerken van het bitstream-formaat.", // "admin.registries.bitstream-formats.edit.failure.head": "Failure", - // TODO New key - Add a translation - "admin.registries.bitstream-formats.edit.failure.head": "Failure", + "admin.registries.bitstream-formats.edit.failure.head": "Gefaald", // "admin.registries.bitstream-formats.edit.head": "Bitstream format: {{ format }}", - "admin.registries.bitstream-formats.edit.head": "Bitstream formaat: {{ format }}", + "admin.registries.bitstream-formats.edit.head": "Bitstream-formaat: {{ format }}", // "admin.registries.bitstream-formats.edit.internal.hint": "Formats marked as internal are hidden from the user, and used for administrative purposes.", - // TODO New key - Add a translation - "admin.registries.bitstream-formats.edit.internal.hint": "Formats marked as internal are hidden from the user, and used for administrative purposes.", + "admin.registries.bitstream-formats.edit.internal.hint": "Formaten die als intern gemarkeerd zijn, worden niet getoond aan de gebruiker en zijn bedoeld voor administratieve doeleinden.", // "admin.registries.bitstream-formats.edit.internal.label": "Internal", "admin.registries.bitstream-formats.edit.internal.label": "Intern", // "admin.registries.bitstream-formats.edit.mimetype.hint": "The MIME type associated with this format, does not have to be unique.", - // TODO New key - Add a translation - "admin.registries.bitstream-formats.edit.mimetype.hint": "The MIME type associated with this format, does not have to be unique.", + "admin.registries.bitstream-formats.edit.mimetype.hint": "Het MIME type dat bij dit formaat hoort. Het hoeft niet uniek te zijn.", // "admin.registries.bitstream-formats.edit.mimetype.label": "MIME Type", "admin.registries.bitstream-formats.edit.mimetype.label": "MIME Type", // "admin.registries.bitstream-formats.edit.shortDescription.hint": "A unique name for this format, (e.g. Microsoft Word XP or Microsoft Word 2000)", - // TODO New key - Add a translation - "admin.registries.bitstream-formats.edit.shortDescription.hint": "A unique name for this format, (e.g. Microsoft Word XP or Microsoft Word 2000)", + "admin.registries.bitstream-formats.edit.shortDescription.hint": "Een unieke naam voor dit formaat (b.v. Microsoft Word XP of Microsoft Word 2000)", // "admin.registries.bitstream-formats.edit.shortDescription.label": "Name", "admin.registries.bitstream-formats.edit.shortDescription.label": "Naam", // "admin.registries.bitstream-formats.edit.success.content": "The bitstream format was successfully edited.", - // TODO New key - Add a translation - "admin.registries.bitstream-formats.edit.success.content": "The bitstream format was successfully edited.", + "admin.registries.bitstream-formats.edit.success.content": "Het bitstream-formaat is bewerkt.", // "admin.registries.bitstream-formats.edit.success.head": "Success", "admin.registries.bitstream-formats.edit.success.head": "Succes", // "admin.registries.bitstream-formats.edit.supportLevel.hint": "The level of support your institution pledges for this format.", - // TODO New key - Add a translation - "admin.registries.bitstream-formats.edit.supportLevel.hint": "The level of support your institution pledges for this format.", + "admin.registries.bitstream-formats.edit.supportLevel.hint": "Het niveau van ondersteuning dat uw instituut belooft te bieden voor dit formaat.", // "admin.registries.bitstream-formats.edit.supportLevel.label": "Support level", - // TODO New key - Add a translation - "admin.registries.bitstream-formats.edit.supportLevel.label": "Support level", + "admin.registries.bitstream-formats.edit.supportLevel.label": "Ondersteuningsniveau", // "admin.registries.bitstream-formats.head": "Bitstream Format Registry", - "admin.registries.bitstream-formats.head": "Bitstream Formaat Register", + "admin.registries.bitstream-formats.head": "Bitstream-formaat Register", // "admin.registries.bitstream-formats.no-items": "No bitstream formats to show.", - // TODO New key - Add a translation - "admin.registries.bitstream-formats.no-items": "No bitstream formats to show.", + "admin.registries.bitstream-formats.no-items": "Geen bitstream-formaten om te tonen.", // "admin.registries.bitstream-formats.table.delete": "Delete selected", - // TODO New key - Add a translation - "admin.registries.bitstream-formats.table.delete": "Delete selected", + "admin.registries.bitstream-formats.table.delete": "Verwijder geselecteerde", // "admin.registries.bitstream-formats.table.deselect-all": "Deselect all", - // TODO New key - Add a translation - "admin.registries.bitstream-formats.table.deselect-all": "Deselect all", + "admin.registries.bitstream-formats.table.deselect-all": "De-selecteer alle", // "admin.registries.bitstream-formats.table.internal": "internal", "admin.registries.bitstream-formats.table.internal": "intern", @@ -177,8 +161,7 @@ "admin.registries.metadata.schemas.no-items": "Er kunnen geen metadataschema's getoond worden.", // "admin.registries.metadata.schemas.table.delete": "Delete selected", - // TODO New key - Add a translation - "admin.registries.metadata.schemas.table.delete": "Delete selected", + "admin.registries.metadata.schemas.table.delete": "Verwijder geselecteerde", // "admin.registries.metadata.schemas.table.id": "ID", "admin.registries.metadata.schemas.table.id": "ID", @@ -204,8 +187,7 @@ "admin.registries.schema.fields.no-items": "Er kunnen geen metadatavelden getoond worden.", // "admin.registries.schema.fields.table.delete": "Delete selected", - // TODO New key - Add a translation - "admin.registries.schema.fields.table.delete": "Delete selected", + "admin.registries.schema.fields.table.delete": "Verwijder geselecteerde", // "admin.registries.schema.fields.table.field": "Field", "admin.registries.schema.fields.table.field": "Veld", @@ -220,55 +202,43 @@ "admin.registries.schema.form.edit": "Bewerk metadataveld", // "admin.registries.schema.form.element": "Element", - // TODO New key - Add a translation "admin.registries.schema.form.element": "Element", // "admin.registries.schema.form.qualifier": "Qualifier", - // TODO New key - Add a translation "admin.registries.schema.form.qualifier": "Qualifier", // "admin.registries.schema.form.scopenote": "Scope Note", - // TODO New key - Add a translation - "admin.registries.schema.form.scopenote": "Scope Note", + "admin.registries.schema.form.scopenote": "Opmerking over het bereik", // "admin.registries.schema.head": "Metadata Schema", - "admin.registries.schema.head": "Metadata Schema", + "admin.registries.schema.head": "Metadataschema", // "admin.registries.schema.notification.created": "Successfully created metadata schema \"{{prefix}}\"", - // TODO New key - Add a translation - "admin.registries.schema.notification.created": "Successfully created metadata schema \"{{prefix}}\"", + "admin.registries.schema.notification.created": "Metadataschema \"{{prefix}}\" is aangemaakt", // "admin.registries.schema.notification.deleted.failure": "Failed to delete {{amount}} metadata schemas", - // TODO New key - Add a translation - "admin.registries.schema.notification.deleted.failure": "Failed to delete {{amount}} metadata schemas", + "admin.registries.schema.notification.deleted.failure": "Het verwijderen van {{amount}} metadataschemas is mislukt", // "admin.registries.schema.notification.deleted.success": "Successfully deleted {{amount}} metadata schemas", - // TODO New key - Add a translation - "admin.registries.schema.notification.deleted.success": "Successfully deleted {{amount}} metadata schemas", + "admin.registries.schema.notification.deleted.success": "{{amount}} Metadataschemas verwijderd", // "admin.registries.schema.notification.edited": "Successfully edited metadata schema \"{{prefix}}\"", - // TODO New key - Add a translation - "admin.registries.schema.notification.edited": "Successfully edited metadata schema \"{{prefix}}\"", + "admin.registries.schema.notification.edited": "Metadataschema \"{{prefix}}\" is bewerkt", // "admin.registries.schema.notification.failure": "Error", - // TODO New key - Add a translation - "admin.registries.schema.notification.failure": "Error", + "admin.registries.schema.notification.failure": "Fout", // "admin.registries.schema.notification.field.created": "Successfully created metadata field \"{{field}}\"", - // TODO New key - Add a translation - "admin.registries.schema.notification.field.created": "Successfully created metadata field \"{{field}}\"", + "admin.registries.schema.notification.field.created": "Metadataveld \"{{field}}\" is aangemaakt", // "admin.registries.schema.notification.field.deleted.failure": "Failed to delete {{amount}} metadata fields", - // TODO New key - Add a translation - "admin.registries.schema.notification.field.deleted.failure": "Failed to delete {{amount}} metadata fields", + "admin.registries.schema.notification.field.deleted.failure": "Het verwijderen van {{amount}} metadatavelden is mislukt", // "admin.registries.schema.notification.field.deleted.success": "Successfully deleted {{amount}} metadata fields", - // TODO New key - Add a translation - "admin.registries.schema.notification.field.deleted.success": "Successfully deleted {{amount}} metadata fields", + "admin.registries.schema.notification.field.deleted.success": "{{amount}} Metadatavelden verwijderd", // "admin.registries.schema.notification.field.edited": "Successfully edited metadata field \"{{field}}\"", - // TODO New key - Add a translation - "admin.registries.schema.notification.field.edited": "Successfully edited metadata field \"{{field}}\"", + "admin.registries.schema.notification.field.edited": "Metadataveld \"{{field}}\" is bewerkt", // "admin.registries.schema.notification.success": "Success", "admin.registries.schema.notification.success": "Succes", @@ -428,60 +398,46 @@ "collection.edit.item-mapper.confirm": "Map de geselecteerde items", // "collection.edit.item-mapper.description": "This is the item mapper tool that allows collection administrators to map items from other collections into this collection. You can search for items from other collections and map them, or browse the list of currently mapped items.", - // TODO New key - Add a translation - "collection.edit.item-mapper.description": "This is the item mapper tool that allows collection administrators to map items from other collections into this collection. You can search for items from other collections and map them, or browse the list of currently mapped items.", + "collection.edit.item-mapper.description": "Dit is de item mapper, waarmee collectiebeheerders items van andere collecties kunnen mappen naar deze collectie. U kunt items van andere collecties zoeken en mappen of de bladeren door de lijst met al gemapte items.", // "collection.edit.item-mapper.head": "Item Mapper - Map Items from Other Collections", - // TODO New key - Add a translation - "collection.edit.item-mapper.head": "Item Mapper - Map Items from Other Collections", + "collection.edit.item-mapper.head": "Item mapper - Map items uit andere collecties", // "collection.edit.item-mapper.no-search": "Please enter a query to search", - // TODO New key - Add a translation - "collection.edit.item-mapper.no-search": "Please enter a query to search", + "collection.edit.item-mapper.no-search": "Vul een zoekterm in om te zoeken", // "collection.edit.item-mapper.notifications.map.error.content": "Errors occurred for mapping of {{amount}} items.", - // TODO New key - Add a translation - "collection.edit.item-mapper.notifications.map.error.content": "Errors occurred for mapping of {{amount}} items.", + "collection.edit.item-mapper.notifications.map.error.content": "Er is een fout opgetreden bij het mappen van {{amount}} items.", // "collection.edit.item-mapper.notifications.map.error.head": "Mapping errors", - // TODO New key - Add a translation - "collection.edit.item-mapper.notifications.map.error.head": "Mapping errors", + "collection.edit.item-mapper.notifications.map.error.head": "Mapping fouten ", // "collection.edit.item-mapper.notifications.map.success.content": "Successfully mapped {{amount}} items.", - // TODO New key - Add a translation - "collection.edit.item-mapper.notifications.map.success.content": "Successfully mapped {{amount}} items.", + "collection.edit.item-mapper.notifications.map.success.content": "Er zijn {{amount}} items gemapt.", // "collection.edit.item-mapper.notifications.map.success.head": "Mapping completed", - // TODO New key - Add a translation - "collection.edit.item-mapper.notifications.map.success.head": "Mapping completed", + "collection.edit.item-mapper.notifications.map.success.head": "Mapping afgerond", // "collection.edit.item-mapper.notifications.unmap.error.content": "Errors occurred for removing the mappings of {{amount}} items.", - // TODO New key - Add a translation - "collection.edit.item-mapper.notifications.unmap.error.content": "Errors occurred for removing the mappings of {{amount}} items.", + "collection.edit.item-mapper.notifications.unmap.error.content": "Er zijn fouten opgetreden bij het verwijderen van de mapping van {{amount}} items.", // "collection.edit.item-mapper.notifications.unmap.error.head": "Remove mapping errors", - // TODO New key - Add a translation - "collection.edit.item-mapper.notifications.unmap.error.head": "Remove mapping errors", + "collection.edit.item-mapper.notifications.unmap.error.head": "Fouten bij het verwijderen van mappings", // "collection.edit.item-mapper.notifications.unmap.success.content": "Successfully removed the mappings of {{amount}} items.", - // TODO New key - Add a translation - "collection.edit.item-mapper.notifications.unmap.success.content": "Successfully removed the mappings of {{amount}} items.", + "collection.edit.item-mapper.notifications.unmap.success.content": "De mappings van {{amount}} items zijn verwijderd.", // "collection.edit.item-mapper.notifications.unmap.success.head": "Remove mapping completed", - // TODO New key - Add a translation - "collection.edit.item-mapper.notifications.unmap.success.head": "Remove mapping completed", + "collection.edit.item-mapper.notifications.unmap.success.head": "Verwijderen van mappings afgerond", // "collection.edit.item-mapper.remove": "Remove selected item mappings", - // TODO New key - Add a translation - "collection.edit.item-mapper.remove": "Remove selected item mappings", + "collection.edit.item-mapper.remove": "Verwijder de geselecteerde item mappings", // "collection.edit.item-mapper.tabs.browse": "Browse mapped items", - // TODO New key - Add a translation - "collection.edit.item-mapper.tabs.browse": "Browse mapped items", + "collection.edit.item-mapper.tabs.browse": "Blader door gemapte items", // "collection.edit.item-mapper.tabs.map": "Map new items", - // TODO New key - Add a translation - "collection.edit.item-mapper.tabs.map": "Map new items", + "collection.edit.item-mapper.tabs.map": "Map nieuwe items", @@ -608,44 +564,34 @@ // "dso-selector.create.collection.head": "New collection", - // TODO New key - Add a translation - "dso-selector.create.collection.head": "New collection", + "dso-selector.create.collection.head": "Nieuwe collectie", // "dso-selector.create.community.head": "New community", - // TODO New key - Add a translation - "dso-selector.create.community.head": "New community", + "dso-selector.create.community.head": "Nieuwe community", // "dso-selector.create.community.sub-level": "Create a new community in", - // TODO New key - Add a translation - "dso-selector.create.community.sub-level": "Create a new community in", + "dso-selector.create.community.sub-level": "Maak een nieuwe community in", // "dso-selector.create.community.top-level": "Create a new top-level community", - // TODO New key - Add a translation - "dso-selector.create.community.top-level": "Create a new top-level community", + "dso-selector.create.community.top-level": "Maak een nieuwe community op het hoogste niveau", // "dso-selector.create.item.head": "New item", - // TODO New key - Add a translation - "dso-selector.create.item.head": "New item", + "dso-selector.create.item.head": "Nieuw item", // "dso-selector.edit.collection.head": "Edit collection", - // TODO New key - Add a translation - "dso-selector.edit.collection.head": "Edit collection", + "dso-selector.edit.collection.head": "Bewerk collectie", // "dso-selector.edit.community.head": "Edit community", - // TODO New key - Add a translation - "dso-selector.edit.community.head": "Edit community", + "dso-selector.edit.community.head": "Bewerk community", // "dso-selector.edit.item.head": "Edit item", - // TODO New key - Add a translation - "dso-selector.edit.item.head": "Edit item", + "dso-selector.edit.item.head": "Bewerk item", // "dso-selector.no-results": "No {{ type }} found", - // TODO New key - Add a translation - "dso-selector.no-results": "No {{ type }} found", + "dso-selector.no-results": "Geen {{ type }} gevonden", // "dso-selector.placeholder": "Search for a {{ type }}", - // TODO New key - Add a translation - "dso-selector.placeholder": "Search for a {{ type }}", + "dso-selector.placeholder": "Zoek een {{ type }}", @@ -664,9 +610,6 @@ // "error.identifier": "No item found for the identifier", "error.identifier": "Geen item gevonden voor deze identifier", - // "error.identifier": "No item found for the identifier", - "error.identifier": "Geen item gevonden voor deze identifier", - // "error.default": "Error", "error.default": "Fout", @@ -692,18 +635,16 @@ "error.sub-communities": "Fout bij het ophalen van sub-communities", // "error.submission.sections.init-form-error": "An error occurred during section initialize, please check your input-form configuration. Details are below :

", - // TODO New key - Add a translation - "error.submission.sections.init-form-error": "An error occurred during section initialize, please check your input-form configuration. Details are below :

", + "error.submission.sections.init-form-error": "Er is een fout opgetreden bij het initialiseren van deze sectie. Controleer de configuratie van het invoerformulier. Details:

", // "error.top-level-communities": "Error fetching top-level communities", "error.top-level-communities": "Fout bij het inladen van communities op het hoogste niveau", // "error.validation.license.notgranted": "You must grant this license to complete your submission. If you are unable to grant this license at this time you may save your work and return later or remove the submission.", - "error.validation.license.notgranted": "U moet de invoerlicentie goedkeuren om de invoer af te werken. Indien u deze licentie momenteel niet kan of mag goedkeuren, kan u uw werk opslaan en de invoer later afwerken. U kunt dit nieuwe item ook verwijderen indien u niet voldoet aan de vereisten van de invoerlicentie.", + "error.validation.license.notgranted": "U moet de invoerlicentie goedkeuren om de invoer af te werken. Indien u deze licentie momenteel niet kan of mag goedkeuren, kunt u uw werk opslaan en de invoer later afwerken. U kunt dit nieuwe item ook verwijderen indien u niet voldoet aan de vereisten van de invoerlicentie.", // "error.validation.pattern": "This input is restricted by the current pattern: {{ pattern }}.", - // TODO New key - Add a translation - "error.validation.pattern": "This input is restricted by the current pattern: {{ pattern }}.", + "error.validation.pattern": "Deze invoer wordt ingeperkt door dit patroon: {{ pattern }}.", @@ -823,190 +764,146 @@ // "item.edit.item-mapper.buttons.add": "Map item to selected collections", - // TODO New key - Add a translation - "item.edit.item-mapper.buttons.add": "Map item to selected collections", + "item.edit.item-mapper.buttons.add": "Map dit item naar de geselecteerde collecties", // "item.edit.item-mapper.buttons.remove": "Remove item's mapping for selected collections", - // TODO New key - Add a translation - "item.edit.item-mapper.buttons.remove": "Remove item's mapping for selected collections", + "item.edit.item-mapper.buttons.remove": "Verwijder de mapping van de item naar de geselecteerde collecties", // "item.edit.item-mapper.cancel": "Cancel", - // TODO New key - Add a translation - "item.edit.item-mapper.cancel": "Cancel", + "item.edit.item-mapper.cancel": "Annuleer", // "item.edit.item-mapper.description": "This is the item mapper tool that allows administrators to map this item to other collections. You can search for collections and map them, or browse the list of collections the item is currently mapped to.", - // TODO New key - Add a translation - "item.edit.item-mapper.description": "This is the item mapper tool that allows administrators to map this item to other collections. You can search for collections and map them, or browse the list of collections the item is currently mapped to.", + "item.edit.item-mapper.description": "Dit is de item mapper, waarmee collectiebeheerders dit item kunnen mappen naar andere collecties. U kunt collecties zoeken en mappen of bladeren door de lijst waar dit item al naar is gemapt.", // "item.edit.item-mapper.head": "Item Mapper - Map Item to Collections", - // TODO New key - Add a translation - "item.edit.item-mapper.head": "Item Mapper - Map Item to Collections", + "item.edit.item-mapper.head": "Item mapper - Map een item naar collecties", // "item.edit.item-mapper.item": "Item: \"{{name}}\"", - // TODO New key - Add a translation "item.edit.item-mapper.item": "Item: \"{{name}}\"", // "item.edit.item-mapper.no-search": "Please enter a query to search", - // TODO New key - Add a translation - "item.edit.item-mapper.no-search": "Please enter a query to search", + "item.edit.item-mapper.no-search": "Vul een zoekterm in om te zoeken", // "item.edit.item-mapper.notifications.add.error.content": "Errors occurred for mapping of item to {{amount}} collections.", - // TODO New key - Add a translation - "item.edit.item-mapper.notifications.add.error.content": "Errors occurred for mapping of item to {{amount}} collections.", + "item.edit.item-mapper.notifications.add.error.content": "Er zijn fouten opgetreden bij het mappen van het item naar {{amount}} collecties.", // "item.edit.item-mapper.notifications.add.error.head": "Mapping errors", - // TODO New key - Add a translation - "item.edit.item-mapper.notifications.add.error.head": "Mapping errors", + "item.edit.item-mapper.notifications.add.error.head": "Mapping fouten", // "item.edit.item-mapper.notifications.add.success.content": "Successfully mapped item to {{amount}} collections.", - // TODO New key - Add a translation - "item.edit.item-mapper.notifications.add.success.content": "Successfully mapped item to {{amount}} collections.", + "item.edit.item-mapper.notifications.add.success.content": "Het item is naar {{amount}} collecties gemapt.", // "item.edit.item-mapper.notifications.add.success.head": "Mapping completed", - // TODO New key - Add a translation - "item.edit.item-mapper.notifications.add.success.head": "Mapping completed", + "item.edit.item-mapper.notifications.add.success.head": "Mapping afgerond", // "item.edit.item-mapper.notifications.remove.error.content": "Errors occurred for the removal of the mapping to {{amount}} collections.", - // TODO New key - Add a translation - "item.edit.item-mapper.notifications.remove.error.content": "Errors occurred for the removal of the mapping to {{amount}} collections.", + "item.edit.item-mapper.notifications.remove.error.content": "Er zijn fouten opgetreden bij het verwijderen van de mapping naar {{amount}} collecties.", // "item.edit.item-mapper.notifications.remove.error.head": "Removal of mapping errors", - // TODO New key - Add a translation - "item.edit.item-mapper.notifications.remove.error.head": "Removal of mapping errors", + "item.edit.item-mapper.notifications.remove.error.head": "Fouten bij het verwijderen van mappings", // "item.edit.item-mapper.notifications.remove.success.content": "Successfully removed mapping of item to {{amount}} collections.", - // TODO New key - Add a translation - "item.edit.item-mapper.notifications.remove.success.content": "Successfully removed mapping of item to {{amount}} collections.", + "item.edit.item-mapper.notifications.remove.success.content": "De mapping van dit item naar {{amount}} collecties is verwijderd.", // "item.edit.item-mapper.notifications.remove.success.head": "Removal of mapping completed", - // TODO New key - Add a translation - "item.edit.item-mapper.notifications.remove.success.head": "Removal of mapping completed", + "item.edit.item-mapper.notifications.remove.success.head": "Verwijderen van mapping afgerond", // "item.edit.item-mapper.tabs.browse": "Browse mapped collections", - // TODO New key - Add a translation - "item.edit.item-mapper.tabs.browse": "Browse mapped collections", + "item.edit.item-mapper.tabs.browse": "Blader door gemapte collecties", // "item.edit.item-mapper.tabs.map": "Map new collections", - // TODO New key - Add a translation - "item.edit.item-mapper.tabs.map": "Map new collections", + "item.edit.item-mapper.tabs.map": "Map een nieuwe collectie", // "item.edit.metadata.add-button": "Add", - // TODO New key - Add a translation - "item.edit.metadata.add-button": "Add", + "item.edit.metadata.add-button": "Voeg toe", // "item.edit.metadata.discard-button": "Discard", - // TODO New key - Add a translation - "item.edit.metadata.discard-button": "Discard", + "item.edit.metadata.discard-button": "Annuleer", // "item.edit.metadata.edit.buttons.edit": "Edit", - // TODO New key - Add a translation - "item.edit.metadata.edit.buttons.edit": "Edit", + "item.edit.metadata.edit.buttons.edit": "Bewerk", // "item.edit.metadata.edit.buttons.remove": "Remove", - // TODO New key - Add a translation - "item.edit.metadata.edit.buttons.remove": "Remove", + "item.edit.metadata.edit.buttons.remove": "Verwijder", // "item.edit.metadata.edit.buttons.undo": "Undo changes", - // TODO New key - Add a translation - "item.edit.metadata.edit.buttons.undo": "Undo changes", + "item.edit.metadata.edit.buttons.undo": "Maak wijzigingen ongedaan", // "item.edit.metadata.edit.buttons.unedit": "Stop editing", - // TODO New key - Add a translation - "item.edit.metadata.edit.buttons.unedit": "Stop editing", + "item.edit.metadata.edit.buttons.unedit": "Stop met bewerken", // "item.edit.metadata.headers.edit": "Edit", - // TODO New key - Add a translation - "item.edit.metadata.headers.edit": "Edit", + "item.edit.metadata.headers.edit": "Bewerk", // "item.edit.metadata.headers.field": "Field", - // TODO New key - Add a translation - "item.edit.metadata.headers.field": "Field", + "item.edit.metadata.headers.field": "Veld", // "item.edit.metadata.headers.language": "Lang", - // TODO New key - Add a translation - "item.edit.metadata.headers.language": "Lang", + "item.edit.metadata.headers.language": "Taal", // "item.edit.metadata.headers.value": "Value", - // TODO New key - Add a translation - "item.edit.metadata.headers.value": "Value", + "item.edit.metadata.headers.value": "Waarde", // "item.edit.metadata.metadatafield.invalid": "Please choose a valid metadata field", - // TODO New key - Add a translation - "item.edit.metadata.metadatafield.invalid": "Please choose a valid metadata field", + "item.edit.metadata.metadatafield.invalid": "Kies een geldig metadataveld", // "item.edit.metadata.notifications.discarded.content": "Your changes were discarded. To reinstate your changes click the 'Undo' button", - // TODO New key - Add a translation - "item.edit.metadata.notifications.discarded.content": "Your changes were discarded. To reinstate your changes click the 'Undo' button", + "item.edit.metadata.notifications.discarded.content": "Uw wijzigingen zijn geannuleerd. Klik 'maak ongedaan' om ze terug te halen.", // "item.edit.metadata.notifications.discarded.title": "Changed discarded", - // TODO New key - Add a translation - "item.edit.metadata.notifications.discarded.title": "Changed discarded", + "item.edit.metadata.notifications.discarded.title": "Wijzingen geannuleerd", // "item.edit.metadata.notifications.invalid.content": "Your changes were not saved. Please make sure all fields are valid before you save.", - // TODO New key - Add a translation - "item.edit.metadata.notifications.invalid.content": "Your changes were not saved. Please make sure all fields are valid before you save.", + "item.edit.metadata.notifications.invalid.content": "Uw wijzingen zijn niet opgeslagen. Controleer of alle velden geldig zijn voor u opslaat.", // "item.edit.metadata.notifications.invalid.title": "Metadata invalid", - // TODO New key - Add a translation - "item.edit.metadata.notifications.invalid.title": "Metadata invalid", + "item.edit.metadata.notifications.invalid.title": "Ongeldige metadata", // "item.edit.metadata.notifications.outdated.content": "The item you're currently working on has been changed by another user. Your current changes are discarded to prevent conflicts", - // TODO New key - Add a translation - "item.edit.metadata.notifications.outdated.content": "The item you're currently working on has been changed by another user. Your current changes are discarded to prevent conflicts", + "item.edit.metadata.notifications.outdated.content": "Het item waar u aan werkt is gewijzigd door een andere gebruiker. Uw huidige wijzigingen worden geannuleerd om conflicten te voorkomen.", // "item.edit.metadata.notifications.outdated.title": "Changed outdated", // TODO New key - Add a translation "item.edit.metadata.notifications.outdated.title": "Changed outdated", // "item.edit.metadata.notifications.saved.content": "Your changes to this item's metadata were saved.", - // TODO New key - Add a translation - "item.edit.metadata.notifications.saved.content": "Your changes to this item's metadata were saved.", + "item.edit.metadata.notifications.saved.content": "Uw wijzingen in de metadata van dit item zijn opgeslagen.", // "item.edit.metadata.notifications.saved.title": "Metadata saved", - // TODO New key - Add a translation - "item.edit.metadata.notifications.saved.title": "Metadata saved", + "item.edit.metadata.notifications.saved.title": "Metadata opgeslagen", // "item.edit.metadata.reinstate-button": "Undo", - // TODO New key - Add a translation - "item.edit.metadata.reinstate-button": "Undo", + "item.edit.metadata.reinstate-button": "Maak ongedaan", // "item.edit.metadata.save-button": "Save", - // TODO New key - Add a translation - "item.edit.metadata.save-button": "Save", + "item.edit.metadata.save-button": "Opslaan", // "item.edit.modify.overview.field": "Field", - // TODO New key - Add a translation - "item.edit.modify.overview.field": "Field", + "item.edit.modify.overview.field": "Veld", // "item.edit.modify.overview.language": "Language", - // TODO New key - Add a translation - "item.edit.modify.overview.language": "Language", + "item.edit.modify.overview.language": "Taal", // "item.edit.modify.overview.value": "Value", - // TODO New key - Add a translation - "item.edit.modify.overview.value": "Value", + "item.edit.modify.overview.value": "Waarde", // "item.edit.move.cancel": "Cancel", - // TODO New key - Add a translation - "item.edit.move.cancel": "Cancel", + "item.edit.move.cancel": "Annuleer", // "item.edit.move.description": "Select the collection you wish to move this item to. To narrow down the list of displayed collections, you can enter a search query in the box.", - // TODO New key - Add a translation - "item.edit.move.description": "Select the collection you wish to move this item to. To narrow down the list of displayed collections, you can enter a search query in the box.", + "item.edit.move.description": "Kies de collectie waar u dit item naartoe wilt verplaatsen. Om de lijst met collecties in te perken kunt een zoekterm invullen in het zoekveld.", // "item.edit.move.error": "An error occurred when attempting to move the item", - // TODO New key - Add a translation - "item.edit.move.error": "An error occurred when attempting to move the item", + "item.edit.move.error": "Er is een fout opgetreden bij het verplaatsen van het item", // "item.edit.move.head": "Move item: {{id}}", - // TODO New key - Add a translation - "item.edit.move.head": "Move item: {{id}}", + "item.edit.move.head": "Verplaats item: {{id}}", // "item.edit.move.inheritpolicies.checkbox": "Inherit policies", // TODO New key - Add a translation @@ -1017,76 +914,60 @@ "item.edit.move.inheritpolicies.description": "Inherit the default policies of the destination collection", // "item.edit.move.move": "Move", - // TODO New key - Add a translation - "item.edit.move.move": "Move", + "item.edit.move.move": "Verplaats", // "item.edit.move.processing": "Moving...", - // TODO New key - Add a translation - "item.edit.move.processing": "Moving...", + "item.edit.move.processing": "Bezig ...", // "item.edit.move.search.placeholder": "Enter a search query to look for collections", - // TODO New key - Add a translation - "item.edit.move.search.placeholder": "Enter a search query to look for collections", + "item.edit.move.search.placeholder": "Vul een zoekterm in om collecties te zoeken", // "item.edit.move.success": "The item has been moved successfully", - // TODO New key - Add a translation - "item.edit.move.success": "The item has been moved successfully", + "item.edit.move.success": "Het item is verplaatst", // "item.edit.move.title": "Move item", - // TODO New key - Add a translation - "item.edit.move.title": "Move item", + "item.edit.move.title": "Verplaats item", // "item.edit.private.cancel": "Cancel", - // TODO New key - Add a translation - "item.edit.private.cancel": "Cancel", + "item.edit.private.cancel": "Annuleer", // "item.edit.private.confirm": "Make it Private", - // TODO New key - Add a translation - "item.edit.private.confirm": "Make it Private", + "item.edit.private.confirm": "Maak privé", // "item.edit.private.description": "Are you sure this item should be made private in the archive?", - // TODO New key - Add a translation - "item.edit.private.description": "Are you sure this item should be made private in the archive?", + "item.edit.private.description": "Weet u zeker dat dit item privé moet worden in het archief?", // "item.edit.private.error": "An error occurred while making the item private", - // TODO New key - Add a translation - "item.edit.private.error": "An error occurred while making the item private", + "item.edit.private.error": "Er is een fout opgetreden bij het privé maken van het item", // "item.edit.private.header": "Make item private: {{ id }}", - // TODO New key - Add a translation - "item.edit.private.header": "Make item private: {{ id }}", + "item.edit.private.header": "Maak item privé: {{ id }}", // "item.edit.private.success": "The item is now private", // TODO New key - Add a translation - "item.edit.private.success": "The item is now private", + "item.edit.private.success": "Dit item is nu privé", // "item.edit.public.cancel": "Cancel", - // TODO New key - Add a translation - "item.edit.public.cancel": "Cancel", + "item.edit.public.cancel": "Annuleer", // "item.edit.public.confirm": "Make it Public", - // TODO New key - Add a translation - "item.edit.public.confirm": "Make it Public", + "item.edit.public.confirm": "Maak openbaar", // "item.edit.public.description": "Are you sure this item should be made public in the archive?", - // TODO New key - Add a translation - "item.edit.public.description": "Are you sure this item should be made public in the archive?", + "item.edit.public.description": "Weet u zeker dat dit item openbaar moet worden in het archief?", // "item.edit.public.error": "An error occurred while making the item public", - // TODO New key - Add a translation - "item.edit.public.error": "An error occurred while making the item public", + "item.edit.public.error": "Er is een fout opgetreden bij het openbaar maken van het item", // "item.edit.public.header": "Make item public: {{ id }}", - // TODO New key - Add a translation - "item.edit.public.header": "Make item public: {{ id }}", + "item.edit.public.header": "Maak item openbaar: {{ id }}", // "item.edit.public.success": "The item is now public", - // TODO New key - Add a translation - "item.edit.public.success": "The item is now public", + "item.edit.public.success": "Het item is nu openbaar", From 423cf7569a72908ad19ecf1d6ed3d1c482c67612 Mon Sep 17 00:00:00 2001 From: muiltje Date: Wed, 8 Jan 2020 14:00:44 +0100 Subject: [PATCH 13/32] First batch of Dutch translations --- resources/i18n/nl.json5 | 713 +++++++++++++--------------------------- 1 file changed, 231 insertions(+), 482 deletions(-) diff --git a/resources/i18n/nl.json5 b/resources/i18n/nl.json5 index 973a045af8..2332197c8d 100644 --- a/resources/i18n/nl.json5 +++ b/resources/i18n/nl.json5 @@ -972,88 +972,69 @@ // "item.edit.reinstate.cancel": "Cancel", - // TODO New key - Add a translation - "item.edit.reinstate.cancel": "Cancel", + "item.edit.reinstate.cancel": "Annuleer", // "item.edit.reinstate.confirm": "Reinstate", - // TODO New key - Add a translation - "item.edit.reinstate.confirm": "Reinstate", + "item.edit.reinstate.confirm": "Zet terug", // "item.edit.reinstate.description": "Are you sure this item should be reinstated to the archive?", - // TODO New key - Add a translation - "item.edit.reinstate.description": "Are you sure this item should be reinstated to the archive?", + "item.edit.reinstate.description": "Weet u zeker dat dit item weer teruggezet moet worden in het archief?", // "item.edit.reinstate.error": "An error occurred while reinstating the item", - // TODO New key - Add a translation - "item.edit.reinstate.error": "An error occurred while reinstating the item", + "item.edit.reinstate.error": "Er is een fout opgetreden bij het terugzetten van het item", // "item.edit.reinstate.header": "Reinstate item: {{ id }}", - // TODO New key - Add a translation - "item.edit.reinstate.header": "Reinstate item: {{ id }}", + "item.edit.reinstate.header": "Zet item terug: {{ id }}", // "item.edit.reinstate.success": "The item was reinstated successfully", - // TODO New key - Add a translation - "item.edit.reinstate.success": "The item was reinstated successfully", + "item.edit.reinstate.success": "Het item is teruggezet", // "item.edit.relationships.discard-button": "Discard", - // TODO New key - Add a translation - "item.edit.relationships.discard-button": "Discard", + "item.edit.relationships.discard-button": "Annuleer", // "item.edit.relationships.edit.buttons.remove": "Remove", - // TODO New key - Add a translation - "item.edit.relationships.edit.buttons.remove": "Remove", + "item.edit.relationships.edit.buttons.remove": "Verwijder", // "item.edit.relationships.edit.buttons.undo": "Undo changes", - // TODO New key - Add a translation - "item.edit.relationships.edit.buttons.undo": "Undo changes", + "item.edit.relationships.edit.buttons.undo": "Maak wijzigingen ongedaan", // "item.edit.relationships.notifications.discarded.content": "Your changes were discarded. To reinstate your changes click the 'Undo' button", - // TODO New key - Add a translation - "item.edit.relationships.notifications.discarded.content": "Your changes were discarded. To reinstate your changes click the 'Undo' button", + "item.edit.relationships.notifications.discarded.content": "Uw wijzigingen zijn ongedaan gemaakt. Klik 'maak ongedaan' om ze weer terug te halen.", // "item.edit.relationships.notifications.discarded.title": "Changes discarded", - // TODO New key - Add a translation - "item.edit.relationships.notifications.discarded.title": "Changes discarded", + "item.edit.relationships.notifications.discarded.title": "Wijzingen geannuleerd", // "item.edit.relationships.notifications.failed.title": "Error deleting relationship", - // TODO New key - Add a translation - "item.edit.relationships.notifications.failed.title": "Error deleting relationship", + "item.edit.relationships.notifications.failed.title": "Er is een fout opgetreden bij het verwijderen van een relatie", // "item.edit.relationships.notifications.outdated.content": "The item you're currently working on has been changed by another user. Your current changes are discarded to prevent conflicts", - // TODO New key - Add a translation - "item.edit.relationships.notifications.outdated.content": "The item you're currently working on has been changed by another user. Your current changes are discarded to prevent conflicts", + "item.edit.relationships.notifications.outdated.content": "Het item waar u aan werkt is gewijzigd door een andere gebruiker. Uw huidige wijzigingen zijn ongedaan gemaakt om conflicten te voorkomen.", // "item.edit.relationships.notifications.outdated.title": "Changes outdated", // TODO New key - Add a translation "item.edit.relationships.notifications.outdated.title": "Changes outdated", // "item.edit.relationships.notifications.saved.content": "Your changes to this item's relationships were saved.", - // TODO New key - Add a translation - "item.edit.relationships.notifications.saved.content": "Your changes to this item's relationships were saved.", + "item.edit.relationships.notifications.saved.content": "Uw wijzingen in de relaties van dit item zijn opgeslagen.", // "item.edit.relationships.notifications.saved.title": "Relationships saved", - // TODO New key - Add a translation - "item.edit.relationships.notifications.saved.title": "Relationships saved", + "item.edit.relationships.notifications.saved.title": "Relaties opgeslagen", // "item.edit.relationships.reinstate-button": "Undo", - // TODO New key - Add a translation - "item.edit.relationships.reinstate-button": "Undo", + "item.edit.relationships.reinstate-button": "Maak ongedaan", // "item.edit.relationships.save-button": "Save", - // TODO New key - Add a translation - "item.edit.relationships.save-button": "Save", + "item.edit.relationships.save-button": "Opslaan", // "item.edit.tabs.bitstreams.head": "Item Bitstreams", - // TODO New key - Add a translation - "item.edit.tabs.bitstreams.head": "Item Bitstreams", + "item.edit.tabs.bitstreams.head": "Item bitstreams", // "item.edit.tabs.bitstreams.title": "Item Edit - Bitstreams", - // TODO New key - Add a translation - "item.edit.tabs.bitstreams.title": "Item Edit - Bitstreams", + "item.edit.tabs.bitstreams.title": "Item bewerken - Bitstreams", // "item.edit.tabs.curate.head": "Curate", // TODO New key - Add a translation @@ -1064,146 +1045,112 @@ "item.edit.tabs.curate.title": "Item Edit - Curate", // "item.edit.tabs.metadata.head": "Item Metadata", - // TODO New key - Add a translation - "item.edit.tabs.metadata.head": "Item Metadata", + "item.edit.tabs.metadata.head": "Item metadata", // "item.edit.tabs.metadata.title": "Item Edit - Metadata", - // TODO New key - Add a translation - "item.edit.tabs.metadata.title": "Item Edit - Metadata", + "item.edit.tabs.metadata.title": "Item bewerken - Metadata", // "item.edit.tabs.relationships.head": "Item Relationships", - // TODO New key - Add a translation - "item.edit.tabs.relationships.head": "Item Relationships", + "item.edit.tabs.relationships.head": "Item relaties", // "item.edit.tabs.relationships.title": "Item Edit - Relationships", - // TODO New key - Add a translation - "item.edit.tabs.relationships.title": "Item Edit - Relationships", + "item.edit.tabs.relationships.title": "Item bewerken - relaties", // "item.edit.tabs.status.buttons.authorizations.button": "Authorizations...", - // TODO New key - Add a translation - "item.edit.tabs.status.buttons.authorizations.button": "Authorizations...", + "item.edit.tabs.status.buttons.authorizations.button": "Autorisaties ..", // "item.edit.tabs.status.buttons.authorizations.label": "Edit item's authorization policies", // TODO New key - Add a translation "item.edit.tabs.status.buttons.authorizations.label": "Edit item's authorization policies", // "item.edit.tabs.status.buttons.delete.button": "Permanently delete", - // TODO New key - Add a translation - "item.edit.tabs.status.buttons.delete.button": "Permanently delete", + "item.edit.tabs.status.buttons.delete.button": "Permanent verwijderen", // "item.edit.tabs.status.buttons.delete.label": "Completely expunge item", - // TODO New key - Add a translation - "item.edit.tabs.status.buttons.delete.label": "Completely expunge item", + "item.edit.tabs.status.buttons.delete.label": "Verwijderen het item geheel", // "item.edit.tabs.status.buttons.mappedCollections.button": "Mapped collections", - // TODO New key - Add a translation - "item.edit.tabs.status.buttons.mappedCollections.button": "Mapped collections", + "item.edit.tabs.status.buttons.mappedCollections.button": "Gemapte collecties", // "item.edit.tabs.status.buttons.mappedCollections.label": "Manage mapped collections", - // TODO New key - Add a translation - "item.edit.tabs.status.buttons.mappedCollections.label": "Manage mapped collections", + "item.edit.tabs.status.buttons.mappedCollections.label": "Beheer gemapte collecties", // "item.edit.tabs.status.buttons.move.button": "Move...", - // TODO New key - Add a translation - "item.edit.tabs.status.buttons.move.button": "Move...", + "item.edit.tabs.status.buttons.move.button": "Verplaats ..", // "item.edit.tabs.status.buttons.move.label": "Move item to another collection", - // TODO New key - Add a translation - "item.edit.tabs.status.buttons.move.label": "Move item to another collection", + "item.edit.tabs.status.buttons.move.label": "Verplaats het item naar een andere collectie", // "item.edit.tabs.status.buttons.private.button": "Make it private...", - // TODO New key - Add a translation - "item.edit.tabs.status.buttons.private.button": "Make it private...", + "item.edit.tabs.status.buttons.private.button": "Maak privé ...", // "item.edit.tabs.status.buttons.private.label": "Make item private", - // TODO New key - Add a translation - "item.edit.tabs.status.buttons.private.label": "Make item private", + "item.edit.tabs.status.buttons.private.label": "Maak het item privé", // "item.edit.tabs.status.buttons.public.button": "Make it public...", - // TODO New key - Add a translation - "item.edit.tabs.status.buttons.public.button": "Make it public...", + "item.edit.tabs.status.buttons.public.button": "Maak openbaar ..", // "item.edit.tabs.status.buttons.public.label": "Make item public", - // TODO New key - Add a translation - "item.edit.tabs.status.buttons.public.label": "Make item public", + "item.edit.tabs.status.buttons.public.label": "Maak het item openbaar", // "item.edit.tabs.status.buttons.reinstate.button": "Reinstate...", - // TODO New key - Add a translation - "item.edit.tabs.status.buttons.reinstate.button": "Reinstate...", + "item.edit.tabs.status.buttons.reinstate.button": "Zet terug ...", // "item.edit.tabs.status.buttons.reinstate.label": "Reinstate item into the repository", - // TODO New key - Add a translation - "item.edit.tabs.status.buttons.reinstate.label": "Reinstate item into the repository", + "item.edit.tabs.status.buttons.reinstate.label": "Zet het item terug in het repository", // "item.edit.tabs.status.buttons.withdraw.button": "Withdraw...", - // TODO New key - Add a translation - "item.edit.tabs.status.buttons.withdraw.button": "Withdraw...", + "item.edit.tabs.status.buttons.withdraw.button": "Trek terug ...", // "item.edit.tabs.status.buttons.withdraw.label": "Withdraw item from the repository", - // TODO New key - Add a translation - "item.edit.tabs.status.buttons.withdraw.label": "Withdraw item from the repository", + "item.edit.tabs.status.buttons.withdraw.label": "Trek het item terug uit het repository", // "item.edit.tabs.status.description": "Welcome to the item management page. From here you can withdraw, reinstate, move or delete the item. You may also update or add new metadata / bitstreams on the other tabs.", - // TODO New key - Add a translation - "item.edit.tabs.status.description": "Welcome to the item management page. From here you can withdraw, reinstate, move or delete the item. You may also update or add new metadata / bitstreams on the other tabs.", + "item.edit.tabs.status.description": "Welkom op de itembeheerpagina. Hier kunt u het item terugtrekken, terugzetten, verplaatsen of verwijderen. Onder de andere tabbladen kunt u metadata / bitstreams bewerken of toevoegen.", // "item.edit.tabs.status.head": "Item Status", - // TODO New key - Add a translation - "item.edit.tabs.status.head": "Item Status", + "item.edit.tabs.status.head": "Item status", // "item.edit.tabs.status.labels.handle": "Handle", - // TODO New key - Add a translation "item.edit.tabs.status.labels.handle": "Handle", // "item.edit.tabs.status.labels.id": "Item Internal ID", - // TODO New key - Add a translation - "item.edit.tabs.status.labels.id": "Item Internal ID", + "item.edit.tabs.status.labels.id": "Intern Item ID", // "item.edit.tabs.status.labels.itemPage": "Item Page", - // TODO New key - Add a translation - "item.edit.tabs.status.labels.itemPage": "Item Page", + "item.edit.tabs.status.labels.itemPage": "Itempagina", // "item.edit.tabs.status.labels.lastModified": "Last Modified", - // TODO New key - Add a translation - "item.edit.tabs.status.labels.lastModified": "Last Modified", + "item.edit.tabs.status.labels.lastModified": "Laatst gewijzigd", // "item.edit.tabs.status.title": "Item Edit - Status", - // TODO New key - Add a translation - "item.edit.tabs.status.title": "Item Edit - Status", + "item.edit.tabs.status.title": "Item bewerken - Status", // "item.edit.tabs.view.head": "View Item", - // TODO New key - Add a translation - "item.edit.tabs.view.head": "View Item", + "item.edit.tabs.view.head": "Bekijk het item", // "item.edit.tabs.view.title": "Item Edit - View", - // TODO New key - Add a translation - "item.edit.tabs.view.title": "Item Edit - View", + "item.edit.tabs.view.title": "Item bewerken - Bekijk", // "item.edit.withdraw.cancel": "Cancel", - // TODO New key - Add a translation - "item.edit.withdraw.cancel": "Cancel", + "item.edit.withdraw.cancel": "Annuleer", // "item.edit.withdraw.confirm": "Withdraw", - // TODO New key - Add a translation - "item.edit.withdraw.confirm": "Withdraw", + "item.edit.withdraw.confirm": "Trek terug", // "item.edit.withdraw.description": "Are you sure this item should be withdrawn from the archive?", - // TODO New key - Add a translation - "item.edit.withdraw.description": "Are you sure this item should be withdrawn from the archive?", + "item.edit.withdraw.description": "Weet u zeker dat dit item uit het archief moet worden teruggetrokken?", // "item.edit.withdraw.error": "An error occurred while withdrawing the item", - // TODO New key - Add a translation - "item.edit.withdraw.error": "An error occurred while withdrawing the item", + "item.edit.withdraw.error": "Er is een fout opgetreden bij het terugtrekken van het item", // "item.edit.withdraw.header": "Withdraw item: {{ id }}", - // TODO New key - Add a translation - "item.edit.withdraw.header": "Withdraw item: {{ id }}", + "item.edit.withdraw.header": "Item terugtrekken: {{ id }}", // "item.edit.withdraw.success": "The item was withdrawn successfully", - // TODO New key - Add a translation - "item.edit.withdraw.success": "The item was withdrawn successfully", + "item.edit.withdraw.success": "Het item is teruggetrokken", @@ -1214,8 +1161,7 @@ "item.page.author": "Auteur", // "item.page.citation": "Citation", - // TODO New key - Add a translation - "item.page.citation": "Citation", + "item.page.citation": "Citeren als", // "item.page.collections": "Collections", "item.page.collections": "Collecties", @@ -1227,27 +1173,22 @@ "item.page.files": "Bestanden", // "item.page.filesection.description": "Description:", - // TODO New key - Add a translation - "item.page.filesection.description": "Description:", + "item.page.filesection.description": "Beschrijving:", // "item.page.filesection.download": "Download", "item.page.filesection.download": "Download", // "item.page.filesection.format": "Format:", - // TODO New key - Add a translation - "item.page.filesection.format": "Format:", + "item.page.filesection.format": "Formaat:", // "item.page.filesection.name": "Name:", - // TODO New key - Add a translation - "item.page.filesection.name": "Name:", + "item.page.filesection.name": "Naam:", // "item.page.filesection.size": "Size:", - // TODO New key - Add a translation - "item.page.filesection.size": "Size:", + "item.page.filesection.size": "Grootte:", // "item.page.journal.search.title": "Articles in this journal", - // TODO New key - Add a translation - "item.page.journal.search.title": "Articles in this journal", + "item.page.journal.search.title": "Artikelen in dit tijdschrift", // "item.page.link.full": "Full item page", "item.page.link.full": "Volledige itemweergave", @@ -1256,20 +1197,16 @@ "item.page.link.simple": "Eenvoudige itemweergave", // "item.page.person.search.title": "Articles by this author", - // TODO New key - Add a translation - "item.page.person.search.title": "Articles by this author", + "item.page.person.search.title": "Artikelen van deze auteur", // "item.page.related-items.view-more": "View more", - // TODO New key - Add a translation - "item.page.related-items.view-more": "View more", + "item.page.related-items.view-more": "Bekijk meer", // "item.page.related-items.view-less": "View less", - // TODO New key - Add a translation - "item.page.related-items.view-less": "View less", + "item.page.related-items.view-less": "Bekijk minder", // "item.page.subject": "Keywords", - // TODO New key - Add a translation - "item.page.subject": "Keywords", + "item.page.subject": "Trefwoorden", // "item.page.uri": "URI", "item.page.uri": "URI", @@ -1277,114 +1214,88 @@ // "item.select.confirm": "Confirm selected", - // TODO New key - Add a translation - "item.select.confirm": "Confirm selected", + "item.select.confirm": "Bevestig selectie", // "item.select.empty": "No items to show", - // TODO New key - Add a translation - "item.select.empty": "No items to show", + "item.select.empty": "Geen items om te tonen", // "item.select.table.author": "Author", - // TODO New key - Add a translation - "item.select.table.author": "Author", + "item.select.table.author": "Auteur", // "item.select.table.collection": "Collection", - // TODO New key - Add a translation - "item.select.table.collection": "Collection", + "item.select.table.collection": "Collectie", // "item.select.table.title": "Title", - // TODO New key - Add a translation - "item.select.table.title": "Title", + "item.select.table.title": "Titel", // "journal.listelement.badge": "Journal", - // TODO New key - Add a translation - "journal.listelement.badge": "Journal", + "journal.listelement.badge": "Tijdschrift", // "journal.page.description": "Description", - // TODO New key - Add a translation - "journal.page.description": "Description", + "journal.page.description": "Beschrijving", // "journal.page.editor": "Editor-in-Chief", - // TODO New key - Add a translation - "journal.page.editor": "Editor-in-Chief", + "journal.page.editor": "Hoofdredacteur", // "journal.page.issn": "ISSN", - // TODO New key - Add a translation "journal.page.issn": "ISSN", // "journal.page.publisher": "Publisher", - // TODO New key - Add a translation - "journal.page.publisher": "Publisher", + "journal.page.publisher": "Uitgever", // "journal.page.titleprefix": "Journal: ", - // TODO New key - Add a translation - "journal.page.titleprefix": "Journal: ", + "journal.page.titleprefix": "Tijdschrift: ", // "journal.search.results.head": "Journal Search Results", - // TODO New key - Add a translation - "journal.search.results.head": "Journal Search Results", + "journal.search.results.head": "Tijdschrift zoekresultaten", // "journal.search.title": "DSpace Angular :: Journal Search", - // TODO New key - Add a translation - "journal.search.title": "DSpace Angular :: Journal Search", + "journal.search.title": "DSpace Angular :: Tijdschrift zoeken", // "journalissue.listelement.badge": "Journal Issue", - // TODO New key - Add a translation - "journalissue.listelement.badge": "Journal Issue", + "journalissue.listelement.badge": "Tijdschrift aflevering", // "journalissue.page.description": "Description", - // TODO New key - Add a translation - "journalissue.page.description": "Description", + "journalissue.page.description": "Beschrijving", // "journalissue.page.issuedate": "Issue Date", - // TODO New key - Add a translation - "journalissue.page.issuedate": "Issue Date", + "journalissue.page.issuedate": "Datum van uitgave", // "journalissue.page.journal-issn": "Journal ISSN", - // TODO New key - Add a translation - "journalissue.page.journal-issn": "Journal ISSN", + "journalissue.page.journal-issn": "Tijdschrift ISSN", // "journalissue.page.journal-title": "Journal Title", - // TODO New key - Add a translation - "journalissue.page.journal-title": "Journal Title", + "journalissue.page.journal-title": "Tijdschrifttitel", // "journalissue.page.keyword": "Keywords", - // TODO New key - Add a translation - "journalissue.page.keyword": "Keywords", + "journalissue.page.keyword": "Trefwoorden", // "journalissue.page.number": "Number", - // TODO New key - Add a translation - "journalissue.page.number": "Number", + "journalissue.page.number": "Nummer", // "journalissue.page.titleprefix": "Journal Issue: ", - // TODO New key - Add a translation - "journalissue.page.titleprefix": "Journal Issue: ", + "journalissue.page.titleprefix": "Tijdschriftaflevering: ", // "journalvolume.listelement.badge": "Journal Volume", - // TODO New key - Add a translation - "journalvolume.listelement.badge": "Journal Volume", + "journalvolume.listelement.badge": "Tijdschriftjaargang", // "journalvolume.page.description": "Description", - // TODO New key - Add a translation - "journalvolume.page.description": "Description", + "journalvolume.page.description": "Beschrijving", // "journalvolume.page.issuedate": "Issue Date", - // TODO New key - Add a translation - "journalvolume.page.issuedate": "Issue Date", + "journalvolume.page.issuedate": "Datum van uitgave", // "journalvolume.page.titleprefix": "Journal Volume: ", - // TODO New key - Add a translation - "journalvolume.page.titleprefix": "Journal Volume: ", + "journalvolume.page.titleprefix": "Tijdschriftjaargang: ", // "journalvolume.page.volume": "Volume", - // TODO New key - Add a translation - "journalvolume.page.volume": "Volume", + "journalvolume.page.volume": "Jaargang", @@ -1392,15 +1303,13 @@ "loading.browse-by": "Items worden ingeladen...", // "loading.browse-by-page": "Loading page...", - // TODO New key - Add a translation - "loading.browse-by-page": "Loading page...", + "loading.browse-by-page": "Pagina wordt ingeladen...", // "loading.collection": "Loading collection...", "loading.collection": "Collectie wordt ingeladen...", // "loading.collections": "Loading collections...", - // TODO New key - Add a translation - "loading.collections": "Loading collections...", + "loading.collections": "Collecties worden ingeladen...", // "loading.community": "Loading community...", "loading.community": "Community wordt ingeladen...", @@ -1412,12 +1321,10 @@ "loading.item": "Item wordt ingeladen...", // "loading.items": "Loading items...", - // TODO New key - Add a translation - "loading.items": "Loading items...", + "loading.items": "Items worden ingeladen...", // "loading.mydspace-results": "Loading items...", - // TODO New key - Add a translation - "loading.mydspace-results": "Loading items...", + "loading.mydspace-results": "Items worden ingeladen...", // "loading.objects": "Loading...", "loading.objects": "Laden...", @@ -1432,11 +1339,10 @@ "loading.sub-collections": "De sub-collecties worden ingeladen...", // "loading.sub-communities": "Loading sub-communities...", - // TODO New key - Add a translation - "loading.sub-communities": "Loading sub-communities...", + "loading.sub-communities": "De sub-communities worden ingeladen...", // "loading.top-level-communities": "Loading top-level communities...", - "loading.top-level-communities": "Inladen van de Communities op het hoogste niveau...", + "loading.top-level-communities": "Inladen van de communities op het hoogste niveau...", @@ -1475,78 +1381,61 @@ // "menu.header.admin": "Admin", - // TODO New key - Add a translation - "menu.header.admin": "Admin", + "menu.header.admin": "Beheer", // "menu.header.image.logo": "Repository logo", - // TODO New key - Add a translation - "menu.header.image.logo": "Repository logo", + "menu.header.image.logo": "Repository logo", // "menu.section.access_control": "Access Control", - // TODO New key - Add a translation - "menu.section.access_control": "Access Control", + "menu.section.access_control": "Toegangscontrole", // "menu.section.access_control_authorizations": "Authorizations", - // TODO New key - Add a translation - "menu.section.access_control_authorizations": "Authorizations", + "menu.section.access_control_authorizations": "Autorisaties", // "menu.section.access_control_groups": "Groups", - // TODO New key - Add a translation - "menu.section.access_control_groups": "Groups", + "menu.section.access_control_groups": "Groepen", // "menu.section.access_control_people": "People", - // TODO New key - Add a translation - "menu.section.access_control_people": "People", + "menu.section.access_control_people": "Personen", // "menu.section.browse_community": "This Community", - // TODO New key - Add a translation - "menu.section.browse_community": "This Community", + "menu.section.browse_community": "Deze community", // "menu.section.browse_community_by_author": "By Author", - // TODO New key - Add a translation - "menu.section.browse_community_by_author": "By Author", + "menu.section.browse_community_by_author": "Op auteur", // "menu.section.browse_community_by_issue_date": "By Issue Date", - // TODO New key - Add a translation - "menu.section.browse_community_by_issue_date": "By Issue Date", + "menu.section.browse_community_by_issue_date": "Op datum van uitgave", // "menu.section.browse_community_by_title": "By Title", - // TODO New key - Add a translation - "menu.section.browse_community_by_title": "By Title", + "menu.section.browse_community_by_title": "Op titel", // "menu.section.browse_global": "All of DSpace", - // TODO New key - Add a translation - "menu.section.browse_global": "All of DSpace", + "menu.section.browse_global": "Heel DSpace", // "menu.section.browse_global_by_author": "By Author", - // TODO New key - Add a translation - "menu.section.browse_global_by_author": "By Author", + "menu.section.browse_global_by_author": "Op auteur", // "menu.section.browse_global_by_dateissued": "By Issue Date", - // TODO New key - Add a translation - "menu.section.browse_global_by_dateissued": "By Issue Date", + "menu.section.browse_global_by_dateissued": "Op datum van uitgave", // "menu.section.browse_global_by_subject": "By Subject", - // TODO New key - Add a translation - "menu.section.browse_global_by_subject": "By Subject", + "menu.section.browse_global_by_subject": "Op onderwerp", // "menu.section.browse_global_by_title": "By Title", - // TODO New key - Add a translation - "menu.section.browse_global_by_title": "By Title", + "menu.section.browse_global_by_title": "Op titel", // "menu.section.browse_global_communities_and_collections": "Communities & Collections", - // TODO New key - Add a translation - "menu.section.browse_global_communities_and_collections": "Communities & Collections", + "menu.section.browse_global_communities_and_collections": "Communities & Collecties", // "menu.section.control_panel": "Control Panel", - // TODO New key - Add a translation - "menu.section.control_panel": "Control Panel", + "menu.section.control_panel": "Controlepaneel", // "menu.section.curation_task": "Curation Task", // TODO New key - Add a translation @@ -1555,180 +1444,141 @@ // "menu.section.edit": "Edit", - // TODO New key - Add a translation - "menu.section.edit": "Edit", + "menu.section.edit": "Bewerk", // "menu.section.edit_collection": "Collection", - // TODO New key - Add a translation - "menu.section.edit_collection": "Collection", + "menu.section.edit_collection": "Collectie", // "menu.section.edit_community": "Community", - // TODO New key - Add a translation "menu.section.edit_community": "Community", // "menu.section.edit_item": "Item", - // TODO New key - Add a translation "menu.section.edit_item": "Item", // "menu.section.export": "Export", - // TODO New key - Add a translation - "menu.section.export": "Export", + "menu.section.export": "Exporteer", // "menu.section.export_collection": "Collection", - // TODO New key - Add a translation - "menu.section.export_collection": "Collection", + "menu.section.export_collection": "Collectie", // "menu.section.export_community": "Community", - // TODO New key - Add a translation "menu.section.export_community": "Community", // "menu.section.export_item": "Item", - // TODO New key - Add a translation "menu.section.export_item": "Item", // "menu.section.export_metadata": "Metadata", - // TODO New key - Add a translation - "menu.section.export_metadata": "Metadata", + "menu.section.export_metadata": "Metadata", // "menu.section.find": "Find", - // TODO New key - Add a translation - "menu.section.find": "Find", + "menu.section.find": "Vind", // "menu.section.find_items": "Items", - // TODO New key - Add a translation "menu.section.find_items": "Items", // "menu.section.find_private_items": "Private Items", - // TODO New key - Add a translation - "menu.section.find_private_items": "Private Items", + "menu.section.find_private_items": "Privé items", // "menu.section.find_withdrawn_items": "Withdrawn Items", - // TODO New key - Add a translation - "menu.section.find_withdrawn_items": "Withdrawn Items", + "menu.section.find_withdrawn_items": "Teruggetrokken items", // "menu.section.icon.access_control": "Access Control menu section", - // TODO New key - Add a translation - "menu.section.icon.access_control": "Access Control menu section", + "menu.section.icon.access_control": "Menusectie toegangscontrole", // "menu.section.icon.control_panel": "Control Panel menu section", - // TODO New key - Add a translation - "menu.section.icon.control_panel": "Control Panel menu section", + "menu.section.icon.control_panel": "Menusectie controlepaneel", // "menu.section.icon.curation_task": "Curation Task menu section", // TODO New key - Add a translation "menu.section.icon.curation_task": "Curation Task menu section", // "menu.section.icon.edit": "Edit menu section", - // TODO New key - Add a translation - "menu.section.icon.edit": "Edit menu section", + "menu.section.icon.edit": "Menusectie bewerkingen", // "menu.section.icon.export": "Export menu section", - // TODO New key - Add a translation - "menu.section.icon.export": "Export menu section", + "menu.section.icon.export": "Menusectie export", // "menu.section.icon.find": "Find menu section", - // TODO New key - Add a translation - "menu.section.icon.find": "Find menu section", + "menu.section.icon.find": "Menusectie vinden", // "menu.section.icon.import": "Import menu section", - // TODO New key - Add a translation - "menu.section.icon.import": "Import menu section", + "menu.section.icon.import": "Menusectie import", // "menu.section.icon.new": "New menu section", - // TODO New key - Add a translation - "menu.section.icon.new": "New menu section", + "menu.section.icon.new": "Menusectie nieuw", // "menu.section.icon.pin": "Pin sidebar", - // TODO New key - Add a translation - "menu.section.icon.pin": "Pin sidebar", + "menu.section.icon.pin": "Zijbalk vastzetten", // "menu.section.icon.registries": "Registries menu section", - // TODO New key - Add a translation - "menu.section.icon.registries": "Registries menu section", + "menu.section.icon.registries": "Menusectie registers", // "menu.section.icon.statistics_task": "Statistics Task menu section", - // TODO New key - Add a translation - "menu.section.icon.statistics_task": "Statistics Task menu section", + "menu.section.icon.statistics_task": "Menusectie statistiektaken", // "menu.section.icon.unpin": "Unpin sidebar", - // TODO New key - Add a translation - "menu.section.icon.unpin": "Unpin sidebar", + "menu.section.icon.unpin": "Zijbalk losmaken", // "menu.section.import": "Import", - // TODO New key - Add a translation "menu.section.import": "Import", // "menu.section.import_batch": "Batch Import (ZIP)", - // TODO New key - Add a translation - "menu.section.import_batch": "Batch Import (ZIP)", + "menu.section.import_batch": "Batch import (ZIP)", // "menu.section.import_metadata": "Metadata", - // TODO New key - Add a translation "menu.section.import_metadata": "Metadata", // "menu.section.new": "New", - // TODO New key - Add a translation - "menu.section.new": "New", + "menu.section.new": "Nieuw", // "menu.section.new_collection": "Collection", - // TODO New key - Add a translation - "menu.section.new_collection": "Collection", + "menu.section.new_collection": "Collectie", // "menu.section.new_community": "Community", - // TODO New key - Add a translation "menu.section.new_community": "Community", // "menu.section.new_item": "Item", - // TODO New key - Add a translation "menu.section.new_item": "Item", // "menu.section.new_item_version": "Item Version", - // TODO New key - Add a translation - "menu.section.new_item_version": "Item Version", + "menu.section.new_item_version": "Item versie", // "menu.section.pin": "Pin sidebar", - // TODO New key - Add a translation - "menu.section.pin": "Pin sidebar", + "menu.section.pin": "Zijbalk vastzetten", // "menu.section.unpin": "Unpin sidebar", - // TODO New key - Add a translation - "menu.section.unpin": "Unpin sidebar", + "menu.section.unpin": "Zijbalk losmaken", // "menu.section.registries": "Registries", - // TODO New key - Add a translation - "menu.section.registries": "Registries", + "menu.section.registries": "Registers", // "menu.section.registries_format": "Format", - // TODO New key - Add a translation - "menu.section.registries_format": "Format", + "menu.section.registries_format": "Formaten", // "menu.section.registries_metadata": "Metadata", - // TODO New key - Add a translation "menu.section.registries_metadata": "Metadata", // "menu.section.statistics": "Statistics", - // TODO New key - Add a translation - "menu.section.statistics": "Statistics", + "menu.section.statistics": "Statistieken", // "menu.section.statistics_task": "Statistics Task", - // TODO New key - Add a translation - "menu.section.statistics_task": "Statistics Task", + "menu.section.statistics_task": "Statistiektaken", @@ -1779,60 +1629,48 @@ "mydspace.description": "", // "mydspace.general.text-here": "HERE", - // TODO New key - Add a translation - "mydspace.general.text-here": "HERE", + "mydspace.general.text-here": "HIER", // "mydspace.messages.controller-help": "Select this option to send a message to item's submitter.", // TODO New key - Add a translation "mydspace.messages.controller-help": "Select this option to send a message to item's submitter.", // "mydspace.messages.description-placeholder": "Insert your message here...", - // TODO New key - Add a translation - "mydspace.messages.description-placeholder": "Insert your message here...", + "mydspace.messages.description-placeholder": " Vul hier uw bericht in...", // "mydspace.messages.hide-msg": "Hide message", - // TODO New key - Add a translation - "mydspace.messages.hide-msg": "Hide message", + "mydspace.messages.hide-msg": "Verberg bericht", // "mydspace.messages.mark-as-read": "Mark as read", - // TODO New key - Add a translation - "mydspace.messages.mark-as-read": "Mark as read", + "mydspace.messages.mark-as-read": "Markeer als gelezen", // "mydspace.messages.mark-as-unread": "Mark as unread", - // TODO New key - Add a translation - "mydspace.messages.mark-as-unread": "Mark as unread", + "mydspace.messages.mark-as-unread": "Markeer als ongelezen", // "mydspace.messages.no-content": "No content.", - // TODO New key - Add a translation - "mydspace.messages.no-content": "No content.", + "mydspace.messages.no-content": "Geen inhoud.", // "mydspace.messages.no-messages": "No messages yet.", - // TODO New key - Add a translation - "mydspace.messages.no-messages": "No messages yet.", + "mydspace.messages.no-messages": "Nog geen berichten.", // "mydspace.messages.send-btn": "Send", - // TODO New key - Add a translation - "mydspace.messages.send-btn": "Send", + "mydspace.messages.send-btn": "Verstuur", // "mydspace.messages.show-msg": "Show message", - // TODO New key - Add a translation - "mydspace.messages.show-msg": "Show message", + "mydspace.messages.show-msg": "Toon bericht", // "mydspace.messages.subject-placeholder": "Subject...", - // TODO New key - Add a translation - "mydspace.messages.subject-placeholder": "Subject...", + "mydspace.messages.subject-placeholder": "Onderwerp...", // "mydspace.messages.submitter-help": "Select this option to send a message to controller.", // TODO New key - Add a translation "mydspace.messages.submitter-help": "Select this option to send a message to controller.", // "mydspace.messages.title": "Messages", - // TODO New key - Add a translation - "mydspace.messages.title": "Messages", + "mydspace.messages.title": "Berichten", // "mydspace.messages.to": "To", - // TODO New key - Add a translation - "mydspace.messages.to": "To", + "mydspace.messages.to": "Aan", // "mydspace.new-submission": "New submission", // TODO New key - Add a translation @@ -1843,67 +1681,54 @@ "mydspace.results.head": "Your submissions", // "mydspace.results.no-abstract": "No Abstract", - // TODO New key - Add a translation - "mydspace.results.no-abstract": "No Abstract", + "mydspace.results.no-abstract": "Geen abstract", // "mydspace.results.no-authors": "No Authors", - // TODO New key - Add a translation - "mydspace.results.no-authors": "No Authors", + "mydspace.results.no-authors": "Geen auteurs", // "mydspace.results.no-collections": "No Collections", - // TODO New key - Add a translation - "mydspace.results.no-collections": "No Collections", + "mydspace.results.no-collections": "Geen collecties", // "mydspace.results.no-date": "No Date", - // TODO New key - Add a translation - "mydspace.results.no-date": "No Date", + "mydspace.results.no-date": "Geen datum", // "mydspace.results.no-files": "No Files", - // TODO New key - Add a translation - "mydspace.results.no-files": "No Files", + "mydspace.results.no-files": "Geen bestanden", // "mydspace.results.no-results": "There were no items to show", - // TODO New key - Add a translation - "mydspace.results.no-results": "There were no items to show", + "mydspace.results.no-results": "Er zijn geen items om getoond te worden", // "mydspace.results.no-title": "No title", - // TODO New key - Add a translation - "mydspace.results.no-title": "No title", + "mydspace.results.no-title": "Geen titel", // "mydspace.results.no-uri": "No Uri", - // TODO New key - Add a translation - "mydspace.results.no-uri": "No Uri", + "mydspace.results.no-uri": "Geen URI", // "mydspace.show.workflow": "All tasks", - // TODO New key - Add a translation - "mydspace.show.workflow": "All tasks", + "mydspace.show.workflow": "Alle taken", // "mydspace.show.workspace": "Your Submissions", // TODO New key - Add a translation "mydspace.show.workspace": "Your Submissions", // "mydspace.status.archived": "Archived", - // TODO New key - Add a translation - "mydspace.status.archived": "Archived", + "mydspace.status.archived": "Opgeslagen", // "mydspace.status.validation": "Validation", - // TODO New key - Add a translation - "mydspace.status.validation": "Validation", + "mydspace.status.validation": "Validatie", // "mydspace.status.waiting-for-controller": "Waiting for controller", // TODO New key - Add a translation "mydspace.status.waiting-for-controller": "Waiting for controller", // "mydspace.status.workflow": "Workflow", - // TODO New key - Add a translation - "mydspace.status.workflow": "Workflow", + "mydspace.status.workflow": "Workflow", // "mydspace.status.workspace": "Workspace", // TODO New key - Add a translation "mydspace.status.workspace": "Workspace", // "mydspace.title": "MyDSpace", - // TODO New key - Add a translation "mydspace.title": "MyDSpace", // "mydspace.upload.upload-failed": "Error creating new workspace. Please verify the content uploaded before retry.", @@ -1919,18 +1744,15 @@ "mydspace.upload.upload-successful": "New workspace item created. Click {{here}} for edit it.", // "mydspace.view-btn": "View", - // TODO New key - Add a translation - "mydspace.view-btn": "View", + "mydspace.view-btn": "Bekijk", // "nav.browse.header": "All of DSpace", - // TODO New key - Add a translation - "nav.browse.header": "All of DSpace", + "nav.browse.header": "Heel DSpace", // "nav.community-browse.header": "By Community", - // TODO New key - Add a translation - "nav.community-browse.header": "By Community", + "nav.community-browse.header": "Per community", // "nav.language": "Language switch", // TODO New key - Add a translation @@ -1943,46 +1765,37 @@ "nav.logout": "Log Uit", // "nav.mydspace": "MyDSpace", - // TODO New key - Add a translation "nav.mydspace": "MyDSpace", // "nav.search": "Search", - // TODO New key - Add a translation - "nav.search": "Search", + "nav.search": "Zoek", // "nav.statistics.header": "Statistics", - // TODO New key - Add a translation - "nav.statistics.header": "Statistics", + "nav.statistics.header": "Statistieken", // "orgunit.listelement.badge": "Organizational Unit", - // TODO New key - Add a translation - "orgunit.listelement.badge": "Organizational Unit", + "orgunit.listelement.badge": "Organisatie-onderdeel", // "orgunit.page.city": "City", - // TODO New key - Add a translation - "orgunit.page.city": "City", + "orgunit.page.city": "Plaats", // "orgunit.page.country": "Country", - // TODO New key - Add a translation - "orgunit.page.country": "Country", + "orgunit.page.country": "Land", // "orgunit.page.dateestablished": "Date established", // TODO New key - Add a translation "orgunit.page.dateestablished": "Date established", // "orgunit.page.description": "Description", - // TODO New key - Add a translation - "orgunit.page.description": "Description", + "orgunit.page.description": "Beschrijving", // "orgunit.page.id": "ID", - // TODO New key - Add a translation "orgunit.page.id": "ID", // "orgunit.page.titleprefix": "Organizational Unit: ", - // TODO New key - Add a translation - "orgunit.page.titleprefix": "Organizational Unit: ", + "orgunit.page.titleprefix": "Organisatie-onderdeel: ", @@ -2001,35 +1814,27 @@ // "person.listelement.badge": "Person", - // TODO New key - Add a translation - "person.listelement.badge": "Person", + "person.listelement.badge": "Persoon", // "person.page.birthdate": "Birth Date", - // TODO New key - Add a translation - "person.page.birthdate": "Birth Date", + "person.page.birthdate": "Geboortedatum", // "person.page.email": "Email Address", - // TODO New key - Add a translation - "person.page.email": "Email Address", + "person.page.email": "Emailadres", // "person.page.firstname": "First Name", - // TODO New key - Add a translation - "person.page.firstname": "First Name", + "person.page.firstname": "Voornaam", // "person.page.jobtitle": "Job Title", - // TODO New key - Add a translation - "person.page.jobtitle": "Job Title", + "person.page.jobtitle": "Functie", // "person.page.lastname": "Last Name", - // TODO New key - Add a translation - "person.page.lastname": "Last Name", + "person.page.lastname": "Achternaam", // "person.page.link.full": "Show all metadata", - // TODO New key - Add a translation - "person.page.link.full": "Show all metadata", + "person.page.link.full": "Toon alle metadata", // "person.page.orcid": "ORCID", - // TODO New key - Add a translation "person.page.orcid": "ORCID", // "person.page.staffid": "Staff ID", @@ -2037,8 +1842,7 @@ "person.page.staffid": "Staff ID", // "person.page.titleprefix": "Person: ", - // TODO New key - Add a translation - "person.page.titleprefix": "Person: ", + "person.page.titleprefix": "Persoon: ", // "person.search.results.head": "Person Search Results", // TODO New key - Add a translation @@ -2051,128 +1855,101 @@ // "project.listelement.badge": "Research Project", - // TODO New key - Add a translation - "project.listelement.badge": "Research Project", + "project.listelement.badge": "Onderzoeksproject", // "project.page.contributor": "Contributors", // TODO New key - Add a translation "project.page.contributor": "Contributors", // "project.page.description": "Description", - // TODO New key - Add a translation - "project.page.description": "Description", + "project.page.description": "Beschrijving", // "project.page.expectedcompletion": "Expected Completion", - // TODO New key - Add a translation - "project.page.expectedcompletion": "Expected Completion", + "project.page.expectedcompletion": "Verwachte afronding", // "project.page.funder": "Funders", // TODO New key - Add a translation "project.page.funder": "Funders", // "project.page.id": "ID", - // TODO New key - Add a translation "project.page.id": "ID", // "project.page.keyword": "Keywords", - // TODO New key - Add a translation - "project.page.keyword": "Keywords", + "project.page.keyword": "Trefwoorden", // "project.page.status": "Status", - // TODO New key - Add a translation "project.page.status": "Status", // "project.page.titleprefix": "Research Project: ", - // TODO New key - Add a translation - "project.page.titleprefix": "Research Project: ", + "project.page.titleprefix": "Onderzoeksproject: ", // "publication.listelement.badge": "Publication", - // TODO New key - Add a translation - "publication.listelement.badge": "Publication", + "publication.listelement.badge": "Publicatie", // "publication.page.description": "Description", - // TODO New key - Add a translation - "publication.page.description": "Description", + "publication.page.description": "Beschrijving", // "publication.page.journal-issn": "Journal ISSN", - // TODO New key - Add a translation - "publication.page.journal-issn": "Journal ISSN", + "publication.page.journal-issn": "Tijdschrift ISSN", // "publication.page.journal-title": "Journal Title", - // TODO New key - Add a translation - "publication.page.journal-title": "Journal Title", + "publication.page.journal-title": "Tijdschrifttitel", // "publication.page.publisher": "Publisher", - // TODO New key - Add a translation - "publication.page.publisher": "Publisher", + "publication.page.publisher": "Uitgever", // "publication.page.titleprefix": "Publication: ", - // TODO New key - Add a translation - "publication.page.titleprefix": "Publication: ", + "publication.page.titleprefix": "Publicatie: ", // "publication.page.volume-title": "Volume Title", // TODO New key - Add a translation "publication.page.volume-title": "Volume Title", // "publication.search.results.head": "Publication Search Results", - // TODO New key - Add a translation - "publication.search.results.head": "Publication Search Results", + "publication.search.results.head": "Publicatie zoekresultaten", // "publication.search.title": "DSpace Angular :: Publication Search", - // TODO New key - Add a translation - "publication.search.title": "DSpace Angular :: Publication Search", + "publication.search.title": "DSpace Angular :: Publicatie zoeken", // "relationships.isAuthorOf": "Authors", - // TODO New key - Add a translation - "relationships.isAuthorOf": "Authors", + "relationships.isAuthorOf": "Auteurs", // "relationships.isIssueOf": "Journal Issues", - // TODO New key - Add a translation - "relationships.isIssueOf": "Journal Issues", + "relationships.isIssueOf": "Tijdschriftafleveringen", // "relationships.isJournalIssueOf": "Journal Issue", - // TODO New key - Add a translation - "relationships.isJournalIssueOf": "Journal Issue", + "relationships.isJournalIssueOf": "Tijdschriftaflevering", // "relationships.isJournalOf": "Journals", - // TODO New key - Add a translation - "relationships.isJournalOf": "Journals", + "relationships.isJournalOf": "Tijdschriften", // "relationships.isOrgUnitOf": "Organizational Units", - // TODO New key - Add a translation - "relationships.isOrgUnitOf": "Organizational Units", + "relationships.isOrgUnitOf": "Organisatie-onderdelen", // "relationships.isPersonOf": "Authors", - // TODO New key - Add a translation - "relationships.isPersonOf": "Authors", + "relationships.isPersonOf": "Auteurs", // "relationships.isProjectOf": "Research Projects", - // TODO New key - Add a translation - "relationships.isProjectOf": "Research Projects", + "relationships.isProjectOf": "Onderzoeksprojecten", // "relationships.isPublicationOf": "Publications", - // TODO New key - Add a translation - "relationships.isPublicationOf": "Publications", + "relationships.isPublicationOf": "Publicaties", // "relationships.isPublicationOfJournalIssue": "Articles", - // TODO New key - Add a translation - "relationships.isPublicationOfJournalIssue": "Articles", + "relationships.isPublicationOfJournalIssue": "Artikelen", // "relationships.isSingleJournalOf": "Journal", - // TODO New key - Add a translation - "relationships.isSingleJournalOf": "Journal", + "relationships.isSingleJournalOf": "Tijdschrift", // "relationships.isSingleVolumeOf": "Journal Volume", - // TODO New key - Add a translation - "relationships.isSingleVolumeOf": "Journal Volume", + "relationships.isSingleVolumeOf": "Tijdschriftjaargang", // "relationships.isVolumeOf": "Journal Volumes", - // TODO New key - Add a translation - "relationships.isVolumeOf": "Journal Volumes", + "relationships.isVolumeOf": "Tijdschriftjaargangen", @@ -2180,8 +1957,7 @@ "search.description": "", // "search.switch-configuration.title": "Show", - // TODO New key - Add a translation - "search.switch-configuration.title": "Show", + "search.switch-configuration.title": "Toon", // "search.title": "DSpace Angular :: Search", "search.title": "DSpace Angular :: Zoek", @@ -2202,22 +1978,19 @@ "search.filters.applied.f.dateSubmitted": "Date submitted", // "search.filters.applied.f.entityType": "Item Type", - // TODO New key - Add a translation - "search.filters.applied.f.entityType": "Item Type", + "search.filters.applied.f.entityType": "Soort item", // "search.filters.applied.f.has_content_in_original_bundle": "Has files", "search.filters.applied.f.has_content_in_original_bundle": "Heeft bestanden", // "search.filters.applied.f.itemtype": "Type", - // TODO New key - Add a translation - "search.filters.applied.f.itemtype": "Type", + "search.filters.applied.f.itemtype": "Type", // "search.filters.applied.f.namedresourcetype": "Status", - // TODO New key - Add a translation "search.filters.applied.f.namedresourcetype": "Status", // "search.filters.applied.f.subject": "Subject", - "search.filters.applied.f.subject": "Sleutelwoord", + "search.filters.applied.f.subject": "Onderwerp", // "search.filters.applied.f.submitter": "Submitter", // TODO New key - Add a translation @@ -2232,44 +2005,34 @@ "search.filters.filter.author.placeholder": "Auteursnaam", // "search.filters.filter.birthDate.head": "Birth Date", - // TODO New key - Add a translation - "search.filters.filter.birthDate.head": "Birth Date", + "search.filters.filter.birthDate.head": "Geboortedatum", // "search.filters.filter.birthDate.placeholder": "Birth Date", - // TODO New key - Add a translation - "search.filters.filter.birthDate.placeholder": "Birth Date", + "search.filters.filter.birthDate.placeholder": "Geboortedatum", // "search.filters.filter.creativeDatePublished.head": "Date Published", - // TODO New key - Add a translation - "search.filters.filter.creativeDatePublished.head": "Date Published", + "search.filters.filter.creativeDatePublished.head": "Datum van uitgave", // "search.filters.filter.creativeDatePublished.placeholder": "Date Published", - // TODO New key - Add a translation - "search.filters.filter.creativeDatePublished.placeholder": "Date Published", + "search.filters.filter.creativeDatePublished.placeholder": "Datum van uitgave", // "search.filters.filter.creativeWorkEditor.head": "Editor", - // TODO New key - Add a translation - "search.filters.filter.creativeWorkEditor.head": "Editor", + "search.filters.filter.creativeWorkEditor.head": "Redacteur", // "search.filters.filter.creativeWorkEditor.placeholder": "Editor", - // TODO New key - Add a translation - "search.filters.filter.creativeWorkEditor.placeholder": "Editor", + "search.filters.filter.creativeWorkEditor.placeholder": "Redacteur", // "search.filters.filter.creativeWorkKeywords.head": "Subject", - // TODO New key - Add a translation - "search.filters.filter.creativeWorkKeywords.head": "Subject", + "search.filters.filter.creativeWorkKeywords.head": "Onderwerp", // "search.filters.filter.creativeWorkKeywords.placeholder": "Subject", - // TODO New key - Add a translation - "search.filters.filter.creativeWorkKeywords.placeholder": "Subject", + "search.filters.filter.creativeWorkKeywords.placeholder": "Onderwerp", // "search.filters.filter.creativeWorkPublisher.head": "Publisher", - // TODO New key - Add a translation - "search.filters.filter.creativeWorkPublisher.head": "Publisher", + "search.filters.filter.creativeWorkPublisher.head": "Uitgever", // "search.filters.filter.creativeWorkPublisher.placeholder": "Publisher", - // TODO New key - Add a translation - "search.filters.filter.creativeWorkPublisher.placeholder": "Publisher", + "search.filters.filter.creativeWorkPublisher.placeholder": "Uitgever", // "search.filters.filter.dateIssued.head": "Date", "search.filters.filter.dateIssued.head": "Datum", @@ -2289,31 +2052,25 @@ "search.filters.filter.dateSubmitted.placeholder": "Date submitted", // "search.filters.filter.entityType.head": "Item Type", - // TODO New key - Add a translation - "search.filters.filter.entityType.head": "Item Type", + "search.filters.filter.entityType.head": "Soort item", // "search.filters.filter.entityType.placeholder": "Item Type", - // TODO New key - Add a translation - "search.filters.filter.entityType.placeholder": "Item Type", + "search.filters.filter.entityType.placeholder": "Soort item", // "search.filters.filter.has_content_in_original_bundle.head": "Has files", "search.filters.filter.has_content_in_original_bundle.head": "Heeft bestanden", // "search.filters.filter.itemtype.head": "Type", - // TODO New key - Add a translation "search.filters.filter.itemtype.head": "Type", // "search.filters.filter.itemtype.placeholder": "Type", - // TODO New key - Add a translation "search.filters.filter.itemtype.placeholder": "Type", // "search.filters.filter.jobTitle.head": "Job Title", - // TODO New key - Add a translation - "search.filters.filter.jobTitle.head": "Job Title", + "search.filters.filter.jobTitle.head": "Functienaam", // "search.filters.filter.jobTitle.placeholder": "Job Title", - // TODO New key - Add a translation - "search.filters.filter.jobTitle.placeholder": "Job Title", + "search.filters.filter.jobTitle.placeholder": "Functienaam", // "search.filters.filter.knowsLanguage.head": "Known language", // TODO New key - Add a translation @@ -2324,36 +2081,28 @@ "search.filters.filter.knowsLanguage.placeholder": "Known language", // "search.filters.filter.namedresourcetype.head": "Status", - // TODO New key - Add a translation "search.filters.filter.namedresourcetype.head": "Status", // "search.filters.filter.namedresourcetype.placeholder": "Status", - // TODO New key - Add a translation "search.filters.filter.namedresourcetype.placeholder": "Status", // "search.filters.filter.objectpeople.head": "People", - // TODO New key - Add a translation - "search.filters.filter.objectpeople.head": "People", + "search.filters.filter.objectpeople.head": "Personen", // "search.filters.filter.objectpeople.placeholder": "People", - // TODO New key - Add a translation - "search.filters.filter.objectpeople.placeholder": "People", + "search.filters.filter.objectpeople.placeholder": "Personen", // "search.filters.filter.organizationAddressCountry.head": "Country", - // TODO New key - Add a translation - "search.filters.filter.organizationAddressCountry.head": "Country", + "search.filters.filter.organizationAddressCountry.head": "Land", // "search.filters.filter.organizationAddressCountry.placeholder": "Country", - // TODO New key - Add a translation - "search.filters.filter.organizationAddressCountry.placeholder": "Country", + "search.filters.filter.organizationAddressCountry.placeholder": "Land", // "search.filters.filter.organizationAddressLocality.head": "City", - // TODO New key - Add a translation - "search.filters.filter.organizationAddressLocality.head": "City", + "search.filters.filter.organizationAddressLocality.head": "Plaats", // "search.filters.filter.organizationAddressLocality.placeholder": "City", - // TODO New key - Add a translation - "search.filters.filter.organizationAddressLocality.placeholder": "City", + "search.filters.filter.organizationAddressLocality.placeholder": "Plaats", // "search.filters.filter.organizationFoundingDate.head": "Date Founded", // TODO New key - Add a translation @@ -2428,7 +2177,7 @@ "search.sidebar.filters.title": "Filters", // "search.sidebar.open": "Search Tools", - "search.sidebar.open": "Zoek Tools", + "search.sidebar.open": "Zoekmogelijkheden", // "search.sidebar.results": "results", "search.sidebar.results": "resultaten", From 5acbf4f2169e659f5175d47d801c8a2a78c05a9c Mon Sep 17 00:00:00 2001 From: muiltje Date: Thu, 9 Jan 2020 12:51:27 +0100 Subject: [PATCH 14/32] Second batch of Dutch translations --- resources/i18n/nl.json5 | 401 +++++++++++++--------------------------- 1 file changed, 132 insertions(+), 269 deletions(-) diff --git a/resources/i18n/nl.json5 b/resources/i18n/nl.json5 index 2332197c8d..344a36e2e8 100644 --- a/resources/i18n/nl.json5 +++ b/resources/i18n/nl.json5 @@ -155,7 +155,7 @@ "admin.registries.metadata.form.namespace": "Namespace", // "admin.registries.metadata.head": "Metadata Registry", - "admin.registries.metadata.head": "Metadata Register", + "admin.registries.metadata.head": "Metadataregister", // "admin.registries.metadata.schemas.no-items": "No metadata schemas to show.", "admin.registries.metadata.schemas.no-items": "Er kunnen geen metadataschema's getoond worden.", @@ -173,7 +173,7 @@ "admin.registries.metadata.schemas.table.namespace": "Namespace", // "admin.registries.metadata.title": "DSpace Angular :: Metadata Registry", - "admin.registries.metadata.title": "DSpace Angular :: Metadata Register", + "admin.registries.metadata.title": "DSpace Angular :: Metadataregister", @@ -702,7 +702,6 @@ "form.no-value": "Geen waarde ingevoerd", // "form.other-information": {}, - // TODO New key - Add a translation "form.other-information": {}, // "form.remove": "Remove", @@ -865,8 +864,7 @@ "item.edit.metadata.notifications.outdated.content": "Het item waar u aan werkt is gewijzigd door een andere gebruiker. Uw huidige wijzigingen worden geannuleerd om conflicten te voorkomen.", // "item.edit.metadata.notifications.outdated.title": "Changed outdated", - // TODO New key - Add a translation - "item.edit.metadata.notifications.outdated.title": "Changed outdated", + "item.edit.metadata.notifications.outdated.title": "Wijzigingen verouderd", // "item.edit.metadata.notifications.saved.content": "Your changes to this item's metadata were saved.", "item.edit.metadata.notifications.saved.content": "Uw wijzingen in de metadata van dit item zijn opgeslagen.", @@ -906,12 +904,10 @@ "item.edit.move.head": "Verplaats item: {{id}}", // "item.edit.move.inheritpolicies.checkbox": "Inherit policies", - // TODO New key - Add a translation - "item.edit.move.inheritpolicies.checkbox": "Inherit policies", + "item.edit.move.inheritpolicies.checkbox": "Erf policies", // "item.edit.move.inheritpolicies.description": "Inherit the default policies of the destination collection", - // TODO New key - Add a translation - "item.edit.move.inheritpolicies.description": "Inherit the default policies of the destination collection", + "item.edit.move.inheritpolicies.description": "Neem de standaard policies van de doelcollectie over", // "item.edit.move.move": "Move", "item.edit.move.move": "Verplaats", @@ -946,8 +942,7 @@ "item.edit.private.header": "Maak item privé: {{ id }}", // "item.edit.private.success": "The item is now private", - // TODO New key - Add a translation - "item.edit.private.success": "Dit item is nu privé", + "item.edit.private.success": "Dit item is nu privé", @@ -1013,8 +1008,7 @@ "item.edit.relationships.notifications.outdated.content": "Het item waar u aan werkt is gewijzigd door een andere gebruiker. Uw huidige wijzigingen zijn ongedaan gemaakt om conflicten te voorkomen.", // "item.edit.relationships.notifications.outdated.title": "Changes outdated", - // TODO New key - Add a translation - "item.edit.relationships.notifications.outdated.title": "Changes outdated", + "item.edit.relationships.notifications.outdated.title": "Wijzingen verouderd", // "item.edit.relationships.notifications.saved.content": "Your changes to this item's relationships were saved.", "item.edit.relationships.notifications.saved.content": "Uw wijzingen in de relaties van dit item zijn opgeslagen.", @@ -1037,12 +1031,10 @@ "item.edit.tabs.bitstreams.title": "Item bewerken - Bitstreams", // "item.edit.tabs.curate.head": "Curate", - // TODO New key - Add a translation - "item.edit.tabs.curate.head": "Curate", + "item.edit.tabs.curate.head": "Beheer", // "item.edit.tabs.curate.title": "Item Edit - Curate", - // TODO New key - Add a translation - "item.edit.tabs.curate.title": "Item Edit - Curate", + "item.edit.tabs.curate.title": "Item bewerken - Beheer", // "item.edit.tabs.metadata.head": "Item Metadata", "item.edit.tabs.metadata.head": "Item metadata", @@ -1060,8 +1052,7 @@ "item.edit.tabs.status.buttons.authorizations.button": "Autorisaties ..", // "item.edit.tabs.status.buttons.authorizations.label": "Edit item's authorization policies", - // TODO New key - Add a translation - "item.edit.tabs.status.buttons.authorizations.label": "Edit item's authorization policies", + "item.edit.tabs.status.buttons.authorizations.label": "Bewerk de autorisatieregels", // "item.edit.tabs.status.buttons.delete.button": "Permanently delete", "item.edit.tabs.status.buttons.delete.button": "Permanent verwijderen", @@ -1438,8 +1429,7 @@ "menu.section.control_panel": "Controlepaneel", // "menu.section.curation_task": "Curation Task", - // TODO New key - Add a translation - "menu.section.curation_task": "Curation Task", + "menu.section.curation_task": "Beheertaak", @@ -1495,8 +1485,7 @@ "menu.section.icon.control_panel": "Menusectie controlepaneel", // "menu.section.icon.curation_task": "Curation Task menu section", - // TODO New key - Add a translation - "menu.section.icon.curation_task": "Curation Task menu section", + "menu.section.icon.curation_task": "Menusectie beheertaken", // "menu.section.icon.edit": "Edit menu section", "menu.section.icon.edit": "Menusectie bewerkingen", @@ -1583,57 +1572,45 @@ // "menu.section.toggle.access_control": "Toggle Access Control section", - // TODO New key - Add a translation - "menu.section.toggle.access_control": "Toggle Access Control section", + "menu.section.toggle.access_control": "Sectie Toegangscontrole aan/uit", // "menu.section.toggle.control_panel": "Toggle Control Panel section", - // TODO New key - Add a translation - "menu.section.toggle.control_panel": "Toggle Control Panel section", + "menu.section.toggle.control_panel": "Sectie Controlepaneel aan/uit", // "menu.section.toggle.curation_task": "Toggle Curation Task section", - // TODO New key - Add a translation - "menu.section.toggle.curation_task": "Toggle Curation Task section", + "menu.section.toggle.curation_task": "Sectie Beheertaken aan/uit", // "menu.section.toggle.edit": "Toggle Edit section", - // TODO New key - Add a translation - "menu.section.toggle.edit": "Toggle Edit section", + "menu.section.toggle.edit": "Sectie Bewerk aan/uit", // "menu.section.toggle.export": "Toggle Export section", - // TODO New key - Add a translation - "menu.section.toggle.export": "Toggle Export section", + "menu.section.toggle.export": "Sectie Export aan/uit", // "menu.section.toggle.find": "Toggle Find section", - // TODO New key - Add a translation - "menu.section.toggle.find": "Toggle Find section", + "menu.section.toggle.find": "Sectie Vind aan/uit", // "menu.section.toggle.import": "Toggle Import section", - // TODO New key - Add a translation - "menu.section.toggle.import": "Toggle Import section", + "menu.section.toggle.import": "Sectie Import aan/uit", // "menu.section.toggle.new": "Toggle New section", - // TODO New key - Add a translation - "menu.section.toggle.new": "Toggle New section", + "menu.section.toggle.new": "Sectie Nieuw aan/uit", // "menu.section.toggle.registries": "Toggle Registries section", - // TODO New key - Add a translation - "menu.section.toggle.registries": "Toggle Registries section", + "menu.section.toggle.registries": "Sectie registers aan/uit", // "menu.section.toggle.statistics_task": "Toggle Statistics Task section", - // TODO New key - Add a translation - "menu.section.toggle.statistics_task": "Toggle Statistics Task section", + "menu.section.toggle.statistics_task": "Sectie statistiektaken aan/uit", // "mydspace.description": "", - // TODO New key - Add a translation - "mydspace.description": "", + "mydspace.description": "", // "mydspace.general.text-here": "HERE", "mydspace.general.text-here": "HIER", // "mydspace.messages.controller-help": "Select this option to send a message to item's submitter.", - // TODO New key - Add a translation - "mydspace.messages.controller-help": "Select this option to send a message to item's submitter.", + "mydspace.messages.controller-help": "Kies deze optie om een bericht te sturen naar de indiener van het item.", // "mydspace.messages.description-placeholder": "Insert your message here...", "mydspace.messages.description-placeholder": " Vul hier uw bericht in...", @@ -1663,8 +1640,7 @@ "mydspace.messages.subject-placeholder": "Onderwerp...", // "mydspace.messages.submitter-help": "Select this option to send a message to controller.", - // TODO New key - Add a translation - "mydspace.messages.submitter-help": "Select this option to send a message to controller.", + "mydspace.messages.submitter-help": "Kies deze optie om een bericht te sturen naar de controlleur.", // "mydspace.messages.title": "Messages", "mydspace.messages.title": "Berichten", @@ -1673,12 +1649,10 @@ "mydspace.messages.to": "Aan", // "mydspace.new-submission": "New submission", - // TODO New key - Add a translation - "mydspace.new-submission": "New submission", + "mydspace.new-submission": "Nieuwe submission", // "mydspace.results.head": "Your submissions", - // TODO New key - Add a translation - "mydspace.results.head": "Your submissions", + "mydspace.results.head": "Uw submissions", // "mydspace.results.no-abstract": "No Abstract", "mydspace.results.no-abstract": "Geen abstract", @@ -1708,8 +1682,7 @@ "mydspace.show.workflow": "Alle taken", // "mydspace.show.workspace": "Your Submissions", - // TODO New key - Add a translation - "mydspace.show.workspace": "Your Submissions", + "mydspace.show.workspace": "Uw Submissions", // "mydspace.status.archived": "Archived", "mydspace.status.archived": "Opgeslagen", @@ -1718,30 +1691,25 @@ "mydspace.status.validation": "Validatie", // "mydspace.status.waiting-for-controller": "Waiting for controller", - // TODO New key - Add a translation - "mydspace.status.waiting-for-controller": "Waiting for controller", + "mydspace.status.waiting-for-controller": "Wachten op controlleur", // "mydspace.status.workflow": "Workflow", "mydspace.status.workflow": "Workflow", // "mydspace.status.workspace": "Workspace", - // TODO New key - Add a translation "mydspace.status.workspace": "Workspace", // "mydspace.title": "MyDSpace", "mydspace.title": "MyDSpace", // "mydspace.upload.upload-failed": "Error creating new workspace. Please verify the content uploaded before retry.", - // TODO New key - Add a translation - "mydspace.upload.upload-failed": "Error creating new workspace. Please verify the content uploaded before retry.", + "mydspace.upload.upload-failed": "Er is een fout opgetreden bij het aanmaken van de nieuwe workspace. Controleer alstublieft de inhoud voordat u het opnieuw probeert.", // "mydspace.upload.upload-multiple-successful": "{{qty}} new workspace items created.", - // TODO New key - Add a translation - "mydspace.upload.upload-multiple-successful": "{{qty}} new workspace items created.", + "mydspace.upload.upload-multiple-successful": "{{qty}} nieuwe workspace items aangemaakt.", // "mydspace.upload.upload-successful": "New workspace item created. Click {{here}} for edit it.", - // TODO New key - Add a translation - "mydspace.upload.upload-successful": "New workspace item created. Click {{here}} for edit it.", + "mydspace.upload.upload-successful": "Nieuw workspace item aangemaakt. Klik {{here}} om het te bewerken.", // "mydspace.view-btn": "View", "mydspace.view-btn": "Bekijk", @@ -1755,8 +1723,7 @@ "nav.community-browse.header": "Per community", // "nav.language": "Language switch", - // TODO New key - Add a translation - "nav.language": "Language switch", + "nav.language": "Verander van taal", // "nav.login": "Log In", "nav.login": "Log In", @@ -1785,8 +1752,7 @@ "orgunit.page.country": "Land", // "orgunit.page.dateestablished": "Date established", - // TODO New key - Add a translation - "orgunit.page.dateestablished": "Date established", + "orgunit.page.dateestablished": "Stichtingsdatum", // "orgunit.page.description": "Description", "orgunit.page.description": "Beschrijving", @@ -1838,19 +1804,16 @@ "person.page.orcid": "ORCID", // "person.page.staffid": "Staff ID", - // TODO New key - Add a translation - "person.page.staffid": "Staff ID", + "person.page.staffid": "Personeels-ID", // "person.page.titleprefix": "Person: ", "person.page.titleprefix": "Persoon: ", // "person.search.results.head": "Person Search Results", - // TODO New key - Add a translation - "person.search.results.head": "Person Search Results", + "person.search.results.head": "Zoekresultaten Persoon", // "person.search.title": "DSpace Angular :: Person Search", - // TODO New key - Add a translation - "person.search.title": "DSpace Angular :: Person Search", + "person.search.title": "DSpace Angular :: Persoon zoeken", @@ -1858,7 +1821,6 @@ "project.listelement.badge": "Onderzoeksproject", // "project.page.contributor": "Contributors", - // TODO New key - Add a translation "project.page.contributor": "Contributors", // "project.page.description": "Description", @@ -1868,7 +1830,6 @@ "project.page.expectedcompletion": "Verwachte afronding", // "project.page.funder": "Funders", - // TODO New key - Add a translation "project.page.funder": "Funders", // "project.page.id": "ID", @@ -1904,8 +1865,7 @@ "publication.page.titleprefix": "Publicatie: ", // "publication.page.volume-title": "Volume Title", - // TODO New key - Add a translation - "publication.page.volume-title": "Volume Title", + "publication.page.volume-title": "Jaargangtitel", // "publication.search.results.head": "Publication Search Results", "publication.search.results.head": "Publicatie zoekresultaten", @@ -1974,8 +1934,7 @@ "search.filters.applied.f.dateIssued.min": "Startdatum", // "search.filters.applied.f.dateSubmitted": "Date submitted", - // TODO New key - Add a translation - "search.filters.applied.f.dateSubmitted": "Date submitted", + "search.filters.applied.f.dateSubmitted": "Indiendatum", // "search.filters.applied.f.entityType": "Item Type", "search.filters.applied.f.entityType": "Soort item", @@ -1993,8 +1952,7 @@ "search.filters.applied.f.subject": "Onderwerp", // "search.filters.applied.f.submitter": "Submitter", - // TODO New key - Add a translation - "search.filters.applied.f.submitter": "Submitter", + "search.filters.applied.f.submitter": "Indiener", @@ -2044,12 +2002,10 @@ "search.filters.filter.dateIssued.min.placeholder": "Laatste Datum", // "search.filters.filter.dateSubmitted.head": "Date submitted", - // TODO New key - Add a translation - "search.filters.filter.dateSubmitted.head": "Date submitted", + "search.filters.filter.dateSubmitted.head": "Indiendatum", // "search.filters.filter.dateSubmitted.placeholder": "Date submitted", - // TODO New key - Add a translation - "search.filters.filter.dateSubmitted.placeholder": "Date submitted", + "search.filters.filter.dateSubmitted.placeholder": "Indiendatum", // "search.filters.filter.entityType.head": "Item Type", "search.filters.filter.entityType.head": "Soort item", @@ -2073,12 +2029,10 @@ "search.filters.filter.jobTitle.placeholder": "Functienaam", // "search.filters.filter.knowsLanguage.head": "Known language", - // TODO New key - Add a translation - "search.filters.filter.knowsLanguage.head": "Known language", + "search.filters.filter.knowsLanguage.head": "Kent taal", // "search.filters.filter.knowsLanguage.placeholder": "Known language", - // TODO New key - Add a translation - "search.filters.filter.knowsLanguage.placeholder": "Known language", + "search.filters.filter.knowsLanguage.placeholder": "Kent taal", // "search.filters.filter.namedresourcetype.head": "Status", "search.filters.filter.namedresourcetype.head": "Status", @@ -2105,12 +2059,10 @@ "search.filters.filter.organizationAddressLocality.placeholder": "Plaats", // "search.filters.filter.organizationFoundingDate.head": "Date Founded", - // TODO New key - Add a translation - "search.filters.filter.organizationFoundingDate.head": "Date Founded", + "search.filters.filter.organizationFoundingDate.head": "Oprichtingsdatum", // "search.filters.filter.organizationFoundingDate.placeholder": "Date Founded", - // TODO New key - Add a translation - "search.filters.filter.organizationFoundingDate.placeholder": "Date Founded", + "search.filters.filter.organizationFoundingDate.placeholder": "Oprichtingsdatum", // "search.filters.filter.scope.head": "Scope", "search.filters.filter.scope.head": "Bereik", @@ -2131,12 +2083,10 @@ "search.filters.filter.subject.placeholder": "Onderwerp", // "search.filters.filter.submitter.head": "Submitter", - // TODO New key - Add a translation - "search.filters.filter.submitter.head": "Submitter", + "search.filters.filter.submitter.head": "Indiener", // "search.filters.filter.submitter.placeholder": "Submitter", - // TODO New key - Add a translation - "search.filters.filter.submitter.placeholder": "Submitter", + "search.filters.filter.submitter.placeholder": "Indiener", @@ -2216,348 +2166,266 @@ // "submission.edit.title": "Edit Submission", - // TODO New key - Add a translation - "submission.edit.title": "Edit Submission", + "submission.edit.title": "Bewerk submission", // "submission.general.cannot_submit": "You have not the privilege to make a new submission.", - // TODO New key - Add a translation - "submission.general.cannot_submit": "You have not the privilege to make a new submission.", + "submission.general.cannot_submit": "U heeft niet voldoende rechten om een nieuwe submission in te dienen.", // "submission.general.deposit": "Deposit", - // TODO New key - Add a translation - "submission.general.deposit": "Deposit", + "submission.general.deposit": "Dien in", // "submission.general.discard.confirm.cancel": "Cancel", - // TODO New key - Add a translation - "submission.general.discard.confirm.cancel": "Cancel", + "submission.general.discard.confirm.cancel": "Annuleer", // "submission.general.discard.confirm.info": "This operation can't be undone. Are you sure?", - // TODO New key - Add a translation - "submission.general.discard.confirm.info": "This operation can't be undone. Are you sure?", + "submission.general.discard.confirm.info": "Deze handeling kan niet ongedaan worden gemaakt. Weet u het zeker?", // "submission.general.discard.confirm.submit": "Yes, I'm sure", - // TODO New key - Add a translation - "submission.general.discard.confirm.submit": "Yes, I'm sure", + "submission.general.discard.confirm.submit": "Ja, ik weet het zeker", // "submission.general.discard.confirm.title": "Discard submission", - // TODO New key - Add a translation - "submission.general.discard.confirm.title": "Discard submission", + "submission.general.discard.confirm.title": "Annuleer submission", // "submission.general.discard.submit": "Discard", - // TODO New key - Add a translation - "submission.general.discard.submit": "Discard", + "submission.general.discard.submit": "Annuleer", // "submission.general.save": "Save", - // TODO New key - Add a translation - "submission.general.save": "Save", + "submission.general.save": "Opslaan", // "submission.general.save-later": "Save for later", - // TODO New key - Add a translation - "submission.general.save-later": "Save for later", + "submission.general.save-later": "Bewaar voor later", // "submission.sections.general.add-more": "Add more", - // TODO New key - Add a translation - "submission.sections.general.add-more": "Add more", + "submission.sections.general.add-more": "Voeg meer toe", // "submission.sections.general.collection": "Collection", - // TODO New key - Add a translation - "submission.sections.general.collection": "Collection", + "submission.sections.general.collection": "Collectie", // "submission.sections.general.deposit_error_notice": "There was an issue when submitting the item, please try again later.", - // TODO New key - Add a translation - "submission.sections.general.deposit_error_notice": "There was an issue when submitting the item, please try again later.", + "submission.sections.general.deposit_error_notice": "Er is een probleem opgetreden bij het indienen van het item. Probeer het later nog eens.", // "submission.sections.general.deposit_success_notice": "Submission deposited successfully.", - // TODO New key - Add a translation - "submission.sections.general.deposit_success_notice": "Submission deposited successfully.", + "submission.sections.general.deposit_success_notice": "Submission ingediend.", // "submission.sections.general.discard_error_notice": "There was an issue when discarding the item, please try again later.", - // TODO New key - Add a translation - "submission.sections.general.discard_error_notice": "There was an issue when discarding the item, please try again later.", + "submission.sections.general.discard_error_notice": "Er is een probleem opgetreden bij het annuleren van de submission. Probeer het later nog eens.", // "submission.sections.general.discard_success_notice": "Submission discarded successfully.", - // TODO New key - Add a translation - "submission.sections.general.discard_success_notice": "Submission discarded successfully.", + "submission.sections.general.discard_success_notice": "Submission geannuleerd.", // "submission.sections.general.metadata-extracted": "New metadata have been extracted and added to the {{sectionId}} section.", - // TODO New key - Add a translation - "submission.sections.general.metadata-extracted": "New metadata have been extracted and added to the {{sectionId}} section.", + "submission.sections.general.metadata-extracted": "Er zijn nieuwe metadata gevonden en toegevoegd aan de {{sectionId}} sectie.", // "submission.sections.general.metadata-extracted-new-section": "New {{sectionId}} section has been added to submission.", - // TODO New key - Add a translation - "submission.sections.general.metadata-extracted-new-section": "New {{sectionId}} section has been added to submission.", + "submission.sections.general.metadata-extracted-new-section": "De nieuwe sectie {{sectionId}} is toegevoegd aaan de submission.", // "submission.sections.general.no-collection": "No collection found", - // TODO New key - Add a translation - "submission.sections.general.no-collection": "No collection found", + "submission.sections.general.no-collection": "Geen collectie gevonden", // "submission.sections.general.no-sections": "No options available", - // TODO New key - Add a translation - "submission.sections.general.no-sections": "No options available", + "submission.sections.general.no-sections": "Geen opties beschikbaar", // "submission.sections.general.save_error_notice": "There was an issue when saving the item, please try again later.", - // TODO New key - Add a translation - "submission.sections.general.save_error_notice": "There was an issue when saving the item, please try again later.", + "submission.sections.general.save_error_notice": "Er is een probleem opgetreden bij het bewaren van het item. Probeer het later nog eens.", // "submission.sections.general.save_success_notice": "Submission saved successfully.", - // TODO New key - Add a translation - "submission.sections.general.save_success_notice": "Submission saved successfully.", + "submission.sections.general.save_success_notice": "Submission is opgeslagen.", // "submission.sections.general.search-collection": "Search for a collection", - // TODO New key - Add a translation - "submission.sections.general.search-collection": "Search for a collection", + "submission.sections.general.search-collection": "Zoek een collectie", // "submission.sections.general.sections_not_valid": "There are incomplete sections.", - // TODO New key - Add a translation - "submission.sections.general.sections_not_valid": "There are incomplete sections.", + "submission.sections.general.sections_not_valid": "Sommige secties zijn onvolledig.", // "submission.sections.submit.progressbar.cclicense": "Creative commons license", - // TODO New key - Add a translation - "submission.sections.submit.progressbar.cclicense": "Creative commons license", + "submission.sections.submit.progressbar.cclicense": "Creative commons licentie", // "submission.sections.submit.progressbar.describe.recycle": "Recycle", - // TODO New key - Add a translation "submission.sections.submit.progressbar.describe.recycle": "Recycle", // "submission.sections.submit.progressbar.describe.stepcustom": "Describe", - // TODO New key - Add a translation - "submission.sections.submit.progressbar.describe.stepcustom": "Describe", + "submission.sections.submit.progressbar.describe.stepcustom": "Beschrijf", // "submission.sections.submit.progressbar.describe.stepone": "Describe", - // TODO New key - Add a translation - "submission.sections.submit.progressbar.describe.stepone": "Describe", + "submission.sections.submit.progressbar.describe.stepone": "Beschrijf", // "submission.sections.submit.progressbar.describe.steptwo": "Describe", - // TODO New key - Add a translation - "submission.sections.submit.progressbar.describe.steptwo": "Describe", + "submission.sections.submit.progressbar.describe.steptwo": "Beschrijf", // "submission.sections.submit.progressbar.detect-duplicate": "Potential duplicates", - // TODO New key - Add a translation - "submission.sections.submit.progressbar.detect-duplicate": "Potential duplicates", + "submission.sections.submit.progressbar.detect-duplicate": "Mogelijke verdubbeling", // "submission.sections.submit.progressbar.license": "Deposit license", - // TODO New key - Add a translation - "submission.sections.submit.progressbar.license": "Deposit license", + "submission.sections.submit.progressbar.license": "Deposit licentie", // "submission.sections.submit.progressbar.upload": "Upload files", - // TODO New key - Add a translation - "submission.sections.submit.progressbar.upload": "Upload files", + "submission.sections.submit.progressbar.upload": "Upload bestanden", // "submission.sections.upload.delete.confirm.cancel": "Cancel", - // TODO New key - Add a translation - "submission.sections.upload.delete.confirm.cancel": "Cancel", + "submission.sections.upload.delete.confirm.cancel": "Annuleer", // "submission.sections.upload.delete.confirm.info": "This operation can't be undone. Are you sure?", - // TODO New key - Add a translation - "submission.sections.upload.delete.confirm.info": "This operation can't be undone. Are you sure?", + "submission.sections.upload.delete.confirm.info": "Deze handeling kan niet ongedaan worden gemaakt. Weet u het zeker?", // "submission.sections.upload.delete.confirm.submit": "Yes, I'm sure", - // TODO New key - Add a translation - "submission.sections.upload.delete.confirm.submit": "Yes, I'm sure", + "submission.sections.upload.delete.confirm.submit": "Ja, ik weet het zeker", // "submission.sections.upload.delete.confirm.title": "Delete bitstream", - // TODO New key - Add a translation - "submission.sections.upload.delete.confirm.title": "Delete bitstream", + "submission.sections.upload.delete.confirm.title": "Verwijder bitstream", // "submission.sections.upload.delete.submit": "Delete", - // TODO New key - Add a translation - "submission.sections.upload.delete.submit": "Delete", + "submission.sections.upload.delete.submit": "Verwijder", // "submission.sections.upload.drop-message": "Drop files to attach them to the item", - // TODO New key - Add a translation - "submission.sections.upload.drop-message": "Drop files to attach them to the item", + "submission.sections.upload.drop-message": "Sleep bestanden om ze toe te voegen aan het item", // "submission.sections.upload.form.access-condition-label": "Access condition type", - // TODO New key - Add a translation - "submission.sections.upload.form.access-condition-label": "Access condition type", + "submission.sections.upload.form.access-condition-label": "Soort toegangsrecht", // "submission.sections.upload.form.date-required": "Date is required.", - // TODO New key - Add a translation - "submission.sections.upload.form.date-required": "Date is required.", + "submission.sections.upload.form.date-required": "De datum is verplicht.", // "submission.sections.upload.form.from-label": "Access grant from", - // TODO New key - Add a translation - "submission.sections.upload.form.from-label": "Access grant from", + "submission.sections.upload.form.from-label": "Toegang vanaf", // "submission.sections.upload.form.from-placeholder": "From", - // TODO New key - Add a translation - "submission.sections.upload.form.from-placeholder": "From", + "submission.sections.upload.form.from-placeholder": "Van", // "submission.sections.upload.form.group-label": "Group", - // TODO New key - Add a translation - "submission.sections.upload.form.group-label": "Group", + "submission.sections.upload.form.group-label": "Groep", // "submission.sections.upload.form.group-required": "Group is required.", - // TODO New key - Add a translation - "submission.sections.upload.form.group-required": "Group is required.", + "submission.sections.upload.form.group-required": "Groep is verplicht.", // "submission.sections.upload.form.until-label": "Access grant until", - // TODO New key - Add a translation - "submission.sections.upload.form.until-label": "Access grant until", + "submission.sections.upload.form.until-label": "Toegang tot", // "submission.sections.upload.form.until-placeholder": "Until", - // TODO New key - Add a translation - "submission.sections.upload.form.until-placeholder": "Until", + "submission.sections.upload.form.until-placeholder": "Tot", // "submission.sections.upload.header.policy.default.nolist": "Uploaded files in the {{collectionName}} collection will be accessible according to the following group(s):", - // TODO New key - Add a translation - "submission.sections.upload.header.policy.default.nolist": "Uploaded files in the {{collectionName}} collection will be accessible according to the following group(s):", + "submission.sections.upload.header.policy.default.nolist": "Bestanden in de collectie {{collectionName}} zullen toegankelijk zijn volgens deze groep(en):", // "submission.sections.upload.header.policy.default.withlist": "Please note that uploaded files in the {{collectionName}} collection will be accessible, in addition to what is explicitly decided for the single file, with the following group(s):", - // TODO New key - Add a translation - "submission.sections.upload.header.policy.default.withlist": "Please note that uploaded files in the {{collectionName}} collection will be accessible, in addition to what is explicitly decided for the single file, with the following group(s):", + "submission.sections.upload.header.policy.default.withlist": "Let op: bestanden in de collectie {{collectionName}} zullen niet alleen toegankelijk zijn volgens de expliciet toegekende rechten per bestand, maar ook volgens de volgende groep(en):", // "submission.sections.upload.info": "Here you will find all the files currently in the item. You can update the file metadata and access conditions or upload additional files just dragging & dropping them everywhere in the page", - // TODO New key - Add a translation - "submission.sections.upload.info": "Here you will find all the files currently in the item. You can update the file metadata and access conditions or upload additional files just dragging & dropping them everywhere in the page", + "submission.sections.upload.info": "Hier vindt u alle bestanden van het item. U kunt de metadata en toegangsrechten bewerken of meer bestanden toevoegen door ze naar deze pagina te slepen.", // "submission.sections.upload.no-entry": "No", - // TODO New key - Add a translation - "submission.sections.upload.no-entry": "No", + "submission.sections.upload.no-entry": "Nee", // "submission.sections.upload.no-file-uploaded": "No file uploaded yet.", - // TODO New key - Add a translation - "submission.sections.upload.no-file-uploaded": "No file uploaded yet.", + "submission.sections.upload.no-file-uploaded": "Nog geen bestand geupload.", // "submission.sections.upload.save-metadata": "Save metadata", - // TODO New key - Add a translation - "submission.sections.upload.save-metadata": "Save metadata", + "submission.sections.upload.save-metadata": "Bewaar metadata", // "submission.sections.upload.undo": "Cancel", - // TODO New key - Add a translation - "submission.sections.upload.undo": "Cancel", + "submission.sections.upload.undo": "Annuleer", // "submission.sections.upload.upload-failed": "Upload failed", - // TODO New key - Add a translation - "submission.sections.upload.upload-failed": "Upload failed", + "submission.sections.upload.upload-failed": "Upload mislukt", // "submission.sections.upload.upload-successful": "Upload successful", - // TODO New key - Add a translation - "submission.sections.upload.upload-successful": "Upload successful", + "submission.sections.upload.upload-successful": "Upload geslaagd", // "submission.submit.title": "Submission", - // TODO New key - Add a translation "submission.submit.title": "Submission", // "submission.workflow.generic.delete": "Delete", - // TODO New key - Add a translation - "submission.workflow.generic.delete": "Delete", + "submission.workflow.generic.delete": "Verwijder", // "submission.workflow.generic.delete-help": "If you would to discard this item, select \"Delete\". You will then be asked to confirm it.", - // TODO New key - Add a translation - "submission.workflow.generic.delete-help": "If you would to discard this item, select \"Delete\". You will then be asked to confirm it.", + "submission.workflow.generic.delete-help": "Als u dit item wilt verwijderen, kies \"Verwijder\". Er zal gevraagd worden dit te bevestigen.", // "submission.workflow.generic.edit": "Edit", - // TODO New key - Add a translation - "submission.workflow.generic.edit": "Edit", + "submission.workflow.generic.edit": "Bewerk", // "submission.workflow.generic.edit-help": "Select this option to change the item's metadata.", - // TODO New key - Add a translation - "submission.workflow.generic.edit-help": "Select this option to change the item's metadata.", + "submission.workflow.generic.edit-help": "Kies deze optie om de metadata van het item te bewerken.", // "submission.workflow.generic.view": "View", - // TODO New key - Add a translation - "submission.workflow.generic.view": "View", + "submission.workflow.generic.view": "Bekijk", // "submission.workflow.generic.view-help": "Select this option to view the item's metadata.", - // TODO New key - Add a translation - "submission.workflow.generic.view-help": "Select this option to view the item's metadata.", + "submission.workflow.generic.view-help": "Kies deze optie om de metadata van het item te bekijken.", // "submission.workflow.tasks.claimed.approve": "Approve", - // TODO New key - Add a translation - "submission.workflow.tasks.claimed.approve": "Approve", + "submission.workflow.tasks.claimed.approve": "Accepteer", // "submission.workflow.tasks.claimed.approve_help": "If you have reviewed the item and it is suitable for inclusion in the collection, select \"Approve\".", - // TODO New key - Add a translation - "submission.workflow.tasks.claimed.approve_help": "If you have reviewed the item and it is suitable for inclusion in the collection, select \"Approve\".", + "submission.workflow.tasks.claimed.approve_help": "Als u het item gecontroleerd heeft en het geschikt is om in de collectie te worden opgenomen, kiest u \"Accepteer\".", // "submission.workflow.tasks.claimed.edit": "Edit", - // TODO New key - Add a translation - "submission.workflow.tasks.claimed.edit": "Edit", + "submission.workflow.tasks.claimed.edit": "Bewerk", // "submission.workflow.tasks.claimed.edit_help": "Select this option to change the item's metadata.", - // TODO New key - Add a translation - "submission.workflow.tasks.claimed.edit_help": "Select this option to change the item's metadata.", + "submission.workflow.tasks.claimed.edit_help": "Kies deze optie om de metadata van het item te bewerken.", // "submission.workflow.tasks.claimed.reject.reason.info": "Please enter your reason for rejecting the submission into the box below, indicating whether the submitter may fix a problem and resubmit.", - // TODO New key - Add a translation - "submission.workflow.tasks.claimed.reject.reason.info": "Please enter your reason for rejecting the submission into the box below, indicating whether the submitter may fix a problem and resubmit.", + "submission.workflow.tasks.claimed.reject.reason.info": "Vul uw reden om dit item te weigeren. Geef hierbij aan of de indiener het probleem kan verhelpen en het item opnieuw kan indienen.", // "submission.workflow.tasks.claimed.reject.reason.placeholder": "Describe the reason of reject", - // TODO New key - Add a translation - "submission.workflow.tasks.claimed.reject.reason.placeholder": "Describe the reason of reject", + "submission.workflow.tasks.claimed.reject.reason.placeholder": "Reden voor weigering", // "submission.workflow.tasks.claimed.reject.reason.submit": "Reject item", - // TODO New key - Add a translation - "submission.workflow.tasks.claimed.reject.reason.submit": "Reject item", + "submission.workflow.tasks.claimed.reject.reason.submit": "Weiger item", // "submission.workflow.tasks.claimed.reject.reason.title": "Reason", - // TODO New key - Add a translation - "submission.workflow.tasks.claimed.reject.reason.title": "Reason", + "submission.workflow.tasks.claimed.reject.reason.title": "Reden", // "submission.workflow.tasks.claimed.reject.submit": "Reject", - // TODO New key - Add a translation - "submission.workflow.tasks.claimed.reject.submit": "Reject", + "submission.workflow.tasks.claimed.reject.submit": "Weiger", // "submission.workflow.tasks.claimed.reject_help": "If you have reviewed the item and found it is not suitable for inclusion in the collection, select \"Reject\". You will then be asked to enter a message indicating why the item is unsuitable, and whether the submitter should change something and resubmit.", - // TODO New key - Add a translation - "submission.workflow.tasks.claimed.reject_help": "If you have reviewed the item and found it is not suitable for inclusion in the collection, select \"Reject\". You will then be asked to enter a message indicating why the item is unsuitable, and whether the submitter should change something and resubmit.", + "submission.workflow.tasks.claimed.reject_help": "Als u het item gecontroleerd heeft en heeft geconstateerd dat het niet geschikt is om opgenomen te worden, kies dan \"Weiger\". Er zal gevraagd worden om de reden van de weigering te geven. Ook kunt u aangeven of de indiener iets kan wijzigen en opnieuw indienen.", // "submission.workflow.tasks.claimed.return": "Return to pool", - // TODO New key - Add a translation - "submission.workflow.tasks.claimed.return": "Return to pool", + "submission.workflow.tasks.claimed.return": "Terug naar pool", // "submission.workflow.tasks.claimed.return_help": "Return the task to the pool so that another user may perform the task.", - // TODO New key - Add a translation - "submission.workflow.tasks.claimed.return_help": "Return the task to the pool so that another user may perform the task.", + "submission.workflow.tasks.claimed.return_help": "Stuur de taak terug naar de pool, zodat iemand anders de taak kan uitvoeren.", // "submission.workflow.tasks.generic.error": "Error occurred during operation...", - // TODO New key - Add a translation - "submission.workflow.tasks.generic.error": "Error occurred during operation...", + "submission.workflow.tasks.generic.error": "Er is een fout opgetreden tijdens de verwerking...", // "submission.workflow.tasks.generic.processing": "Processing...", - // TODO New key - Add a translation - "submission.workflow.tasks.generic.processing": "Processing...", + "submission.workflow.tasks.generic.processing": "Bezig met verwerken...", // "submission.workflow.tasks.generic.submitter": "Submitter", - // TODO New key - Add a translation - "submission.workflow.tasks.generic.submitter": "Submitter", + "submission.workflow.tasks.generic.submitter": "Indiener", // "submission.workflow.tasks.generic.success": "Operation successful", - // TODO New key - Add a translation - "submission.workflow.tasks.generic.success": "Operation successful", + "submission.workflow.tasks.generic.success": "Verwerking geslaagd", // "submission.workflow.tasks.pool.claim": "Claim", - // TODO New key - Add a translation "submission.workflow.tasks.pool.claim": "Claim", // "submission.workflow.tasks.pool.claim_help": "Assign this task to yourself.", - // TODO New key - Add a translation - "submission.workflow.tasks.pool.claim_help": "Assign this task to yourself.", + "submission.workflow.tasks.pool.claim_help": "Ken uzelf deze taak toe.", // "submission.workflow.tasks.pool.hide-detail": "Hide detail", - // TODO New key - Add a translation - "submission.workflow.tasks.pool.hide-detail": "Hide detail", + "submission.workflow.tasks.pool.hide-detail": "Verberg detail", // "submission.workflow.tasks.pool.show-detail": "Show detail", - // TODO New key - Add a translation - "submission.workflow.tasks.pool.show-detail": "Show detail", + "submission.workflow.tasks.pool.show-detail": "Toon detail", @@ -2567,24 +2435,19 @@ // "uploader.browse": "browse", - // TODO New key - Add a translation - "uploader.browse": "browse", + "uploader.browse": "blader", // "uploader.drag-message": "Drag & Drop your files here", - // TODO New key - Add a translation - "uploader.drag-message": "Drag & Drop your files here", + "uploader.drag-message": "Sleep uw bestanden hierheen", // "uploader.or": ", or", - // TODO New key - Add a translation - "uploader.or": ", or", + "uploader.or": ", of", // "uploader.processing": "Processing", - // TODO New key - Add a translation - "uploader.processing": "Processing", + "uploader.processing": "Bezig", // "uploader.queue-length": "Queue length", - // TODO New key - Add a translation - "uploader.queue-length": "Queue length", + "uploader.queue-length": "Queue lengte", From 4814ed0c686c7c21d1f9c528bba525a30f0d74d4 Mon Sep 17 00:00:00 2001 From: Bram Luyten Date: Thu, 27 Feb 2020 09:51:57 +0100 Subject: [PATCH 15/32] Rebase and enabling Dutch translation by default --- config/environment.default.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/environment.default.js b/config/environment.default.js index 58193d31bc..1ea9787a55 100644 --- a/config/environment.default.js +++ b/config/environment.default.js @@ -140,7 +140,7 @@ module.exports = { }, { code: 'nl', label: 'Nederlands', - active: false, + active: true, }, { code: 'pt', label: 'Português', From 500f5c645f43286e4bf37eaec4c3e9abf16aa939 Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Thu, 27 Feb 2020 11:15:31 +0100 Subject: [PATCH 16/32] Fixed issue with DataService's delete method that used wrong uuid to make the request --- .../bitstream-formats.component.spec.ts | 16 ++++++++-------- .../bitstream-formats.component.ts | 2 +- .../item-delete/item-delete.component.spec.ts | 2 +- .../item-delete/item-delete.component.ts | 4 ++-- .../data/bitstream-format-data.service.spec.ts | 2 +- .../core/data/bitstream-format-data.service.ts | 8 ++++---- src/app/core/data/data.service.ts | 15 +++++++++++---- .../delete-comcol-page.component.spec.ts | 2 +- .../delete-comcol-page.component.ts | 2 +- .../workspaceitem-actions.component.spec.ts | 4 ++-- .../workspaceitem-actions.component.ts | 4 ++-- 11 files changed, 34 insertions(+), 27 deletions(-) diff --git a/src/app/+admin/admin-registries/bitstream-formats/bitstream-formats.component.spec.ts b/src/app/+admin/admin-registries/bitstream-formats/bitstream-formats.component.spec.ts index 5fd2c9cde0..7ff15cad6d 100644 --- a/src/app/+admin/admin-registries/bitstream-formats/bitstream-formats.component.spec.ts +++ b/src/app/+admin/admin-registries/bitstream-formats/bitstream-formats.component.spec.ts @@ -230,10 +230,10 @@ describe('BitstreamFormatsComponent', () => { comp.deleteFormats(); expect(bitstreamFormatService.clearBitStreamFormatRequests).toHaveBeenCalled(); - expect(bitstreamFormatService.delete).toHaveBeenCalledWith(bitstreamFormat1); - expect(bitstreamFormatService.delete).toHaveBeenCalledWith(bitstreamFormat2); - expect(bitstreamFormatService.delete).toHaveBeenCalledWith(bitstreamFormat3); - expect(bitstreamFormatService.delete).toHaveBeenCalledWith(bitstreamFormat4); + expect(bitstreamFormatService.delete).toHaveBeenCalledWith(bitstreamFormat1.id); + expect(bitstreamFormatService.delete).toHaveBeenCalledWith(bitstreamFormat2.id); + expect(bitstreamFormatService.delete).toHaveBeenCalledWith(bitstreamFormat3.id); + expect(bitstreamFormatService.delete).toHaveBeenCalledWith(bitstreamFormat4.id); expect(notificationsServiceStub.success).toHaveBeenCalledWith('admin.registries.bitstream-formats.delete.success.head', 'admin.registries.bitstream-formats.delete.success.amount'); @@ -276,10 +276,10 @@ describe('BitstreamFormatsComponent', () => { comp.deleteFormats(); expect(bitstreamFormatService.clearBitStreamFormatRequests).toHaveBeenCalled(); - expect(bitstreamFormatService.delete).toHaveBeenCalledWith(bitstreamFormat1); - expect(bitstreamFormatService.delete).toHaveBeenCalledWith(bitstreamFormat2); - expect(bitstreamFormatService.delete).toHaveBeenCalledWith(bitstreamFormat3); - expect(bitstreamFormatService.delete).toHaveBeenCalledWith(bitstreamFormat4); + expect(bitstreamFormatService.delete).toHaveBeenCalledWith(bitstreamFormat1.id); + expect(bitstreamFormatService.delete).toHaveBeenCalledWith(bitstreamFormat2.id); + expect(bitstreamFormatService.delete).toHaveBeenCalledWith(bitstreamFormat3.id); + expect(bitstreamFormatService.delete).toHaveBeenCalledWith(bitstreamFormat4.id); expect(notificationsServiceStub.error).toHaveBeenCalledWith('admin.registries.bitstream-formats.delete.failure.head', 'admin.registries.bitstream-formats.delete.failure.amount'); diff --git a/src/app/+admin/admin-registries/bitstream-formats/bitstream-formats.component.ts b/src/app/+admin/admin-registries/bitstream-formats/bitstream-formats.component.ts index ec4003c108..52010e0132 100644 --- a/src/app/+admin/admin-registries/bitstream-formats/bitstream-formats.component.ts +++ b/src/app/+admin/admin-registries/bitstream-formats/bitstream-formats.component.ts @@ -64,7 +64,7 @@ export class BitstreamFormatsComponent implements OnInit { const tasks$ = []; for (const format of formats) { if (hasValue(format.id)) { - tasks$.push(this.bitstreamFormatService.delete(format)); + tasks$.push(this.bitstreamFormatService.delete(format.id)); } } zip(...tasks$).subscribe((results: boolean[]) => { diff --git a/src/app/+item-page/edit-item-page/item-delete/item-delete.component.spec.ts b/src/app/+item-page/edit-item-page/item-delete/item-delete.component.spec.ts index bb9085d31f..a22d81a5dd 100644 --- a/src/app/+item-page/edit-item-page/item-delete/item-delete.component.spec.ts +++ b/src/app/+item-page/edit-item-page/item-delete/item-delete.component.spec.ts @@ -220,7 +220,7 @@ describe('ItemDeleteComponent', () => { spyOn(comp, 'notify'); comp.performAction(); expect(mockItemDataService.delete) - .toHaveBeenCalledWith(mockItem, types.filter((type) => typesSelection[type]).map((type) => type.id)); + .toHaveBeenCalledWith(mockItem.id, types.filter((type) => typesSelection[type]).map((type) => type.id)); expect(comp.notify).toHaveBeenCalled(); }); }); diff --git a/src/app/+item-page/edit-item-page/item-delete/item-delete.component.ts b/src/app/+item-page/edit-item-page/item-delete/item-delete.component.ts index 6fe44c109b..eecbdf8c6f 100644 --- a/src/app/+item-page/edit-item-page/item-delete/item-delete.component.ts +++ b/src/app/+item-page/edit-item-page/item-delete/item-delete.component.ts @@ -312,7 +312,7 @@ export class ItemDeleteComponent ) ), ).subscribe((types) => { - this.itemDataService.delete(this.item, types).pipe(first()).subscribe( + this.itemDataService.delete(this.item.id, types).pipe(first()).subscribe( (succeeded: boolean) => { this.notify(succeeded); } @@ -322,7 +322,7 @@ export class ItemDeleteComponent /** * When the item is successfully delete, navigate to the homepage, otherwise navigate back to the item edit page - * @param response + * @param succeeded */ notify(succeeded: boolean) { if (succeeded) { diff --git a/src/app/core/data/bitstream-format-data.service.spec.ts b/src/app/core/data/bitstream-format-data.service.spec.ts index daf3dea87c..7954416010 100644 --- a/src/app/core/data/bitstream-format-data.service.spec.ts +++ b/src/app/core/data/bitstream-format-data.service.spec.ts @@ -282,7 +282,7 @@ describe('BitstreamFormatDataService', () => { format.id = 'format-id'; const expected = cold('(b|)', {b: true}); - const result = service.delete(format); + const result = service.delete(format.id); expect(result).toBeObservable(expected); }); diff --git a/src/app/core/data/bitstream-format-data.service.ts b/src/app/core/data/bitstream-format-data.service.ts index 5c7029a09f..e8cf030a52 100644 --- a/src/app/core/data/bitstream-format-data.service.ts +++ b/src/app/core/data/bitstream-format-data.service.ts @@ -154,19 +154,19 @@ export class BitstreamFormatDataService extends DataService { /** * Delete an existing DSpace Object on the server - * @param format The DSpace Object to be removed + * @param formatID The DSpace Object'id to be removed * Return an observable that emits true when the deletion was successful, false when it failed */ - delete(format: BitstreamFormat): Observable { + delete(formatID: string): Observable { const requestId = this.requestService.generateRequestId(); const hrefObs = this.halService.getEndpoint(this.linkPath).pipe( - map((endpoint: string) => this.getIDHref(endpoint, format.id))); + map((endpoint: string) => this.getIDHref(endpoint, formatID))); hrefObs.pipe( find((href: string) => hasValue(href)), map((href: string) => { - const request = new DeleteByIDRequest(requestId, href, format.id); + const request = new DeleteByIDRequest(requestId, href, formatID); this.requestService.configure(request); }) ).subscribe(); diff --git a/src/app/core/data/data.service.ts b/src/app/core/data/data.service.ts index 3be1ef9768..7dcfb6bd6e 100644 --- a/src/app/core/data/data.service.ts +++ b/src/app/core/data/data.service.ts @@ -152,7 +152,11 @@ export abstract class DataService { /** * Returns {@link RemoteData} of all object with a list of {@link FollowLinkConfig}, to indicate which embedded * info should be added to the objects + * + * @param options Find list options object * @param linksToFollow List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved + * @return {Observable>>} + * Return an observable that emits object list */ findAll(options: FindListOptions = {}, ...linksToFollow: Array>): Observable>> { return this.findList(this.getFindAllHref(options), options, ...linksToFollow); @@ -162,6 +166,7 @@ export abstract class DataService { * Returns an observable of {@link RemoteData} of an object, based on href observable, * with a list of {@link FollowLinkConfig}, to automatically resolve {@link HALLink}s of the object * @param href$ Observable of href of object we want to retrieve + * @param options Find list options object * @param linksToFollow List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved */ protected findList(href$, options: FindListOptions, ...linksToFollow: Array>) { @@ -231,6 +236,7 @@ export abstract class DataService { * Returns a list of observables of {@link RemoteData} of objects, based on an href, with a list of {@link FollowLinkConfig}, * to automatically resolve {@link HALLink}s of the object * @param href The url of object we want to retrieve + * @param findListOptions Find list options object * @param linksToFollow List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved */ findAllByHref(href: string, findListOptions: FindListOptions = {}, ...linksToFollow: Array>): Observable>> { @@ -259,6 +265,7 @@ export abstract class DataService { * * @param searchMethod The search method for the object * @param options The [[FindListOptions]] object + * @param linksToFollow The array of [[FollowLinkConfig]] * @return {Observable>} * Return an observable that emits response from the server */ @@ -367,16 +374,16 @@ export abstract class DataService { /** * Delete an existing DSpace Object on the server - * @param dso The DSpace Object to be removed + * @param dsoID The DSpace Object' id to be removed * @param copyVirtualMetadata (optional parameter) the identifiers of the relationship types for which the virtual * metadata should be saved as real metadata * @return an observable that emits true when the deletion was successful, false when it failed */ - delete(dso: T, copyVirtualMetadata?: string[]): Observable { + delete(dsoID: string, copyVirtualMetadata?: string[]): Observable { const requestId = this.requestService.generateRequestId(); const hrefObs = this.halService.getEndpoint(this.linkPath).pipe( - map((endpoint: string) => this.getIDHref(endpoint, dso.uuid))); + map((endpoint: string) => this.getIDHref(endpoint, dsoID))); hrefObs.pipe( find((href: string) => hasValue(href)), @@ -388,7 +395,7 @@ export abstract class DataService { + id ); } - const request = new DeleteByIDRequest(requestId, href, dso.uuid); + const request = new DeleteByIDRequest(requestId, href, dsoID); this.requestService.configure(request); }) ).subscribe(); diff --git a/src/app/shared/comcol-forms/delete-comcol-page/delete-comcol-page.component.spec.ts b/src/app/shared/comcol-forms/delete-comcol-page/delete-comcol-page.component.spec.ts index 3b39d36008..dbbeea5bc6 100644 --- a/src/app/shared/comcol-forms/delete-comcol-page/delete-comcol-page.component.spec.ts +++ b/src/app/shared/comcol-forms/delete-comcol-page/delete-comcol-page.component.spec.ts @@ -125,7 +125,7 @@ describe('DeleteComColPageComponent', () => { it('should call delete on the data service', () => { comp.onConfirm(data1); fixture.detectChanges(); - expect(dsoDataService.delete).toHaveBeenCalledWith(data1); + expect(dsoDataService.delete).toHaveBeenCalledWith(data1.id); }); }); diff --git a/src/app/shared/comcol-forms/delete-comcol-page/delete-comcol-page.component.ts b/src/app/shared/comcol-forms/delete-comcol-page/delete-comcol-page.component.ts index 57c860e04f..f5a1a84af5 100644 --- a/src/app/shared/comcol-forms/delete-comcol-page/delete-comcol-page.component.ts +++ b/src/app/shared/comcol-forms/delete-comcol-page/delete-comcol-page.component.ts @@ -43,7 +43,7 @@ export class DeleteComColPageComponent implements * Deletes an existing DSO and redirects to the home page afterwards, showing a notification that states whether or not the deletion was successful */ onConfirm(dso: TDomain) { - this.dsoDataService.delete(dso) + this.dsoDataService.delete(dso.id) .pipe(first()) .subscribe((success: boolean) => { if (success) { diff --git a/src/app/shared/mydspace-actions/workspaceitem/workspaceitem-actions.component.spec.ts b/src/app/shared/mydspace-actions/workspaceitem/workspaceitem-actions.component.spec.ts index 8950966e26..00f5422b27 100644 --- a/src/app/shared/mydspace-actions/workspaceitem/workspaceitem-actions.component.spec.ts +++ b/src/app/shared/mydspace-actions/workspaceitem/workspaceitem-actions.component.spec.ts @@ -1,5 +1,5 @@ import { ChangeDetectionStrategy, Injector, NO_ERRORS_SCHEMA } from '@angular/core'; -import { async, ComponentFixture, fakeAsync, TestBed } from '@angular/core/testing'; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { Router } from '@angular/router'; import { By } from '@angular/platform-browser'; @@ -141,7 +141,7 @@ describe('WorkspaceitemActionsComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { - expect(mockDataService.delete).toHaveBeenCalledWith(mockObject); + expect(mockDataService.delete).toHaveBeenCalledWith(mockObject.id); }); }); diff --git a/src/app/shared/mydspace-actions/workspaceitem/workspaceitem-actions.component.ts b/src/app/shared/mydspace-actions/workspaceitem/workspaceitem-actions.component.ts index 2378c8e251..27512d899e 100644 --- a/src/app/shared/mydspace-actions/workspaceitem/workspaceitem-actions.component.ts +++ b/src/app/shared/mydspace-actions/workspaceitem/workspaceitem-actions.component.ts @@ -1,4 +1,4 @@ -import { Component, Injector, Input, OnDestroy } from '@angular/core'; +import { Component, Injector, Input } from '@angular/core'; import { Router } from '@angular/router'; import { BehaviorSubject } from 'rxjs'; @@ -62,7 +62,7 @@ export class WorkspaceitemActionsComponent extends MyDSpaceActionsComponent { if (result === 'ok') { this.processingDelete$.next(true); - this.objectDataService.delete(this.object) + this.objectDataService.delete(this.object.id) .subscribe((response: boolean) => { this.processingDelete$.next(false); this.handleActionResponse(response); From 355d9984b4495d7df7ccf8825265a9101e676a56 Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Thu, 27 Feb 2020 11:16:42 +0100 Subject: [PATCH 17/32] Fixed initialization of workspaceitem/workflowitem's selfUrl --- src/app/submission/edit/submission-edit.component.spec.ts | 2 +- src/app/submission/edit/submission-edit.component.ts | 2 +- src/app/submission/submit/submission-submit.component.spec.ts | 2 +- src/app/submission/submit/submission-submit.component.ts | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/app/submission/edit/submission-edit.component.spec.ts b/src/app/submission/edit/submission-edit.component.spec.ts index 115016d2fe..3b8695b023 100644 --- a/src/app/submission/edit/submission-edit.component.spec.ts +++ b/src/app/submission/edit/submission-edit.component.spec.ts @@ -74,7 +74,7 @@ describe('SubmissionEditComponent Component', () => { expect(comp.submissionId).toBe(submissionId); expect(comp.collectionId).toBe(submissionObject.collection.id); - expect(comp.selfUrl).toBe(submissionObject.self); + expect(comp.selfUrl).toBe(submissionObject._links.self.href); expect(comp.sections).toBe(submissionObject.sections); expect(comp.submissionDefinition).toBe(submissionObject.submissionDefinition); diff --git a/src/app/submission/edit/submission-edit.component.ts b/src/app/submission/edit/submission-edit.component.ts index 60c8b9a7a3..908f473136 100644 --- a/src/app/submission/edit/submission-edit.component.ts +++ b/src/app/submission/edit/submission-edit.component.ts @@ -94,7 +94,7 @@ export class SubmissionEditComponent implements OnDestroy, OnInit { } else { this.submissionId = submissionObjectRD.payload.id.toString(); this.collectionId = (submissionObjectRD.payload.collection as Collection).id; - this.selfUrl = submissionObjectRD.payload.self; + this.selfUrl = submissionObjectRD.payload._links.self.href; this.sections = submissionObjectRD.payload.sections; this.submissionDefinition = (submissionObjectRD.payload.submissionDefinition as SubmissionDefinitionsModel); this.changeDetectorRef.detectChanges(); diff --git a/src/app/submission/submit/submission-submit.component.spec.ts b/src/app/submission/submit/submission-submit.component.spec.ts index ca3316669f..809a4dd627 100644 --- a/src/app/submission/submit/submission-submit.component.spec.ts +++ b/src/app/submission/submit/submission-submit.component.spec.ts @@ -68,7 +68,7 @@ describe('SubmissionSubmitComponent Component', () => { expect(comp.submissionId.toString()).toEqual(submissionId); expect(comp.collectionId).toBe(submissionObject.collection.id); - expect(comp.selfUrl).toBe(submissionObject.self); + expect(comp.selfUrl).toBe(submissionObject._links.self.href); expect(comp.submissionDefinition).toBe(submissionObject.submissionDefinition); })); diff --git a/src/app/submission/submit/submission-submit.component.ts b/src/app/submission/submit/submission-submit.component.ts index 0aa0380a25..d3d3ca4e66 100644 --- a/src/app/submission/submit/submission-submit.component.ts +++ b/src/app/submission/submit/submission-submit.component.ts @@ -95,7 +95,7 @@ export class SubmissionSubmitComponent implements OnDestroy, OnInit { this.router.navigate(['/mydspace']); } else { this.collectionId = (submissionObject.collection as Collection).id; - this.selfUrl = submissionObject.self; + this.selfUrl = submissionObject._links.self.href; this.submissionDefinition = (submissionObject.submissionDefinition as SubmissionDefinitionsModel); this.submissionId = submissionObject.id; this.changeDetectorRef.detectChanges(); From 653cf8e921be4b502320704ff16fdc04eda5ccbf Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Thu, 27 Feb 2020 11:20:00 +0100 Subject: [PATCH 18/32] Temporary fix for Collection defaultAccessConditions issue --- .../submission/sections/upload/section-upload.component.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/app/submission/sections/upload/section-upload.component.ts b/src/app/submission/sections/upload/section-upload.component.ts index 86da00c816..f8f096d4bd 100644 --- a/src/app/submission/sections/upload/section-upload.component.ts +++ b/src/app/submission/sections/upload/section-upload.component.ts @@ -164,7 +164,8 @@ export class SubmissionSectionUploadComponent extends SectionModelComponent { flatMap((submissionObject: SubmissionObjectEntry) => this.collectionDataService.findById(submissionObject.collection)), filter((rd: RemoteData) => isNotUndefined((rd.payload))), tap((collectionRemoteData: RemoteData) => this.collectionName = collectionRemoteData.payload.name), - flatMap((collectionRemoteData: RemoteData) => { + // TODO review this part when https://github.com/DSpace/dspace-angular/issues/575 is resolved +/* flatMap((collectionRemoteData: RemoteData) => { return this.resourcePolicyService.findByHref( (collectionRemoteData.payload as any)._links.defaultAccessConditions.href ); @@ -176,7 +177,7 @@ export class SubmissionSectionUploadComponent extends SectionModelComponent { this.collectionDefaultAccessConditions = Array.isArray(defaultAccessConditionsRemoteData.payload) ? defaultAccessConditionsRemoteData.payload : [defaultAccessConditionsRemoteData.payload]; } - }), + }),*/ flatMap(() => config$), flatMap((config: SubmissionUploadsModel) => { this.required$.next(config.required); From 5d22ba7d367b3451b078af4e7122deadb2d43e4f Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Wed, 26 Feb 2020 13:58:36 +0100 Subject: [PATCH 19/32] Fixed Related Dynamic Form Controls functionality after Angular 8 upgrade --- src/app/app.module.ts | 10 +++++----- .../section-upload-file-edit.component.ts | 10 ++++++---- .../edit/section-upload-file-edit.model.ts | 19 +++++++++++-------- 3 files changed, 22 insertions(+), 17 deletions(-) diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 7bc4ee1c5a..f5db7ef096 100755 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -3,12 +3,11 @@ import { HttpClientModule } from '@angular/common/http'; import { NgModule } from '@angular/core'; import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; - import { EffectsModule } from '@ngrx/effects'; import { RouterStateSerializer, StoreRouterConnectingModule } from '@ngrx/router-store'; -import { META_REDUCERS, MetaReducer, StoreModule, USER_PROVIDED_META_REDUCERS } from '@ngrx/store'; +import { MetaReducer, StoreModule, USER_PROVIDED_META_REDUCERS } from '@ngrx/store'; import { StoreDevtoolsModule } from '@ngrx/store-devtools'; - +import { DYNAMIC_MATCHER_PROVIDERS } from '@ng-dynamic-forms/core'; import { TranslateModule } from '@ngx-translate/core'; import { ScrollToModule } from '@nicky-lenaers/ngx-scroll-to'; @@ -21,7 +20,7 @@ import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; import { appEffects } from './app.effects'; -import { appMetaReducers, debugMetaReducers, universalMetaReducer } from './app.metareducers'; +import { appMetaReducers, debugMetaReducers } from './app.metareducers'; import { appReducers, AppState } from './app.reducer'; import { CoreModule } from './core/core.module'; @@ -97,7 +96,8 @@ const PROVIDERS = [ provide: RouterStateSerializer, useClass: DSpaceRouterStateSerializer }, - ClientCookieService + ClientCookieService, + ...DYNAMIC_MATCHER_PROVIDERS, ]; const DECLARATIONS = [ diff --git a/src/app/submission/sections/upload/file/edit/section-upload-file-edit.component.ts b/src/app/submission/sections/upload/file/edit/section-upload-file-edit.component.ts index 19ee5d6d3d..217754b42e 100644 --- a/src/app/submission/sections/upload/file/edit/section-upload-file-edit.component.ts +++ b/src/app/submission/sections/upload/file/edit/section-upload-file-edit.component.ts @@ -10,7 +10,9 @@ import { DynamicFormControlEvent, DynamicFormControlModel, DynamicFormGroupModel, - DynamicSelectModel + DynamicSelectModel, + MATCH_ENABLED, + OR_OPERATOR } from '@ng-dynamic-forms/core'; import { WorkspaceitemSectionUploadFileObject } from '../../../../../core/submission/models/workspaceitem-section-upload-file.model'; @@ -206,9 +208,9 @@ export class SubmissionSectionUploadFileEditComponent implements OnChanges { hasGroups.push({ id: 'name', value: condition.name }); } }); - const confStart = { relation: [{ action: 'ENABLE', connective: 'OR', when: hasStart }] }; - const confEnd = { relation: [{ action: 'ENABLE', connective: 'OR', when: hasEnd }] }; - const confGroup = { relation: [{ action: 'ENABLE', connective: 'OR', when: hasGroups }] }; + const confStart = { relations: [{ match: MATCH_ENABLED, operator: OR_OPERATOR, when: hasStart }] }; + const confEnd = { relations: [{ match: MATCH_ENABLED, operator: OR_OPERATOR, when: hasEnd }] }; + const confGroup = { relations: [{ match: MATCH_ENABLED, operator: OR_OPERATOR, when: hasGroups }] }; accessConditionsArrayConfig.groupFactory = () => { const type = new DynamicSelectModel(accessConditionTypeModelConfig, BITSTREAM_FORM_ACCESS_CONDITION_TYPE_LAYOUT); diff --git a/src/app/submission/sections/upload/file/edit/section-upload-file-edit.model.ts b/src/app/submission/sections/upload/file/edit/section-upload-file-edit.model.ts index bc994aac52..dd2ac7a2a7 100644 --- a/src/app/submission/sections/upload/file/edit/section-upload-file-edit.model.ts +++ b/src/app/submission/sections/upload/file/edit/section-upload-file-edit.model.ts @@ -1,8 +1,11 @@ import { DynamicDatePickerModelConfig, DynamicFormArrayModelConfig, + DynamicFormControlLayout, + DynamicFormGroupModelConfig, DynamicSelectModelConfig, - DynamicFormGroupModelConfig, DynamicFormControlLayout, + MATCH_ENABLED, + OR_OPERATOR, } from '@ng-dynamic-forms/core'; export const BITSTREAM_METADATA_FORM_GROUP_CONFIG: DynamicFormGroupModelConfig = { @@ -15,7 +18,7 @@ export const BITSTREAM_METADATA_FORM_GROUP_LAYOUT: DynamicFormControlLayout = { label: 'col-form-label' }, grid: { - label: 'col-sm-3' + label: 'col-sm-3' } }; @@ -52,8 +55,8 @@ export const BITSTREAM_FORM_ACCESS_CONDITION_START_DATE_CONFIG: DynamicDatePicke toggleIcon: 'far fa-calendar-alt', relations: [ { - match: 'ENABLE', - operator: 'OR', + match: MATCH_ENABLED, + operator: OR_OPERATOR, when: [] } ], @@ -83,8 +86,8 @@ export const BITSTREAM_FORM_ACCESS_CONDITION_END_DATE_CONFIG: DynamicDatePickerM toggleIcon: 'far fa-calendar-alt', relations: [ { - match: 'ENABLE', - operator: 'OR', + match: MATCH_ENABLED, + operator: OR_OPERATOR, when: [] } ], @@ -112,8 +115,8 @@ export const BITSTREAM_FORM_ACCESS_CONDITION_GROUPS_CONFIG: DynamicSelectModelCo options: [], relations: [ { - match: 'ENABLE', - operator: 'OR', + match: MATCH_ENABLED, + operator: OR_OPERATOR, when: [] } ], From 3d1e93f5ef2d38e07c2929891ec33332086560bb Mon Sep 17 00:00:00 2001 From: lotte Date: Thu, 27 Feb 2020 16:53:47 +0100 Subject: [PATCH 20/32] feedback --- resources/i18n/en.json5 | 9 +++- .../browse-by-metadata-page.component.spec.ts | 1 - .../browse-by-dso-breadcrumb.resolver.ts | 41 +++++++++++++++++++ src/app/+browse-by/browse-by-guard.ts | 10 ++--- .../browse-by-i18n-breadcrumb.resolver.ts | 28 +++++++++++++ .../+browse-by/browse-by-routing.module.ts | 21 +++++++++- .../edit-collection-page.routing.module.ts | 9 ++-- .../edit-community-page.routing.module.ts | 7 ++-- .../edit-item-page.routing.module.ts | 12 +++--- src/app/+item-page/item-page.resolver.ts | 2 +- src/app/app-routing.module.ts | 3 +- .../breadcrumb/breadcrumb-config.model.ts | 14 +++++++ .../breadcrumb/breadcrumb.model.ts | 9 ++++ src/app/breadcrumbs/breadcrumbs.component.ts | 10 +++-- .../collection-breadcrumb.resolver.ts | 14 +++++++ .../community-breadcrumb.resolver.ts | 12 ++++++ .../dso-breadcrumb.resolver.spec.ts | 3 +- .../breadcrumbs/dso-breadcrumb.resolver.ts | 13 ++++-- .../breadcrumbs/i18n-breadcrumb.resolver.ts | 4 +- .../breadcrumbs/item-breadcrumb.resolver.ts | 17 ++++++++ .../core/shared/child-hal-resource.model.ts | 7 ++++ 21 files changed, 213 insertions(+), 33 deletions(-) create mode 100644 src/app/+browse-by/browse-by-dso-breadcrumb.resolver.ts create mode 100644 src/app/+browse-by/browse-by-i18n-breadcrumb.resolver.ts diff --git a/resources/i18n/en.json5 b/resources/i18n/en.json5 index 044cf216b8..cfa202fe4a 100644 --- a/resources/i18n/en.json5 +++ b/resources/i18n/en.json5 @@ -196,6 +196,14 @@ "browse.metadata.title": "Title", + "browse.metadata.author.breadcrumbs": "Browse by Author", + + "browse.metadata.dateissued.breadcrumbs": "Browse by Date", + + "browse.metadata.subject.breadcrumbs": "Browse by Subject", + + "browse.metadata.title.breadcrumbs": "Browse by Title", + "browse.startsWith.choose_start": "(Choose start)", "browse.startsWith.choose_year": "(Choose year)", @@ -237,7 +245,6 @@ "browse.title": "Browsing {{ collection }} by {{ field }} {{ value }}", - "chips.remove": "Remove chip", diff --git a/src/app/+browse-by/+browse-by-metadata-page/browse-by-metadata-page.component.spec.ts b/src/app/+browse-by/+browse-by-metadata-page/browse-by-metadata-page.component.spec.ts index 21e7e9ad99..601e7153e9 100644 --- a/src/app/+browse-by/+browse-by-metadata-page/browse-by-metadata-page.component.spec.ts +++ b/src/app/+browse-by/+browse-by-metadata-page/browse-by-metadata-page.component.spec.ts @@ -20,7 +20,6 @@ import { Item } from '../../core/shared/item.model'; import { DSpaceObjectDataService } from '../../core/data/dspace-object-data.service'; import { Community } from '../../core/shared/community.model'; import { MockRouter } from '../../shared/mocks/mock-router'; -import { ResourceType } from '../../core/shared/resource-type'; import { createSuccessfulRemoteDataObject$ } from '../../shared/testing/utils'; import { BrowseEntry } from '../../core/shared/browse-entry.model'; import { VarDirective } from '../../shared/utils/var.directive'; diff --git a/src/app/+browse-by/browse-by-dso-breadcrumb.resolver.ts b/src/app/+browse-by/browse-by-dso-breadcrumb.resolver.ts new file mode 100644 index 0000000000..5759e28754 --- /dev/null +++ b/src/app/+browse-by/browse-by-dso-breadcrumb.resolver.ts @@ -0,0 +1,41 @@ +import { Injectable } from '@angular/core'; +import { Community } from '../core/shared/community.model'; +import { DSpaceObjectDataService } from '../core/data/dspace-object-data.service'; +import { DSOBreadcrumbsService } from '../core/breadcrumbs/dso-breadcrumbs.service'; +import { Collection } from '../core/shared/collection.model'; +import { ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router'; +import { BreadcrumbConfig } from '../breadcrumbs/breadcrumb/breadcrumb-config.model'; +import { Observable } from 'rxjs'; +import { getRemoteDataPayload, getSucceededRemoteData } from '../core/shared/operators'; +import { map } from 'rxjs/operators'; +import { hasValue } from '../shared/empty.util'; +import { getDSOPath } from '../app-routing.module'; + +/** + * The class that resolves the BreadcrumbConfig object for a DSpaceObject on a browse by page + */ +@Injectable() +export class BrowseByDSOBreadcrumbResolver { + constructor(protected breadcrumbService: DSOBreadcrumbsService, protected dataService: DSpaceObjectDataService) { + } + + /** + * Method for resolving a breadcrumb config object + * @param {ActivatedRouteSnapshot} route The current ActivatedRouteSnapshot + * @param {RouterStateSnapshot} state The current RouterStateSnapshot + * @returns BreadcrumbConfig object + */ + resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable> { + const uuid = route.queryParams.scope; + if (hasValue(uuid)) { + return this.dataService.findById(uuid).pipe( + getSucceededRemoteData(), + getRemoteDataPayload(), + map((object: Community | Collection) => { + return { provider: this.breadcrumbService, key: object, url: getDSOPath(object) }; + }) + ); + } + return undefined; + } +} diff --git a/src/app/+browse-by/browse-by-guard.ts b/src/app/+browse-by/browse-by-guard.ts index 3813f7e656..9659a8c7b4 100644 --- a/src/app/+browse-by/browse-by-guard.ts +++ b/src/app/+browse-by/browse-by-guard.ts @@ -37,24 +37,24 @@ export class BrowseByGuard implements CanActivate { return dsoAndMetadata$.pipe( map((dsoRD) => { const name = dsoRD.payload.name; - route.data = this.createData(title, id, metadataField, name, metadataTranslated, value); + route.data = this.createData(title, id, metadataField, name, metadataTranslated, value, route); return true; }) ); } else { - route.data = this.createData(title, id, metadataField, '', metadataTranslated, value); + route.data = this.createData(title, id, metadataField, '', metadataTranslated, value, route); return observableOf(true); } } - private createData(title, id, metadataField, collection, field, value) { - return { + private createData(title, id, metadataField, collection, field, value, route) { + return Object.assign({}, route.data, { title: title, id: id, metadataField: metadataField, collection: collection, field: field, value: hasValue(value) ? `"${value}"` : '' - } + }); } } diff --git a/src/app/+browse-by/browse-by-i18n-breadcrumb.resolver.ts b/src/app/+browse-by/browse-by-i18n-breadcrumb.resolver.ts new file mode 100644 index 0000000000..c173bd414e --- /dev/null +++ b/src/app/+browse-by/browse-by-i18n-breadcrumb.resolver.ts @@ -0,0 +1,28 @@ +import { Injectable } from '@angular/core'; +import { ActivatedRouteSnapshot, Resolve, RouterStateSnapshot } from '@angular/router'; +import { I18nBreadcrumbsService } from '../core/breadcrumbs/i18n-breadcrumbs.service'; +import { BreadcrumbConfig } from '../breadcrumbs/breadcrumb/breadcrumb-config.model'; +import { I18nBreadcrumbResolver } from '../core/breadcrumbs/i18n-breadcrumb.resolver'; + +/** + * This class resolves a BreadcrumbConfig object with an i18n key string for a route + * It adds the metadata field of the current browse-by page + */ +@Injectable() +export class BrowseByI18nBreadcrumbResolver extends I18nBreadcrumbResolver { + constructor(protected breadcrumbService: I18nBreadcrumbsService) { + super(breadcrumbService); + } + + /** + * Method for resolving a browse-by i18n breadcrumb configuration object + * @param {ActivatedRouteSnapshot} route The current ActivatedRouteSnapshot + * @param {RouterStateSnapshot} state The current RouterStateSnapshot + * @returns BreadcrumbConfig object for a browse-by page + */ + resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): BreadcrumbConfig { + const extendedBreadcrumbKey = route.data.breadcrumbKey + '.' + route.params.id; + route.data = Object.assign({}, route.data, { breadcrumbKey: extendedBreadcrumbKey }); + return super.resolve(route, state); + } +} diff --git a/src/app/+browse-by/browse-by-routing.module.ts b/src/app/+browse-by/browse-by-routing.module.ts index e549c0f4e6..a686e7007e 100644 --- a/src/app/+browse-by/browse-by-routing.module.ts +++ b/src/app/+browse-by/browse-by-routing.module.ts @@ -2,12 +2,29 @@ import { RouterModule } from '@angular/router'; import { NgModule } from '@angular/core'; import { BrowseByGuard } from './browse-by-guard'; import { BrowseBySwitcherComponent } from './+browse-by-switcher/browse-by-switcher.component'; +import { BrowseByDSOBreadcrumbResolver } from './browse-by-dso-breadcrumb.resolver'; +import { BrowseByI18nBreadcrumbResolver } from './browse-by-i18n-breadcrumb.resolver'; @NgModule({ imports: [ RouterModule.forChild([ - { path: ':id', component: BrowseBySwitcherComponent, canActivate: [BrowseByGuard], data: { title: 'browse.title' } } - ]) + { + path: '', + resolve: { breadcrumb: BrowseByDSOBreadcrumbResolver }, + children: [ + { + path: ':id', + component: BrowseBySwitcherComponent, + canActivate: [BrowseByGuard], + resolve: { breadcrumb: BrowseByI18nBreadcrumbResolver }, + data: { title: 'browse.title', breadcrumbKey: 'browse.metadata' } + } + ] + }]) + ], + providers: [ + BrowseByI18nBreadcrumbResolver, + BrowseByDSOBreadcrumbResolver ] }) export class BrowseByRoutingModule { diff --git a/src/app/+collection-page/edit-collection-page/edit-collection-page.routing.module.ts b/src/app/+collection-page/edit-collection-page/edit-collection-page.routing.module.ts index e3d5749472..0569de9cd9 100644 --- a/src/app/+collection-page/edit-collection-page/edit-collection-page.routing.module.ts +++ b/src/app/+collection-page/edit-collection-page/edit-collection-page.routing.module.ts @@ -31,23 +31,24 @@ import { I18nBreadcrumbResolver } from '../../core/breadcrumbs/i18n-breadcrumb.r component: CollectionMetadataComponent, data: { title: 'collection.edit.tabs.metadata.title', - hideReturnButton: true + hideReturnButton: true, + showBreadcrumbs: true } }, { path: 'roles', component: CollectionRolesComponent, - data: { title: 'collection.edit.tabs.roles.title' } + data: { title: 'collection.edit.tabs.roles.title', showBreadcrumbs: true } }, { path: 'source', component: CollectionSourceComponent, - data: { title: 'collection.edit.tabs.source.title' } + data: { title: 'collection.edit.tabs.source.title', showBreadcrumbs: true } }, { path: 'curate', component: CollectionCurateComponent, - data: { title: 'collection.edit.tabs.curate.title' } + data: { title: 'collection.edit.tabs.curate.title', showBreadcrumbs: true } } ] } diff --git a/src/app/+community-page/edit-community-page/edit-community-page.routing.module.ts b/src/app/+community-page/edit-community-page/edit-community-page.routing.module.ts index f0a7813bac..3197e00829 100644 --- a/src/app/+community-page/edit-community-page/edit-community-page.routing.module.ts +++ b/src/app/+community-page/edit-community-page/edit-community-page.routing.module.ts @@ -31,18 +31,19 @@ import { I18nBreadcrumbResolver } from '../../core/breadcrumbs/i18n-breadcrumb.r component: CommunityMetadataComponent, data: { title: 'community.edit.tabs.metadata.title', - hideReturnButton: true + hideReturnButton: true, + showBreadcrumbs: true } }, { path: 'roles', component: CommunityRolesComponent, - data: { title: 'community.edit.tabs.roles.title' } + data: { title: 'community.edit.tabs.roles.title', showBreadcrumbs: true } }, { path: 'curate', component: CommunityCurateComponent, - data: { title: 'community.edit.tabs.curate.title' } + data: { title: 'community.edit.tabs.curate.title', showBreadcrumbs: true } } ] } diff --git a/src/app/+item-page/edit-item-page/edit-item-page.routing.module.ts b/src/app/+item-page/edit-item-page/edit-item-page.routing.module.ts index af78eeea6f..da667847f7 100644 --- a/src/app/+item-page/edit-item-page/edit-item-page.routing.module.ts +++ b/src/app/+item-page/edit-item-page/edit-item-page.routing.module.ts @@ -47,34 +47,34 @@ const ITEM_EDIT_MOVE_PATH = 'move'; { path: 'status', component: ItemStatusComponent, - data: { title: 'item.edit.tabs.status.title' } + data: { title: 'item.edit.tabs.status.title', showBreadcrumbs: true } }, { path: 'bitstreams', component: ItemBitstreamsComponent, - data: { title: 'item.edit.tabs.bitstreams.title' } + data: { title: 'item.edit.tabs.bitstreams.title', showBreadcrumbs: true } }, { path: 'metadata', component: ItemMetadataComponent, - data: { title: 'item.edit.tabs.metadata.title' } + data: { title: 'item.edit.tabs.metadata.title', showBreadcrumbs: true } }, { path: 'relationships', component: ItemRelationshipsComponent, - data: { title: 'item.edit.tabs.relationships.title' } + data: { title: 'item.edit.tabs.relationships.title', showBreadcrumbs: true } }, { path: 'view', /* TODO - change when view page exists */ component: ItemBitstreamsComponent, - data: { title: 'item.edit.tabs.view.title' } + data: { title: 'item.edit.tabs.view.title', showBreadcrumbs: true } }, { path: 'curate', /* TODO - change when curate page exists */ component: ItemBitstreamsComponent, - data: { title: 'item.edit.tabs.curate.title' } + data: { title: 'item.edit.tabs.curate.title', showBreadcrumbs: true } } ] }, diff --git a/src/app/+item-page/item-page.resolver.ts b/src/app/+item-page/item-page.resolver.ts index 2645f0228c..0f73dc6170 100644 --- a/src/app/+item-page/item-page.resolver.ts +++ b/src/app/+item-page/item-page.resolver.ts @@ -27,7 +27,7 @@ export class ItemPageResolver implements Resolve> { return this.itemService.findById(route.params.id, followLink('owningCollection'), followLink('bundles'), - followLink('relationships') + followLink('relationships'), ).pipe( find((RD) => hasValue(RD.error) || RD.hasSucceeded), ); diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index ede1879894..4cf5efae41 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -11,6 +11,7 @@ import { Collection } from './core/shared/collection.model'; import { Item } from './core/shared/item.model'; import { getItemPageRoute } from './+item-page/item-page-routing.module'; import { getCollectionPageRoute } from './+collection-page/collection-page-routing.module'; +import { BrowseByDSOBreadcrumbResolver } from './+browse-by/browse-by-dso-breadcrumb.resolver'; const ITEM_MODULE_PATH = 'items'; @@ -60,7 +61,7 @@ export function getDSOPath(dso: DSpaceObject): string { { path: ITEM_MODULE_PATH, loadChildren: './+item-page/item-page.module#ItemPageModule' }, { path: 'mydspace', loadChildren: './+my-dspace-page/my-dspace-page.module#MyDSpacePageModule', canActivate: [AuthenticatedGuard] }, { path: 'search', loadChildren: './+search-page/search-page.module#SearchPageModule' }, - { path: 'browse', loadChildren: './+browse-by/browse-by.module#BrowseByModule' }, + { path: 'browse', loadChildren: './+browse-by/browse-by.module#BrowseByModule'}, { path: ADMIN_MODULE_PATH, loadChildren: './+admin/admin.module#AdminModule', canActivate: [AuthenticatedGuard] }, { path: 'login', loadChildren: './+login-page/login-page.module#LoginPageModule' }, { path: 'logout', loadChildren: './+logout-page/logout-page.module#LogoutPageModule' }, diff --git a/src/app/breadcrumbs/breadcrumb/breadcrumb-config.model.ts b/src/app/breadcrumbs/breadcrumb/breadcrumb-config.model.ts index 17ec96e2bd..0ff8fc5033 100644 --- a/src/app/breadcrumbs/breadcrumb/breadcrumb-config.model.ts +++ b/src/app/breadcrumbs/breadcrumb/breadcrumb-config.model.ts @@ -1,7 +1,21 @@ import { BreadcrumbsService } from '../../core/breadcrumbs/breadcrumbs.service'; +/** + * Interface for breadcrumb configuration objects + */ export interface BreadcrumbConfig { + /** + * The service used to calculate the breadcrumb object + */ provider: BreadcrumbsService; + + /** + * The key that is used to calculate the breadcrumb display value + */ key: T; + + /** + * The url of the breadcrumb + */ url?: string; } diff --git a/src/app/breadcrumbs/breadcrumb/breadcrumb.model.ts b/src/app/breadcrumbs/breadcrumb/breadcrumb.model.ts index 99cf66533a..c6ab8491b4 100644 --- a/src/app/breadcrumbs/breadcrumb/breadcrumb.model.ts +++ b/src/app/breadcrumbs/breadcrumb/breadcrumb.model.ts @@ -1,6 +1,15 @@ +/** + * Class representing a single breadcrumb + */ export class Breadcrumb { constructor( + /** + * The display value of the breadcrumb + */ public text: string, + /** + * The optional url of the breadcrumb + */ public url?: string) { } } diff --git a/src/app/breadcrumbs/breadcrumbs.component.ts b/src/app/breadcrumbs/breadcrumbs.component.ts index 861fda844b..2bba3c76b6 100644 --- a/src/app/breadcrumbs/breadcrumbs.component.ts +++ b/src/app/breadcrumbs/breadcrumbs.component.ts @@ -1,7 +1,7 @@ import { Component, OnDestroy, OnInit } from '@angular/core'; import { ActivatedRoute, NavigationEnd, Router } from '@angular/router'; import { Breadcrumb } from './breadcrumb/breadcrumb.model'; -import { hasNoValue, hasValue, isNotUndefined } from '../shared/empty.util'; +import { hasNoValue, hasValue, isNotUndefined, isUndefined } from '../shared/empty.util'; import { filter, map, switchMap, tap } from 'rxjs/operators'; import { combineLatest, Observable, Subscription, of as observableOf } from 'rxjs'; @@ -58,8 +58,12 @@ export class BreadcrumbsComponent implements OnInit, OnDestroy { const routeConfig = route.snapshot.routeConfig; const last: boolean = hasNoValue(route.firstChild); - if (last && isNotUndefined(data.showBreadcrumbs)) { - this.showBreadcrumbs = data.showBreadcrumbs; + if (last) { + if (hasValue(data.showBreadcrumbs)) { + this.showBreadcrumbs = data.showBreadcrumbs; + } else if (isUndefined(data.breadcrumb)) { + this.showBreadcrumbs = false; + } } if ( diff --git a/src/app/core/breadcrumbs/collection-breadcrumb.resolver.ts b/src/app/core/breadcrumbs/collection-breadcrumb.resolver.ts index c662ead129..d9df7cd767 100644 --- a/src/app/core/breadcrumbs/collection-breadcrumb.resolver.ts +++ b/src/app/core/breadcrumbs/collection-breadcrumb.resolver.ts @@ -3,6 +3,7 @@ import { DSOBreadcrumbsService } from './dso-breadcrumbs.service'; import { DSOBreadcrumbResolver } from './dso-breadcrumb.resolver'; import { Collection } from '../shared/collection.model'; import { CollectionDataService } from '../data/collection-data.service'; +import { followLink, FollowLinkConfig } from '../../shared/utils/follow-link-config.model'; /** * The class that resolves the BreadcrumbConfig object for a Collection @@ -12,4 +13,17 @@ export class CollectionBreadcrumbResolver extends DSOBreadcrumbResolver> { + return [ + followLink('parentCommunity', undefined, + followLink('parentCommunity') + ) + ]; + } } diff --git a/src/app/core/breadcrumbs/community-breadcrumb.resolver.ts b/src/app/core/breadcrumbs/community-breadcrumb.resolver.ts index 1e4959f9e5..d1f21455f2 100644 --- a/src/app/core/breadcrumbs/community-breadcrumb.resolver.ts +++ b/src/app/core/breadcrumbs/community-breadcrumb.resolver.ts @@ -3,6 +3,7 @@ import { DSOBreadcrumbsService } from './dso-breadcrumbs.service'; import { DSOBreadcrumbResolver } from './dso-breadcrumb.resolver'; import { CommunityDataService } from '../data/community-data.service'; import { Community } from '../shared/community.model'; +import { followLink, FollowLinkConfig } from '../../shared/utils/follow-link-config.model'; /** * The class that resolves the BreadcrumbConfig object for a Community @@ -12,4 +13,15 @@ export class CommunityBreadcrumbResolver extends DSOBreadcrumbResolver> { + return [ + followLink('parentCommunity') + ]; + } } diff --git a/src/app/core/breadcrumbs/dso-breadcrumb.resolver.spec.ts b/src/app/core/breadcrumbs/dso-breadcrumb.resolver.spec.ts index 774fcd04d5..2a0005f548 100644 --- a/src/app/core/breadcrumbs/dso-breadcrumb.resolver.spec.ts +++ b/src/app/core/breadcrumbs/dso-breadcrumb.resolver.spec.ts @@ -2,6 +2,7 @@ import { DSOBreadcrumbResolver } from './dso-breadcrumb.resolver'; import { Collection } from '../shared/collection.model'; import { createSuccessfulRemoteDataObject$ } from '../../shared/testing/utils'; import { getTestScheduler } from 'jasmine-marbles'; +import { CollectionBreadcrumbResolver } from './collection-breadcrumb.resolver'; describe('DSOBreadcrumbResolver', () => { describe('resolve', () => { @@ -22,7 +23,7 @@ describe('DSOBreadcrumbResolver', () => { collectionService = { findById: (id: string) => createSuccessfulRemoteDataObject$(testCollection) }; - resolver = new DSOBreadcrumbResolver(dsoBreadcrumbService, collectionService); + resolver = new CollectionBreadcrumbResolver(dsoBreadcrumbService, collectionService); }); it('should resolve a breadcrumb config for the correct DSO', () => { diff --git a/src/app/core/breadcrumbs/dso-breadcrumb.resolver.ts b/src/app/core/breadcrumbs/dso-breadcrumb.resolver.ts index 78ba349a5c..80e68a16f5 100644 --- a/src/app/core/breadcrumbs/dso-breadcrumb.resolver.ts +++ b/src/app/core/breadcrumbs/dso-breadcrumb.resolver.ts @@ -8,12 +8,13 @@ import { map } from 'rxjs/operators'; import { Observable } from 'rxjs'; import { DSpaceObject } from '../shared/dspace-object.model'; import { ChildHALResource } from '../shared/child-hal-resource.model'; +import { FollowLinkConfig } from '../../shared/utils/follow-link-config.model'; /** * The class that resolves the BreadcrumbConfig object for a DSpaceObject */ @Injectable() -export class DSOBreadcrumbResolver implements Resolve> { +export abstract class DSOBreadcrumbResolver implements Resolve> { constructor(protected breadcrumbService: DSOBreadcrumbsService, protected dataService: DataService) { } @@ -25,7 +26,7 @@ export class DSOBreadcrumbResolver im */ resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable> { const uuid = route.params.id; - return this.dataService.findById(uuid).pipe( + return this.dataService.findById(uuid, ...this.followLinks).pipe( getSucceededRemoteData(), getRemoteDataPayload(), map((object: T) => { @@ -34,6 +35,12 @@ export class DSOBreadcrumbResolver im return { provider: this.breadcrumbService, key: object, url: url }; }) ); - } + + /** + * Method that returns the follow links to already resolve + * The self links defined in this list are expected to be requested somewhere in the near future + * Requesting them as embeds will limit the number of requests + */ + abstract get followLinks(): Array>; } diff --git a/src/app/core/breadcrumbs/i18n-breadcrumb.resolver.ts b/src/app/core/breadcrumbs/i18n-breadcrumb.resolver.ts index 0978648ba3..de7d061a3f 100644 --- a/src/app/core/breadcrumbs/i18n-breadcrumb.resolver.ts +++ b/src/app/core/breadcrumbs/i18n-breadcrumb.resolver.ts @@ -9,11 +9,11 @@ import { hasNoValue } from '../../shared/empty.util'; */ @Injectable() export class I18nBreadcrumbResolver implements Resolve> { - constructor(private breadcrumbService: I18nBreadcrumbsService) { + constructor(protected breadcrumbService: I18nBreadcrumbsService) { } /** - * Method for resolving a site object + * Method for resolving an I18n breadcrumb configuration object * @param {ActivatedRouteSnapshot} route The current ActivatedRouteSnapshot * @param {RouterStateSnapshot} state The current RouterStateSnapshot * @returns BreadcrumbConfig object diff --git a/src/app/core/breadcrumbs/item-breadcrumb.resolver.ts b/src/app/core/breadcrumbs/item-breadcrumb.resolver.ts index c447f7de2a..8390c0e001 100644 --- a/src/app/core/breadcrumbs/item-breadcrumb.resolver.ts +++ b/src/app/core/breadcrumbs/item-breadcrumb.resolver.ts @@ -3,6 +3,7 @@ import { DSOBreadcrumbsService } from './dso-breadcrumbs.service'; import { ItemDataService } from '../data/item-data.service'; import { Item } from '../shared/item.model'; import { DSOBreadcrumbResolver } from './dso-breadcrumb.resolver'; +import { followLink, FollowLinkConfig } from '../../shared/utils/follow-link-config.model'; /** * The class that resolves the BreadcrumbConfig object for an Item @@ -12,4 +13,20 @@ export class ItemBreadcrumbResolver extends DSOBreadcrumbResolver { constructor(protected breadcrumbService: DSOBreadcrumbsService, protected dataService: ItemDataService) { super(breadcrumbService, dataService); } + + /** + * Method that returns the follow links to already resolve + * The self links defined in this list are expected to be requested somewhere in the near future + * Requesting them as embeds will limit the number of requests + */ + get followLinks(): Array> { + return [ + followLink('owningCollection', undefined, + followLink('parentCommunity', undefined, + followLink('parentCommunity')) + ), + followLink('bundles'), + followLink('relationships') + ]; + } } diff --git a/src/app/core/shared/child-hal-resource.model.ts b/src/app/core/shared/child-hal-resource.model.ts index b7682e2631..ee022942bb 100644 --- a/src/app/core/shared/child-hal-resource.model.ts +++ b/src/app/core/shared/child-hal-resource.model.ts @@ -1,5 +1,12 @@ import { HALResource } from './hal-resource.model'; +/** + * Interface for HALResources with a parent object link + */ export interface ChildHALResource extends HALResource { + + /** + * Returns the key of the parent link + */ getParentLinkKey(): keyof this['_links']; } From aa5383ca5a7a8097fe00dc80c4bfcaedf32bbb31 Mon Sep 17 00:00:00 2001 From: lotte Date: Thu, 27 Feb 2020 16:56:51 +0100 Subject: [PATCH 21/32] remove unnecessary async that causes test timeout --- .../org-unit-item-metadata-list-element.component.spec.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/app/entity-groups/research-entities/metadata-representations/org-unit/org-unit-item-metadata-list-element.component.spec.ts b/src/app/entity-groups/research-entities/metadata-representations/org-unit/org-unit-item-metadata-list-element.component.spec.ts index 7d27b605ec..290fac7522 100644 --- a/src/app/entity-groups/research-entities/metadata-representations/org-unit/org-unit-item-metadata-list-element.component.spec.ts +++ b/src/app/entity-groups/research-entities/metadata-representations/org-unit/org-unit-item-metadata-list-element.component.spec.ts @@ -13,7 +13,7 @@ const mockItem = Object.assign(new Item(), { metadata: { 'dc.description': [{ va const virtMD = Object.assign(new MetadataValue(), { value: organisation }); const mockItemMetadataRepresentation = Object.assign(new ItemMetadataRepresentation(virtMD), mockItem); -describe('OrgUnitItemMetadataListElementComponent', () => { +fdescribe('OrgUnitItemMetadataListElementComponent', () => { let comp: OrgUnitItemMetadataListElementComponent; let fixture: ComponentFixture; @@ -27,12 +27,12 @@ describe('OrgUnitItemMetadataListElementComponent', () => { }).compileComponents(); })); - beforeEach(async(() => { + beforeEach(() => { fixture = TestBed.createComponent(OrgUnitItemMetadataListElementComponent); comp = fixture.componentInstance; comp.metadataRepresentation = mockItemMetadataRepresentation; fixture.detectChanges(); - })); + }); it('should show the name of the organisation as a link', () => { const linkText = fixture.debugElement.query(By.css('a')).nativeElement.textContent; From 8b6b478df9a8fdef570c6b0d7b04e01a339d58ee Mon Sep 17 00:00:00 2001 From: lotte Date: Thu, 27 Feb 2020 16:59:34 +0100 Subject: [PATCH 22/32] fixed other async --- .../org-unit-item-metadata-list-element.component.spec.ts | 2 +- .../person-item-metadata-list-element.component.spec.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/app/entity-groups/research-entities/metadata-representations/org-unit/org-unit-item-metadata-list-element.component.spec.ts b/src/app/entity-groups/research-entities/metadata-representations/org-unit/org-unit-item-metadata-list-element.component.spec.ts index 290fac7522..2d28821738 100644 --- a/src/app/entity-groups/research-entities/metadata-representations/org-unit/org-unit-item-metadata-list-element.component.spec.ts +++ b/src/app/entity-groups/research-entities/metadata-representations/org-unit/org-unit-item-metadata-list-element.component.spec.ts @@ -13,7 +13,7 @@ const mockItem = Object.assign(new Item(), { metadata: { 'dc.description': [{ va const virtMD = Object.assign(new MetadataValue(), { value: organisation }); const mockItemMetadataRepresentation = Object.assign(new ItemMetadataRepresentation(virtMD), mockItem); -fdescribe('OrgUnitItemMetadataListElementComponent', () => { +describe('OrgUnitItemMetadataListElementComponent', () => { let comp: OrgUnitItemMetadataListElementComponent; let fixture: ComponentFixture; diff --git a/src/app/entity-groups/research-entities/metadata-representations/person/person-item-metadata-list-element.component.spec.ts b/src/app/entity-groups/research-entities/metadata-representations/person/person-item-metadata-list-element.component.spec.ts index 1081e45884..97087728f8 100644 --- a/src/app/entity-groups/research-entities/metadata-representations/person/person-item-metadata-list-element.component.spec.ts +++ b/src/app/entity-groups/research-entities/metadata-representations/person/person-item-metadata-list-element.component.spec.ts @@ -29,12 +29,12 @@ describe('PersonItemMetadataListElementComponent', () => { }).compileComponents(); })); - beforeEach(async(() => { + beforeEach(() => { fixture = TestBed.createComponent(PersonItemMetadataListElementComponent); comp = fixture.componentInstance; comp.metadataRepresentation = mockItemMetadataRepresentation; fixture.detectChanges(); - })); + }); it('should show the person\'s name as a link', () => { const linkText = fixture.debugElement.query(By.css('a')).nativeElement.textContent; From df8ef2b5c384d928ef04ec2ced2f8c2cb41b7fac Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Mon, 2 Mar 2020 13:06:47 +0100 Subject: [PATCH 23/32] Fixed issue with field's required property during form filed initialization --- src/app/shared/form/builder/parsers/field-parser.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/shared/form/builder/parsers/field-parser.ts b/src/app/shared/form/builder/parsers/field-parser.ts index f7bf12353c..f218d442e1 100644 --- a/src/app/shared/form/builder/parsers/field-parser.ts +++ b/src/app/shared/form/builder/parsers/field-parser.ts @@ -49,7 +49,7 @@ export abstract class FieldParser { label: this.configData.label, initialCount: this.getInitArrayIndex(), notRepeatable: !this.configData.repeatable, - required: isNotEmpty(this.configData.mandatory), + required: JSON.parse( this.configData.mandatory), groupFactory: () => { let model; if ((arrayCounter === 0)) { From 18e17f0dadfe702f0cca2acc8f254112d50b2fc2 Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Mon, 2 Mar 2020 13:09:17 +0100 Subject: [PATCH 24/32] Added action to retrieve authenticated eperson object --- src/app/core/auth/auth-request.service.ts | 1 - src/app/core/auth/auth.actions.ts | 58 +++++++++- src/app/core/auth/auth.effects.spec.ts | 104 +++++++++++++----- src/app/core/auth/auth.effects.ts | 23 +++- src/app/core/auth/auth.reducer.spec.ts | 55 ++++++++- src/app/core/auth/auth.reducer.ts | 11 +- src/app/core/auth/auth.service.spec.ts | 39 ++++--- src/app/core/auth/auth.service.ts | 33 ++++-- src/app/core/auth/server-auth.service.ts | 11 +- .../testing/auth-request-service-stub.ts | 20 +++- src/app/shared/testing/auth-service-stub.ts | 9 +- 11 files changed, 281 insertions(+), 83 deletions(-) diff --git a/src/app/core/auth/auth-request.service.ts b/src/app/core/auth/auth-request.service.ts index 222214c76f..8773b1a9fb 100644 --- a/src/app/core/auth/auth-request.service.ts +++ b/src/app/core/auth/auth-request.service.ts @@ -1,7 +1,6 @@ import { Observable, of as observableOf, throwError as observableThrowError } from 'rxjs'; import { distinctUntilChanged, filter, map, mergeMap, tap } from 'rxjs/operators'; import { Inject, Injectable } from '@angular/core'; -import { EPersonDataService } from '../eperson/eperson-data.service'; import { HALEndpointService } from '../shared/hal-endpoint.service'; import { RequestService } from '../data/request.service'; import { GLOBAL_CONFIG } from '../../../config'; diff --git a/src/app/core/auth/auth.actions.ts b/src/app/core/auth/auth.actions.ts index d0969d38d4..2681ed39a2 100644 --- a/src/app/core/auth/auth.actions.ts +++ b/src/app/core/auth/auth.actions.ts @@ -1,9 +1,7 @@ // import @ngrx import { Action } from '@ngrx/store'; - // import type function import { type } from '../../shared/ngrx/type'; - // import models import { EPerson } from '../eperson/models/eperson.model'; import { AuthTokenInfo } from './models/auth-token-info.model'; @@ -31,6 +29,9 @@ export const AuthActionTypes = { REGISTRATION_ERROR: type('dspace/auth/REGISTRATION_ERROR'), REGISTRATION_SUCCESS: type('dspace/auth/REGISTRATION_SUCCESS'), SET_REDIRECT_URL: type('dspace/auth/SET_REDIRECT_URL'), + RETRIEVE_AUTHENTICATED_EPERSON: type('dspace/auth/RETRIEVE_AUTHENTICATED_EPERSON'), + RETRIEVE_AUTHENTICATED_EPERSON_SUCCESS: type('dspace/auth/RETRIEVE_AUTHENTICATED_EPERSON_SUCCESS'), + RETRIEVE_AUTHENTICATED_EPERSON_ERROR: type('dspace/auth/RETRIEVE_AUTHENTICATED_EPERSON_ERROR'), }; /* tslint:disable:max-classes-per-file */ @@ -76,11 +77,11 @@ export class AuthenticatedSuccessAction implements Action { payload: { authenticated: boolean; authToken: AuthTokenInfo; - user: EPerson + userHref: string }; - constructor(authenticated: boolean, authToken: AuthTokenInfo, user: EPerson) { - this.payload = { authenticated, authToken, user }; + constructor(authenticated: boolean, authToken: AuthTokenInfo, userHref: string) { + this.payload = { authenticated, authToken, userHref }; } } @@ -322,6 +323,47 @@ export class SetRedirectUrlAction implements Action { } } +/** + * Retrieve the authenticated eperson. + * @class RetrieveAuthenticatedEpersonAction + * @implements {Action} + */ +export class RetrieveAuthenticatedEpersonAction implements Action { + public type: string = AuthActionTypes.RETRIEVE_AUTHENTICATED_EPERSON; + payload: string; + + constructor(user: string) { + this.payload = user ; + } +} + +/** + * Set the authenticated eperson in the state. + * @class RetrieveAuthenticatedEpersonSuccessAction + * @implements {Action} + */ +export class RetrieveAuthenticatedEpersonSuccessAction implements Action { + public type: string = AuthActionTypes.RETRIEVE_AUTHENTICATED_EPERSON_SUCCESS; + payload: EPerson; + + constructor(user: EPerson) { + this.payload = user ; + } +} + +/** + * Set the authenticated eperson in the state. + * @class RetrieveAuthenticatedEpersonSuccessAction + * @implements {Action} + */ +export class RetrieveAuthenticatedEpersonErrorAction implements Action { + public type: string = AuthActionTypes.RETRIEVE_AUTHENTICATED_EPERSON_ERROR; + payload: Error; + + constructor(payload: Error) { + this.payload = payload ; + } +} /* tslint:enable:max-classes-per-file */ /** @@ -343,4 +385,8 @@ export type AuthActions | RegistrationErrorAction | RegistrationSuccessAction | AddAuthenticationMessageAction - | ResetAuthenticationMessagesAction; + | ResetAuthenticationMessagesAction + | RetrieveAuthenticatedEpersonAction + | RetrieveAuthenticatedEpersonErrorAction + | RetrieveAuthenticatedEpersonSuccessAction + | SetRedirectUrlAction; diff --git a/src/app/core/auth/auth.effects.spec.ts b/src/app/core/auth/auth.effects.spec.ts index 8c2b4026e0..34b900fe7e 100644 --- a/src/app/core/auth/auth.effects.spec.ts +++ b/src/app/core/auth/auth.effects.spec.ts @@ -18,12 +18,14 @@ import { LogOutErrorAction, LogOutSuccessAction, RefreshTokenErrorAction, - RefreshTokenSuccessAction + RefreshTokenSuccessAction, + RetrieveAuthenticatedEpersonAction, + RetrieveAuthenticatedEpersonErrorAction, + RetrieveAuthenticatedEpersonSuccessAction } from './auth.actions'; import { AuthServiceStub } from '../../shared/testing/auth-service-stub'; import { AuthService } from './auth.service'; import { AuthState } from './auth.reducer'; - import { EPersonMock } from '../../shared/testing/eperson-mock'; describe('AuthEffects', () => { @@ -42,13 +44,14 @@ describe('AuthEffects', () => { authServiceStub = new AuthServiceStub(); token = authServiceStub.getToken(); } + beforeEach(() => { init(); TestBed.configureTestingModule({ providers: [ AuthEffects, - {provide: AuthService, useValue: authServiceStub}, - {provide: Store, useValue: store}, + { provide: AuthService, useValue: authServiceStub }, + { provide: Store, useValue: store }, provideMockActions(() => actions), // other providers ], @@ -63,11 +66,11 @@ describe('AuthEffects', () => { actions = hot('--a-', { a: { type: AuthActionTypes.AUTHENTICATE, - payload: {email: 'user', password: 'password'} + payload: { email: 'user', password: 'password' } } }); - const expected = cold('--b-', {b: new AuthenticationSuccessAction(token)}); + const expected = cold('--b-', { b: new AuthenticationSuccessAction(token) }); expect(authEffects.authenticate$).toBeObservable(expected); }); @@ -80,11 +83,11 @@ describe('AuthEffects', () => { actions = hot('--a-', { a: { type: AuthActionTypes.AUTHENTICATE, - payload: {email: 'user', password: 'wrongpassword'} + payload: { email: 'user', password: 'wrongpassword' } } }); - const expected = cold('--b-', {b: new AuthenticationErrorAction(new Error('Message Error test'))}); + const expected = cold('--b-', { b: new AuthenticationErrorAction(new Error('Message Error test')) }); expect(authEffects.authenticate$).toBeObservable(expected); }); @@ -94,9 +97,9 @@ describe('AuthEffects', () => { describe('authenticateSuccess$', () => { it('should return a AUTHENTICATED action in response to a AUTHENTICATE_SUCCESS action', () => { - actions = hot('--a-', {a: {type: AuthActionTypes.AUTHENTICATE_SUCCESS, payload: token}}); + actions = hot('--a-', { a: { type: AuthActionTypes.AUTHENTICATE_SUCCESS, payload: token } }); - const expected = cold('--b-', {b: new AuthenticatedAction(token)}); + const expected = cold('--b-', { b: new AuthenticatedAction(token) }); expect(authEffects.authenticateSuccess$).toBeObservable(expected); }); @@ -106,9 +109,9 @@ describe('AuthEffects', () => { describe('when token is valid', () => { it('should return a AUTHENTICATED_SUCCESS action in response to a AUTHENTICATED action', () => { - actions = hot('--a-', {a: {type: AuthActionTypes.AUTHENTICATED, payload: token}}); + actions = hot('--a-', { a: { type: AuthActionTypes.AUTHENTICATED, payload: token } }); - const expected = cold('--b-', {b: new AuthenticatedSuccessAction(true, token, EPersonMock)}); + const expected = cold('--b-', { b: new AuthenticatedSuccessAction(true, token, EPersonMock._links.self.href) }); expect(authEffects.authenticated$).toBeObservable(expected); }); @@ -118,23 +121,42 @@ describe('AuthEffects', () => { it('should return a AUTHENTICATED_ERROR action in response to a AUTHENTICATED action', () => { spyOn((authEffects as any).authService, 'authenticatedUser').and.returnValue(observableThrow(new Error('Message Error test'))); - actions = hot('--a-', {a: {type: AuthActionTypes.AUTHENTICATED, payload: token}}); + actions = hot('--a-', { a: { type: AuthActionTypes.AUTHENTICATED, payload: token } }); - const expected = cold('--b-', {b: new AuthenticatedErrorAction(new Error('Message Error test'))}); + const expected = cold('--b-', { b: new AuthenticatedErrorAction(new Error('Message Error test')) }); expect(authEffects.authenticated$).toBeObservable(expected); }); }); }); + describe('authenticatedSuccess$', () => { + + it('should return a RETRIEVE_AUTHENTICATED_EPERSON action in response to a AUTHENTICATED_SUCCESS action', () => { + actions = hot('--a-', { + a: { + type: AuthActionTypes.AUTHENTICATED_SUCCESS, payload: { + authenticated: true, + authToken: token, + userHref: EPersonMock._links.self.href + } + } + }); + + const expected = cold('--b-', { b: new RetrieveAuthenticatedEpersonAction(EPersonMock._links.self.href) }); + + expect(authEffects.authenticatedSuccess$).toBeObservable(expected); + }); + }); + describe('checkToken$', () => { describe('when check token succeeded', () => { it('should return a AUTHENTICATED action in response to a CHECK_AUTHENTICATION_TOKEN action', () => { - actions = hot('--a-', {a: {type: AuthActionTypes.CHECK_AUTHENTICATION_TOKEN}}); + actions = hot('--a-', { a: { type: AuthActionTypes.CHECK_AUTHENTICATION_TOKEN } }); - const expected = cold('--b-', {b: new AuthenticatedAction(token)}); + const expected = cold('--b-', { b: new AuthenticatedAction(token) }); expect(authEffects.checkToken$).toBeObservable(expected); }); @@ -144,23 +166,53 @@ describe('AuthEffects', () => { it('should return a CHECK_AUTHENTICATION_TOKEN_ERROR action in response to a CHECK_AUTHENTICATION_TOKEN action', () => { spyOn((authEffects as any).authService, 'hasValidAuthenticationToken').and.returnValue(observableThrow('')); - actions = hot('--a-', {a: {type: AuthActionTypes.CHECK_AUTHENTICATION_TOKEN, payload: token}}); + actions = hot('--a-', { a: { type: AuthActionTypes.CHECK_AUTHENTICATION_TOKEN, payload: token } }); - const expected = cold('--b-', {b: new CheckAuthenticationTokenErrorAction()}); + const expected = cold('--b-', { b: new CheckAuthenticationTokenErrorAction() }); expect(authEffects.checkToken$).toBeObservable(expected); }); }) }); + describe('retrieveAuthenticatedEperson$', () => { + + describe('when request is successful', () => { + it('should return a RETRIEVE_AUTHENTICATED_EPERSON_SUCCESS action in response to a RETRIEVE_AUTHENTICATED_EPERSON action', () => { + actions = hot('--a-', { + a: { + type: AuthActionTypes.RETRIEVE_AUTHENTICATED_EPERSON, + payload: EPersonMock._links.self.href + } + }); + + const expected = cold('--b-', { b: new RetrieveAuthenticatedEpersonSuccessAction(EPersonMock) }); + + expect(authEffects.retrieveAuthenticatedEperson$).toBeObservable(expected); + }); + }); + + describe('when request is not successful', () => { + it('should return a RETRIEVE_AUTHENTICATED_EPERSON_ERROR action in response to a RETRIEVE_AUTHENTICATED_EPERSON action', () => { + spyOn((authEffects as any).authService, 'retrieveAuthenticatedUserByHref').and.returnValue(observableThrow(new Error('Message Error test'))); + + actions = hot('--a-', { a: { type: AuthActionTypes.RETRIEVE_AUTHENTICATED_EPERSON, payload: token } }); + + const expected = cold('--b-', { b: new RetrieveAuthenticatedEpersonErrorAction(new Error('Message Error test')) }); + + expect(authEffects.retrieveAuthenticatedEperson$).toBeObservable(expected); + }); + }); + }); + describe('refreshToken$', () => { describe('when refresh token succeeded', () => { it('should return a REFRESH_TOKEN_SUCCESS action in response to a REFRESH_TOKEN action', () => { - actions = hot('--a-', {a: {type: AuthActionTypes.REFRESH_TOKEN}}); + actions = hot('--a-', { a: { type: AuthActionTypes.REFRESH_TOKEN } }); - const expected = cold('--b-', {b: new RefreshTokenSuccessAction(token)}); + const expected = cold('--b-', { b: new RefreshTokenSuccessAction(token) }); expect(authEffects.refreshToken$).toBeObservable(expected); }); @@ -170,9 +222,9 @@ describe('AuthEffects', () => { it('should return a REFRESH_TOKEN_ERROR action in response to a REFRESH_TOKEN action', () => { spyOn((authEffects as any).authService, 'refreshAuthenticationToken').and.returnValue(observableThrow('')); - actions = hot('--a-', {a: {type: AuthActionTypes.REFRESH_TOKEN, payload: token}}); + actions = hot('--a-', { a: { type: AuthActionTypes.REFRESH_TOKEN, payload: token } }); - const expected = cold('--b-', {b: new RefreshTokenErrorAction()}); + const expected = cold('--b-', { b: new RefreshTokenErrorAction() }); expect(authEffects.refreshToken$).toBeObservable(expected); }); @@ -184,9 +236,9 @@ describe('AuthEffects', () => { describe('when refresh token succeeded', () => { it('should return a LOG_OUT_SUCCESS action in response to a LOG_OUT action', () => { - actions = hot('--a-', {a: {type: AuthActionTypes.LOG_OUT}}); + actions = hot('--a-', { a: { type: AuthActionTypes.LOG_OUT } }); - const expected = cold('--b-', {b: new LogOutSuccessAction()}); + const expected = cold('--b-', { b: new LogOutSuccessAction() }); expect(authEffects.logOut$).toBeObservable(expected); }); @@ -196,9 +248,9 @@ describe('AuthEffects', () => { it('should return a REFRESH_TOKEN_ERROR action in response to a LOG_OUT action', () => { spyOn((authEffects as any).authService, 'logout').and.returnValue(observableThrow(new Error('Message Error test'))); - actions = hot('--a-', {a: {type: AuthActionTypes.LOG_OUT, payload: token}}); + actions = hot('--a-', { a: { type: AuthActionTypes.LOG_OUT, payload: token } }); - const expected = cold('--b-', {b: new LogOutErrorAction(new Error('Message Error test'))}); + const expected = cold('--b-', { b: new LogOutErrorAction(new Error('Message Error test')) }); expect(authEffects.logOut$).toBeObservable(expected); }); diff --git a/src/app/core/auth/auth.effects.ts b/src/app/core/auth/auth.effects.ts index 1e68802af8..5ee63ccd92 100644 --- a/src/app/core/auth/auth.effects.ts +++ b/src/app/core/auth/auth.effects.ts @@ -26,7 +26,10 @@ import { RefreshTokenSuccessAction, RegistrationAction, RegistrationErrorAction, - RegistrationSuccessAction + RegistrationSuccessAction, + RetrieveAuthenticatedEpersonAction, + RetrieveAuthenticatedEpersonErrorAction, + RetrieveAuthenticatedEpersonSuccessAction } from './auth.actions'; import { EPerson } from '../eperson/models/eperson.model'; import { AuthStatus } from './models/auth-status.model'; @@ -66,11 +69,17 @@ export class AuthEffects { ofType(AuthActionTypes.AUTHENTICATED), switchMap((action: AuthenticatedAction) => { return this.authService.authenticatedUser(action.payload).pipe( - map((user: EPerson) => new AuthenticatedSuccessAction((user !== null), action.payload, user)), + map((userHref: string) => new AuthenticatedSuccessAction((userHref !== null), action.payload, userHref)), catchError((error) => observableOf(new AuthenticatedErrorAction(error))),); }) ); + @Effect() + public authenticatedSuccess$: Observable = this.actions$.pipe( + ofType(AuthActionTypes.AUTHENTICATED_SUCCESS), + map((action: AuthenticatedSuccessAction) => new RetrieveAuthenticatedEpersonAction(action.payload.userHref)) + ); + // It means "reacts to this action but don't send another" @Effect({ dispatch: false }) public authenticatedError$: Observable = this.actions$.pipe( @@ -78,6 +87,16 @@ export class AuthEffects { tap((action: LogOutSuccessAction) => this.authService.removeToken()) ); + @Effect() + public retrieveAuthenticatedEperson$: Observable = this.actions$.pipe( + ofType(AuthActionTypes.RETRIEVE_AUTHENTICATED_EPERSON), + switchMap((action: RetrieveAuthenticatedEpersonAction) => { + return this.authService.retrieveAuthenticatedUserByHref(action.payload).pipe( + map((user: EPerson) => new RetrieveAuthenticatedEpersonSuccessAction(user)), + catchError((error) => observableOf(new RetrieveAuthenticatedEpersonErrorAction(error)))); + }) + ); + @Effect() public checkToken$: Observable = this.actions$.pipe(ofType(AuthActionTypes.CHECK_AUTHENTICATION_TOKEN), switchMap(() => { diff --git a/src/app/core/auth/auth.reducer.spec.ts b/src/app/core/auth/auth.reducer.spec.ts index ca2ba00036..f299696007 100644 --- a/src/app/core/auth/auth.reducer.spec.ts +++ b/src/app/core/auth/auth.reducer.spec.ts @@ -17,7 +17,7 @@ import { RefreshTokenAction, RefreshTokenErrorAction, RefreshTokenSuccessAction, - ResetAuthenticationMessagesAction, + ResetAuthenticationMessagesAction, RetrieveAuthenticatedEpersonErrorAction, RetrieveAuthenticatedEpersonSuccessAction, SetRedirectUrlAction } from './auth.actions'; import { AuthTokenInfo } from './models/auth-token-info.model'; @@ -107,16 +107,15 @@ describe('authReducer', () => { loading: true, info: undefined }; - const action = new AuthenticatedSuccessAction(true, mockTokenInfo, EPersonMock); + const action = new AuthenticatedSuccessAction(true, mockTokenInfo, EPersonMock._links.self.href); const newState = authReducer(initialState, action); state = { authenticated: true, authToken: mockTokenInfo, - loaded: true, + loaded: false, error: undefined, - loading: false, - info: undefined, - user: EPersonMock + loading: true, + info: undefined }; expect(newState).toEqual(state); }); @@ -242,6 +241,50 @@ describe('authReducer', () => { expect(newState).toEqual(state); }); + it('should properly set the state, in response to a RETRIEVE_AUTHENTICATED_EPERSON_SUCCESS action', () => { + initialState = { + authenticated: true, + authToken: mockTokenInfo, + loaded: false, + error: undefined, + loading: true, + info: undefined + }; + const action = new RetrieveAuthenticatedEpersonSuccessAction(EPersonMock); + const newState = authReducer(initialState, action); + state = { + authenticated: true, + authToken: mockTokenInfo, + loaded: true, + error: undefined, + loading: false, + info: undefined, + user: EPersonMock + }; + expect(newState).toEqual(state); + }); + + it('should properly set the state, in response to a RETRIEVE_AUTHENTICATED_EPERSON_ERROR action', () => { + initialState = { + authenticated: false, + loaded: false, + error: undefined, + loading: true, + info: undefined + }; + const action = new RetrieveAuthenticatedEpersonErrorAction(mockError); + const newState = authReducer(initialState, action); + state = { + authenticated: false, + authToken: undefined, + error: 'Test error message', + loaded: true, + loading: false, + info: undefined + }; + expect(newState).toEqual(state); + }); + it('should properly set the state, in response to a REFRESH_TOKEN action', () => { initialState = { authenticated: true, diff --git a/src/app/core/auth/auth.reducer.ts b/src/app/core/auth/auth.reducer.ts index 98827d842e..7d5e50c432 100644 --- a/src/app/core/auth/auth.reducer.ts +++ b/src/app/core/auth/auth.reducer.ts @@ -8,7 +8,7 @@ import { LogOutErrorAction, RedirectWhenAuthenticationIsRequiredAction, RedirectWhenTokenExpiredAction, - RefreshTokenSuccessAction, + RefreshTokenSuccessAction, RetrieveAuthenticatedEpersonSuccessAction, SetRedirectUrlAction } from './auth.actions'; // import models @@ -80,6 +80,7 @@ export function authReducer(state: any = initialState, action: AuthActions): Aut }); case AuthActionTypes.AUTHENTICATED_ERROR: + case AuthActionTypes.RETRIEVE_AUTHENTICATED_EPERSON_ERROR: return Object.assign({}, state, { authenticated: false, authToken: undefined, @@ -91,12 +92,16 @@ export function authReducer(state: any = initialState, action: AuthActions): Aut case AuthActionTypes.AUTHENTICATED_SUCCESS: return Object.assign({}, state, { authenticated: true, - authToken: (action as AuthenticatedSuccessAction).payload.authToken, + authToken: (action as AuthenticatedSuccessAction).payload.authToken + }); + + case AuthActionTypes.RETRIEVE_AUTHENTICATED_EPERSON_SUCCESS: + return Object.assign({}, state, { loaded: true, error: undefined, loading: false, info: undefined, - user: (action as AuthenticatedSuccessAction).payload.user + user: (action as RetrieveAuthenticatedEpersonSuccessAction).payload }); case AuthActionTypes.AUTHENTICATE_ERROR: diff --git a/src/app/core/auth/auth.service.spec.ts b/src/app/core/auth/auth.service.spec.ts index 0928afcb19..31649abe32 100644 --- a/src/app/core/auth/auth.service.spec.ts +++ b/src/app/core/auth/auth.service.spec.ts @@ -5,14 +5,12 @@ import { ActivatedRoute, Router } from '@angular/router'; import { Store, StoreModule } from '@ngrx/store'; import { REQUEST } from '@nguniversal/express-engine/tokens'; import { of as observableOf } from 'rxjs'; -import { LinkService } from '../cache/builders/link.service'; import { authReducer, AuthState } from './auth.reducer'; import { NativeWindowRef, NativeWindowService } from '../services/window.service'; import { AuthService } from './auth.service'; import { RouterStub } from '../../shared/testing/router-stub'; import { ActivatedRouteStub } from '../../shared/testing/active-router-stub'; - import { CookieService } from '../services/cookie.service'; import { AuthRequestServiceStub } from '../../shared/testing/auth-request-service-stub'; import { AuthRequestService } from './auth-request.service'; @@ -23,12 +21,21 @@ import { EPersonMock } from '../../shared/testing/eperson-mock'; import { AppState } from '../../app.reducer'; import { ClientCookieService } from '../services/client-cookie.service'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; -import { getMockRemoteDataBuildService } from '../../shared/mocks/mock-remote-data-build.service'; import { routeServiceStub } from '../../shared/testing/route-service-stub'; import { RouteService } from '../services/route.service'; +import { Observable } from 'rxjs/internal/Observable'; +import { RemoteData } from '../data/remote-data'; +import { createSuccessfulRemoteDataObject$ } from '../../shared/testing/utils'; +import { EPersonDataService } from '../eperson/eperson-data.service'; describe('AuthService test', () => { + const mockEpersonDataService: any = { + findByHref(href: string): Observable> { + return createSuccessfulRemoteDataObject$(EPersonMock); + } + }; + let mockStore: Store; let authService: AuthService; let routeServiceMock: RouteService; @@ -62,7 +69,7 @@ describe('AuthService test', () => { linkService = { resolveLinks: {} }; - spyOn(linkService, 'resolveLinks').and.returnValue({authenticated: true, eperson: observableOf({payload: {}})}); + spyOn(linkService, 'resolveLinks').and.returnValue({ authenticated: true, eperson: observableOf({ payload: {} }) }); } @@ -83,7 +90,7 @@ describe('AuthService test', () => { { provide: RouteService, useValue: routeServiceStub }, { provide: ActivatedRoute, useValue: routeStub }, { provide: Store, useValue: mockStore }, - { provide: LinkService, useValue: linkService }, + { provide: EPersonDataService, useValue: mockEpersonDataService }, CookieService, AuthService ], @@ -101,8 +108,14 @@ describe('AuthService test', () => { expect(authService.authenticate.bind(null, 'user', 'passwordwrong')).toThrow(); }); - it('should return the authenticated user object when user token is valid', () => { - authService.authenticatedUser(new AuthTokenInfo('test_token')).subscribe((user: EPerson) => { + it('should return the authenticated user href when user token is valid', () => { + authService.authenticatedUser(new AuthTokenInfo('test_token')).subscribe((userHref: string) => { + expect(userHref).toBeDefined(); + }); + }); + + it('should return the authenticated user', () => { + authService.retrieveAuthenticatedUserByHref(EPersonMock._links.self.href).subscribe((user: EPerson) => { expect(user).toBeDefined(); }); }); @@ -159,7 +172,7 @@ describe('AuthService test', () => { (state as any).core = Object.create({}); (state as any).core.auth = authenticatedState; }); - authService = new AuthService({}, window, undefined, authReqService, router, routeService, cookieService, store, linkService); + authService = new AuthService({}, window, undefined, authReqService, mockEpersonDataService, router, routeService, cookieService, store); })); it('should return true when user is logged in', () => { @@ -221,7 +234,7 @@ describe('AuthService test', () => { (state as any).core = Object.create({}); (state as any).core.auth = authenticatedState; }); - authService = new AuthService({}, window, undefined, authReqService, router, routeService, cookieService, store, linkService); + authService = new AuthService({}, window, undefined, authReqService, mockEpersonDataService, router, routeService, cookieService, store); storage = (authService as any).storage; routeServiceMock = TestBed.get(RouteService); routerStub = TestBed.get(Router); @@ -250,7 +263,7 @@ describe('AuthService test', () => { expect(storage.remove).toHaveBeenCalled(); }); - it ('should set redirect url to previous page', () => { + it('should set redirect url to previous page', () => { spyOn(routeServiceMock, 'getHistory').and.callThrough(); spyOn(routerStub, 'navigateByUrl'); authService.redirectAfterLoginSuccess(true); @@ -258,7 +271,7 @@ describe('AuthService test', () => { expect(routerStub.navigateByUrl).toHaveBeenCalledWith('/collection/123'); }); - it ('should set redirect url to current page', () => { + it('should set redirect url to current page', () => { spyOn(routeServiceMock, 'getHistory').and.callThrough(); spyOn(routerStub, 'navigateByUrl'); authService.redirectAfterLoginSuccess(false); @@ -266,7 +279,7 @@ describe('AuthService test', () => { expect(routerStub.navigateByUrl).toHaveBeenCalledWith('/home'); }); - it ('should redirect to / and not to /login', () => { + it('should redirect to / and not to /login', () => { spyOn(routeServiceMock, 'getHistory').and.returnValue(observableOf(['/login', '/login'])); spyOn(routerStub, 'navigateByUrl'); authService.redirectAfterLoginSuccess(true); @@ -274,7 +287,7 @@ describe('AuthService test', () => { expect(routerStub.navigateByUrl).toHaveBeenCalledWith('/'); }); - it ('should redirect to / when no redirect url is found', () => { + it('should redirect to / when no redirect url is found', () => { spyOn(routeServiceMock, 'getHistory').and.returnValue(observableOf([''])); spyOn(routerStub, 'navigateByUrl'); authService.redirectAfterLoginSuccess(true); diff --git a/src/app/core/auth/auth.service.ts b/src/app/core/auth/auth.service.ts index 1da9f63b27..fd5c98f789 100644 --- a/src/app/core/auth/auth.service.ts +++ b/src/app/core/auth/auth.service.ts @@ -4,12 +4,10 @@ import { HttpHeaders } from '@angular/common/http'; import { REQUEST, RESPONSE } from '@nguniversal/express-engine/tokens'; import { Observable, of as observableOf } from 'rxjs'; -import { distinctUntilChanged, filter, map, startWith, switchMap, take, withLatestFrom } from 'rxjs/operators'; +import { distinctUntilChanged, filter, map, startWith, take, withLatestFrom } from 'rxjs/operators'; import { RouterReducerState } from '@ngrx/router-store'; import { select, Store } from '@ngrx/store'; import { CookieAttributes } from 'js-cookie'; -import { followLink } from '../../shared/utils/follow-link-config.model'; -import { LinkService } from '../cache/builders/link.service'; import { EPerson } from '../eperson/models/eperson.model'; import { AuthRequestService } from './auth-request.service'; @@ -24,6 +22,8 @@ import { ResetAuthenticationMessagesAction, SetRedirectUrlAction } from './auth. import { NativeWindowRef, NativeWindowService } from '../services/window.service'; import { Base64EncodeUrl } from '../../shared/utils/encode-decode.util'; import { RouteService } from '../services/route.service'; +import { EPersonDataService } from '../eperson/eperson-data.service'; +import { getFirstSucceededRemoteDataPayload } from '../shared/operators'; export const LOGIN_ROUTE = '/login'; export const LOGOUT_ROUTE = '/logout'; @@ -44,13 +44,13 @@ export class AuthService { constructor(@Inject(REQUEST) protected req: any, @Inject(NativeWindowService) protected _window: NativeWindowRef, - protected authRequestService: AuthRequestService, @Optional() @Inject(RESPONSE) private response: any, + protected authRequestService: AuthRequestService, + protected epersonService: EPersonDataService, protected router: Router, protected routeService: RouteService, protected storage: CookieService, - protected store: Store, - protected linkService: LinkService + protected store: Store ) { this.store.pipe( select(isAuthenticated), @@ -123,10 +123,10 @@ export class AuthService { } /** - * Returns the authenticated user - * @returns {User} + * Returns the href link to authenticated user + * @returns {string} */ - public authenticatedUser(token: AuthTokenInfo): Observable { + public authenticatedUser(token: AuthTokenInfo): Observable { // Determine if the user has an existing auth session on the server const options: HttpOptions = Object.create({}); let headers = new HttpHeaders(); @@ -134,16 +134,25 @@ export class AuthService { headers = headers.append('Authorization', `Bearer ${token.accessToken}`); options.headers = headers; return this.authRequestService.getRequest('status', options).pipe( - map((status) => this.linkService.resolveLinks(status, followLink('eperson'))), - switchMap((status: AuthStatus) => { + map((status: AuthStatus) => { if (status.authenticated) { - return status.eperson.pipe(map((eperson) => eperson.payload)); + return status._links.eperson.href; } else { throw(new Error('Not authenticated')); } })) } + /** + * Returns the authenticated user + * @returns {User} + */ + public retrieveAuthenticatedUserByHref(userHref: string): Observable { + return this.epersonService.findByHref(userHref).pipe( + getFirstSucceededRemoteDataPayload() + ) + } + /** * Checks if token is present into browser storage and is valid. (NB Check is done only on SSR) */ diff --git a/src/app/core/auth/server-auth.service.ts b/src/app/core/auth/server-auth.service.ts index eea2d83867..c8cba0206b 100644 --- a/src/app/core/auth/server-auth.service.ts +++ b/src/app/core/auth/server-auth.service.ts @@ -2,11 +2,9 @@ import { HttpHeaders } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; -import { filter, map, switchMap, take } from 'rxjs/operators'; +import { filter, map, take } from 'rxjs/operators'; import { isNotEmpty } from '../../shared/empty.util'; -import { followLink } from '../../shared/utils/follow-link-config.model'; import { HttpOptions } from '../dspace-rest-v2/dspace-rest-v2.service'; -import { EPerson } from '../eperson/models/eperson.model'; import { CheckAuthenticationTokenAction } from './auth.actions'; import { AuthService } from './auth.service'; import { AuthStatus } from './models/auth-status.model'; @@ -22,7 +20,7 @@ export class ServerAuthService extends AuthService { * Returns the authenticated user * @returns {User} */ - public authenticatedUser(token: AuthTokenInfo): Observable { + public authenticatedUser(token: AuthTokenInfo): Observable { // Determine if the user has an existing auth session on the server const options: HttpOptions = Object.create({}); let headers = new HttpHeaders(); @@ -35,10 +33,9 @@ export class ServerAuthService extends AuthService { options.headers = headers; return this.authRequestService.getRequest('status', options).pipe( - map((status) => this.linkService.resolveLinks(status, followLink('eperson'))), - switchMap((status: AuthStatus) => { + map((status: AuthStatus) => { if (status.authenticated) { - return status.eperson.pipe(map((eperson) => eperson.payload)); + return status._links.eperson.href; } else { throw(new Error('Not authenticated')); } diff --git a/src/app/shared/testing/auth-request-service-stub.ts b/src/app/shared/testing/auth-request-service-stub.ts index 82ce682a9b..b32b5395ba 100644 --- a/src/app/shared/testing/auth-request-service-stub.ts +++ b/src/app/shared/testing/auth-request-service-stub.ts @@ -5,8 +5,6 @@ import { AuthTokenInfo } from '../../core/auth/models/auth-token-info.model'; import { EPerson } from '../../core/eperson/models/eperson.model'; import { isNotEmpty } from '../empty.util'; import { EPersonMock } from './eperson-mock'; -import { RemoteData } from '../../core/data/remote-data'; -import { createSuccessfulRemoteDataObject$ } from './utils'; export class AuthRequestServiceStub { protected mockUser: EPerson = EPersonMock; @@ -28,7 +26,14 @@ export class AuthRequestServiceStub { if (this.validateToken(token)) { authStatusStub.authenticated = true; authStatusStub.token = this.mockTokenInfo; - authStatusStub.eperson = createSuccessfulRemoteDataObject$(this.mockUser); + authStatusStub._links = { + self: { + href: 'dspace.org/api/status', + }, + eperson: { + href: this.mockUser._links.self.href + } + }; } else { authStatusStub.authenticated = false; } @@ -47,7 +52,14 @@ export class AuthRequestServiceStub { if (this.validateToken(token)) { authStatusStub.authenticated = true; authStatusStub.token = this.mockTokenInfo; - authStatusStub.eperson = createSuccessfulRemoteDataObject$(this.mockUser); + authStatusStub._links = { + self: { + href: 'dspace.org/api/status', + }, + eperson: { + href: this.mockUser._links.self.href + } + }; } else { authStatusStub.authenticated = false; } diff --git a/src/app/shared/testing/auth-service-stub.ts b/src/app/shared/testing/auth-service-stub.ts index a6d24d5c8b..a3c6351ccd 100644 --- a/src/app/shared/testing/auth-service-stub.ts +++ b/src/app/shared/testing/auth-service-stub.ts @@ -3,7 +3,6 @@ import { AuthStatus } from '../../core/auth/models/auth-status.model'; import { AuthTokenInfo } from '../../core/auth/models/auth-token-info.model'; import { EPersonMock } from './eperson-mock'; import { EPerson } from '../../core/eperson/models/eperson.model'; -import { RemoteData } from '../../core/data/remote-data'; import { createSuccessfulRemoteDataObject$ } from './utils'; export class AuthServiceStub { @@ -30,14 +29,18 @@ export class AuthServiceStub { } } - public authenticatedUser(token: AuthTokenInfo): Observable { + public authenticatedUser(token: AuthTokenInfo): Observable { if (token.accessToken === 'token_test') { - return observableOf(EPersonMock); + return observableOf(EPersonMock._links.self.href); } else { throw(new Error('Message Error test')); } } + public retrieveAuthenticatedUserByHref(href: string): Observable { + return observableOf(EPersonMock); + } + public buildAuthHeader(token?: AuthTokenInfo): string { return `Bearer ${token.accessToken}`; } From ccb3c98f813d34b7b8c718ed9e2d0dae4c5035d9 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Mon, 2 Mar 2020 13:26:26 -0600 Subject: [PATCH 25/32] Increase network timeout for Docker builds to 5min --- Dockerfile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 4897b43ee2..d848666175 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,5 +6,7 @@ WORKDIR /app ADD . /app/ EXPOSE 3000 -RUN yarn install +# We run yarn install with an increased network timeout (5min) to avoid "ESOCKETTIMEDOUT" errors from hub.docker.com +# See, for example https://github.com/yarnpkg/yarn/issues/5540 +RUN yarn install --network-timeout 300000 CMD yarn run watch From 64c96c78f0bb9c154e5798cb8748f0889b462411 Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Tue, 3 Mar 2020 12:09:33 +0100 Subject: [PATCH 26/32] Fixed issue while retrieve undefined item's bitstreams on ItemDetailPreviewComponent --- src/app/core/data/bitstream-data.service.ts | 6 +++--- .../item-detail-preview.component.html | 4 ++-- .../item-detail-preview.component.spec.ts | 20 ++++++++++++------ .../item-detail-preview.component.ts | 21 +++++-------------- 4 files changed, 24 insertions(+), 27 deletions(-) diff --git a/src/app/core/data/bitstream-data.service.ts b/src/app/core/data/bitstream-data.service.ts index 408dceb56e..c571c7f96c 100644 --- a/src/app/core/data/bitstream-data.service.ts +++ b/src/app/core/data/bitstream-data.service.ts @@ -3,7 +3,7 @@ import { Injectable } from '@angular/core'; import { Store } from '@ngrx/store'; import { Observable } from 'rxjs/internal/Observable'; import { map, switchMap } from 'rxjs/operators'; -import { hasValue } from '../../shared/empty.util'; +import { hasValue, isNotEmpty } from '../../shared/empty.util'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { FollowLinkConfig } from '../../shared/utils/follow-link-config.model'; import { dataService } from '../cache/builders/build-decorators'; @@ -72,7 +72,7 @@ export class BitstreamDataService extends DataService { public getThumbnailFor(item: Item): Observable> { return this.bundleService.findByItemAndName(item, 'THUMBNAIL').pipe( switchMap((bundleRD: RemoteData) => { - if (hasValue(bundleRD.payload)) { + if (isNotEmpty(bundleRD.payload)) { return this.findAllByBundle(bundleRD.payload, { elementsPerPage: 1 }).pipe( map((bitstreamRD: RemoteData>) => { if (hasValue(bitstreamRD.payload) && hasValue(bitstreamRD.payload.page)) { @@ -108,7 +108,7 @@ export class BitstreamDataService extends DataService { public getMatchingThumbnail(item: Item, bitstreamInOriginal: Bitstream): Observable> { return this.bundleService.findByItemAndName(item, 'THUMBNAIL').pipe( switchMap((bundleRD: RemoteData) => { - if (hasValue(bundleRD.payload)) { + if (isNotEmpty(bundleRD.payload)) { return this.findAllByBundle(bundleRD.payload, { elementsPerPage: Number.MAX_SAFE_INTEGER }).pipe( map((bitstreamRD: RemoteData>) => { if (hasValue(bitstreamRD.payload) && hasValue(bitstreamRD.payload.page)) { diff --git a/src/app/shared/object-detail/my-dspace-result-detail-element/item-detail-preview/item-detail-preview.component.html b/src/app/shared/object-detail/my-dspace-result-detail-element/item-detail-preview/item-detail-preview.component.html index ab2c24c435..2e6951c94d 100644 --- a/src/app/shared/object-detail/my-dspace-result-detail-element/item-detail-preview/item-detail-preview.component.html +++ b/src/app/shared/object-detail/my-dspace-result-detail-element/item-detail-preview/item-detail-preview.component.html @@ -10,9 +10,9 @@
- + - +