mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 10:04:11 +00:00
Merge branch 'w2p-101127_browse-by-controlled-vocabulary' into w2p-101127_browse-by-controlled-vocabulary-7.6.0-next
Conflicts: src/app/browse-by/browse-by-routing.module.ts src/app/browse-by/browse-by.module.ts src/app/core/browse/browse-definition-data.service.ts src/app/core/core.module.ts
This commit is contained in:
@@ -2,8 +2,8 @@ import { first } from 'rxjs/operators';
|
||||
import { BrowseByGuard } from './browse-by-guard';
|
||||
import { of as observableOf } from 'rxjs';
|
||||
import { createSuccessfulRemoteDataObject$ } from '../shared/remote-data.utils';
|
||||
import { BrowseDefinition } from '../core/shared/browse-definition.model';
|
||||
import { BrowseByDataType } from './browse-by-switcher/browse-by-decorator';
|
||||
import { ValueListBrowseDefinition } from '../core/shared/value-list-browse-definition.model';
|
||||
|
||||
describe('BrowseByGuard', () => {
|
||||
describe('canActivate', () => {
|
||||
@@ -18,7 +18,7 @@ describe('BrowseByGuard', () => {
|
||||
const id = 'author';
|
||||
const scope = '1234-65487-12354-1235';
|
||||
const value = 'Filter';
|
||||
const browseDefinition = Object.assign(new BrowseDefinition(), { type: BrowseByDataType.Metadata, metadataKeys: ['dc.contributor'] });
|
||||
const browseDefinition = Object.assign(new ValueListBrowseDefinition(), { type: BrowseByDataType.Metadata, metadataKeys: ['dc.contributor'] });
|
||||
|
||||
beforeEach(() => {
|
||||
dsoService = {
|
||||
|
@@ -5,8 +5,6 @@ import { BrowseByDSOBreadcrumbResolver } from './browse-by-dso-breadcrumb.resolv
|
||||
import { BrowseByI18nBreadcrumbResolver } from './browse-by-i18n-breadcrumb.resolver';
|
||||
import { ThemedBrowseBySwitcherComponent } from './browse-by-switcher/themed-browse-by-switcher.component';
|
||||
import { DSOEditMenuResolver } from '../shared/dso-page/dso-edit-menu.resolver';
|
||||
import { BrowseByTaxonomyPageComponent } from './browse-by-taxonomy-page/browse-by-taxonomy-page.component';
|
||||
import { I18nBreadcrumbResolver } from '../core/breadcrumbs/i18n-breadcrumb.resolver';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
@@ -18,13 +16,6 @@ import { I18nBreadcrumbResolver } from '../core/breadcrumbs/i18n-breadcrumb.reso
|
||||
menu: DSOEditMenuResolver
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'srsc',
|
||||
component: BrowseByTaxonomyPageComponent,
|
||||
canActivate: [BrowseByGuard],
|
||||
resolve: { breadcrumb: I18nBreadcrumbResolver },
|
||||
data: { title: 'browse.title.page', breadcrumbKey: 'browse.metadata.srsc' }
|
||||
},
|
||||
{
|
||||
path: ':id',
|
||||
component: ThemedBrowseBySwitcherComponent,
|
||||
|
@@ -26,7 +26,7 @@ const map = new Map();
|
||||
* @param browseByType The type of page
|
||||
* @param theme The optional theme for the component
|
||||
*/
|
||||
export function rendersBrowseBy(browseByType: BrowseByDataType, theme = DEFAULT_THEME) {
|
||||
export function rendersBrowseBy(browseByType: string, theme = DEFAULT_THEME) {
|
||||
return function decorator(component: any) {
|
||||
if (hasNoValue(map.get(browseByType))) {
|
||||
map.set(browseByType, new Map());
|
||||
|
@@ -3,9 +3,11 @@ import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { BROWSE_BY_COMPONENT_FACTORY, BrowseByDataType } from './browse-by-decorator';
|
||||
import { BrowseDefinition } from '../../core/shared/browse-definition.model';
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
import { ThemeService } from '../../shared/theme-support/theme.service';
|
||||
import { FlatBrowseDefinition } from '../../core/shared/flat-browse-definition.model';
|
||||
import { ValueListBrowseDefinition } from '../../core/shared/value-list-browse-definition.model';
|
||||
import { NonHierarchicalBrowseDefinition } from '../../core/shared/non-hierarchical-browse-definition';
|
||||
|
||||
describe('BrowseBySwitcherComponent', () => {
|
||||
let comp: BrowseBySwitcherComponent;
|
||||
@@ -13,33 +15,33 @@ describe('BrowseBySwitcherComponent', () => {
|
||||
|
||||
const types = [
|
||||
Object.assign(
|
||||
new BrowseDefinition(), {
|
||||
new FlatBrowseDefinition(), {
|
||||
id: 'title',
|
||||
dataType: BrowseByDataType.Title,
|
||||
}
|
||||
),
|
||||
Object.assign(
|
||||
new BrowseDefinition(), {
|
||||
new FlatBrowseDefinition(), {
|
||||
id: 'dateissued',
|
||||
dataType: BrowseByDataType.Date,
|
||||
metadataKeys: ['dc.date.issued']
|
||||
}
|
||||
),
|
||||
Object.assign(
|
||||
new BrowseDefinition(), {
|
||||
new ValueListBrowseDefinition(), {
|
||||
id: 'author',
|
||||
dataType: BrowseByDataType.Metadata,
|
||||
}
|
||||
),
|
||||
Object.assign(
|
||||
new BrowseDefinition(), {
|
||||
new ValueListBrowseDefinition(), {
|
||||
id: 'subject',
|
||||
dataType: BrowseByDataType.Metadata,
|
||||
}
|
||||
),
|
||||
];
|
||||
|
||||
const data = new BehaviorSubject(createDataWithBrowseDefinition(new BrowseDefinition()));
|
||||
const data = new BehaviorSubject(createDataWithBrowseDefinition(new FlatBrowseDefinition()));
|
||||
|
||||
const activatedRouteStub = {
|
||||
data
|
||||
@@ -70,7 +72,7 @@ describe('BrowseBySwitcherComponent', () => {
|
||||
comp = fixture.componentInstance;
|
||||
}));
|
||||
|
||||
types.forEach((type: BrowseDefinition) => {
|
||||
types.forEach((type: NonHierarchicalBrowseDefinition) => {
|
||||
describe(`when switching to a browse-by page for "${type.id}"`, () => {
|
||||
beforeEach(() => {
|
||||
data.next(createDataWithBrowseDefinition(type));
|
||||
|
@@ -31,7 +31,7 @@ export class BrowseBySwitcherComponent implements OnInit {
|
||||
*/
|
||||
ngOnInit(): void {
|
||||
this.browseByComponent = this.route.data.pipe(
|
||||
map((data: { browseDefinition: BrowseDefinition }) => this.getComponentByBrowseByType(data.browseDefinition.dataType, this.themeService.getThemeName()))
|
||||
map((data: { browseDefinition: BrowseDefinition }) => this.getComponentByBrowseByType(data.browseDefinition.getRenderType(), this.themeService.getThemeName()))
|
||||
);
|
||||
}
|
||||
|
||||
|
@@ -6,5 +6,5 @@
|
||||
(deselect)="onDeselect($event)">
|
||||
</ds-vocabulary-treeview>
|
||||
</div>
|
||||
<a class="btn btn-primary" [routerLink]="['/search']" [queryParams]="{ 'f.subject': filterValues }">{{ 'browse.taxonomy.button' | translate }}</a>
|
||||
<a class="btn btn-primary" [routerLink]="['/search']" [queryParams]="queryParams">{{ 'browse.taxonomy.button' | translate }}</a>
|
||||
</div>
|
||||
|
@@ -4,17 +4,36 @@ import { BrowseByTaxonomyPageComponent } from './browse-by-taxonomy-page.compone
|
||||
import { VocabularyEntryDetail } from '../../core/submission/vocabularies/models/vocabulary-entry-detail.model';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
import { createDataWithBrowseDefinition } from '../browse-by-switcher/browse-by-switcher.component.spec';
|
||||
import { HierarchicalBrowseDefinition } from '../../core/shared/hierarchical-browse-definition.model';
|
||||
import { ThemeService } from '../../shared/theme-support/theme.service';
|
||||
|
||||
describe('BrowseByTaxonomyPageComponent', () => {
|
||||
let component: BrowseByTaxonomyPageComponent;
|
||||
let fixture: ComponentFixture<BrowseByTaxonomyPageComponent>;
|
||||
let themeService: ThemeService;
|
||||
let detail1: VocabularyEntryDetail;
|
||||
let detail2: VocabularyEntryDetail;
|
||||
|
||||
const data = new BehaviorSubject(createDataWithBrowseDefinition(new HierarchicalBrowseDefinition()));
|
||||
const activatedRouteStub = {
|
||||
data
|
||||
};
|
||||
|
||||
beforeEach(async () => {
|
||||
themeService = jasmine.createSpyObj('themeService', {
|
||||
getThemeName: 'dspace',
|
||||
});
|
||||
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [ TranslateModule.forRoot() ],
|
||||
declarations: [ BrowseByTaxonomyPageComponent ],
|
||||
providers: [
|
||||
{ provide: ActivatedRoute, useValue: activatedRouteStub },
|
||||
{ provide: ThemeService, useValue: themeService },
|
||||
],
|
||||
schemas: [NO_ERRORS_SCHEMA]
|
||||
})
|
||||
.compileComponents();
|
||||
|
@@ -1,6 +1,14 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { Component, OnInit, Inject, OnDestroy } from '@angular/core';
|
||||
import { VocabularyOptions } from '../../core/submission/vocabularies/models/vocabulary-options.model';
|
||||
import { VocabularyEntryDetail } from '../../core/submission/vocabularies/models/vocabulary-entry-detail.model';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { Observable, Subscription } from 'rxjs';
|
||||
import { BrowseDefinition } from '../../core/shared/browse-definition.model';
|
||||
import { GenericConstructor } from '../../core/shared/generic-constructor';
|
||||
import { BROWSE_BY_COMPONENT_FACTORY } from '../browse-by-switcher/browse-by-decorator';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { ThemeService } from 'src/app/shared/theme-support/theme.service';
|
||||
import { HierarchicalBrowseDefinition } from '../../core/shared/hierarchical-browse-definition.model';
|
||||
|
||||
@Component({
|
||||
selector: 'ds-browse-by-taxonomy-page',
|
||||
@@ -10,7 +18,7 @@ import { VocabularyEntryDetail } from '../../core/submission/vocabularies/models
|
||||
/**
|
||||
* Component for browsing items by metadata in a hierarchical controlled vocabulary
|
||||
*/
|
||||
export class BrowseByTaxonomyPageComponent implements OnInit {
|
||||
export class BrowseByTaxonomyPageComponent implements OnInit, OnDestroy {
|
||||
|
||||
/**
|
||||
* The {@link VocabularyOptions} object
|
||||
@@ -27,8 +35,48 @@ export class BrowseByTaxonomyPageComponent implements OnInit {
|
||||
*/
|
||||
filterValues: string[];
|
||||
|
||||
ngOnInit() {
|
||||
this.vocabularyOptions = { name: 'srsc', closed: true };
|
||||
/**
|
||||
* The facet the use when filtering
|
||||
*/
|
||||
facetType: string;
|
||||
|
||||
/**
|
||||
* The used vocabulary
|
||||
*/
|
||||
vocabularyName: string;
|
||||
|
||||
/**
|
||||
* The parameters used in the URL
|
||||
*/
|
||||
queryParams: any;
|
||||
|
||||
/**
|
||||
* Resolved browse-by component
|
||||
*/
|
||||
browseByComponent: Observable<any>;
|
||||
|
||||
/**
|
||||
* Subscriptions to track
|
||||
*/
|
||||
browseByComponentSubs: Subscription[] = [];
|
||||
|
||||
public constructor( protected route: ActivatedRoute,
|
||||
protected themeService: ThemeService,
|
||||
@Inject(BROWSE_BY_COMPONENT_FACTORY) private getComponentByBrowseByType: (browseByType, theme) => GenericConstructor<any>) {
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.browseByComponent = this.route.data.pipe(
|
||||
map((data: { browseDefinition: BrowseDefinition }) => {
|
||||
this.getComponentByBrowseByType(data.browseDefinition.getRenderType(), this.themeService.getThemeName());
|
||||
return data.browseDefinition;
|
||||
})
|
||||
);
|
||||
this.browseByComponentSubs.push(this.browseByComponent.subscribe((browseDefinition: HierarchicalBrowseDefinition) => {
|
||||
this.facetType = browseDefinition.facetType;
|
||||
this.vocabularyName = browseDefinition.vocabulary;
|
||||
this.vocabularyOptions = { name: this.vocabularyName, closed: true };
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -41,10 +89,30 @@ export class BrowseByTaxonomyPageComponent implements OnInit {
|
||||
this.selectedItems.push(detail);
|
||||
this.filterValues = this.selectedItems
|
||||
.map((item: VocabularyEntryDetail) => `${item.value},equals`);
|
||||
this.updateQueryParams();
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes detail from selectedItems and filterValues.
|
||||
*
|
||||
* @param detail VocabularyEntryDetail to be removed
|
||||
*/
|
||||
onDeselect(detail: VocabularyEntryDetail): void {
|
||||
this.selectedItems = this.selectedItems.filter((entry: VocabularyEntryDetail) => { return entry !== detail; });
|
||||
this.filterValues = this.filterValues.filter((value: string) => { return value !== `${detail.value},equals`; });
|
||||
this.updateQueryParams();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates queryParams based on the current facetType and filterValues.
|
||||
*/
|
||||
private updateQueryParams(): void {
|
||||
this.queryParams = {
|
||||
['f.' + this.facetType]: this.filterValues
|
||||
};
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.browseByComponentSubs.forEach((sub: Subscription) => sub.unsubscribe());
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,28 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { ThemedComponent } from '../../shared/theme-support/themed.component';
|
||||
import { rendersBrowseBy } from '../browse-by-switcher/browse-by-decorator';
|
||||
import { BrowseByTaxonomyPageComponent } from './browse-by-taxonomy-page.component';
|
||||
|
||||
@Component({
|
||||
selector: 'ds-themed-browse-by-taxonomy-page',
|
||||
templateUrl: '../../shared/theme-support/themed.component.html',
|
||||
styleUrls: []
|
||||
})
|
||||
/**
|
||||
* Themed wrapper for BrowseByTaxonomyPageComponent
|
||||
*/
|
||||
@rendersBrowseBy('hierarchy')
|
||||
export class ThemedBrowseByTaxonomyPageComponent extends ThemedComponent<BrowseByTaxonomyPageComponent>{
|
||||
|
||||
protected getComponentName(): string {
|
||||
return 'BrowseByTaxonomyPageComponent';
|
||||
}
|
||||
|
||||
protected importThemedComponent(themeName: string): Promise<any> {
|
||||
return import(`../../../themes/${themeName}/app/browse-by/browse-by-taxonomy-page/browse-by-taxonomy-page.component`);
|
||||
}
|
||||
|
||||
protected importUnthemedComponent(): Promise<any> {
|
||||
return import(`./browse-by-taxonomy-page.component`);
|
||||
}
|
||||
}
|
@@ -10,6 +10,7 @@ import { ComcolModule } from '../shared/comcol/comcol.module';
|
||||
import { ThemedBrowseByMetadataPageComponent } from './browse-by-metadata-page/themed-browse-by-metadata-page.component';
|
||||
import { ThemedBrowseByDatePageComponent } from './browse-by-date-page/themed-browse-by-date-page.component';
|
||||
import { ThemedBrowseByTitlePageComponent } from './browse-by-title-page/themed-browse-by-title-page.component';
|
||||
import { ThemedBrowseByTaxonomyPageComponent } from './browse-by-taxonomy-page/themed-browse-by-taxonomy-page.component';
|
||||
import { SharedBrowseByModule } from '../shared/browse-by/shared-browse-by.module';
|
||||
import { DsoPageModule } from '../shared/dso-page/dso-page.module';
|
||||
import { FormModule } from '../shared/form/form.module';
|
||||
@@ -19,11 +20,12 @@ const ENTRY_COMPONENTS = [
|
||||
BrowseByTitlePageComponent,
|
||||
BrowseByMetadataPageComponent,
|
||||
BrowseByDatePageComponent,
|
||||
BrowseByTaxonomyPageComponent,
|
||||
|
||||
ThemedBrowseByMetadataPageComponent,
|
||||
ThemedBrowseByDatePageComponent,
|
||||
ThemedBrowseByTitlePageComponent,
|
||||
|
||||
ThemedBrowseByTaxonomyPageComponent,
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
@@ -37,7 +39,6 @@ const ENTRY_COMPONENTS = [
|
||||
declarations: [
|
||||
BrowseBySwitcherComponent,
|
||||
ThemedBrowseBySwitcherComponent,
|
||||
BrowseByTaxonomyPageComponent,
|
||||
...ENTRY_COMPONENTS
|
||||
],
|
||||
exports: [
|
||||
|
@@ -1,20 +1,60 @@
|
||||
// eslint-disable-next-line max-classes-per-file
|
||||
import { Injectable } from '@angular/core';
|
||||
import { BROWSE_DEFINITION } from '../shared/browse-definition.resource-type';
|
||||
import { BrowseDefinition } from '../shared/browse-definition.model';
|
||||
import { RequestService } from '../data/request.service';
|
||||
import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service';
|
||||
import { ObjectCacheService } from '../cache/object-cache.service';
|
||||
import { HALEndpointService } from '../shared/hal-endpoint.service';
|
||||
import { FollowLinkConfig } from '../../shared/utils/follow-link-config.model';
|
||||
import { Observable } from 'rxjs';
|
||||
import { Observable, of as observableOf } from 'rxjs';
|
||||
import { RemoteData } from '../data/remote-data';
|
||||
import { PaginatedList } from '../data/paginated-list.model';
|
||||
import { FindListOptions } from '../data/find-list-options.model';
|
||||
import { IdentifiableDataService } from '../data/base/identifiable-data.service';
|
||||
import { FindAllData, FindAllDataImpl } from '../data/base/find-all-data';
|
||||
import { dataService } from '../data/base/data-service.decorator';
|
||||
import { isNotEmpty, isNotEmptyOperator, hasValue } from '../../shared/empty.util';
|
||||
import { take } from 'rxjs/operators';
|
||||
import { BrowseDefinitionRestRequest } from '../data/request.models';
|
||||
import { RequestParam } from '../cache/models/request-param.model';
|
||||
import { SearchData, SearchDataImpl } from '../data/base/search-data';
|
||||
import { BrowseDefinition } from '../shared/browse-definition.model';
|
||||
|
||||
/**
|
||||
* Create a GET request for the given href, and send it.
|
||||
* Use a GET request specific for BrowseDefinitions.
|
||||
*/
|
||||
export const createAndSendBrowseDefinitionGetRequest = (requestService: RequestService,
|
||||
responseMsToLive: number,
|
||||
href$: string | Observable<string>,
|
||||
useCachedVersionIfAvailable: boolean = true): void => {
|
||||
if (isNotEmpty(href$)) {
|
||||
if (typeof href$ === 'string') {
|
||||
href$ = observableOf(href$);
|
||||
}
|
||||
|
||||
href$.pipe(
|
||||
isNotEmptyOperator(),
|
||||
take(1)
|
||||
).subscribe((href: string) => {
|
||||
const requestId = requestService.generateRequestId();
|
||||
const request = new BrowseDefinitionRestRequest(requestId, href);
|
||||
if (hasValue(responseMsToLive)) {
|
||||
request.responseMsToLive = responseMsToLive;
|
||||
}
|
||||
requestService.send(request, useCachedVersionIfAvailable);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Custom extension of {@link FindAllDataImpl} to be able to send BrowseDefinitionRestRequests
|
||||
*/
|
||||
class BrowseDefinitionFindAllDataImpl extends FindAllDataImpl<BrowseDefinition> {
|
||||
createAndSendGetRequest(href$: string | Observable<string>, useCachedVersionIfAvailable: boolean = true) {
|
||||
createAndSendBrowseDefinitionGetRequest(this.requestService, this.responseMsToLive, href$, useCachedVersionIfAvailable);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Data service responsible for retrieving browse definitions from the REST server
|
||||
@@ -24,7 +64,7 @@ import { SearchData, SearchDataImpl } from '../data/base/search-data';
|
||||
})
|
||||
@dataService(BROWSE_DEFINITION)
|
||||
export class BrowseDefinitionDataService extends IdentifiableDataService<BrowseDefinition> implements FindAllData<BrowseDefinition>, SearchData<BrowseDefinition> {
|
||||
private findAllData: FindAllDataImpl<BrowseDefinition>;
|
||||
private findAllData: BrowseDefinitionFindAllDataImpl;
|
||||
private searchData: SearchDataImpl<BrowseDefinition>;
|
||||
|
||||
constructor(
|
||||
@@ -35,7 +75,7 @@ export class BrowseDefinitionDataService extends IdentifiableDataService<BrowseD
|
||||
) {
|
||||
super('browses', requestService, rdbService, objectCache, halService);
|
||||
this.searchData = new SearchDataImpl(this.linkPath, requestService, rdbService, objectCache, halService, this.responseMsToLive);
|
||||
this.findAllData = new FindAllDataImpl(this.linkPath, requestService, rdbService, objectCache, halService, this.responseMsToLive);
|
||||
this.findAllData = new BrowseDefinitionFindAllDataImpl(this.linkPath, requestService, rdbService, objectCache, halService, this.responseMsToLive);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -121,5 +161,8 @@ export class BrowseDefinitionDataService extends IdentifiableDataService<BrowseD
|
||||
);
|
||||
}
|
||||
|
||||
createAndSendGetRequest(href$: string | Observable<string>, useCachedVersionIfAvailable: boolean = true) {
|
||||
createAndSendBrowseDefinitionGetRequest(this.requestService, this.responseMsToLive, href$, useCachedVersionIfAvailable);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -6,13 +6,15 @@ import { getMockRequestService } from '../../shared/mocks/request.service.mock';
|
||||
import { HALEndpointServiceStub } from '../../shared/testing/hal-endpoint-service.stub';
|
||||
import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service';
|
||||
import { RequestService } from '../data/request.service';
|
||||
import { BrowseDefinition } from '../shared/browse-definition.model';
|
||||
import { BrowseEntrySearchOptions } from './browse-entry-search-options.model';
|
||||
import { BrowseService } from './browse.service';
|
||||
import { createSuccessfulRemoteDataObject, createSuccessfulRemoteDataObject$ } from '../../shared/remote-data.utils';
|
||||
import { createPaginatedList, getFirstUsedArgumentOfSpyMethod } from '../../shared/testing/utils.test';
|
||||
import { getMockHrefOnlyDataService } from '../../shared/mocks/href-only-data.service.mock';
|
||||
import { RequestEntry } from '../data/request-entry.model';
|
||||
import { FlatBrowseDefinition } from '../shared/flat-browse-definition.model';
|
||||
import { ValueListBrowseDefinition } from '../shared/value-list-browse-definition.model';
|
||||
import { HierarchicalBrowseDefinition } from '../shared/hierarchical-browse-definition.model';
|
||||
|
||||
describe('BrowseService', () => {
|
||||
let scheduler: TestScheduler;
|
||||
@@ -23,7 +25,7 @@ describe('BrowseService', () => {
|
||||
const browsesEndpointURL = 'https://rest.api/browses';
|
||||
const halService: any = new HALEndpointServiceStub(browsesEndpointURL);
|
||||
const browseDefinitions = [
|
||||
Object.assign(new BrowseDefinition(), {
|
||||
Object.assign(new FlatBrowseDefinition(), {
|
||||
id: 'date',
|
||||
metadataBrowse: false,
|
||||
sortOptions: [
|
||||
@@ -50,7 +52,7 @@ describe('BrowseService', () => {
|
||||
items: { href: 'https://rest.api/discover/browses/dateissued/items' }
|
||||
}
|
||||
}),
|
||||
Object.assign(new BrowseDefinition(), {
|
||||
Object.assign(new ValueListBrowseDefinition(), {
|
||||
id: 'author',
|
||||
metadataBrowse: true,
|
||||
sortOptions: [
|
||||
@@ -78,7 +80,23 @@ describe('BrowseService', () => {
|
||||
entries: { href: 'https://rest.api/discover/browses/author/entries' },
|
||||
items: { href: 'https://rest.api/discover/browses/author/items' }
|
||||
}
|
||||
})
|
||||
}),
|
||||
Object.assign(new HierarchicalBrowseDefinition(), {
|
||||
id: 'srsc',
|
||||
browseType: 'hierarchicalBrowse',
|
||||
facetType: 'subject',
|
||||
vocabulary: 'srsc',
|
||||
type: 'browse',
|
||||
metadata: [
|
||||
'dc.subject'
|
||||
],
|
||||
_links: {
|
||||
vocabulary: { 'href': 'https://rest.api/submission/vocabularies/srsc/' },
|
||||
items: { 'href': 'https://rest.api/discover/browses/srsc/items' },
|
||||
entries: { 'href': 'https://rest.api/discover/browses/srsc/entries' },
|
||||
self: { 'href': 'https://rest.api/discover/browses/srsc' }
|
||||
}
|
||||
}),
|
||||
];
|
||||
|
||||
let browseDefinitionDataService;
|
||||
|
@@ -7,6 +7,7 @@ import { PaginatedList } from '../data/paginated-list.model';
|
||||
import { RemoteData } from '../data/remote-data';
|
||||
import { RequestService } from '../data/request.service';
|
||||
import { BrowseDefinition } from '../shared/browse-definition.model';
|
||||
import { FlatBrowseDefinition } from '../shared/flat-browse-definition.model';
|
||||
import { BrowseEntry } from '../shared/browse-entry.model';
|
||||
import { HALEndpointService } from '../shared/hal-endpoint.service';
|
||||
import { Item } from '../shared/item.model';
|
||||
@@ -240,7 +241,12 @@ export class BrowseService {
|
||||
getPaginatedListPayload(),
|
||||
map((browseDefinitions: BrowseDefinition[]) => browseDefinitions
|
||||
.find((def: BrowseDefinition) => {
|
||||
const matchingKeys = def.metadataKeys.find((key: string) => searchKeyArray.indexOf(key) >= 0);
|
||||
let matchingKeys = '';
|
||||
|
||||
if (Array.isArray((def as FlatBrowseDefinition).metadataKeys)) {
|
||||
matchingKeys = (def as FlatBrowseDefinition).metadataKeys.find((key: string) => searchKeyArray.indexOf(key) >= 0);
|
||||
}
|
||||
|
||||
return isNotEmpty(matchingKeys);
|
||||
})
|
||||
),
|
||||
|
@@ -177,6 +177,10 @@ import { IdentifierData } from '../shared/object-list/identifier-data/identifier
|
||||
import { Subscription } from '../shared/subscriptions/models/subscription.model';
|
||||
import { SupervisionOrderDataService } from './supervision-order/supervision-order-data.service';
|
||||
import { ItemRequest } from './shared/item-request.model';
|
||||
import { HierarchicalBrowseDefinition } from './shared/hierarchical-browse-definition.model';
|
||||
import { FlatBrowseDefinition } from './shared/flat-browse-definition.model';
|
||||
import { ValueListBrowseDefinition } from './shared/value-list-browse-definition.model';
|
||||
import { NonHierarchicalBrowseDefinition } from './shared/non-hierarchical-browse-definition';
|
||||
|
||||
/**
|
||||
* When not in production, endpoint responses can be mocked for testing purposes
|
||||
@@ -333,6 +337,10 @@ export const models =
|
||||
AuthStatus,
|
||||
BrowseEntry,
|
||||
BrowseDefinition,
|
||||
NonHierarchicalBrowseDefinition,
|
||||
FlatBrowseDefinition,
|
||||
ValueListBrowseDefinition,
|
||||
HierarchicalBrowseDefinition,
|
||||
ClaimedTask,
|
||||
TaskObject,
|
||||
PoolTask,
|
||||
|
64
src/app/core/data/browse-response-parsing.service.spec.ts
Normal file
64
src/app/core/data/browse-response-parsing.service.spec.ts
Normal file
@@ -0,0 +1,64 @@
|
||||
import { getMockObjectCacheService } from '../../shared/mocks/object-cache.service.mock';
|
||||
import { BrowseResponseParsingService } from './browse-response-parsing.service';
|
||||
import { ObjectCacheService } from '../cache/object-cache.service';
|
||||
import { HIERARCHICAL_BROWSE_DEFINITION } from '../shared/hierarchical-browse-definition.resource-type';
|
||||
import { FLAT_BROWSE_DEFINITION } from '../shared/flat-browse-definition.resource-type';
|
||||
import { VALUE_LIST_BROWSE_DEFINITION } from '../shared/value-list-browse-definition.resource-type';
|
||||
|
||||
class TestService extends BrowseResponseParsingService {
|
||||
constructor(protected objectCache: ObjectCacheService) {
|
||||
super(objectCache);
|
||||
}
|
||||
|
||||
// Overwrite method to make it public for testing
|
||||
public deserialize<ObjectDomain>(obj): any {
|
||||
return super.deserialize(obj);
|
||||
}
|
||||
}
|
||||
|
||||
describe('BrowseResponseParsingService', () => {
|
||||
let service: TestService;
|
||||
|
||||
|
||||
beforeEach(() => {
|
||||
service = new TestService(getMockObjectCacheService());
|
||||
});
|
||||
|
||||
describe('', () => {
|
||||
const mockFlatBrowse = {
|
||||
id: 'title',
|
||||
browseType: 'flatBrowse',
|
||||
type: 'browse',
|
||||
};
|
||||
|
||||
const mockValueList = {
|
||||
id: 'author',
|
||||
browseType: 'valueList',
|
||||
type: 'browse',
|
||||
};
|
||||
|
||||
const mockHierarchicalBrowse = {
|
||||
id: 'srsc',
|
||||
browseType: 'hierarchicalBrowse',
|
||||
type: 'browse',
|
||||
};
|
||||
|
||||
it('should deserialize flatBrowses correctly', () => {
|
||||
let deserialized = service.deserialize(mockFlatBrowse);
|
||||
expect(deserialized.type).toBe(FLAT_BROWSE_DEFINITION);
|
||||
expect(deserialized.id).toBe(mockFlatBrowse.id);
|
||||
});
|
||||
|
||||
it('should deserialize valueList browses correctly', () => {
|
||||
let deserialized = service.deserialize(mockValueList);
|
||||
expect(deserialized.type).toBe(VALUE_LIST_BROWSE_DEFINITION);
|
||||
expect(deserialized.id).toBe(mockValueList.id);
|
||||
});
|
||||
|
||||
it('should deserialize hierarchicalBrowses correctly', () => {
|
||||
let deserialized = service.deserialize(mockHierarchicalBrowse);
|
||||
expect(deserialized.type).toBe(HIERARCHICAL_BROWSE_DEFINITION);
|
||||
expect(deserialized.id).toBe(mockHierarchicalBrowse.id);
|
||||
});
|
||||
});
|
||||
});
|
48
src/app/core/data/browse-response-parsing.service.ts
Normal file
48
src/app/core/data/browse-response-parsing.service.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { ObjectCacheService } from '../cache/object-cache.service';
|
||||
import { hasValue } from '../../shared/empty.util';
|
||||
import {
|
||||
HIERARCHICAL_BROWSE_DEFINITION
|
||||
} from '../shared/hierarchical-browse-definition.resource-type';
|
||||
import { FLAT_BROWSE_DEFINITION } from '../shared/flat-browse-definition.resource-type';
|
||||
import { HierarchicalBrowseDefinition } from '../shared/hierarchical-browse-definition.model';
|
||||
import { FlatBrowseDefinition } from '../shared/flat-browse-definition.model';
|
||||
import { DspaceRestResponseParsingService } from './dspace-rest-response-parsing.service';
|
||||
import { Serializer } from '../serializer';
|
||||
import { BrowseDefinition } from '../shared/browse-definition.model';
|
||||
import { BROWSE_DEFINITION } from '../shared/browse-definition.resource-type';
|
||||
import { ValueListBrowseDefinition } from '../shared/value-list-browse-definition.model';
|
||||
import { VALUE_LIST_BROWSE_DEFINITION } from '../shared/value-list-browse-definition.resource-type';
|
||||
|
||||
/**
|
||||
* A ResponseParsingService used to parse a REST API response to a BrowseDefinition object
|
||||
*/
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class BrowseResponseParsingService extends DspaceRestResponseParsingService {
|
||||
constructor(
|
||||
protected objectCache: ObjectCacheService,
|
||||
) {
|
||||
super(objectCache);
|
||||
}
|
||||
|
||||
protected deserialize<ObjectDomain>(obj): any {
|
||||
const browseType: string = obj.browseType;
|
||||
if (obj.type === BROWSE_DEFINITION.value && hasValue(browseType)) {
|
||||
let serializer: Serializer<BrowseDefinition>;
|
||||
if (browseType === HIERARCHICAL_BROWSE_DEFINITION.value) {
|
||||
serializer = new this.serializerConstructor(HierarchicalBrowseDefinition);
|
||||
} else if (browseType === FLAT_BROWSE_DEFINITION.value) {
|
||||
serializer = new this.serializerConstructor(FlatBrowseDefinition);
|
||||
} else if (browseType === VALUE_LIST_BROWSE_DEFINITION.value) {
|
||||
serializer = new this.serializerConstructor(ValueListBrowseDefinition);
|
||||
} else {
|
||||
throw new Error('An error occurred while retrieving the browse definitions.');
|
||||
}
|
||||
return serializer.deserialize(obj);
|
||||
} else {
|
||||
throw new Error('An error occurred while retrieving the browse definitions.');
|
||||
}
|
||||
}
|
||||
}
|
@@ -10,6 +10,10 @@ import { hasNoValue, hasValue } from '../../shared/empty.util';
|
||||
import { DSpaceObject } from '../shared/dspace-object.model';
|
||||
import { RestRequest } from './rest-request.model';
|
||||
|
||||
/**
|
||||
* @deprecated use DspaceRestResponseParsingService for new code, this is only left to support a
|
||||
* few legacy use cases, and should get removed eventually
|
||||
*/
|
||||
@Injectable()
|
||||
export class DSOResponseParsingService extends BaseResponseParsingService implements ResponseParsingService {
|
||||
protected toCache = true;
|
||||
|
@@ -11,6 +11,7 @@ import { TaskResponseParsingService } from '../tasks/task-response-parsing.servi
|
||||
import { ContentSourceResponseParsingService } from './content-source-response-parsing.service';
|
||||
import { RestRequestWithResponseParser } from './rest-request-with-response-parser.model';
|
||||
import { DspaceRestResponseParsingService } from './dspace-rest-response-parsing.service';
|
||||
import { BrowseResponseParsingService } from './browse-response-parsing.service';
|
||||
import { FindListOptions } from './find-list-options.model';
|
||||
|
||||
|
||||
@@ -118,6 +119,15 @@ export class PatchRequest extends DSpaceRestRequest {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class representing a BrowseDefinition HTTP Rest request object
|
||||
*/
|
||||
export class BrowseDefinitionRestRequest extends DSpaceRestRequest {
|
||||
getResponseParser(): GenericConstructor<ResponseParsingService> {
|
||||
return BrowseResponseParsingService;
|
||||
}
|
||||
}
|
||||
|
||||
export class FindListRequest extends GetRequest {
|
||||
constructor(
|
||||
uuid: string,
|
||||
|
@@ -1,50 +1,16 @@
|
||||
import { autoserialize, autoserializeAs, deserialize } from 'cerialize';
|
||||
import { typedObject } from '../cache/builders/build-decorators';
|
||||
import { excludeFromEquals } from '../utilities/equals.decorators';
|
||||
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 { autoserialize } from 'cerialize';
|
||||
import { CacheableObject } from '../cache/cacheable-object.model';
|
||||
import { BrowseByDataType } from '../../browse-by/browse-by-switcher/browse-by-decorator';
|
||||
|
||||
@typedObject
|
||||
export class BrowseDefinition extends CacheableObject {
|
||||
static type = BROWSE_DEFINITION;
|
||||
|
||||
/**
|
||||
* The object type
|
||||
/**
|
||||
* Base class for BrowseDefinition models
|
||||
*/
|
||||
@excludeFromEquals
|
||||
@autoserialize
|
||||
type: ResourceType;
|
||||
export abstract class BrowseDefinition extends CacheableObject {
|
||||
|
||||
@autoserialize
|
||||
id: string;
|
||||
|
||||
@autoserialize
|
||||
metadataBrowse: boolean;
|
||||
|
||||
@autoserialize
|
||||
sortOptions: SortOption[];
|
||||
|
||||
@autoserializeAs('order')
|
||||
defaultSortOrder: string;
|
||||
|
||||
@autoserializeAs('metadata')
|
||||
metadataKeys: string[];
|
||||
|
||||
@autoserialize
|
||||
dataType: BrowseByDataType;
|
||||
|
||||
get self(): string {
|
||||
return this._links.self.href;
|
||||
}
|
||||
|
||||
@deserialize
|
||||
_links: {
|
||||
self: HALLink;
|
||||
entries: HALLink;
|
||||
items: HALLink;
|
||||
};
|
||||
/**
|
||||
* Get the render type of the BrowseDefinition model
|
||||
*/
|
||||
abstract getRenderType(): string;
|
||||
}
|
||||
|
29
src/app/core/shared/flat-browse-definition.model.ts
Normal file
29
src/app/core/shared/flat-browse-definition.model.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { inheritSerialization } from 'cerialize';
|
||||
import { typedObject } from '../cache/builders/build-decorators';
|
||||
import { excludeFromEquals } from '../utilities/equals.decorators';
|
||||
import { FLAT_BROWSE_DEFINITION } from './flat-browse-definition.resource-type';
|
||||
import { ResourceType } from './resource-type';
|
||||
import { NonHierarchicalBrowseDefinition } from './non-hierarchical-browse-definition';
|
||||
|
||||
/**
|
||||
* BrowseDefinition model for browses of type 'flatBrowse'
|
||||
*/
|
||||
@typedObject
|
||||
@inheritSerialization(NonHierarchicalBrowseDefinition)
|
||||
export class FlatBrowseDefinition extends NonHierarchicalBrowseDefinition {
|
||||
static type = FLAT_BROWSE_DEFINITION;
|
||||
|
||||
/**
|
||||
* The object type
|
||||
*/
|
||||
@excludeFromEquals
|
||||
type: ResourceType = FLAT_BROWSE_DEFINITION;
|
||||
|
||||
get self(): string {
|
||||
return this._links.self.href;
|
||||
}
|
||||
|
||||
getRenderType(): string {
|
||||
return this.dataType;
|
||||
}
|
||||
}
|
@@ -0,0 +1,9 @@
|
||||
import { ResourceType } from './resource-type';
|
||||
|
||||
/**
|
||||
* The resource type for FlatBrowseDefinition
|
||||
*
|
||||
* Needs to be in a separate file to prevent circular
|
||||
* dependencies in webpack.
|
||||
*/
|
||||
export const FLAT_BROWSE_DEFINITION = new ResourceType('flatBrowse');
|
47
src/app/core/shared/hierarchical-browse-definition.model.ts
Normal file
47
src/app/core/shared/hierarchical-browse-definition.model.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
import { autoserialize, autoserializeAs, deserialize, inheritSerialization } from 'cerialize';
|
||||
import { typedObject } from '../cache/builders/build-decorators';
|
||||
import { excludeFromEquals } from '../utilities/equals.decorators';
|
||||
import { HIERARCHICAL_BROWSE_DEFINITION } from './hierarchical-browse-definition.resource-type';
|
||||
import { HALLink } from './hal-link.model';
|
||||
import { ResourceType } from './resource-type';
|
||||
import { BrowseDefinition } from './browse-definition.model';
|
||||
|
||||
/**
|
||||
* BrowseDefinition model for browses of type 'hierarchicalBrowse'
|
||||
*/
|
||||
@typedObject
|
||||
@inheritSerialization(BrowseDefinition)
|
||||
export class HierarchicalBrowseDefinition extends BrowseDefinition {
|
||||
static type = HIERARCHICAL_BROWSE_DEFINITION;
|
||||
|
||||
/**
|
||||
* The object type
|
||||
*/
|
||||
@excludeFromEquals
|
||||
type: ResourceType = HIERARCHICAL_BROWSE_DEFINITION;
|
||||
|
||||
@autoserialize
|
||||
facetType: string;
|
||||
|
||||
@autoserialize
|
||||
vocabulary: string;
|
||||
|
||||
@autoserializeAs('metadata')
|
||||
metadataKeys: string[];
|
||||
|
||||
get self(): string {
|
||||
return this._links.self.href;
|
||||
}
|
||||
|
||||
@deserialize
|
||||
_links: {
|
||||
self: HALLink;
|
||||
entries: HALLink;
|
||||
items: HALLink;
|
||||
vocabulary: HALLink;
|
||||
};
|
||||
|
||||
getRenderType(): string {
|
||||
return 'hierarchy';
|
||||
}
|
||||
}
|
@@ -0,0 +1,9 @@
|
||||
import { ResourceType } from './resource-type';
|
||||
|
||||
/**
|
||||
* The resource type for HierarchicalBrowseDefinition
|
||||
*
|
||||
* Needs to be in a separate file to prevent circular
|
||||
* dependencies in webpack.
|
||||
*/
|
||||
export const HIERARCHICAL_BROWSE_DEFINITION = new ResourceType('hierarchicalBrowse');
|
32
src/app/core/shared/non-hierarchical-browse-definition.ts
Normal file
32
src/app/core/shared/non-hierarchical-browse-definition.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import { autoserialize, autoserializeAs, deserialize, inheritSerialization } from 'cerialize';
|
||||
import { SortOption } from './sort-option.model';
|
||||
import { BrowseByDataType } from '../../browse-by/browse-by-switcher/browse-by-decorator';
|
||||
import { HALLink } from './hal-link.model';
|
||||
import { BrowseDefinition } from './browse-definition.model';
|
||||
|
||||
/**
|
||||
* Super class for NonHierarchicalBrowseDefinition models,
|
||||
* e.g. FlatBrowseDefinition and ValueListBrowseDefinition
|
||||
*/
|
||||
@inheritSerialization(BrowseDefinition)
|
||||
export abstract class NonHierarchicalBrowseDefinition extends BrowseDefinition {
|
||||
|
||||
@autoserialize
|
||||
sortOptions: SortOption[];
|
||||
|
||||
@autoserializeAs('order')
|
||||
defaultSortOrder: string;
|
||||
|
||||
@autoserializeAs('metadata')
|
||||
metadataKeys: string[];
|
||||
|
||||
@autoserialize
|
||||
dataType: BrowseByDataType;
|
||||
|
||||
@deserialize
|
||||
_links: {
|
||||
self: HALLink;
|
||||
entries: HALLink;
|
||||
items: HALLink;
|
||||
};
|
||||
}
|
29
src/app/core/shared/value-list-browse-definition.model.ts
Normal file
29
src/app/core/shared/value-list-browse-definition.model.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { inheritSerialization } from 'cerialize';
|
||||
import { typedObject } from '../cache/builders/build-decorators';
|
||||
import { excludeFromEquals } from '../utilities/equals.decorators';
|
||||
import { VALUE_LIST_BROWSE_DEFINITION } from './value-list-browse-definition.resource-type';
|
||||
import { ResourceType } from './resource-type';
|
||||
import { NonHierarchicalBrowseDefinition } from './non-hierarchical-browse-definition';
|
||||
|
||||
/**
|
||||
* BrowseDefinition model for browses of type 'valueList'
|
||||
*/
|
||||
@typedObject
|
||||
@inheritSerialization(NonHierarchicalBrowseDefinition)
|
||||
export class ValueListBrowseDefinition extends NonHierarchicalBrowseDefinition {
|
||||
static type = VALUE_LIST_BROWSE_DEFINITION;
|
||||
|
||||
/**
|
||||
* The object type
|
||||
*/
|
||||
@excludeFromEquals
|
||||
type: ResourceType = VALUE_LIST_BROWSE_DEFINITION;
|
||||
|
||||
get self(): string {
|
||||
return this._links.self.href;
|
||||
}
|
||||
|
||||
getRenderType(): string {
|
||||
return this.dataType;
|
||||
}
|
||||
}
|
@@ -0,0 +1,9 @@
|
||||
import { ResourceType } from './resource-type';
|
||||
|
||||
/**
|
||||
* The resource type for ValueListBrowseDefinition
|
||||
*
|
||||
* Needs to be in a separate file to prevent circular
|
||||
* dependencies in webpack.
|
||||
*/
|
||||
export const VALUE_LIST_BROWSE_DEFINITION = new ResourceType('valueList');
|
@@ -137,20 +137,6 @@ export class MenuResolver implements Resolve<boolean> {
|
||||
} as TextMenuItemModel,
|
||||
}
|
||||
);
|
||||
menuList.push(
|
||||
{
|
||||
id: 'browse_global_by_srsc',
|
||||
parentID: 'browse_global',
|
||||
active: false,
|
||||
visible: true,
|
||||
index: 99,
|
||||
model: {
|
||||
type: MenuItemType.LINK,
|
||||
text: `menu.section.browse_global_by_srsc`,
|
||||
link: `/browse/srsc`
|
||||
} as LinkMenuItemModel
|
||||
}
|
||||
);
|
||||
}
|
||||
menuList.forEach((menuSection) => this.menuService.addSection(MenuID.PUBLIC, Object.assign(menuSection, {
|
||||
shouldPersistOnRouteChange: true
|
||||
|
@@ -16,7 +16,6 @@ import { RouterTestingModule } from '@angular/router/testing';
|
||||
import { BrowseService } from '../core/browse/browse.service';
|
||||
import { createSuccessfulRemoteDataObject, 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';
|
||||
import { Item } from '../core/shared/item.model';
|
||||
import { AuthorizationDataService } from '../core/data/feature-authorization/authorization-data.service';
|
||||
@@ -28,6 +27,9 @@ import { authReducer } from '../core/auth/auth.reducer';
|
||||
import { provideMockStore } from '@ngrx/store/testing';
|
||||
import { AuthTokenInfo } from '../core/auth/models/auth-token-info.model';
|
||||
import { EPersonMock } from '../shared/testing/eperson.mock';
|
||||
import { FlatBrowseDefinition } from '../core/shared/flat-browse-definition.model';
|
||||
import { ValueListBrowseDefinition } from '../core/shared/value-list-browse-definition.model';
|
||||
import { HierarchicalBrowseDefinition } from '../core/shared/hierarchical-browse-definition.model';
|
||||
|
||||
let comp: NavbarComponent;
|
||||
let fixture: ComponentFixture<NavbarComponent>;
|
||||
@@ -66,30 +68,35 @@ describe('NavbarComponent', () => {
|
||||
beforeEach(waitForAsync(() => {
|
||||
browseDefinitions = [
|
||||
Object.assign(
|
||||
new BrowseDefinition(), {
|
||||
new FlatBrowseDefinition(), {
|
||||
id: 'title',
|
||||
dataType: BrowseByDataType.Title,
|
||||
}
|
||||
),
|
||||
Object.assign(
|
||||
new BrowseDefinition(), {
|
||||
new FlatBrowseDefinition(), {
|
||||
id: 'dateissued',
|
||||
dataType: BrowseByDataType.Date,
|
||||
metadataKeys: ['dc.date.issued']
|
||||
}
|
||||
),
|
||||
Object.assign(
|
||||
new BrowseDefinition(), {
|
||||
new ValueListBrowseDefinition(), {
|
||||
id: 'author',
|
||||
dataType: BrowseByDataType.Metadata,
|
||||
}
|
||||
),
|
||||
Object.assign(
|
||||
new BrowseDefinition(), {
|
||||
new ValueListBrowseDefinition(), {
|
||||
id: 'subject',
|
||||
dataType: BrowseByDataType.Metadata,
|
||||
}
|
||||
),
|
||||
Object.assign(
|
||||
new HierarchicalBrowseDefinition(), {
|
||||
id: 'srsc',
|
||||
}
|
||||
),
|
||||
];
|
||||
initialState = {
|
||||
core: {
|
||||
|
@@ -248,7 +248,7 @@ export class VocabularyTreeviewComponent implements OnDestroy, OnInit {
|
||||
}
|
||||
|
||||
/**
|
||||
* Method called on entry select
|
||||
* Method called on entry select/deselect
|
||||
*/
|
||||
onSelect(item: VocabularyEntryDetail) {
|
||||
if (!this.selectedItems.includes(item.id)) {
|
||||
|
@@ -0,0 +1,15 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { BrowseByTaxonomyPageComponent as BaseComponent } from '../../../../../app/browse-by/browse-by-taxonomy-page/browse-by-taxonomy-page.component';
|
||||
|
||||
@Component({
|
||||
selector: 'ds-browse-by-taxonomy-page',
|
||||
// templateUrl: './browse-by-taxonomy-page.component.html',
|
||||
templateUrl: '../../../../../app/browse-by/browse-by-taxonomy-page/browse-by-taxonomy-page.component.html',
|
||||
// styleUrls: ['./browse-by-taxonomy-page.component.scss'],
|
||||
styleUrls: ['../../../../../app/browse-by/browse-by-taxonomy-page/browse-by-taxonomy-page.component.scss'],
|
||||
})
|
||||
/**
|
||||
* Component for browsing items by metadata in a hierarchical controlled vocabulary
|
||||
*/
|
||||
export class BrowseByTaxonomyPageComponent extends BaseComponent {
|
||||
}
|
@@ -114,6 +114,7 @@ import { ObjectListComponent } from './app/shared/object-list/object-list.compon
|
||||
import { BrowseByMetadataPageComponent } from './app/browse-by/browse-by-metadata-page/browse-by-metadata-page.component';
|
||||
import { BrowseByDatePageComponent } from './app/browse-by/browse-by-date-page/browse-by-date-page.component';
|
||||
import { BrowseByTitlePageComponent } from './app/browse-by/browse-by-title-page/browse-by-title-page.component';
|
||||
import { BrowseByTaxonomyPageComponent } from './app/browse-by/browse-by-taxonomy-page/browse-by-taxonomy-page.component';
|
||||
import {
|
||||
ExternalSourceEntryImportModalComponent
|
||||
} from './app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component';
|
||||
@@ -200,6 +201,7 @@ const DECLARATIONS = [
|
||||
BrowseByMetadataPageComponent,
|
||||
BrowseByDatePageComponent,
|
||||
BrowseByTitlePageComponent,
|
||||
BrowseByTaxonomyPageComponent,
|
||||
ExternalSourceEntryImportModalComponent,
|
||||
ResultsBackButtonComponent,
|
||||
DsoEditMetadataComponent,
|
||||
|
Reference in New Issue
Block a user