diff --git a/src/app/browse-by/browse-by-date-page/browse-by-date-page.component.ts b/src/app/browse-by/browse-by-date-page/browse-by-date-page.component.ts index 3158c3d7cc..d0b63a00f9 100644 --- a/src/app/browse-by/browse-by-date-page/browse-by-date-page.component.ts +++ b/src/app/browse-by/browse-by-date-page/browse-by-date-page.component.ts @@ -12,12 +12,13 @@ import { ActivatedRoute, Params, Router } from '@angular/router'; import { BrowseService } from '../../core/browse/browse.service'; import { DSpaceObjectDataService } from '../../core/data/dspace-object-data.service'; import { StartsWithType } from '../../shared/starts-with/starts-with-decorator'; -import { BrowseByType, rendersBrowseBy } from '../browse-by-switcher/browse-by-decorator'; +import { BrowseByDataType, rendersBrowseBy } from '../browse-by-switcher/browse-by-decorator'; import { environment } from '../../../environments/environment'; import { PaginationService } from '../../core/pagination/pagination.service'; import { map } from 'rxjs/operators'; import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model'; import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model'; +import { BrowseDefinition } from '../../core/shared/browse-definition.model'; @Component({ selector: 'ds-browse-by-date-page', @@ -29,13 +30,13 @@ import { SortDirection, SortOptions } from '../../core/cache/models/sort-options * A metadata definition (a.k.a. browse id) is a short term used to describe one or multiple metadata fields. * An example would be 'dateissued' for 'dc.date.issued' */ -@rendersBrowseBy(BrowseByType.Date) +@rendersBrowseBy(BrowseByDataType.Date) export class BrowseByDatePageComponent extends BrowseByMetadataPageComponent { /** * The default metadata-field to use for determining the lower limit of the StartsWith dropdown options */ - defaultMetadataField = 'dc.date.issued'; + defaultBrowseDefinition = Object.assign(new BrowseDefinition(), {metadataKeys: ['dc.date.issued']}); public constructor(protected route: ActivatedRoute, protected browseService: BrowseService, @@ -59,13 +60,13 @@ export class BrowseByDatePageComponent extends BrowseByMetadataPageComponent { return [Object.assign({}, routeParams, queryParams, data), currentPage, currentSort]; }) ).subscribe(([params, currentPage, currentSort]: [Params, PaginationComponentOptions, SortOptions]) => { - const metadataField = params.metadataField || this.defaultMetadataField; + const browseDefinition = params.browseDefinition || this.defaultBrowseDefinition; this.browseId = params.id || this.defaultBrowseId; this.startsWith = +params.startsWith || params.startsWith; const searchOptions = browseParamsToOptions(params, currentPage, currentSort, this.browseId); this.updatePageWithItems(searchOptions, this.value); this.updateParent(params.scope); - this.updateStartsWithOptions(this.browseId, metadataField, params.scope); + this.updateStartsWithOptions(this.browseId, browseDefinition, params.scope); })); } @@ -79,12 +80,12 @@ export class BrowseByDatePageComponent extends BrowseByMetadataPageComponent { * @param metadataField The metadata field to fetch the earliest date from (expects a date field) * @param scope The scope under which to fetch the earliest item for */ - updateStartsWithOptions(definition: string, metadataField: string, scope?: string) { + updateStartsWithOptions(definition: string, browseDefinition: BrowseDefinition, scope?: string) { this.subs.push( this.browseService.getFirstItemFor(definition, scope).subscribe((firstItemRD: RemoteData) => { let lowerLimit = environment.browseBy.defaultLowerLimit; if (hasValue(firstItemRD.payload)) { - const date = firstItemRD.payload.firstMetadataValue(metadataField); + const date = firstItemRD.payload.firstMetadataValue(browseDefinition.metadataKeys); if (hasValue(date)) { const dateObj = new Date(date); // TODO: it appears that getFullYear (based on local time) is sometimes unreliable. Switching to UTC. diff --git a/src/app/browse-by/browse-by-guard.spec.ts b/src/app/browse-by/browse-by-guard.spec.ts index 4592f47175..fc483d87e2 100644 --- a/src/app/browse-by/browse-by-guard.spec.ts +++ b/src/app/browse-by/browse-by-guard.spec.ts @@ -1,20 +1,25 @@ import { first } from 'rxjs/operators'; import { BrowseByGuard } from './browse-by-guard'; import { of as observableOf } from 'rxjs'; +import { BrowseDefinitionDataService } from '../core/browse/browse-definition-data.service'; +import { createSuccessfulRemoteDataObject$ } from '../shared/remote-data.utils'; +import { BrowseDefinition } from '../core/shared/browse-definition.model'; +import { BrowseByDataType } from './browse-by-switcher/browse-by-decorator'; describe('BrowseByGuard', () => { describe('canActivate', () => { let guard: BrowseByGuard; let dsoService: any; let translateService: any; + let browseDefinitionService: any; const name = 'An interesting DSO'; const title = 'Author'; const field = 'Author'; const id = 'author'; - const metadataField = 'dc.contributor'; const scope = '1234-65487-12354-1235'; const value = 'Filter'; + const browseDefinition = Object.assign(new BrowseDefinition(), { type: BrowseByDataType.Metadata, metadataKeys: ['dc.contributor'] }); beforeEach(() => { dsoService = { @@ -24,14 +29,19 @@ describe('BrowseByGuard', () => { translateService = { instant: () => field }; - guard = new BrowseByGuard(dsoService, translateService); + + browseDefinitionService = { + findById: () => createSuccessfulRemoteDataObject$(browseDefinition) + }; + + guard = new BrowseByGuard(dsoService, translateService, browseDefinitionService); }); it('should return true, and sets up the data correctly, with a scope and value', () => { const scopedRoute = { data: { title: field, - metadataField, + browseDefinition, }, params: { id, @@ -48,7 +58,7 @@ describe('BrowseByGuard', () => { const result = { title, id, - metadataField, + browseDefinition, collection: name, field, value: '"' + value + '"' @@ -63,7 +73,7 @@ describe('BrowseByGuard', () => { const scopedNoValueRoute = { data: { title: field, - metadataField, + browseDefinition, }, params: { id, @@ -80,7 +90,7 @@ describe('BrowseByGuard', () => { const result = { title, id, - metadataField, + browseDefinition, collection: name, field, value: '' @@ -95,7 +105,7 @@ describe('BrowseByGuard', () => { const route = { data: { title: field, - metadataField, + browseDefinition, }, params: { id, @@ -111,7 +121,7 @@ describe('BrowseByGuard', () => { const result = { title, id, - metadataField, + browseDefinition, collection: '', field, value: '"' + value + '"' diff --git a/src/app/browse-by/browse-by-guard.ts b/src/app/browse-by/browse-by-guard.ts index 8ac77bbd64..0a46d59613 100644 --- a/src/app/browse-by/browse-by-guard.ts +++ b/src/app/browse-by/browse-by-guard.ts @@ -2,11 +2,14 @@ import { ActivatedRouteSnapshot, CanActivate, RouterStateSnapshot } from '@angul import { Injectable } from '@angular/core'; import { DSpaceObjectDataService } from '../core/data/dspace-object-data.service'; import { hasNoValue, hasValue } from '../shared/empty.util'; -import { map } from 'rxjs/operators'; -import { getFirstSucceededRemoteData } from '../core/shared/operators'; +import { map, switchMap } from 'rxjs/operators'; +import { getFirstSucceededRemoteData, getFirstSucceededRemoteDataPayload } from '../core/shared/operators'; import { TranslateService } from '@ngx-translate/core'; -import { of as observableOf } from 'rxjs'; +import { Observable, of as observableOf } from 'rxjs'; import { environment } from '../../environments/environment'; +import { BrowseDefinitionDataService } from '../core/browse/browse-definition-data.service'; +import { RemoteData } from '../core/data/remote-data'; +import { BrowseDefinition } from '../core/shared/browse-definition.model'; @Injectable() /** @@ -15,42 +18,46 @@ import { environment } from '../../environments/environment'; export class BrowseByGuard implements CanActivate { constructor(protected dsoService: DSpaceObjectDataService, - protected translate: TranslateService) { + protected translate: TranslateService, + protected browseDefinitionService: BrowseDefinitionDataService) { } canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) { const title = route.data.title; const id = route.params.id || route.queryParams.id || route.data.id; - let metadataField = route.data.metadataField; - if (hasNoValue(metadataField) && hasValue(id)) { - const config = environment.browseBy.types.find((conf) => conf.id === id); - if (hasValue(config) && hasValue(config.metadataField)) { - metadataField = config.metadataField; - } + let browseDefinition$: Observable; + if (hasNoValue(route.data.browseDefinition) && hasValue(id)) { + browseDefinition$ = this.browseDefinitionService.findById(id).pipe(getFirstSucceededRemoteDataPayload()); + } else { + browseDefinition$ = observableOf(route.data.browseDefinition); } const scope = route.queryParams.scope; const value = route.queryParams.value; const metadataTranslated = this.translate.instant('browse.metadata.' + id); - if (hasValue(scope)) { - const dsoAndMetadata$ = this.dsoService.findById(scope).pipe(getFirstSucceededRemoteData()); - return dsoAndMetadata$.pipe( - map((dsoRD) => { - const name = dsoRD.payload.name; - route.data = this.createData(title, id, metadataField, name, metadataTranslated, value, route); - return true; - }) - ); - } else { - route.data = this.createData(title, id, metadataField, '', metadataTranslated, value, route); - return observableOf(true); - } + return browseDefinition$.pipe( + switchMap((browseDefinition) => { + if (hasValue(scope)) { + const dsoAndMetadata$ = this.dsoService.findById(scope).pipe(getFirstSucceededRemoteData()); + return dsoAndMetadata$.pipe( + map((dsoRD) => { + const name = dsoRD.payload.name; + route.data = this.createData(title, id, browseDefinition, name, metadataTranslated, value, route); + return true; + }) + ); + } else { + route.data = this.createData(title, id, browseDefinition, '', metadataTranslated, value, route); + return observableOf(true); + } + }) + ) } - private createData(title, id, metadataField, collection, field, value, route) { + private createData(title, id, browseDefinition, collection, field, value, route) { return Object.assign({}, route.data, { title: title, id: id, - metadataField: metadataField, + browseDefinition: browseDefinition, collection: collection, field: field, value: hasValue(value) ? `"${value}"` : '' diff --git a/src/app/browse-by/browse-by-metadata-page/browse-by-metadata-page.component.ts b/src/app/browse-by/browse-by-metadata-page/browse-by-metadata-page.component.ts index 3573ffb264..6655f98392 100644 --- a/src/app/browse-by/browse-by-metadata-page/browse-by-metadata-page.component.ts +++ b/src/app/browse-by/browse-by-metadata-page/browse-by-metadata-page.component.ts @@ -14,7 +14,7 @@ import { getFirstSucceededRemoteData } from '../../core/shared/operators'; import { DSpaceObjectDataService } from '../../core/data/dspace-object-data.service'; import { DSpaceObject } from '../../core/shared/dspace-object.model'; import { StartsWithType } from '../../shared/starts-with/starts-with-decorator'; -import { BrowseByType, rendersBrowseBy } from '../browse-by-switcher/browse-by-decorator'; +import { BrowseByDataType, rendersBrowseBy } from '../browse-by-switcher/browse-by-decorator'; import { PaginationService } from '../../core/pagination/pagination.service'; import { map } from 'rxjs/operators'; @@ -28,7 +28,7 @@ import { map } from 'rxjs/operators'; * A metadata definition (a.k.a. browse id) is a short term used to describe one or multiple metadata fields. * An example would be 'author' for 'dc.contributor.*' */ -@rendersBrowseBy(BrowseByType.Metadata) +@rendersBrowseBy(BrowseByDataType.Metadata) export class BrowseByMetadataPageComponent implements OnInit { /** diff --git a/src/app/browse-by/browse-by-switcher/browse-by-decorator.spec.ts b/src/app/browse-by/browse-by-switcher/browse-by-decorator.spec.ts index f54efb9378..19a6277151 100644 --- a/src/app/browse-by/browse-by-switcher/browse-by-decorator.spec.ts +++ b/src/app/browse-by/browse-by-switcher/browse-by-decorator.spec.ts @@ -1,9 +1,9 @@ -import { BrowseByType, rendersBrowseBy } from './browse-by-decorator'; +import { BrowseByDataType, rendersBrowseBy } from './browse-by-decorator'; describe('BrowseByDecorator', () => { - const titleDecorator = rendersBrowseBy(BrowseByType.Title); - const dateDecorator = rendersBrowseBy(BrowseByType.Date); - const metadataDecorator = rendersBrowseBy(BrowseByType.Metadata); + const titleDecorator = rendersBrowseBy(BrowseByDataType.Title); + const dateDecorator = rendersBrowseBy(BrowseByDataType.Date); + const metadataDecorator = rendersBrowseBy(BrowseByDataType.Metadata); it('should have a decorator for all types', () => { expect(titleDecorator.length).not.toEqual(0); expect(dateDecorator.length).not.toEqual(0); diff --git a/src/app/browse-by/browse-by-switcher/browse-by-decorator.ts b/src/app/browse-by/browse-by-switcher/browse-by-decorator.ts index efb4a4a9f4..1ebaa7face 100644 --- a/src/app/browse-by/browse-by-switcher/browse-by-decorator.ts +++ b/src/app/browse-by/browse-by-switcher/browse-by-decorator.ts @@ -2,13 +2,13 @@ import { hasNoValue } from '../../shared/empty.util'; import { InjectionToken } from '@angular/core'; import { GenericConstructor } from '../../core/shared/generic-constructor'; -export enum BrowseByType { +export enum BrowseByDataType { Title = 'title', - Metadata = 'metadata', + Metadata = 'text', Date = 'date' } -export const DEFAULT_BROWSE_BY_TYPE = BrowseByType.Metadata; +export const DEFAULT_BROWSE_BY_TYPE = BrowseByDataType.Metadata; export const BROWSE_BY_COMPONENT_FACTORY = new InjectionToken<(browseByType) => GenericConstructor>('getComponentByBrowseByType', { providedIn: 'root', @@ -21,7 +21,7 @@ const map = new Map(); * Decorator used for rendering Browse-By pages by type * @param browseByType The type of page */ -export function rendersBrowseBy(browseByType: BrowseByType) { +export function rendersBrowseBy(browseByType: BrowseByDataType) { return function decorator(component: any) { if (hasNoValue(map.get(browseByType))) { map.set(browseByType, component); diff --git a/src/app/browse-by/browse-by-switcher/browse-by-switcher.component.spec.ts b/src/app/browse-by/browse-by-switcher/browse-by-switcher.component.spec.ts index f340237e26..cb82ddb7c4 100644 --- a/src/app/browse-by/browse-by-switcher/browse-by-switcher.component.spec.ts +++ b/src/app/browse-by/browse-by-switcher/browse-by-switcher.component.spec.ts @@ -2,20 +2,46 @@ import { BrowseBySwitcherComponent } from './browse-by-switcher.component'; import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; import { NO_ERRORS_SCHEMA } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; -import { BehaviorSubject } from 'rxjs'; -import { environment } from '../../../environments/environment'; -import { BROWSE_BY_COMPONENT_FACTORY } from './browse-by-decorator'; +import { BROWSE_BY_COMPONENT_FACTORY, BrowseByDataType } from './browse-by-decorator'; +import { BrowseDefinition } from '../../core/shared/browse-definition.model'; +import { BehaviorSubject, of as observableOf } from 'rxjs'; describe('BrowseBySwitcherComponent', () => { let comp: BrowseBySwitcherComponent; let fixture: ComponentFixture; - const types = environment.browseBy.types; + const types = [ + Object.assign( + new BrowseDefinition(), { + id: 'title', + dataType: BrowseByDataType.Title, + } + ), + Object.assign( + new BrowseDefinition(), { + id: 'dateissued', + dataType: BrowseByDataType.Date, + metadataKeys: ['dc.date.issued'] + } + ), + Object.assign( + new BrowseDefinition(), { + id: 'author', + dataType: BrowseByDataType.Metadata, + } + ), + Object.assign( + new BrowseDefinition(), { + id: 'subject', + dataType: BrowseByDataType.Metadata, + } + ), + ]; - const params = new BehaviorSubject(createParamsWithId('initialValue')); + const data = new BehaviorSubject(createDataWithBrowseDefinition(new BrowseDefinition())); const activatedRouteStub = { - params: params + data }; beforeEach(waitForAsync(() => { @@ -34,20 +60,20 @@ describe('BrowseBySwitcherComponent', () => { comp = fixture.componentInstance; })); - types.forEach((type) => { + types.forEach((type: BrowseDefinition) => { describe(`when switching to a browse-by page for "${type.id}"`, () => { beforeEach(() => { - params.next(createParamsWithId(type.id)); + data.next(createDataWithBrowseDefinition(type)); fixture.detectChanges(); }); - it(`should call getComponentByBrowseByType with type "${type.type}"`, () => { - expect((comp as any).getComponentByBrowseByType).toHaveBeenCalledWith(type.type); + it(`should call getComponentByBrowseByType with type "${type.dataType}"`, () => { + expect((comp as any).getComponentByBrowseByType).toHaveBeenCalledWith(type.dataType); }); }); }); }); -export function createParamsWithId(id) { - return { id: id }; +export function createDataWithBrowseDefinition(browseDefinition) { + return { browseDefinition: browseDefinition }; } diff --git a/src/app/browse-by/browse-by-switcher/browse-by-switcher.component.ts b/src/app/browse-by/browse-by-switcher/browse-by-switcher.component.ts index 043a4ce90a..55fcebf477 100644 --- a/src/app/browse-by/browse-by-switcher/browse-by-switcher.component.ts +++ b/src/app/browse-by/browse-by-switcher/browse-by-switcher.component.ts @@ -1,11 +1,11 @@ import { Component, Inject, OnInit } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { Observable } from 'rxjs'; -import { BrowseByTypeConfig } from '../../../config/browse-by-type-config.interface'; import { map } from 'rxjs/operators'; import { BROWSE_BY_COMPONENT_FACTORY } from './browse-by-decorator'; import { environment } from '../../../environments/environment'; import { GenericConstructor } from '../../core/shared/generic-constructor'; +import { BrowseDefinition } from '../../core/shared/browse-definition.model'; @Component({ selector: 'ds-browse-by-switcher', @@ -26,15 +26,11 @@ export class BrowseBySwitcherComponent implements OnInit { } /** - * Fetch the correct browse-by component by using the relevant config from environment.js + * Fetch the correct browse-by component by using the relevant config from the route data */ ngOnInit(): void { - this.browseByComponent = this.route.params.pipe( - map((params) => { - const id = params.id; - return environment.browseBy.types.find((config: BrowseByTypeConfig) => config.id === id); - }), - map((config: BrowseByTypeConfig) => this.getComponentByBrowseByType(config.type)) + this.browseByComponent = this.route.data.pipe( + map((data: { browseDefinition: BrowseDefinition }) => this.getComponentByBrowseByType(data.browseDefinition.dataType)) ); } diff --git a/src/app/browse-by/browse-by-title-page/browse-by-title-page.component.ts b/src/app/browse-by/browse-by-title-page/browse-by-title-page.component.ts index b3a2ceed00..b4a8331458 100644 --- a/src/app/browse-by/browse-by-title-page/browse-by-title-page.component.ts +++ b/src/app/browse-by/browse-by-title-page/browse-by-title-page.component.ts @@ -10,7 +10,7 @@ import { BrowseEntrySearchOptions } from '../../core/browse/browse-entry-search- import { DSpaceObjectDataService } from '../../core/data/dspace-object-data.service'; import { BrowseService } from '../../core/browse/browse.service'; import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model'; -import { BrowseByType, rendersBrowseBy } from '../browse-by-switcher/browse-by-decorator'; +import { BrowseByDataType, rendersBrowseBy } from '../browse-by-switcher/browse-by-decorator'; import { PaginationService } from '../../core/pagination/pagination.service'; import { map } from 'rxjs/operators'; import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model'; @@ -23,7 +23,7 @@ import { PaginationComponentOptions } from '../../shared/pagination/pagination-c /** * Component for browsing items by title (dc.title) */ -@rendersBrowseBy(BrowseByType.Title) +@rendersBrowseBy(BrowseByDataType.Title) export class BrowseByTitlePageComponent extends BrowseByMetadataPageComponent { public constructor(protected route: ActivatedRoute, diff --git a/src/app/core/browse/browse-definition-data.service.ts b/src/app/core/browse/browse-definition-data.service.ts index 31338417ca..dd66d8fa53 100644 --- a/src/app/core/browse/browse-definition-data.service.ts +++ b/src/app/core/browse/browse-definition-data.service.ts @@ -106,6 +106,21 @@ export class BrowseDefinitionDataService { findAllByHref(href: string, findListOptions: FindListOptions = {}, useCachedVersionIfAvailable = true, reRequestOnStale = true, ...linksToFollow: FollowLinkConfig[]): Observable>> { return this.dataService.findAllByHref(href, findListOptions, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow); } + + /** + * Returns an observable of {@link RemoteData} of an object, based on its ID, with a list of + * {@link FollowLinkConfig}, to automatically resolve {@link HALLink}s of the object + * @param id ID of object we want to retrieve + * @param useCachedVersionIfAvailable If this is true, the request will only be sent if there's + * no valid cached version. Defaults to true + * @param reRequestOnStale Whether or not the request should automatically be re- + * requested after the response becomes stale + * @param linksToFollow List of {@link FollowLinkConfig} that indicate which + * {@link HALLink}s should be automatically resolved + */ + findById(id: string, useCachedVersionIfAvailable = true, reRequestOnStale = true, ...linksToFollow: FollowLinkConfig[]): Observable> { + return this.dataService.findById(id, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow); + } } /* tslint:enable:max-classes-per-file */ diff --git a/src/app/core/shared/browse-definition.model.ts b/src/app/core/shared/browse-definition.model.ts index 2c08417b6d..b5dc47cd3e 100644 --- a/src/app/core/shared/browse-definition.model.ts +++ b/src/app/core/shared/browse-definition.model.ts @@ -6,6 +6,7 @@ import { BROWSE_DEFINITION } from './browse-definition.resource-type'; import { HALLink } from './hal-link.model'; import { ResourceType } from './resource-type'; import { SortOption } from './sort-option.model'; +import { BrowseByDataType } from '../../browse-by/browse-by-switcher/browse-by-decorator'; @typedObject export class BrowseDefinition extends CacheableObject { @@ -33,6 +34,9 @@ export class BrowseDefinition extends CacheableObject { @autoserializeAs('metadata') metadataKeys: string[]; + @autoserializeAs('dataType') + dataType: BrowseByDataType; + get self(): string { return this._links.self.href; } diff --git a/src/app/navbar/navbar.component.spec.ts b/src/app/navbar/navbar.component.spec.ts index cbe6738241..5aa2bf1786 100644 --- a/src/app/navbar/navbar.component.spec.ts +++ b/src/app/navbar/navbar.component.spec.ts @@ -13,15 +13,48 @@ import { MenuService } from '../shared/menu/menu.service'; import { MenuServiceStub } from '../shared/testing/menu-service.stub'; import { ActivatedRoute } from '@angular/router'; import { RouterTestingModule } from '@angular/router/testing'; +import { BrowseService } from '../core/browse/browse.service'; +import { createSuccessfulRemoteDataObject$ } from '../shared/remote-data.utils'; +import { buildPaginatedList } from '../core/data/paginated-list.model'; +import { BrowseDefinition } from '../core/shared/browse-definition.model'; +import { BrowseByDataType } from '../browse-by/browse-by-switcher/browse-by-decorator'; let comp: NavbarComponent; let fixture: ComponentFixture; describe('NavbarComponent', () => { const menuService = new MenuServiceStub(); - + let browseDefinitions; // waitForAsync beforeEach beforeEach(waitForAsync(() => { + browseDefinitions = [ + Object.assign( + new BrowseDefinition(), { + id: 'title', + dataType: BrowseByDataType.Title, + } + ), + Object.assign( + new BrowseDefinition(), { + id: 'dateissued', + dataType: BrowseByDataType.Date, + metadataKeys: ['dc.date.issued'] + } + ), + Object.assign( + new BrowseDefinition(), { + id: 'author', + dataType: BrowseByDataType.Metadata, + } + ), + Object.assign( + new BrowseDefinition(), { + id: 'subject', + dataType: BrowseByDataType.Metadata, + } + ), + ]; + TestBed.configureTestingModule({ imports: [ TranslateModule.forRoot(), @@ -33,7 +66,8 @@ describe('NavbarComponent', () => { Injector, { provide: MenuService, useValue: menuService }, { provide: HostWindowService, useValue: new HostWindowServiceStub(800) }, - { provide: ActivatedRoute, useValue: {} } + { provide: ActivatedRoute, useValue: {} }, + { provide: BrowseService, useValue: { getBrowseDefinitions: createSuccessfulRemoteDataObject$(buildPaginatedList(undefined, browseDefinitions)) } } ], schemas: [NO_ERRORS_SCHEMA] }) 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 5dec1e27f8..08f7ec67ee 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 @@ -2,8 +2,6 @@ import { Component, Input, OnInit } from '@angular/core'; import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; import { ActivatedRoute, Params, Router } from '@angular/router'; -import { BrowseByTypeConfig } from '../../../config/browse-by-type-config.interface'; -import { environment } from '../../../environments/environment'; import { getCommunityPageRoute } from '../../community-page/community-page-routing-paths'; import { getCollectionPageRoute } from '../../collection-page/collection-page-routing-paths'; import { getFirstCompletedRemoteData } from '../../core/shared/operators'; @@ -34,10 +32,6 @@ export class ComcolPageBrowseByComponent implements OnInit { */ @Input() id: string; @Input() contentType: string; - /** - * List of currently active browse configurations - */ - types: BrowseByTypeConfig[]; allOptions: ComColPageNavOption[]; @@ -46,7 +40,7 @@ export class ComcolPageBrowseByComponent implements OnInit { constructor( private route: ActivatedRoute, private router: Router, - public browseService: BrowseService + private browseService: BrowseService ) { } @@ -62,23 +56,23 @@ export class ComcolPageBrowseByComponent implements OnInit { routerLink: `/browse/${config.id}`, params: { scope: this.id } })); + + if (this.contentType === 'collection') { + this.allOptions = [{ + id: this.id, + label: 'collection.page.browse.recent.head', + routerLink: getCollectionPageRoute(this.id) + }, ...this.allOptions]; + } else if (this.contentType === 'community') { + this.allOptions = [{ + id: this.id, + label: 'community.all-lists.head', + routerLink: getCommunityPageRoute(this.id) + }, ...this.allOptions]; + } } }); - if (this.contentType === 'collection') { - this.allOptions = [{ - id: this.id, - label: 'collection.page.browse.recent.head', - routerLink: getCollectionPageRoute(this.id) - }, ...this.allOptions]; - } else if (this.contentType === 'community') { - this.allOptions = [{ - id: this.id, - label: 'community.all-lists.head', - routerLink: getCommunityPageRoute(this.id) - }, ...this.allOptions]; - } - this.currentOptionId$ = this.route.params.pipe( map((params: Params) => params.id) ); diff --git a/src/config/browse-by-config.interface.ts b/src/config/browse-by-config.interface.ts index 719e127b4b..6adba66b92 100644 --- a/src/config/browse-by-config.interface.ts +++ b/src/config/browse-by-config.interface.ts @@ -1,5 +1,4 @@ import { Config } from './config.interface'; -import { BrowseByTypeConfig } from './browse-by-type-config.interface'; /** * Config that determines how the dropdown list of years are created for browse-by-date components @@ -19,9 +18,4 @@ export interface BrowseByConfig extends Config { * The absolute lowest year to display in the dropdown when no lowest date can be found for all items */ defaultLowerLimit: number; - - /** - * A list of all the active Browse-By pages - */ - types: BrowseByTypeConfig[]; } diff --git a/src/config/browse-by-type-config.interface.ts b/src/config/browse-by-type-config.interface.ts deleted file mode 100644 index f15846c210..0000000000 --- a/src/config/browse-by-type-config.interface.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { Config } from './config.interface'; -import { BrowseByType } from '../app/browse-by/browse-by-switcher/browse-by-decorator'; - -/** - * Config used for rendering Browse-By pages and links - */ -export interface BrowseByTypeConfig extends Config { - /** - * The browse id used for fetching browse data from the rest api - * e.g. author - */ - id: string; - - /** - * The type of Browse-By page to render - */ - type: BrowseByType | string; - - /** - * The metadata field to use for rendering starts-with options (only necessary when type is set to BrowseByType.Date) - */ - metadataField?: string; -} diff --git a/src/config/global-config.interface.ts b/src/config/global-config.interface.ts index d46822eb61..f8c226bdb1 100644 --- a/src/config/global-config.interface.ts +++ b/src/config/global-config.interface.ts @@ -6,13 +6,13 @@ import { INotificationBoardOptions } from './notifications-config.interfaces'; import { SubmissionConfig } from './submission-config.interface'; import { FormConfig } from './form-config.interfaces'; import { LangConfig } from './lang-config.interface'; -import { BrowseByConfig } from './browse-by-config.interface'; import { ItemPageConfig } from './item-page-config.interface'; import { CollectionPageConfig } from './collection-page-config.interface'; import { ThemeConfig } from './theme.model'; import { AuthConfig } from './auth-config.interfaces'; import { UIServerConfig } from './ui-server-config.interface'; import { MediaViewerConfig } from './media-viewer-config.interface'; +import { BrowseByConfig } from './browse-by-config.interface'; export interface GlobalConfig extends Config { ui: UIServerConfig; diff --git a/src/environments/environment.common.ts b/src/environments/environment.common.ts index b1cbd699a3..1441accf04 100644 --- a/src/environments/environment.common.ts +++ b/src/environments/environment.common.ts @@ -1,6 +1,5 @@ import { GlobalConfig } from '../config/global-config.interface'; import { NotificationAnimationsType } from '../app/shared/notifications/models/notification-animations-type'; -import { BrowseByType } from '../app/browse-by/browse-by-switcher/browse-by-decorator'; import { RestRequestMethod } from '../app/core/data/rest-request-method'; export const environment: GlobalConfig = { @@ -207,32 +206,6 @@ export const environment: GlobalConfig = { fiveYearLimit: 30, // The absolute lowest year to display in the dropdown (only used when no lowest date can be found for all items) defaultLowerLimit: 1900, - // List of all the active Browse-By types - // Adding a type will activate their Browse-By page and add them to the global navigation menu, - // as well as community and collection pages - // Allowed fields and their purpose: - // id: The browse id to use for fetching info from the rest api - // type: The type of Browse-By page to display - // metadataField: The metadata-field used to create starts-with options (only necessary when the type is set to 'date') - types: [ - { - id: 'title', - type: BrowseByType.Title, - }, - { - id: 'dateissued', - type: BrowseByType.Date, - metadataField: 'dc.date.issued' - }, - { - id: 'author', - type: BrowseByType.Metadata - }, - { - id: 'subject', - type: BrowseByType.Metadata - } - ] }, item: { edit: { diff --git a/src/environments/mock-environment.ts b/src/environments/mock-environment.ts index 824c8c8a83..f21de7fae3 100644 --- a/src/environments/mock-environment.ts +++ b/src/environments/mock-environment.ts @@ -1,5 +1,5 @@ // This configuration is only used for unit tests, end-to-end tests use environment.prod.ts -import { BrowseByType } from '../app/browse-by/browse-by-switcher/browse-by-decorator'; +import { BrowseByDataType } from '../app/browse-by/browse-by-switcher/browse-by-decorator'; import { RestRequestMethod } from '../app/core/data/rest-request-method'; import { NotificationAnimationsType } from '../app/shared/notifications/models/notification-animations-type'; import { GlobalConfig } from '../config/global-config.interface'; @@ -169,32 +169,6 @@ export const environment: Partial = { fiveYearLimit: 30, // The absolute lowest year to display in the dropdown (only used when no lowest date can be found for all items) defaultLowerLimit: 1900, - // List of all the active Browse-By types - // Adding a type will activate their Browse-By page and add them to the global navigation menu, - // as well as community and collection pages - // Allowed fields and their purpose: - // id: The browse id to use for fetching info from the rest api - // type: The type of Browse-By page to display - // metadataField: The metadata-field used to create starts-with options (only necessary when the type is set to 'date') - types: [ - { - id: 'title', - type: BrowseByType.Title, - }, - { - id: 'dateissued', - type: BrowseByType.Date, - metadataField: 'dc.date.issued' - }, - { - id: 'author', - type: BrowseByType.Metadata - }, - { - id: 'subject', - type: BrowseByType.Metadata - } - ] }, item: { edit: {