mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 10:04:11 +00:00
Merge branch 'w2p-63724_ConfigurationSearchPageComponent' into w2p-62849_relationships-in-submission
Conflicts: src/app/+search-page/search-page.module.ts src/app/+search-page/search-results/search-results.component.html src/app/core/shared/search/search-configuration.service.ts src/app/shared/search/search-result-element-decorator.ts
This commit is contained in:
@@ -149,7 +149,32 @@ module.exports = {
|
|||||||
// Limit for years to display using jumps of five years (current year - fiveYearLimit)
|
// Limit for years to display using jumps of five years (current year - fiveYearLimit)
|
||||||
fiveYearLimit: 30,
|
fiveYearLimit: 30,
|
||||||
// The absolute lowest year to display in the dropdown (only used when no lowest date can be found for all items)
|
// The absolute lowest year to display in the dropdown (only used when no lowest date can be found for all items)
|
||||||
defaultLowerLimit: 1900
|
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: 'title'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'dateissued',
|
||||||
|
type: 'date',
|
||||||
|
metadataField: 'dc.date.issued'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'author',
|
||||||
|
type: 'metadata'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'subject',
|
||||||
|
type: 'metadata'
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
item: {
|
item: {
|
||||||
edit: {
|
edit: {
|
||||||
|
@@ -418,7 +418,10 @@
|
|||||||
"titleprefix": "Publication: ",
|
"titleprefix": "Publication: ",
|
||||||
"journal-title": "Journal Title",
|
"journal-title": "Journal Title",
|
||||||
"journal-issn": "Journal ISSN",
|
"journal-issn": "Journal ISSN",
|
||||||
"volume-title": "Volume Title"
|
"volume-title": "Volume Title",
|
||||||
|
"publisher": "Publisher",
|
||||||
|
"description": "Description"
|
||||||
|
|
||||||
},
|
},
|
||||||
"listelement": {
|
"listelement": {
|
||||||
"badge": "Publication"
|
"badge": "Publication"
|
||||||
@@ -641,6 +644,34 @@
|
|||||||
"birthDate": {
|
"birthDate": {
|
||||||
"placeholder": "Birth Date",
|
"placeholder": "Birth Date",
|
||||||
"head": "Birth Date"
|
"head": "Birth Date"
|
||||||
|
},
|
||||||
|
"creativeWorkPublisher": {
|
||||||
|
"placeholder": "Publisher",
|
||||||
|
"head": "Publisher"
|
||||||
|
},
|
||||||
|
"creativeWorkEditor": {
|
||||||
|
"placeholder": "Editor",
|
||||||
|
"head": "Editor"
|
||||||
|
},
|
||||||
|
"creativeWorkKeywords": {
|
||||||
|
"placeholder": "Subject",
|
||||||
|
"head": "Subject"
|
||||||
|
},
|
||||||
|
"creativeDatePublished": {
|
||||||
|
"placeholder": "Date Published",
|
||||||
|
"head": "Date Published"
|
||||||
|
},
|
||||||
|
"organizationAddressCountry": {
|
||||||
|
"placeholder": "Country",
|
||||||
|
"head": "Country"
|
||||||
|
},
|
||||||
|
"organizationAddressLocality": {
|
||||||
|
"placeholder": "City",
|
||||||
|
"head": "City"
|
||||||
|
},
|
||||||
|
"organizationFoundingDate": {
|
||||||
|
"placeholder": "Date Founded",
|
||||||
|
"head": "Date Founded"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -813,7 +844,7 @@
|
|||||||
"control_panel": "Control Panel",
|
"control_panel": "Control Panel",
|
||||||
"browse_global": "All of DSpace",
|
"browse_global": "All of DSpace",
|
||||||
"browse_global_communities_and_collections": "Communities & Collections",
|
"browse_global_communities_and_collections": "Communities & Collections",
|
||||||
"browse_global_by_issue_date": "By Issue Date",
|
"browse_global_by_dateissued": "By Issue Date",
|
||||||
"browse_global_by_author": "By Author",
|
"browse_global_by_author": "By Author",
|
||||||
"browse_global_by_title": "By Title",
|
"browse_global_by_title": "By Title",
|
||||||
"browse_global_by_subject": "By Subject",
|
"browse_global_by_subject": "By Subject",
|
||||||
|
@@ -13,6 +13,7 @@ import { BrowseService } from '../../core/browse/browse.service';
|
|||||||
import { DSpaceObjectDataService } from '../../core/data/dspace-object-data.service';
|
import { DSpaceObjectDataService } from '../../core/data/dspace-object-data.service';
|
||||||
import { GLOBAL_CONFIG, GlobalConfig } from '../../../config';
|
import { GLOBAL_CONFIG, GlobalConfig } from '../../../config';
|
||||||
import { StartsWithType } from '../../shared/starts-with/starts-with-decorator';
|
import { StartsWithType } from '../../shared/starts-with/starts-with-decorator';
|
||||||
|
import { BrowseByType, rendersBrowseBy } from '../+browse-by-switcher/browse-by-decorator';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ds-browse-by-date-page',
|
selector: 'ds-browse-by-date-page',
|
||||||
@@ -21,9 +22,10 @@ import { StartsWithType } from '../../shared/starts-with/starts-with-decorator';
|
|||||||
})
|
})
|
||||||
/**
|
/**
|
||||||
* Component for browsing items by metadata definition of type 'date'
|
* Component for browsing items by metadata definition of type 'date'
|
||||||
* A metadata definition is a short term used to describe one or multiple metadata fields.
|
* 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'
|
* An example would be 'dateissued' for 'dc.date.issued'
|
||||||
*/
|
*/
|
||||||
|
@rendersBrowseBy(BrowseByType.Date)
|
||||||
export class BrowseByDatePageComponent extends BrowseByMetadataPageComponent {
|
export class BrowseByDatePageComponent extends BrowseByMetadataPageComponent {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -53,12 +55,12 @@ export class BrowseByDatePageComponent extends BrowseByMetadataPageComponent {
|
|||||||
})
|
})
|
||||||
.subscribe((params) => {
|
.subscribe((params) => {
|
||||||
const metadataField = params.metadataField || this.defaultMetadataField;
|
const metadataField = params.metadataField || this.defaultMetadataField;
|
||||||
this.metadata = params.metadata || this.defaultMetadata;
|
this.browseId = params.id || this.defaultBrowseId;
|
||||||
this.startsWith = +params.startsWith || params.startsWith;
|
this.startsWith = +params.startsWith || params.startsWith;
|
||||||
const searchOptions = browseParamsToOptions(params, Object.assign({}), this.sortConfig, this.metadata);
|
const searchOptions = browseParamsToOptions(params, Object.assign({}), this.sortConfig, this.browseId);
|
||||||
this.updatePageWithItems(searchOptions, this.value);
|
this.updatePageWithItems(searchOptions, this.value);
|
||||||
this.updateParent(params.scope);
|
this.updateParent(params.scope);
|
||||||
this.updateStartsWithOptions(this.metadata, metadataField, params.scope);
|
this.updateStartsWithOptions(this.browseId, metadataField, params.scope);
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,8 +80,9 @@ export class BrowseByDatePageComponent extends BrowseByMetadataPageComponent {
|
|||||||
let lowerLimit = this.config.browseBy.defaultLowerLimit;
|
let lowerLimit = this.config.browseBy.defaultLowerLimit;
|
||||||
if (hasValue(firstItemRD.payload)) {
|
if (hasValue(firstItemRD.payload)) {
|
||||||
const date = firstItemRD.payload.firstMetadataValue(metadataField);
|
const date = firstItemRD.payload.firstMetadataValue(metadataField);
|
||||||
if (hasValue(date) && hasValue(+date.split('-')[0])) {
|
if (hasValue(date)) {
|
||||||
lowerLimit = +date.split('-')[0];
|
const dateObj = new Date(date);
|
||||||
|
lowerLimit = dateObj.getFullYear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const options = [];
|
const options = [];
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="browse-by-metadata w-100">
|
<div class="browse-by-metadata w-100">
|
||||||
<ds-browse-by *ngIf="startsWithOptions" class="col-xs-12 w-100"
|
<ds-browse-by *ngIf="startsWithOptions" class="col-xs-12 w-100"
|
||||||
title="{{'browse.title' | translate:{collection: (parent$ | async)?.payload?.name || '', field: 'browse.metadata.' + metadata | translate, value: (value)? '"' + value + '"': ''} }}"
|
title="{{'browse.title' | translate:{collection: (parent$ | async)?.payload?.name || '', field: 'browse.metadata.' + browseId | translate, value: (value)? '"' + value + '"': ''} }}"
|
||||||
[objects$]="(items$ !== undefined)? items$ : browseEntries$"
|
[objects$]="(items$ !== undefined)? items$ : browseEntries$"
|
||||||
[paginationConfig]="paginationConfig"
|
[paginationConfig]="paginationConfig"
|
||||||
[sortConfig]="sortConfig"
|
[sortConfig]="sortConfig"
|
||||||
|
@@ -15,6 +15,7 @@ import { DSpaceObjectDataService } from '../../core/data/dspace-object-data.serv
|
|||||||
import { DSpaceObject } from '../../core/shared/dspace-object.model';
|
import { DSpaceObject } from '../../core/shared/dspace-object.model';
|
||||||
import { take } from 'rxjs/operators';
|
import { take } from 'rxjs/operators';
|
||||||
import { StartsWithType } from '../../shared/starts-with/starts-with-decorator';
|
import { StartsWithType } from '../../shared/starts-with/starts-with-decorator';
|
||||||
|
import { BrowseByType, rendersBrowseBy } from '../+browse-by-switcher/browse-by-decorator';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ds-browse-by-metadata-page',
|
selector: 'ds-browse-by-metadata-page',
|
||||||
@@ -23,9 +24,10 @@ import { StartsWithType } from '../../shared/starts-with/starts-with-decorator';
|
|||||||
})
|
})
|
||||||
/**
|
/**
|
||||||
* Component for browsing (items) by metadata definition
|
* Component for browsing (items) by metadata definition
|
||||||
* A metadata definition is a short term used to describe one or multiple metadata fields.
|
* 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.*'
|
* An example would be 'author' for 'dc.contributor.*'
|
||||||
*/
|
*/
|
||||||
|
@rendersBrowseBy(BrowseByType.Metadata)
|
||||||
export class BrowseByMetadataPageComponent implements OnInit {
|
export class BrowseByMetadataPageComponent implements OnInit {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -63,14 +65,14 @@ export class BrowseByMetadataPageComponent implements OnInit {
|
|||||||
subs: Subscription[] = [];
|
subs: Subscription[] = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The default metadata definition to resort to when none is provided
|
* The default browse id to resort to when none is provided
|
||||||
*/
|
*/
|
||||||
defaultMetadata = 'author';
|
defaultBrowseId = 'author';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The current metadata definition
|
* The current browse id
|
||||||
*/
|
*/
|
||||||
metadata = this.defaultMetadata;
|
browseId = this.defaultBrowseId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The type of StartsWith options to render
|
* The type of StartsWith options to render
|
||||||
@@ -112,10 +114,10 @@ export class BrowseByMetadataPageComponent implements OnInit {
|
|||||||
return Object.assign({}, params, queryParams);
|
return Object.assign({}, params, queryParams);
|
||||||
})
|
})
|
||||||
.subscribe((params) => {
|
.subscribe((params) => {
|
||||||
this.metadata = params.metadata || this.defaultMetadata;
|
this.browseId = params.id || this.defaultBrowseId;
|
||||||
this.value = +params.value || params.value || '';
|
this.value = +params.value || params.value || '';
|
||||||
this.startsWith = +params.startsWith || params.startsWith;
|
this.startsWith = +params.startsWith || params.startsWith;
|
||||||
const searchOptions = browseParamsToOptions(params, this.paginationConfig, this.sortConfig, this.metadata);
|
const searchOptions = browseParamsToOptions(params, this.paginationConfig, this.sortConfig, this.browseId);
|
||||||
if (isNotEmpty(this.value)) {
|
if (isNotEmpty(this.value)) {
|
||||||
this.updatePageWithItems(searchOptions, this.value);
|
this.updatePageWithItems(searchOptions, this.value);
|
||||||
} else {
|
} else {
|
||||||
|
@@ -0,0 +1,12 @@
|
|||||||
|
import { BrowseByType, rendersBrowseBy } from './browse-by-decorator';
|
||||||
|
|
||||||
|
describe('BrowseByDecorator', () => {
|
||||||
|
const titleDecorator = rendersBrowseBy(BrowseByType.Title);
|
||||||
|
const dateDecorator = rendersBrowseBy(BrowseByType.Date);
|
||||||
|
const metadataDecorator = rendersBrowseBy(BrowseByType.Metadata);
|
||||||
|
it('should have a decorator for all types', () => {
|
||||||
|
expect(titleDecorator.length).not.toEqual(0);
|
||||||
|
expect(dateDecorator.length).not.toEqual(0);
|
||||||
|
expect(metadataDecorator.length).not.toEqual(0);
|
||||||
|
});
|
||||||
|
});
|
@@ -0,0 +1,37 @@
|
|||||||
|
import { hasNoValue } from '../../shared/empty.util';
|
||||||
|
|
||||||
|
export enum BrowseByType {
|
||||||
|
Title = 'title',
|
||||||
|
Metadata = 'metadata',
|
||||||
|
Date = 'date'
|
||||||
|
}
|
||||||
|
|
||||||
|
export const DEFAULT_BROWSE_BY_TYPE = BrowseByType.Metadata;
|
||||||
|
|
||||||
|
const map = new Map();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decorator used for rendering Browse-By pages by type
|
||||||
|
* @param browseByType The type of page
|
||||||
|
*/
|
||||||
|
export function rendersBrowseBy(browseByType: BrowseByType) {
|
||||||
|
return function decorator(component: any) {
|
||||||
|
if (hasNoValue(map.get(browseByType))) {
|
||||||
|
map.set(browseByType, component);
|
||||||
|
} else {
|
||||||
|
throw new Error(`There can't be more than one component to render Browse-By of type "${browseByType}"`);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the component used for rendering a Browse-By page by type
|
||||||
|
* @param browseByType The type of page
|
||||||
|
*/
|
||||||
|
export function getComponentByBrowseByType(browseByType) {
|
||||||
|
const comp = map.get(browseByType);
|
||||||
|
if (hasNoValue(comp)) {
|
||||||
|
map.get(DEFAULT_BROWSE_BY_TYPE);
|
||||||
|
}
|
||||||
|
return comp;
|
||||||
|
}
|
@@ -0,0 +1 @@
|
|||||||
|
<ng-container *ngComponentOutlet="browseByComponent | async"></ng-container>
|
@@ -0,0 +1,55 @@
|
|||||||
|
import { BrowseBySwitcherComponent } from './browse-by-switcher.component';
|
||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
||||||
|
import { ENV_CONFIG, GLOBAL_CONFIG } from '../../../config';
|
||||||
|
import { ActivatedRoute } from '@angular/router';
|
||||||
|
import * as decorator from './browse-by-decorator';
|
||||||
|
import createSpy = jasmine.createSpy;
|
||||||
|
import { BehaviorSubject } from 'rxjs/internal/BehaviorSubject';
|
||||||
|
|
||||||
|
describe('BrowseBySwitcherComponent', () => {
|
||||||
|
let comp: BrowseBySwitcherComponent;
|
||||||
|
let fixture: ComponentFixture<BrowseBySwitcherComponent>;
|
||||||
|
|
||||||
|
const types = ENV_CONFIG.browseBy.types;
|
||||||
|
|
||||||
|
const params = new BehaviorSubject(createParamsWithId('initialValue'));
|
||||||
|
|
||||||
|
const activatedRouteStub = {
|
||||||
|
params: params
|
||||||
|
};
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ BrowseBySwitcherComponent ],
|
||||||
|
providers: [
|
||||||
|
{ provide: GLOBAL_CONFIG, useValue: ENV_CONFIG },
|
||||||
|
{ provide: ActivatedRoute, useValue: activatedRouteStub }
|
||||||
|
],
|
||||||
|
schemas: [ NO_ERRORS_SCHEMA ]
|
||||||
|
}).compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
fixture = TestBed.createComponent(BrowseBySwitcherComponent);
|
||||||
|
comp = fixture.componentInstance;
|
||||||
|
spyOnProperty(decorator, 'getComponentByBrowseByType').and.returnValue(createSpy('getComponentByItemType'));
|
||||||
|
}));
|
||||||
|
|
||||||
|
types.forEach((type) => {
|
||||||
|
describe(`when switching to a browse-by page for "${type.id}"`, () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
params.next(createParamsWithId(type.id));
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`should call getComponentByBrowseByType with type "${type.type}"`, () => {
|
||||||
|
expect(decorator.getComponentByBrowseByType).toHaveBeenCalledWith(type.type);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
export function createParamsWithId(id) {
|
||||||
|
return { id: id };
|
||||||
|
}
|
@@ -0,0 +1,40 @@
|
|||||||
|
import { Component, Inject, OnInit } from '@angular/core';
|
||||||
|
import { ActivatedRoute } from '@angular/router';
|
||||||
|
import { Observable } from 'rxjs/internal/Observable';
|
||||||
|
import { GLOBAL_CONFIG, GlobalConfig } from '../../../config';
|
||||||
|
import { BrowseByTypeConfig } from '../../../config/browse-by-type-config.interface';
|
||||||
|
import { map, tap } from 'rxjs/operators';
|
||||||
|
import { getComponentByBrowseByType } from './browse-by-decorator';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'ds-browse-by-switcher',
|
||||||
|
templateUrl: './browse-by-switcher.component.html'
|
||||||
|
})
|
||||||
|
/**
|
||||||
|
* Component for determining what Browse-By component to use depending on the metadata (browse ID) provided
|
||||||
|
*/
|
||||||
|
export class BrowseBySwitcherComponent implements OnInit {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolved browse-by component
|
||||||
|
*/
|
||||||
|
browseByComponent: Observable<any>;
|
||||||
|
|
||||||
|
public constructor(@Inject(GLOBAL_CONFIG) public config: GlobalConfig,
|
||||||
|
protected route: ActivatedRoute) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch the correct browse-by component by using the relevant config from environment.js
|
||||||
|
*/
|
||||||
|
ngOnInit(): void {
|
||||||
|
this.browseByComponent = this.route.params.pipe(
|
||||||
|
map((params) => {
|
||||||
|
const id = params.id;
|
||||||
|
return this.config.browseBy.types.find((config: BrowseByTypeConfig) => config.id === id);
|
||||||
|
}),
|
||||||
|
map((config: BrowseByTypeConfig) => getComponentByBrowseByType(config.type))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -1,6 +1,5 @@
|
|||||||
import { combineLatest as observableCombineLatest } from 'rxjs';
|
import { combineLatest as observableCombineLatest } from 'rxjs';
|
||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
import { ItemDataService } from '../../core/data/item-data.service';
|
|
||||||
import { ActivatedRoute, Router } from '@angular/router';
|
import { ActivatedRoute, Router } from '@angular/router';
|
||||||
import { hasValue } from '../../shared/empty.util';
|
import { hasValue } from '../../shared/empty.util';
|
||||||
import {
|
import {
|
||||||
@@ -11,6 +10,7 @@ import { BrowseEntrySearchOptions } from '../../core/browse/browse-entry-search-
|
|||||||
import { DSpaceObjectDataService } from '../../core/data/dspace-object-data.service';
|
import { DSpaceObjectDataService } from '../../core/data/dspace-object-data.service';
|
||||||
import { BrowseService } from '../../core/browse/browse.service';
|
import { BrowseService } from '../../core/browse/browse.service';
|
||||||
import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model';
|
import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model';
|
||||||
|
import { BrowseByType, rendersBrowseBy } from '../+browse-by-switcher/browse-by-decorator';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ds-browse-by-title-page',
|
selector: 'ds-browse-by-title-page',
|
||||||
@@ -20,6 +20,7 @@ import { SortDirection, SortOptions } from '../../core/cache/models/sort-options
|
|||||||
/**
|
/**
|
||||||
* Component for browsing items by title (dc.title)
|
* Component for browsing items by title (dc.title)
|
||||||
*/
|
*/
|
||||||
|
@rendersBrowseBy(BrowseByType.Title)
|
||||||
export class BrowseByTitlePageComponent extends BrowseByMetadataPageComponent {
|
export class BrowseByTitlePageComponent extends BrowseByMetadataPageComponent {
|
||||||
|
|
||||||
public constructor(protected route: ActivatedRoute,
|
public constructor(protected route: ActivatedRoute,
|
||||||
@@ -41,8 +42,8 @@ export class BrowseByTitlePageComponent extends BrowseByMetadataPageComponent {
|
|||||||
return Object.assign({}, params, queryParams, data);
|
return Object.assign({}, params, queryParams, data);
|
||||||
})
|
})
|
||||||
.subscribe((params) => {
|
.subscribe((params) => {
|
||||||
this.metadata = params.metadata || this.defaultMetadata;
|
this.browseId = params.id || this.defaultBrowseId;
|
||||||
this.updatePageWithItems(browseParamsToOptions(params, this.paginationConfig, this.sortConfig, this.metadata), undefined);
|
this.updatePageWithItems(browseParamsToOptions(params, this.paginationConfig, this.sortConfig, this.browseId), undefined);
|
||||||
this.updateParent(params.scope)
|
this.updateParent(params.scope)
|
||||||
}));
|
}));
|
||||||
this.updateStartsWithTextOptions();
|
this.updateStartsWithTextOptions();
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
import { first } from 'rxjs/operators';
|
import { first } from 'rxjs/operators';
|
||||||
import { BrowseByGuard } from './browse-by-guard';
|
import { BrowseByGuard } from './browse-by-guard';
|
||||||
import { of as observableOf } from 'rxjs';
|
import { of as observableOf } from 'rxjs';
|
||||||
|
import { ENV_CONFIG } from '../../config';
|
||||||
|
|
||||||
describe('BrowseByGuard', () => {
|
describe('BrowseByGuard', () => {
|
||||||
describe('canActivate', () => {
|
describe('canActivate', () => {
|
||||||
@@ -11,20 +12,20 @@ describe('BrowseByGuard', () => {
|
|||||||
const name = 'An interesting DSO';
|
const name = 'An interesting DSO';
|
||||||
const title = 'Author';
|
const title = 'Author';
|
||||||
const field = 'Author';
|
const field = 'Author';
|
||||||
const metadata = 'author';
|
const id = 'author';
|
||||||
const metadataField = 'dc.contributor';
|
const metadataField = 'dc.contributor';
|
||||||
const scope = '1234-65487-12354-1235';
|
const scope = '1234-65487-12354-1235';
|
||||||
const value = 'Filter';
|
const value = 'Filter';
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
dsoService = {
|
dsoService = {
|
||||||
findById: (id: string) => observableOf({ payload: { name: name }, hasSucceeded: true })
|
findById: (dsoId: string) => observableOf({ payload: { name: name }, hasSucceeded: true })
|
||||||
};
|
};
|
||||||
|
|
||||||
translateService = {
|
translateService = {
|
||||||
instant: () => field
|
instant: () => field
|
||||||
};
|
};
|
||||||
guard = new BrowseByGuard(dsoService, translateService);
|
guard = new BrowseByGuard(ENV_CONFIG, dsoService, translateService);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return true, and sets up the data correctly, with a scope and value', () => {
|
it('should return true, and sets up the data correctly, with a scope and value', () => {
|
||||||
@@ -34,7 +35,7 @@ describe('BrowseByGuard', () => {
|
|||||||
metadataField,
|
metadataField,
|
||||||
},
|
},
|
||||||
params: {
|
params: {
|
||||||
metadata,
|
id,
|
||||||
},
|
},
|
||||||
queryParams: {
|
queryParams: {
|
||||||
scope,
|
scope,
|
||||||
@@ -47,7 +48,7 @@ describe('BrowseByGuard', () => {
|
|||||||
(canActivate) => {
|
(canActivate) => {
|
||||||
const result = {
|
const result = {
|
||||||
title,
|
title,
|
||||||
metadata,
|
id,
|
||||||
metadataField,
|
metadataField,
|
||||||
collection: name,
|
collection: name,
|
||||||
field,
|
field,
|
||||||
@@ -66,7 +67,7 @@ describe('BrowseByGuard', () => {
|
|||||||
metadataField,
|
metadataField,
|
||||||
},
|
},
|
||||||
params: {
|
params: {
|
||||||
metadata,
|
id,
|
||||||
},
|
},
|
||||||
queryParams: {
|
queryParams: {
|
||||||
scope
|
scope
|
||||||
@@ -79,7 +80,7 @@ describe('BrowseByGuard', () => {
|
|||||||
(canActivate) => {
|
(canActivate) => {
|
||||||
const result = {
|
const result = {
|
||||||
title,
|
title,
|
||||||
metadata,
|
id,
|
||||||
metadataField,
|
metadataField,
|
||||||
collection: name,
|
collection: name,
|
||||||
field,
|
field,
|
||||||
@@ -98,7 +99,7 @@ describe('BrowseByGuard', () => {
|
|||||||
metadataField,
|
metadataField,
|
||||||
},
|
},
|
||||||
params: {
|
params: {
|
||||||
metadata,
|
id,
|
||||||
},
|
},
|
||||||
queryParams: {
|
queryParams: {
|
||||||
value
|
value
|
||||||
@@ -110,7 +111,7 @@ describe('BrowseByGuard', () => {
|
|||||||
(canActivate) => {
|
(canActivate) => {
|
||||||
const result = {
|
const result = {
|
||||||
title,
|
title,
|
||||||
metadata,
|
id,
|
||||||
metadataField,
|
metadataField,
|
||||||
collection: '',
|
collection: '',
|
||||||
field,
|
field,
|
||||||
|
@@ -1,11 +1,12 @@
|
|||||||
import { ActivatedRouteSnapshot, CanActivate, RouterStateSnapshot } from '@angular/router';
|
import { ActivatedRouteSnapshot, CanActivate, RouterStateSnapshot } from '@angular/router';
|
||||||
import { Injectable } from '@angular/core';
|
import { Inject, Injectable } from '@angular/core';
|
||||||
import { DSpaceObjectDataService } from '../core/data/dspace-object-data.service';
|
import { DSpaceObjectDataService } from '../core/data/dspace-object-data.service';
|
||||||
import { hasValue } from '../shared/empty.util';
|
import { hasNoValue, hasValue } from '../shared/empty.util';
|
||||||
import { map } from 'rxjs/operators';
|
import { map } from 'rxjs/operators';
|
||||||
import { getSucceededRemoteData } from '../core/shared/operators';
|
import { getSucceededRemoteData } from '../core/shared/operators';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
import { of as observableOf } from 'rxjs';
|
import { of as observableOf } from 'rxjs';
|
||||||
|
import { GLOBAL_CONFIG, GlobalConfig } from '../../config';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
/**
|
/**
|
||||||
@@ -13,36 +14,43 @@ import { of as observableOf } from 'rxjs';
|
|||||||
*/
|
*/
|
||||||
export class BrowseByGuard implements CanActivate {
|
export class BrowseByGuard implements CanActivate {
|
||||||
|
|
||||||
constructor(protected dsoService: DSpaceObjectDataService,
|
constructor(@Inject(GLOBAL_CONFIG) public config: GlobalConfig,
|
||||||
|
protected dsoService: DSpaceObjectDataService,
|
||||||
protected translate: TranslateService) {
|
protected translate: TranslateService) {
|
||||||
}
|
}
|
||||||
|
|
||||||
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
||||||
const title = route.data.title;
|
const title = route.data.title;
|
||||||
const metadata = route.params.metadata || route.queryParams.metadata || route.data.metadata;
|
const id = route.params.id || route.queryParams.id || route.data.id;
|
||||||
const metadataField = route.data.metadataField;
|
let metadataField = route.data.metadataField;
|
||||||
|
if (hasNoValue(metadataField) && hasValue(id)) {
|
||||||
|
const config = this.config.browseBy.types.find((conf) => conf.id === id);
|
||||||
|
if (hasValue(config) && hasValue(config.metadataField)) {
|
||||||
|
metadataField = config.metadataField;
|
||||||
|
}
|
||||||
|
}
|
||||||
const scope = route.queryParams.scope;
|
const scope = route.queryParams.scope;
|
||||||
const value = route.queryParams.value;
|
const value = route.queryParams.value;
|
||||||
const metadataTranslated = this.translate.instant('browse.metadata.' + metadata);
|
const metadataTranslated = this.translate.instant('browse.metadata.' + id);
|
||||||
if (hasValue(scope)) {
|
if (hasValue(scope)) {
|
||||||
const dsoAndMetadata$ = this.dsoService.findById(scope).pipe(getSucceededRemoteData());
|
const dsoAndMetadata$ = this.dsoService.findById(scope).pipe(getSucceededRemoteData());
|
||||||
return dsoAndMetadata$.pipe(
|
return dsoAndMetadata$.pipe(
|
||||||
map((dsoRD) => {
|
map((dsoRD) => {
|
||||||
const name = dsoRD.payload.name;
|
const name = dsoRD.payload.name;
|
||||||
route.data = this.createData(title, metadata, metadataField, name, metadataTranslated, value);
|
route.data = this.createData(title, id, metadataField, name, metadataTranslated, value);
|
||||||
return true;
|
return true;
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
route.data = this.createData(title, metadata, metadataField, '', metadataTranslated, value);
|
route.data = this.createData(title, id, metadataField, '', metadataTranslated, value);
|
||||||
return observableOf(true);
|
return observableOf(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private createData(title, metadata, metadataField, collection, field, value) {
|
private createData(title, id, metadataField, collection, field, value) {
|
||||||
return {
|
return {
|
||||||
title: title,
|
title: title,
|
||||||
metadata: metadata,
|
id: id,
|
||||||
metadataField: metadataField,
|
metadataField: metadataField,
|
||||||
collection: collection,
|
collection: collection,
|
||||||
field: field,
|
field: field,
|
||||||
|
@@ -1,16 +1,12 @@
|
|||||||
import { RouterModule } from '@angular/router';
|
import { RouterModule } from '@angular/router';
|
||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
import { BrowseByTitlePageComponent } from './+browse-by-title-page/browse-by-title-page.component';
|
|
||||||
import { BrowseByMetadataPageComponent } from './+browse-by-metadata-page/browse-by-metadata-page.component';
|
|
||||||
import { BrowseByDatePageComponent } from './+browse-by-date-page/browse-by-date-page.component';
|
|
||||||
import { BrowseByGuard } from './browse-by-guard';
|
import { BrowseByGuard } from './browse-by-guard';
|
||||||
|
import { BrowseBySwitcherComponent } from './+browse-by-switcher/browse-by-switcher.component';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
RouterModule.forChild([
|
RouterModule.forChild([
|
||||||
{ path: 'title', component: BrowseByTitlePageComponent, canActivate: [BrowseByGuard], data: { metadata: 'title', title: 'browse.title' } },
|
{ path: ':id', component: BrowseBySwitcherComponent, canActivate: [BrowseByGuard], data: { title: 'browse.title' } }
|
||||||
{ path: 'dateissued', component: BrowseByDatePageComponent, canActivate: [BrowseByGuard], data: { metadata: 'dateissued', metadataField: 'dc.date.issued', title: 'browse.title' } },
|
|
||||||
{ path: ':metadata', component: BrowseByMetadataPageComponent, canActivate: [BrowseByGuard], data: { title: 'browse.title' } }
|
|
||||||
])
|
])
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
@@ -8,6 +8,7 @@ import { BrowseService } from '../core/browse/browse.service';
|
|||||||
import { BrowseByMetadataPageComponent } from './+browse-by-metadata-page/browse-by-metadata-page.component';
|
import { BrowseByMetadataPageComponent } from './+browse-by-metadata-page/browse-by-metadata-page.component';
|
||||||
import { BrowseByDatePageComponent } from './+browse-by-date-page/browse-by-date-page.component';
|
import { BrowseByDatePageComponent } from './+browse-by-date-page/browse-by-date-page.component';
|
||||||
import { BrowseByGuard } from './browse-by-guard';
|
import { BrowseByGuard } from './browse-by-guard';
|
||||||
|
import { BrowseBySwitcherComponent } from './+browse-by-switcher/browse-by-switcher.component';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
@@ -18,12 +19,18 @@ import { BrowseByGuard } from './browse-by-guard';
|
|||||||
declarations: [
|
declarations: [
|
||||||
BrowseByTitlePageComponent,
|
BrowseByTitlePageComponent,
|
||||||
BrowseByMetadataPageComponent,
|
BrowseByMetadataPageComponent,
|
||||||
BrowseByDatePageComponent
|
BrowseByDatePageComponent,
|
||||||
|
BrowseBySwitcherComponent
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
ItemDataService,
|
ItemDataService,
|
||||||
BrowseService,
|
BrowseService,
|
||||||
BrowseByGuard
|
BrowseByGuard
|
||||||
|
],
|
||||||
|
entryComponents: [
|
||||||
|
BrowseByTitlePageComponent,
|
||||||
|
BrowseByMetadataPageComponent,
|
||||||
|
BrowseByDatePageComponent
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class BrowseByModule {
|
export class BrowseByModule {
|
||||||
|
@@ -21,6 +21,10 @@
|
|||||||
[fields]="['journalvolume.identifier.name']"
|
[fields]="['journalvolume.identifier.name']"
|
||||||
[label]="'publication.page.volume-title'">
|
[label]="'publication.page.volume-title'">
|
||||||
</ds-generic-item-page-field>
|
</ds-generic-item-page-field>
|
||||||
|
<ds-generic-item-page-field [item]="item"
|
||||||
|
[fields]="['dc.publisher']"
|
||||||
|
[label]="'publication.page.publisher'">
|
||||||
|
</ds-generic-item-page-field>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-xs-12 col-md-6">
|
<div class="col-xs-12 col-md-6">
|
||||||
<ds-metadata-representation-list
|
<ds-metadata-representation-list
|
||||||
@@ -40,6 +44,11 @@
|
|||||||
[label]="'relationships.isJournalIssueOf' | translate">
|
[label]="'relationships.isJournalIssueOf' | translate">
|
||||||
</ds-related-items>
|
</ds-related-items>
|
||||||
<ds-item-page-abstract-field [item]="item"></ds-item-page-abstract-field>
|
<ds-item-page-abstract-field [item]="item"></ds-item-page-abstract-field>
|
||||||
|
<ds-generic-item-page-field [item]="item"
|
||||||
|
[fields]="['dc.description']"
|
||||||
|
[label]="'publication.page.description'">
|
||||||
|
</ds-generic-item-page-field>
|
||||||
|
|
||||||
<ds-generic-item-page-field [item]="item"
|
<ds-generic-item-page-field [item]="item"
|
||||||
[fields]="['dc.subject']"
|
[fields]="['dc.subject']"
|
||||||
[separator]="','"
|
[separator]="','"
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
<ds-filtered-search-page
|
<ds-filtered-search-page
|
||||||
[fixedFilterQuery]="fixedFilter"
|
[fixedFilterQuery]="fixedFilter"
|
||||||
[fixedFilter$]="fixedFilter$"
|
[configuration$]="configuration$"
|
||||||
[searchEnabled]="searchEnabled"
|
[searchEnabled]="searchEnabled"
|
||||||
[sideBarWidth]="sideBarWidth">
|
[sideBarWidth]="sideBarWidth">
|
||||||
</ds-filtered-search-page>
|
</ds-filtered-search-page>
|
||||||
|
@@ -47,9 +47,9 @@ describe('RelatedEntitiesSearchComponent', () => {
|
|||||||
expect(comp.fixedFilter).toEqual(mockFilter);
|
expect(comp.fixedFilter).toEqual(mockFilter);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should create a fixedFilter$', () => {
|
it('should create a configuration$', () => {
|
||||||
comp.fixedFilter$.subscribe((fixedFilter) => {
|
comp.configuration$.subscribe((configuration) => {
|
||||||
expect(fixedFilter).toEqual(mockRelationEntityType);
|
expect(configuration).toEqual(mockRelationEntityType);
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@@ -47,7 +47,7 @@ export class RelatedEntitiesSearchComponent implements OnInit {
|
|||||||
@Input() sideBarWidth = 4;
|
@Input() sideBarWidth = 4;
|
||||||
|
|
||||||
fixedFilter: string;
|
fixedFilter: string;
|
||||||
fixedFilter$: Observable<string>;
|
configuration$: Observable<string>;
|
||||||
|
|
||||||
constructor(private fixedFilterService: SearchFixedFilterService) {
|
constructor(private fixedFilterService: SearchFixedFilterService) {
|
||||||
}
|
}
|
||||||
@@ -57,7 +57,7 @@ export class RelatedEntitiesSearchComponent implements OnInit {
|
|||||||
this.fixedFilter = this.fixedFilterService.getFilterByRelation(this.relationType, this.item.id);
|
this.fixedFilter = this.fixedFilterService.getFilterByRelation(this.relationType, this.item.id);
|
||||||
}
|
}
|
||||||
if (isNotEmpty(this.relationEntityType)) {
|
if (isNotEmpty(this.relationEntityType)) {
|
||||||
this.fixedFilter$ = of(this.relationEntityType);
|
this.configuration$ = of(this.relationEntityType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -0,0 +1,21 @@
|
|||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
import { configureSearchComponentTestingModule } from './search-page.component.spec';
|
||||||
|
import { SearchConfigurationService } from './search-service/search-configuration.service';
|
||||||
|
import { ConfigurationSearchPageComponent } from './configuration-search-page.component';
|
||||||
|
|
||||||
|
describe('ConfigurationSearchPageComponent', () => {
|
||||||
|
let comp: ConfigurationSearchPageComponent;
|
||||||
|
let fixture: ComponentFixture<ConfigurationSearchPageComponent>;
|
||||||
|
let searchConfigService: SearchConfigurationService;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
configureSearchComponentTestingModule(ConfigurationSearchPageComponent);
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(ConfigurationSearchPageComponent);
|
||||||
|
comp = fixture.componentInstance;
|
||||||
|
searchConfigService = (comp as any).searchConfigService;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
});
|
71
src/app/+search-page/configuration-search-page.component.ts
Normal file
71
src/app/+search-page/configuration-search-page.component.ts
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
import { HostWindowService } from '../shared/host-window.service';
|
||||||
|
import { SearchService } from './search-service/search.service';
|
||||||
|
import { SearchSidebarService } from './search-sidebar/search-sidebar.service';
|
||||||
|
import { SearchPageComponent } from './search-page.component';
|
||||||
|
import { ChangeDetectionStrategy, Component, Inject, Input, OnInit } from '@angular/core';
|
||||||
|
import { pushInOut } from '../shared/animations/push';
|
||||||
|
import { RouteService } from '../shared/services/route.service';
|
||||||
|
import { SearchConfigurationService } from './search-service/search-configuration.service';
|
||||||
|
import { Observable } from 'rxjs';
|
||||||
|
import { PaginatedSearchOptions } from './paginated-search-options.model';
|
||||||
|
import { SEARCH_CONFIG_SERVICE } from '../+my-dspace-page/my-dspace-page.component';
|
||||||
|
import { map } from 'rxjs/operators';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This component renders a search page using a configuration as input.
|
||||||
|
*/
|
||||||
|
@Component({
|
||||||
|
selector: 'ds-configuration-search-page',
|
||||||
|
styleUrls: ['./search-page.component.scss'],
|
||||||
|
templateUrl: './search-page.component.html',
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
|
animations: [pushInOut],
|
||||||
|
providers: [
|
||||||
|
{
|
||||||
|
provide: SEARCH_CONFIG_SERVICE,
|
||||||
|
useClass: SearchConfigurationService
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
export class ConfigurationSearchPageComponent extends SearchPageComponent implements OnInit {
|
||||||
|
/**
|
||||||
|
* The configuration to use for the search options
|
||||||
|
* If empty, the configuration will be determined by the route parameter called 'configuration'
|
||||||
|
*/
|
||||||
|
@Input() configuration: string;
|
||||||
|
|
||||||
|
constructor(protected service: SearchService,
|
||||||
|
protected sidebarService: SearchSidebarService,
|
||||||
|
protected windowService: HostWindowService,
|
||||||
|
@Inject(SEARCH_CONFIG_SERVICE) public searchConfigService: SearchConfigurationService,
|
||||||
|
protected routeService: RouteService) {
|
||||||
|
super(service, sidebarService, windowService, searchConfigService, routeService);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Listening to changes in the paginated search options
|
||||||
|
* If something changes, update the search results
|
||||||
|
*
|
||||||
|
* Listen to changes in the scope
|
||||||
|
* If something changes, update the list of scopes for the dropdown
|
||||||
|
*/
|
||||||
|
ngOnInit(): void {
|
||||||
|
super.ngOnInit();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current paginated search options after updating the configuration using the configuration input
|
||||||
|
* This is to make sure the configuration is included in the paginated search options, as it is not part of any
|
||||||
|
* query or route parameters
|
||||||
|
* @returns {Observable<PaginatedSearchOptions>}
|
||||||
|
*/
|
||||||
|
protected getSearchOptions(): Observable<PaginatedSearchOptions> {
|
||||||
|
return this.searchConfigService.paginatedSearchOptions.pipe(
|
||||||
|
map((options: PaginatedSearchOptions) => {
|
||||||
|
const config = this.configuration || options.configuration;
|
||||||
|
return Object.assign(options, { configuration: config });
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
22
src/app/+search-page/configuration-search-page.guard.ts
Normal file
22
src/app/+search-page/configuration-search-page.guard.ts
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
|
||||||
|
import { Observable } from 'rxjs';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
/**
|
||||||
|
* Assemble the correct i18n key for the configuration search page's title depending on the current route's configuration parameter.
|
||||||
|
* The format of the key will be "{configuration}.search.title" with:
|
||||||
|
* - configuration: The current configuration stored in route.params
|
||||||
|
*/
|
||||||
|
export class ConfigurationSearchPageGuard implements CanActivate {
|
||||||
|
canActivate(
|
||||||
|
route: ActivatedRouteSnapshot,
|
||||||
|
state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {
|
||||||
|
const configuration = route.params.configuration;
|
||||||
|
|
||||||
|
const newTitle = configuration + '.search.title';
|
||||||
|
|
||||||
|
route.data = { title: newTitle };
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
@@ -1,22 +0,0 @@
|
|||||||
import { Injectable } from '@angular/core';
|
|
||||||
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
|
|
||||||
import { Observable } from 'rxjs';
|
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
/**
|
|
||||||
* Assemble the correct i18n key for the filtered search page's title depending on the current route's filter parameter.
|
|
||||||
* The format of the key will be "{filter}.search.title" with:
|
|
||||||
* - filter: The current filter stored in route.params
|
|
||||||
*/
|
|
||||||
export class FilteredSearchPageGuard implements CanActivate {
|
|
||||||
canActivate(
|
|
||||||
route: ActivatedRouteSnapshot,
|
|
||||||
state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {
|
|
||||||
const filter = route.params.filter;
|
|
||||||
|
|
||||||
const newTitle = filter + '.search.title';
|
|
||||||
|
|
||||||
route.data = { title: newTitle };
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -2,14 +2,14 @@ import { NgModule } from '@angular/core';
|
|||||||
import { RouterModule } from '@angular/router';
|
import { RouterModule } from '@angular/router';
|
||||||
|
|
||||||
import { SearchPageComponent } from './search-page.component';
|
import { SearchPageComponent } from './search-page.component';
|
||||||
import { FilteredSearchPageComponent } from './filtered-search-page.component';
|
import { ConfigurationSearchPageGuard } from './configuration-search-page.guard';
|
||||||
import { FilteredSearchPageGuard } from './filtered-search-page.guard';
|
import { ConfigurationSearchPageComponent } from './configuration-search-page.component';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
RouterModule.forChild([
|
RouterModule.forChild([
|
||||||
{ path: '', component: SearchPageComponent, data: { title: 'search.title' } },
|
{ path: '', component: SearchPageComponent, data: { title: 'search.title' } },
|
||||||
{ path: ':filter', component: FilteredSearchPageComponent, canActivate: [FilteredSearchPageGuard]}
|
{ path: ':configuration', component: ConfigurationSearchPageComponent, canActivate: [ConfigurationSearchPageGuard]}
|
||||||
])
|
])
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
@@ -33,7 +33,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<ds-search-results [searchResults]="resultsRD$ | async"
|
<ds-search-results [searchResults]="resultsRD$ | async"
|
||||||
[searchConfig]="searchOptions$ | async"
|
[searchConfig]="searchOptions$ | async"
|
||||||
[fixedFilter]="fixedFilter$ | async"
|
[configuration]="configuration$ | async"
|
||||||
[disableHeader]="!searchEnabled"></ds-search-results>
|
[disableHeader]="!searchEnabled"></ds-search-results>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -88,10 +88,10 @@ export class SearchPageComponent implements OnInit {
|
|||||||
sideBarWidth = 3;
|
sideBarWidth = 3;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The currently applied filter (determines title of search)
|
* The currently applied configuration (determines title of search)
|
||||||
*/
|
*/
|
||||||
@Input()
|
@Input()
|
||||||
fixedFilter$: Observable<string>;
|
configuration$: Observable<string>;
|
||||||
|
|
||||||
constructor(protected service: SearchService,
|
constructor(protected service: SearchService,
|
||||||
protected sidebarService: SearchSidebarService,
|
protected sidebarService: SearchSidebarService,
|
||||||
@@ -119,8 +119,8 @@ export class SearchPageComponent implements OnInit {
|
|||||||
this.scopeListRD$ = this.searchConfigService.getCurrentScope('').pipe(
|
this.scopeListRD$ = this.searchConfigService.getCurrentScope('').pipe(
|
||||||
switchMap((scopeId) => this.service.getScopes(scopeId))
|
switchMap((scopeId) => this.service.getScopes(scopeId))
|
||||||
);
|
);
|
||||||
if (!isNotEmpty(this.fixedFilter$)) {
|
if (!isNotEmpty(this.configuration$)) {
|
||||||
this.fixedFilter$ = this.routeService.getRouteParameterValue('filter');
|
this.configuration$ = this.routeService.getRouteParameterValue('configuration');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -9,17 +9,17 @@ import {
|
|||||||
of as observableOf,
|
of as observableOf,
|
||||||
Subscription
|
Subscription
|
||||||
} from 'rxjs';
|
} from 'rxjs';
|
||||||
import { filter, flatMap, map, switchMap, tap } from 'rxjs/operators';
|
import { filter, flatMap, map, startWith, switchMap, tap } from 'rxjs/operators';
|
||||||
import { SortDirection, SortOptions } from '../../cache/models/sort-options.model';
|
import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model';
|
||||||
import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model';
|
import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model';
|
||||||
import { SearchOptions } from '../../../shared/search/search-options.model';
|
import { SearchOptions } from '../../../shared/search/search-options.model';
|
||||||
import { PaginatedSearchOptions } from '../../../shared/search/paginated-search-options.model';
|
import { PaginatedSearchOptions } from '../../../shared/search/paginated-search-options.model';
|
||||||
import { RouteService } from '../../../shared/services/route.service';
|
import { RouteService } from '../../../shared/services/route.service';
|
||||||
import { hasNoValue, hasValue, isNotEmpty, isNotEmptyOperator } from '../../../shared/empty.util';
|
import { hasNoValue, hasValue, isNotEmpty, isNotEmptyOperator } from '../../../shared/empty.util';
|
||||||
import { RemoteData } from '../../data/remote-data';
|
import { RemoteData } from '../../core/data/remote-data';
|
||||||
import { getSucceededRemoteData } from '../operators';
|
import { getSucceededRemoteData } from '../../core/shared/operators';
|
||||||
import { SearchFilter } from '../../../shared/search/search-filter.model';
|
import { SearchFilter } from '../../../shared/search/search-filter.model';
|
||||||
import { DSpaceObjectType } from '../dspace-object-type.model';
|
import { DSpaceObjectType } from '../../core/shared/dspace-object-type.model';
|
||||||
import { SearchFixedFilterService } from './search-fixed-filter.service';
|
import { SearchFixedFilterService } from './search-fixed-filter.service';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -109,9 +109,14 @@ export class SearchConfigurationService implements OnDestroy {
|
|||||||
* @returns {Observable<string>} Emits the current configuration string
|
* @returns {Observable<string>} Emits the current configuration string
|
||||||
*/
|
*/
|
||||||
getCurrentConfiguration(defaultConfiguration: string) {
|
getCurrentConfiguration(defaultConfiguration: string) {
|
||||||
return this.routeService.getQueryParameterValue('configuration').pipe(map((configuration) => {
|
return observableCombineLatest(
|
||||||
return configuration || defaultConfiguration;
|
this.routeService.getQueryParameterValue('configuration').pipe(startWith(undefined)),
|
||||||
}));
|
this.routeService.getRouteParameterValue('configuration').pipe(startWith(undefined))
|
||||||
|
).pipe(
|
||||||
|
map(([queryConfig, routeConfig]) => {
|
||||||
|
return queryConfig || routeConfig || defaultConfiguration;
|
||||||
|
})
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -4,14 +4,14 @@
|
|||||||
[innerHTML]="firstMetadataValue('dc.title')"></a>
|
[innerHTML]="firstMetadataValue('dc.title')"></a>
|
||||||
<span class="text-muted">
|
<span class="text-muted">
|
||||||
<ds-truncatable-part [id]="item.id" [minLines]="1">
|
<ds-truncatable-part [id]="item.id" [minLines]="1">
|
||||||
<span *ngIf="item.allMetadata(['journalvolume.identifier.volume']).length > 0"
|
<span *ngIf="item.allMetadata(['publicationvolume.volumeNumber']).length > 0"
|
||||||
class="item-list-journal-issues">
|
class="item-list-journal-issues">
|
||||||
<span *ngFor="let value of allMetadataValues(['journalvolume.identifier.volume']); let last=last;">
|
<span *ngFor="let value of allMetadataValues(['publicationvolume.volumeNumber']); let last=last;">
|
||||||
<span [innerHTML]="value"><span [innerHTML]="value"></span></span>
|
<span [innerHTML]="value"><span [innerHTML]="value"></span></span>
|
||||||
</span>
|
</span>
|
||||||
<span *ngIf="item.allMetadata(['journalissue.identifier.number']).length > 0"
|
<span *ngIf="item.allMetadata(['publicationissue.issueNumber']).length > 0"
|
||||||
class="item-list-journal-issue-numbers">
|
class="item-list-journal-issue-numbers">
|
||||||
<span *ngFor="let value of allMetadataValues(['journalissue.identifier.number']); let last=last;">
|
<span *ngFor="let value of allMetadataValues(['publicationissue.issueNumber']); let last=last;">
|
||||||
<span> - </span><span [innerHTML]="value"><span [innerHTML]="value"></span></span>
|
<span> - </span><span [innerHTML]="value"><span [innerHTML]="value"></span></span>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
|
@@ -20,13 +20,13 @@ const mockItemWithMetadata: Item = Object.assign(new Item(), {
|
|||||||
value: 'This is just another title'
|
value: 'This is just another title'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
'journalvolume.identifier.volume': [
|
'publicationvolume.volumeNumber': [
|
||||||
{
|
{
|
||||||
language: 'en_US',
|
language: 'en_US',
|
||||||
value: '1234'
|
value: '1234'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
'journalissue.identifier.number': [
|
'publicationissue.issueNumber': [
|
||||||
{
|
{
|
||||||
language: 'en_US',
|
language: 'en_US',
|
||||||
value: '5678'
|
value: '5678'
|
||||||
|
@@ -10,9 +10,9 @@
|
|||||||
<span [innerHTML]="value"><span [innerHTML]="value"></span></span>
|
<span [innerHTML]="value"><span [innerHTML]="value"></span></span>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
<span *ngIf="item.allMetadata(['journalvolume.identifier.volume']).length > 0"
|
<span *ngIf="item.allMetadata(['publicationvolume.volumeNumber']).length > 0"
|
||||||
class="item-list-journal-volume-identifiers">
|
class="item-list-journal-volume-identifiers">
|
||||||
<span *ngFor="let value of allMetadataValues(['journalvolume.identifier.volume']); let last=last;">
|
<span *ngFor="let value of allMetadataValues(['publicationvolume.volumeNumber']); let last=last;">
|
||||||
<span> (</span><span [innerHTML]="value"><span [innerHTML]="value"></span></span><span>)</span>
|
<span> (</span><span [innerHTML]="value"><span [innerHTML]="value"></span></span><span>)</span>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
|
@@ -26,7 +26,7 @@ const mockItemWithMetadata: Item = Object.assign(new Item(), {
|
|||||||
value: 'This is just another journal title'
|
value: 'This is just another journal title'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
'journalvolume.identifier.volume': [
|
'publicationvolume.volumeNumber': [
|
||||||
{
|
{
|
||||||
language: 'en_US',
|
language: 'en_US',
|
||||||
value: '1234'
|
value: '1234'
|
||||||
|
@@ -4,9 +4,9 @@
|
|||||||
[innerHTML]="firstMetadataValue('dc.title')"></a>
|
[innerHTML]="firstMetadataValue('dc.title')"></a>
|
||||||
<span class="text-muted">
|
<span class="text-muted">
|
||||||
<ds-truncatable-part [id]="item.id" [minLines]="1">
|
<ds-truncatable-part [id]="item.id" [minLines]="1">
|
||||||
<span *ngIf="item.allMetadata(['journal.identifier.issn']).length > 0"
|
<span *ngIf="item.allMetadata(['creativeworkseries.issn']).length > 0"
|
||||||
class="item-list-journals">
|
class="item-list-journals">
|
||||||
<span *ngFor="let value of allMetadataValues(['journal.identifier.issn']); let last=last;">
|
<span *ngFor="let value of allMetadataValues(['creativeworkseries.issn']); let last=last;">
|
||||||
<span [innerHTML]="value"><span [innerHTML]="value"></span></span>
|
<span [innerHTML]="value"><span [innerHTML]="value"></span></span>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
|
@@ -20,7 +20,7 @@ const mockItemWithMetadata: Item = Object.assign(new Item(), {
|
|||||||
value: 'This is just another title'
|
value: 'This is just another title'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
'journal.identifier.issn': [
|
'creativeworkseries.issn': [
|
||||||
{
|
{
|
||||||
language: 'en_US',
|
language: 'en_US',
|
||||||
value: '1234'
|
value: '1234'
|
||||||
|
@@ -7,11 +7,15 @@
|
|||||||
<ds-thumbnail [thumbnail]="this.item.getThumbnail() | async"></ds-thumbnail>
|
<ds-thumbnail [thumbnail]="this.item.getThumbnail() | async"></ds-thumbnail>
|
||||||
</ds-metadata-field-wrapper>
|
</ds-metadata-field-wrapper>
|
||||||
<ds-generic-item-page-field [item]="item"
|
<ds-generic-item-page-field [item]="item"
|
||||||
[fields]="['journalissue.identifier.number']"
|
[fields]="['publicationvolume.volumeNumber']"
|
||||||
|
[label]="'journalvolume.page.volume'">
|
||||||
|
</ds-generic-item-page-field>
|
||||||
|
<ds-generic-item-page-field [item]="item"
|
||||||
|
[fields]="['publicationissue.issueNumber']"
|
||||||
[label]="'journalissue.page.number'">
|
[label]="'journalissue.page.number'">
|
||||||
</ds-generic-item-page-field>
|
</ds-generic-item-page-field>
|
||||||
<ds-generic-item-page-field [item]="item"
|
<ds-generic-item-page-field [item]="item"
|
||||||
[fields]="['journalissue.issuedate']"
|
[fields]="['creativework.datePublished']"
|
||||||
[label]="'journalissue.page.issuedate'">
|
[label]="'journalissue.page.issuedate'">
|
||||||
</ds-generic-item-page-field>
|
</ds-generic-item-page-field>
|
||||||
<ds-generic-item-page-field [item]="item"
|
<ds-generic-item-page-field [item]="item"
|
||||||
@@ -19,7 +23,7 @@
|
|||||||
[label]="'journalissue.page.journal-title'">
|
[label]="'journalissue.page.journal-title'">
|
||||||
</ds-generic-item-page-field>
|
</ds-generic-item-page-field>
|
||||||
<ds-generic-item-page-field [item]="item"
|
<ds-generic-item-page-field [item]="item"
|
||||||
[fields]="['journal.identifier.issn']"
|
[fields]="['creativeworkseries.issn']"
|
||||||
[label]="'journalissue.page.journal-issn'">
|
[label]="'journalissue.page.journal-issn'">
|
||||||
</ds-generic-item-page-field>
|
</ds-generic-item-page-field>
|
||||||
</div>
|
</div>
|
||||||
@@ -34,11 +38,11 @@
|
|||||||
[label]="'relationships.isPublicationOfJournalIssue' | translate">
|
[label]="'relationships.isPublicationOfJournalIssue' | translate">
|
||||||
</ds-related-items>
|
</ds-related-items>
|
||||||
<ds-generic-item-page-field [item]="item"
|
<ds-generic-item-page-field [item]="item"
|
||||||
[fields]="['journalissue.identifier.description']"
|
[fields]="['dc.description']"
|
||||||
[label]="'journalissue.page.description'">
|
[label]="'journalissue.page.description'">
|
||||||
</ds-generic-item-page-field>
|
</ds-generic-item-page-field>
|
||||||
<ds-generic-item-page-field [item]="item"
|
<ds-generic-item-page-field [item]="item"
|
||||||
[fields]="['journalissue.identifier.keyword']"
|
[fields]="['creativework.keywords']"
|
||||||
[label]="'journalissue.page.keyword'">
|
[label]="'journalissue.page.keyword'">
|
||||||
</ds-generic-item-page-field>
|
</ds-generic-item-page-field>
|
||||||
<div>
|
<div>
|
||||||
|
@@ -12,25 +12,25 @@ import {
|
|||||||
const mockItem: Item = Object.assign(new Item(), {
|
const mockItem: Item = Object.assign(new Item(), {
|
||||||
bitstreams: observableOf(new RemoteData(false, false, true, null, new PaginatedList(new PageInfo(), []))),
|
bitstreams: observableOf(new RemoteData(false, false, true, null, new PaginatedList(new PageInfo(), []))),
|
||||||
metadata: {
|
metadata: {
|
||||||
'journalissue.identifier.number': [
|
'publicationissue.issueNumber': [
|
||||||
{
|
{
|
||||||
language: 'en_US',
|
language: 'en_US',
|
||||||
value: '1234'
|
value: '1234'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
'journalissue.issuedate': [
|
'creativework.datePublished': [
|
||||||
{
|
{
|
||||||
language: 'en_US',
|
language: 'en_US',
|
||||||
value: '2018'
|
value: '2018'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
'journalissue.identifier.description': [
|
'dc.description': [
|
||||||
{
|
{
|
||||||
language: 'en_US',
|
language: 'en_US',
|
||||||
value: 'desc'
|
value: 'desc'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
'journalissue.identifier.keyword': [
|
'creativework.keywords': [
|
||||||
{
|
{
|
||||||
language: 'en_US',
|
language: 'en_US',
|
||||||
value: 'keyword'
|
value: 'keyword'
|
||||||
|
@@ -7,11 +7,11 @@
|
|||||||
<ds-thumbnail [thumbnail]="this.item.getThumbnail() | async"></ds-thumbnail>
|
<ds-thumbnail [thumbnail]="this.item.getThumbnail() | async"></ds-thumbnail>
|
||||||
</ds-metadata-field-wrapper>
|
</ds-metadata-field-wrapper>
|
||||||
<ds-generic-item-page-field [item]="item"
|
<ds-generic-item-page-field [item]="item"
|
||||||
[fields]="['journalvolume.identifier.volume']"
|
[fields]="['publicationvolume.volumeNumber']"
|
||||||
[label]="'journalvolume.page.volume'">
|
[label]="'journalvolume.page.volume'">
|
||||||
</ds-generic-item-page-field>
|
</ds-generic-item-page-field>
|
||||||
<ds-generic-item-page-field [item]="item"
|
<ds-generic-item-page-field [item]="item"
|
||||||
[fields]="['journalvolume.issuedate']"
|
[fields]="['creativework.datePublished']"
|
||||||
[label]="'journalvolume.page.issuedate'">
|
[label]="'journalvolume.page.issuedate'">
|
||||||
</ds-generic-item-page-field>
|
</ds-generic-item-page-field>
|
||||||
</div>
|
</div>
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
[label]="'relationships.isIssueOf' | translate">
|
[label]="'relationships.isIssueOf' | translate">
|
||||||
</ds-related-items>
|
</ds-related-items>
|
||||||
<ds-generic-item-page-field [item]="item"
|
<ds-generic-item-page-field [item]="item"
|
||||||
[fields]="['journalvolume.identifier.description']"
|
[fields]="['dc.description']"
|
||||||
[label]="'journalvolume.page.description'">
|
[label]="'journalvolume.page.description'">
|
||||||
</ds-generic-item-page-field>
|
</ds-generic-item-page-field>
|
||||||
<div>
|
<div>
|
||||||
|
@@ -12,19 +12,19 @@ import {
|
|||||||
const mockItem: Item = Object.assign(new Item(), {
|
const mockItem: Item = Object.assign(new Item(), {
|
||||||
bitstreams: observableOf(new RemoteData(false, false, true, null, new PaginatedList(new PageInfo(), []))),
|
bitstreams: observableOf(new RemoteData(false, false, true, null, new PaginatedList(new PageInfo(), []))),
|
||||||
metadata: {
|
metadata: {
|
||||||
'journalvolume.identifier.volume': [
|
'publicationvolume.volumeNumber': [
|
||||||
{
|
{
|
||||||
language: 'en_US',
|
language: 'en_US',
|
||||||
value: '1234'
|
value: '1234'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
'journalvolume.issuedate': [
|
'creativework.datePublished': [
|
||||||
{
|
{
|
||||||
language: 'en_US',
|
language: 'en_US',
|
||||||
value: '2018'
|
value: '2018'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
'journalvolume.identifier.description': [
|
'dc.description': [
|
||||||
{
|
{
|
||||||
language: 'en_US',
|
language: 'en_US',
|
||||||
value: 'desc'
|
value: 'desc'
|
||||||
|
@@ -7,15 +7,15 @@
|
|||||||
<ds-thumbnail [thumbnail]="this.item.getThumbnail() | async"></ds-thumbnail>
|
<ds-thumbnail [thumbnail]="this.item.getThumbnail() | async"></ds-thumbnail>
|
||||||
</ds-metadata-field-wrapper>
|
</ds-metadata-field-wrapper>
|
||||||
<ds-generic-item-page-field class="item-page-fields" [item]="item"
|
<ds-generic-item-page-field class="item-page-fields" [item]="item"
|
||||||
[fields]="['journal.identifier.issn']"
|
[fields]="['creativeworkseries.issn']"
|
||||||
[label]="'journal.page.issn'">
|
[label]="'journal.page.issn'">
|
||||||
</ds-generic-item-page-field>
|
</ds-generic-item-page-field>
|
||||||
<ds-generic-item-page-field class="item-page-fields" [item]="item"
|
<ds-generic-item-page-field class="item-page-fields" [item]="item"
|
||||||
[fields]="['journal.publisher']"
|
[fields]="['creativework.publisher']"
|
||||||
[label]="'journal.page.publisher'">
|
[label]="'journal.page.publisher'">
|
||||||
</ds-generic-item-page-field>
|
</ds-generic-item-page-field>
|
||||||
<ds-generic-item-page-field [item]="item"
|
<ds-generic-item-page-field [item]="item"
|
||||||
[fields]="['journal.contributor.editor']"
|
[fields]="['creativework.editor']"
|
||||||
[label]="'journal.page.editor'">
|
[label]="'journal.page.editor'">
|
||||||
</ds-generic-item-page-field>
|
</ds-generic-item-page-field>
|
||||||
</div>
|
</div>
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
[label]="'relationships.isVolumeOf' | translate">
|
[label]="'relationships.isVolumeOf' | translate">
|
||||||
</ds-related-items>
|
</ds-related-items>
|
||||||
<ds-generic-item-page-field class="item-page-fields" [item]="item"
|
<ds-generic-item-page-field class="item-page-fields" [item]="item"
|
||||||
[fields]="['journal.identifier.description']"
|
[fields]="['dc.description']"
|
||||||
[label]="'journal.page.description'">
|
[label]="'journal.page.description'">
|
||||||
</ds-generic-item-page-field>
|
</ds-generic-item-page-field>
|
||||||
<div>
|
<div>
|
||||||
|
@@ -22,19 +22,19 @@ let fixture: ComponentFixture<JournalComponent>;
|
|||||||
const mockItem: Item = Object.assign(new Item(), {
|
const mockItem: Item = Object.assign(new Item(), {
|
||||||
bitstreams: observableOf(new RemoteData(false, false, true, null, new PaginatedList(new PageInfo(), []))),
|
bitstreams: observableOf(new RemoteData(false, false, true, null, new PaginatedList(new PageInfo(), []))),
|
||||||
metadata: {
|
metadata: {
|
||||||
'journal.identifier.issn': [
|
'creativeworkseries.issn': [
|
||||||
{
|
{
|
||||||
language: 'en_US',
|
language: 'en_US',
|
||||||
value: '1234'
|
value: '1234'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
'journal.publisher': [
|
'creativework.publisher': [
|
||||||
{
|
{
|
||||||
language: 'en_US',
|
language: 'en_US',
|
||||||
value: 'a publisher'
|
value: 'a publisher'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
'journal.identifier.description': [
|
'dc.description': [
|
||||||
{
|
{
|
||||||
language: 'en_US',
|
language: 'en_US',
|
||||||
value: 'desc'
|
value: 'desc'
|
||||||
|
@@ -1,13 +1,13 @@
|
|||||||
<ds-truncatable [id]="item.id">
|
<ds-truncatable [id]="item.id">
|
||||||
<a
|
<a
|
||||||
[routerLink]="['/items/' + item.id]" class="lead"
|
[routerLink]="['/items/' + item.id]" class="lead"
|
||||||
[innerHTML]="firstMetadataValue('orgunit.identifier.name')"></a>
|
[innerHTML]="firstMetadataValue('organization.legalName')"></a>
|
||||||
<span class="text-muted">
|
<span class="text-muted">
|
||||||
<ds-truncatable-part [id]="item.id" [minLines]="3">
|
<ds-truncatable-part [id]="item.id" [minLines]="3">
|
||||||
<span *ngIf="item.allMetadata(['orgunit.identifier.description']).length > 0"
|
<span *ngIf="item.allMetadata(['dc.description']).length > 0"
|
||||||
class="item-list-orgunit-description">
|
class="item-list-orgunit-description">
|
||||||
<ds-truncatable-part [id]="item.id" [minLines]="3"><span
|
<ds-truncatable-part [id]="item.id" [minLines]="3"><span
|
||||||
[innerHTML]="firstMetadataValue('orgunit.identifier.description')"></span>
|
[innerHTML]="firstMetadataValue('dc.description')"></span>
|
||||||
</ds-truncatable-part>
|
</ds-truncatable-part>
|
||||||
</span>
|
</span>
|
||||||
</ds-truncatable-part>
|
</ds-truncatable-part>
|
||||||
|
@@ -20,7 +20,7 @@ const mockItemWithMetadata: Item = Object.assign(new Item(), {
|
|||||||
value: 'This is just another title'
|
value: 'This is just another title'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
'orgunit.identifier.description': [
|
'dc.description': [
|
||||||
{
|
{
|
||||||
language: 'en_US',
|
language: 'en_US',
|
||||||
value: 'A description about the OrgUnit'
|
value: 'A description about the OrgUnit'
|
||||||
|
@@ -1,13 +1,13 @@
|
|||||||
<ng-template #descTemplate>
|
<ng-template #descTemplate>
|
||||||
<span class="text-muted">
|
<span class="text-muted">
|
||||||
<span *ngIf="item.allMetadata(['orgunit.identifier.description']).length > 0"
|
<span *ngIf="item.allMetadata(['dc.description']).length > 0"
|
||||||
class="item-list-job-title">
|
class="item-list-job-title">
|
||||||
<span [innerHTML]="firstMetadataValue(['orgunit.identifier.description'])"></span>
|
<span [innerHTML]="firstMetadataValue(['dc.description'])"></span>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
<ds-truncatable [id]="item.id">
|
<ds-truncatable [id]="item.id">
|
||||||
<a [routerLink]="['/items/' + item.id]"
|
<a [routerLink]="['/items/' + item.id]"
|
||||||
[innerHTML]="firstMetadataValue('orgunit.identifier.name')"
|
[innerHTML]="firstMetadataValue('organization.legalName')"
|
||||||
[tooltip]="descTemplate"></a>
|
[tooltip]="descTemplate"></a>
|
||||||
</ds-truncatable>
|
</ds-truncatable>
|
||||||
|
@@ -1,12 +1,12 @@
|
|||||||
<ds-truncatable [id]="item.id">
|
<ds-truncatable [id]="item.id">
|
||||||
<a
|
<a
|
||||||
[routerLink]="['/items/' + item.id]" class="lead"
|
[routerLink]="['/items/' + item.id]" class="lead"
|
||||||
[innerHTML]="firstMetadataValue('dc.contributor.author')"></a>
|
[innerHTML]="firstMetadataValue('person.familyName') + ', ' + firstMetadataValue('person.givenName')"></a>
|
||||||
<span class="text-muted">
|
<span class="text-muted">
|
||||||
<ds-truncatable-part [id]="item.id" [minLines]="1">
|
<ds-truncatable-part [id]="item.id" [minLines]="1">
|
||||||
<span *ngIf="item.allMetadata(['person.identifier.jobtitle']).length > 0"
|
<span *ngIf="item.allMetadata(['person.jobTitle']).length > 0"
|
||||||
class="item-list-job-title">
|
class="item-list-job-title">
|
||||||
<span *ngFor="let value of allMetadataValues(['person.identifier.jobtitle']); let last=last;">
|
<span *ngFor="let value of allMetadataValues(['person.jobTitle']); let last=last;">
|
||||||
<span [innerHTML]="value"><span [innerHTML]="value"></span></span>
|
<span [innerHTML]="value"><span [innerHTML]="value"></span></span>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
|
@@ -20,7 +20,7 @@ const mockItemWithMetadata: Item = Object.assign(new Item(), {
|
|||||||
value: 'This is just another title'
|
value: 'This is just another title'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
'person.identifier.jobtitle': [
|
'person.jobTitle': [
|
||||||
{
|
{
|
||||||
language: 'en_US',
|
language: 'en_US',
|
||||||
value: 'Developer'
|
value: 'Developer'
|
||||||
|
@@ -1,8 +1,8 @@
|
|||||||
<ng-template #descTemplate>
|
<ng-template #descTemplate>
|
||||||
<span class="text-muted">
|
<span class="text-muted">
|
||||||
<span *ngIf="item.allMetadata(['person.identifier.jobtitle']).length > 0"
|
<span *ngIf="item.allMetadata(['person.jobTitle']).length > 0"
|
||||||
class="item-list-job-title">
|
class="item-list-job-title">
|
||||||
<span *ngFor="let value of allMetadataValues(['person.identifier.jobtitle']); let last=last;">
|
<span *ngFor="let value of allMetadataValues(['person.jobTitle']); let last=last;">
|
||||||
<span [innerHTML]="value"><span [innerHTML]="value"></span></span>
|
<span [innerHTML]="value"><span [innerHTML]="value"></span></span>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
@@ -10,6 +10,6 @@
|
|||||||
</ng-template>
|
</ng-template>
|
||||||
<ds-truncatable [id]="item.id">
|
<ds-truncatable [id]="item.id">
|
||||||
<a [routerLink]="['/items/' + item.id]"
|
<a [routerLink]="['/items/' + item.id]"
|
||||||
[innerHTML]="firstMetadataValue('dc.contributor.author')"
|
[innerHTML]="firstMetadataValue('person.familyName') + ', ' + firstMetadataValue('person.givenName')"
|
||||||
[tooltip]="descTemplate"></a>
|
[tooltip]="descTemplate"></a>
|
||||||
</ds-truncatable>
|
</ds-truncatable>
|
||||||
|
@@ -1,16 +1,16 @@
|
|||||||
<ds-truncatable [id]="item.id">
|
<ds-truncatable [id]="item.id">
|
||||||
<a
|
<a
|
||||||
[routerLink]="['/items/' + item.id]" class="lead"
|
[routerLink]="['/items/' + item.id]" class="lead"
|
||||||
[innerHTML]="firstMetadataValue('project.identifier.name')"></a>
|
[innerHTML]="firstMetadataValue('dc.title')"></a>
|
||||||
<span class="text-muted">
|
<!--<span class="text-muted">-->
|
||||||
<ds-truncatable-part [id]="item.id" [minLines]="1">
|
<!--<ds-truncatable-part [id]="item.id" [minLines]="1">-->
|
||||||
<span *ngIf="item.allMetadata(['project.identifier.status']).length > 0"
|
<!--<span *ngIf="item.allMetadata(['project.identifier.status']).length > 0"-->
|
||||||
class="item-list-status">
|
<!--class="item-list-status">-->
|
||||||
<span *ngFor="let value of allMetadataValues(['project.identifier.status']); let last=last;">
|
<!--<span *ngFor="let value of allMetadataValues(['project.identifier.status']); let last=last;">-->
|
||||||
<span [innerHTML]="value"><span [innerHTML]="value"></span></span>
|
<!--<span [innerHTML]="value"><span [innerHTML]="value"></span></span>-->
|
||||||
</span>
|
<!--</span>-->
|
||||||
</span>
|
<!--</span>-->
|
||||||
</ds-truncatable-part>
|
<!--</ds-truncatable-part>-->
|
||||||
</span>
|
<!--</span>-->
|
||||||
</ds-truncatable>
|
</ds-truncatable>
|
||||||
|
|
||||||
|
@@ -20,12 +20,12 @@ const mockItemWithMetadata: Item = Object.assign(new Item(), {
|
|||||||
value: 'This is just another title'
|
value: 'This is just another title'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
'project.identifier.status': [
|
// 'project.identifier.status': [
|
||||||
{
|
// {
|
||||||
language: 'en_US',
|
// language: 'en_US',
|
||||||
value: 'A status about the project'
|
// value: 'A status about the project'
|
||||||
}
|
// }
|
||||||
]
|
// ]
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
const mockItemWithoutMetadata: Item = Object.assign(new Item(), {
|
const mockItemWithoutMetadata: Item = Object.assign(new Item(), {
|
||||||
@@ -61,27 +61,27 @@ describe('ProjectListElementComponent', () => {
|
|||||||
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
describe('When the item has a status', () => {
|
// describe('When the item has a status', () => {
|
||||||
beforeEach(() => {
|
// beforeEach(() => {
|
||||||
projectListElementComponent.item = mockItemWithMetadata;
|
// projectListElementComponent.item = mockItemWithMetadata;
|
||||||
fixture.detectChanges();
|
// fixture.detectChanges();
|
||||||
});
|
// });
|
||||||
|
//
|
||||||
it('should show the status span', () => {
|
// it('should show the status span', () => {
|
||||||
const statusField = fixture.debugElement.query(By.css('span.item-list-status'));
|
// const statusField = fixture.debugElement.query(By.css('span.item-list-status'));
|
||||||
expect(statusField).not.toBeNull();
|
// expect(statusField).not.toBeNull();
|
||||||
});
|
// });
|
||||||
});
|
// });
|
||||||
|
//
|
||||||
describe('When the item has no status', () => {
|
// describe('When the item has no status', () => {
|
||||||
beforeEach(() => {
|
// beforeEach(() => {
|
||||||
projectListElementComponent.item = mockItemWithoutMetadata;
|
// projectListElementComponent.item = mockItemWithoutMetadata;
|
||||||
fixture.detectChanges();
|
// fixture.detectChanges();
|
||||||
});
|
// });
|
||||||
|
//
|
||||||
it('should not show the status span', () => {
|
// it('should not show the status span', () => {
|
||||||
const statusField = fixture.debugElement.query(By.css('span.item-list-status'));
|
// const statusField = fixture.debugElement.query(By.css('span.item-list-status'));
|
||||||
expect(statusField).toBeNull();
|
// expect(statusField).toBeNull();
|
||||||
});
|
// });
|
||||||
});
|
// });
|
||||||
});
|
});
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
<h2 class="item-page-title-field">
|
<h2 class="item-page-title-field">
|
||||||
{{'orgunit.page.titleprefix' | translate}}<ds-metadata-values [mdValues]="item?.allMetadata(['orgunit.identifier.name'])"></ds-metadata-values>
|
{{'orgunit.page.titleprefix' | translate}}<ds-metadata-values [mdValues]="item?.allMetadata(['organization.legalName'])"></ds-metadata-values>
|
||||||
</h2>
|
</h2>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-xs-12 col-md-4">
|
<div class="col-xs-12 col-md-4">
|
||||||
@@ -7,19 +7,19 @@
|
|||||||
<ds-thumbnail [thumbnail]="this.item.getThumbnail() | async" [defaultImage]="'assets/images/orgunit-placeholder.svg'"></ds-thumbnail>
|
<ds-thumbnail [thumbnail]="this.item.getThumbnail() | async" [defaultImage]="'assets/images/orgunit-placeholder.svg'"></ds-thumbnail>
|
||||||
</ds-metadata-field-wrapper>
|
</ds-metadata-field-wrapper>
|
||||||
<ds-generic-item-page-field [item]="item"
|
<ds-generic-item-page-field [item]="item"
|
||||||
[fields]="['orgunit.identifier.dateestablished']"
|
[fields]="['organization.foundingDate']"
|
||||||
[label]="'orgunit.page.dateestablished'">
|
[label]="'orgunit.page.dateestablished'">
|
||||||
</ds-generic-item-page-field>
|
</ds-generic-item-page-field>
|
||||||
<ds-generic-item-page-field [item]="item"
|
<ds-generic-item-page-field [item]="item"
|
||||||
[fields]="['orgunit.identifier.city']"
|
[fields]="['organization.address.addressLocality']"
|
||||||
[label]="'orgunit.page.city'">
|
[label]="'orgunit.page.city'">
|
||||||
</ds-generic-item-page-field>
|
</ds-generic-item-page-field>
|
||||||
<ds-generic-item-page-field [item]="item"
|
<ds-generic-item-page-field [item]="item"
|
||||||
[fields]="['orgunit.identifier.country']"
|
[fields]="['organization.adress.addressCountry']"
|
||||||
[label]="'orgunit.page.country'">
|
[label]="'orgunit.page.country'">
|
||||||
</ds-generic-item-page-field>
|
</ds-generic-item-page-field>
|
||||||
<ds-generic-item-page-field [item]="item"
|
<ds-generic-item-page-field [item]="item"
|
||||||
[fields]="['orgunit.identifier.id']"
|
[fields]="['dc.identifier']"
|
||||||
[label]="'orgunit.page.id'">
|
[label]="'orgunit.page.id'">
|
||||||
</ds-generic-item-page-field>
|
</ds-generic-item-page-field>
|
||||||
</div>
|
</div>
|
||||||
@@ -37,7 +37,7 @@
|
|||||||
[label]="'relationships.isPublicationOf' | translate">
|
[label]="'relationships.isPublicationOf' | translate">
|
||||||
</ds-related-items>
|
</ds-related-items>
|
||||||
<ds-generic-item-page-field [item]="item"
|
<ds-generic-item-page-field [item]="item"
|
||||||
[fields]="['orgunit.identifier.description']"
|
[fields]="['dc.description']"
|
||||||
[label]="'orgunit.page.description'">
|
[label]="'orgunit.page.description'">
|
||||||
</ds-generic-item-page-field>
|
</ds-generic-item-page-field>
|
||||||
<div>
|
<div>
|
||||||
|
@@ -12,31 +12,31 @@ import {
|
|||||||
const mockItem: Item = Object.assign(new Item(), {
|
const mockItem: Item = Object.assign(new Item(), {
|
||||||
bitstreams: observableOf(new RemoteData(false, false, true, null, new PaginatedList(new PageInfo(), []))),
|
bitstreams: observableOf(new RemoteData(false, false, true, null, new PaginatedList(new PageInfo(), []))),
|
||||||
metadata: {
|
metadata: {
|
||||||
'orgunit.identifier.dateestablished': [
|
'organization.foundingDate': [
|
||||||
{
|
{
|
||||||
language: 'en_US',
|
language: 'en_US',
|
||||||
value: '2018'
|
value: '2018'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
'orgunit.identifier.city': [
|
'organization.address.addressLocality': [
|
||||||
{
|
{
|
||||||
language: 'en_US',
|
language: 'en_US',
|
||||||
value: 'New York'
|
value: 'New York'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
'orgunit.identifier.country': [
|
'organization.adress.addressCountry': [
|
||||||
{
|
{
|
||||||
language: 'en_US',
|
language: 'en_US',
|
||||||
value: 'USA'
|
value: 'USA'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
'orgunit.identifier.id': [
|
'dc.identifier': [
|
||||||
{
|
{
|
||||||
language: 'en_US',
|
language: 'en_US',
|
||||||
value: '1'
|
value: '1'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
'orgunit.identifier.description': [
|
'dc.description': [
|
||||||
{
|
{
|
||||||
language: 'en_US',
|
language: 'en_US',
|
||||||
value: 'desc'
|
value: 'desc'
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
<h2 class="item-page-title-field">
|
<h2 class="item-page-title-field">
|
||||||
{{'person.page.titleprefix' | translate}}<ds-metadata-values [mdValues]="item?.allMetadata(['dc.contributor.author'])"></ds-metadata-values>
|
{{'person.page.titleprefix' | translate}}<ds-metadata-values [mdValues]="[item?.firstMetadata('person.familyName'), item?.firstMetadata('person.givenName')]" [separator]="', '"></ds-metadata-values>
|
||||||
</h2>
|
</h2>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-xs-12 col-md-4">
|
<div class="col-xs-12 col-md-4">
|
||||||
@@ -7,21 +7,21 @@
|
|||||||
<ds-thumbnail [thumbnail]="this.item.getThumbnail() | async" [defaultImage]="'assets/images/person-placeholder.svg'"></ds-thumbnail>
|
<ds-thumbnail [thumbnail]="this.item.getThumbnail() | async" [defaultImage]="'assets/images/person-placeholder.svg'"></ds-thumbnail>
|
||||||
</ds-metadata-field-wrapper>
|
</ds-metadata-field-wrapper>
|
||||||
<ds-generic-item-page-field [item]="item"
|
<ds-generic-item-page-field [item]="item"
|
||||||
[fields]="['person.identifier.email']"
|
[fields]="['person.email']"
|
||||||
[label]="'person.page.email'">
|
[label]="'person.page.email'">
|
||||||
</ds-generic-item-page-field>
|
</ds-generic-item-page-field>
|
||||||
|
<!--<ds-generic-item-page-field [item]="item"-->
|
||||||
|
<!--[fields]="['person.identifier.orcid']"-->
|
||||||
|
<!--[label]="'person.page.orcid'">-->
|
||||||
|
<!--</ds-generic-item-page-field>-->
|
||||||
<ds-generic-item-page-field [item]="item"
|
<ds-generic-item-page-field [item]="item"
|
||||||
[fields]="['person.identifier.orcid']"
|
[fields]="['person.birthDate']"
|
||||||
[label]="'person.page.orcid'">
|
|
||||||
</ds-generic-item-page-field>
|
|
||||||
<ds-generic-item-page-field [item]="item"
|
|
||||||
[fields]="['person.identifier.birthdate']"
|
|
||||||
[label]="'person.page.birthdate'">
|
[label]="'person.page.birthdate'">
|
||||||
</ds-generic-item-page-field>
|
</ds-generic-item-page-field>
|
||||||
<ds-generic-item-page-field [item]="item"
|
<!--<ds-generic-item-page-field [item]="item"-->
|
||||||
[fields]="['person.identifier.staffid']"
|
<!--[fields]="['person.identifier.staffid']"-->
|
||||||
[label]="'person.page.staffid'">
|
<!--[label]="'person.page.staffid'">-->
|
||||||
</ds-generic-item-page-field>
|
<!--</ds-generic-item-page-field>-->
|
||||||
</div>
|
</div>
|
||||||
<div class="col-xs-12 col-md-6">
|
<div class="col-xs-12 col-md-6">
|
||||||
<ds-related-items
|
<ds-related-items
|
||||||
@@ -33,15 +33,15 @@
|
|||||||
[label]="'relationships.isOrgUnitOf' | translate">
|
[label]="'relationships.isOrgUnitOf' | translate">
|
||||||
</ds-related-items>
|
</ds-related-items>
|
||||||
<ds-generic-item-page-field [item]="item"
|
<ds-generic-item-page-field [item]="item"
|
||||||
[fields]="['person.identifier.jobtitle']"
|
[fields]="['person.jobTitle']"
|
||||||
[label]="'person.page.jobtitle'">
|
[label]="'person.page.jobtitle'">
|
||||||
</ds-generic-item-page-field>
|
</ds-generic-item-page-field>
|
||||||
<ds-generic-item-page-field [item]="item"
|
<ds-generic-item-page-field [item]="item"
|
||||||
[fields]="['person.identifier.lastname']"
|
[fields]="['person.familyName']"
|
||||||
[label]="'person.page.lastname'">
|
[label]="'person.page.lastname'">
|
||||||
</ds-generic-item-page-field>
|
</ds-generic-item-page-field>
|
||||||
<ds-generic-item-page-field [item]="item"
|
<ds-generic-item-page-field [item]="item"
|
||||||
[fields]="['person.identifier.firstname']"
|
[fields]="['person.givenName']"
|
||||||
[label]="'person.page.firstname'">
|
[label]="'person.page.firstname'">
|
||||||
</ds-generic-item-page-field>
|
</ds-generic-item-page-field>
|
||||||
<div>
|
<div>
|
||||||
|
@@ -12,43 +12,43 @@ import {
|
|||||||
const mockItem: Item = Object.assign(new Item(), {
|
const mockItem: Item = Object.assign(new Item(), {
|
||||||
bitstreams: observableOf(new RemoteData(false, false, true, null, new PaginatedList(new PageInfo(), []))),
|
bitstreams: observableOf(new RemoteData(false, false, true, null, new PaginatedList(new PageInfo(), []))),
|
||||||
metadata: {
|
metadata: {
|
||||||
'person.identifier.email': [
|
'person.email': [
|
||||||
{
|
{
|
||||||
language: 'en_US',
|
language: 'en_US',
|
||||||
value: 'fake@email.com'
|
value: 'fake@email.com'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
'person.identifier.orcid': [
|
// 'person.identifier.orcid': [
|
||||||
{
|
// {
|
||||||
language: 'en_US',
|
// language: 'en_US',
|
||||||
value: 'ORCID-1'
|
// value: 'ORCID-1'
|
||||||
}
|
// }
|
||||||
],
|
// ],
|
||||||
'person.identifier.birthdate': [
|
'person.birthDate': [
|
||||||
{
|
{
|
||||||
language: 'en_US',
|
language: 'en_US',
|
||||||
value: '1993'
|
value: '1993'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
'person.identifier.staffid': [
|
// 'person.identifier.staffid': [
|
||||||
{
|
// {
|
||||||
language: 'en_US',
|
// language: 'en_US',
|
||||||
value: '1'
|
// value: '1'
|
||||||
}
|
// }
|
||||||
],
|
// ],
|
||||||
'person.identifier.jobtitle': [
|
'person.jobTitle': [
|
||||||
{
|
{
|
||||||
language: 'en_US',
|
language: 'en_US',
|
||||||
value: 'Developer'
|
value: 'Developer'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
'person.identifier.lastname': [
|
'person.familyName': [
|
||||||
{
|
{
|
||||||
language: 'en_US',
|
language: 'en_US',
|
||||||
value: 'Doe'
|
value: 'Doe'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
'person.identifier.firstname': [
|
'person.givenName': [
|
||||||
{
|
{
|
||||||
language: 'en_US',
|
language: 'en_US',
|
||||||
value: 'John'
|
value: 'John'
|
||||||
|
@@ -1,15 +1,15 @@
|
|||||||
<h2 class="item-page-title-field">
|
<h2 class="item-page-title-field">
|
||||||
{{'project.page.titleprefix' | translate}}<ds-metadata-values [mdValues]="item?.allMetadata(['project.identifier.name'])"></ds-metadata-values>
|
{{'project.page.titleprefix' | translate}}<ds-metadata-values [mdValues]="item?.allMetadata(['dc.title'])"></ds-metadata-values>
|
||||||
</h2>
|
</h2>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-xs-12 col-md-4">
|
<div class="col-xs-12 col-md-4">
|
||||||
<ds-metadata-field-wrapper>
|
<ds-metadata-field-wrapper>
|
||||||
<ds-thumbnail [thumbnail]="this.item.getThumbnail() | async" [defaultImage]="'assets/images/project-placeholder.svg'"></ds-thumbnail>
|
<ds-thumbnail [thumbnail]="this.item.getThumbnail() | async" [defaultImage]="'assets/images/project-placeholder.svg'"></ds-thumbnail>
|
||||||
</ds-metadata-field-wrapper>
|
</ds-metadata-field-wrapper>
|
||||||
<ds-generic-item-page-field [item]="item"
|
<!--<ds-generic-item-page-field [item]="item"-->
|
||||||
[fields]="['project.identifier.status']"
|
<!--[fields]="['project.identifier.status']"-->
|
||||||
[label]="'project.page.status'">
|
<!--[label]="'project.page.status'">-->
|
||||||
</ds-generic-item-page-field>
|
<!--</ds-generic-item-page-field>-->
|
||||||
<ds-metadata-representation-list
|
<ds-metadata-representation-list
|
||||||
[label]="'project.page.contributor' | translate"
|
[label]="'project.page.contributor' | translate"
|
||||||
[representations]="contributors$ | async">
|
[representations]="contributors$ | async">
|
||||||
@@ -19,13 +19,13 @@
|
|||||||
[label]="'project.page.funder'">
|
[label]="'project.page.funder'">
|
||||||
</ds-generic-item-page-field>
|
</ds-generic-item-page-field>
|
||||||
<ds-generic-item-page-field [item]="item"
|
<ds-generic-item-page-field [item]="item"
|
||||||
[fields]="['project.identifier.id']"
|
[fields]="['dc.identifier']"
|
||||||
[label]="'project.page.id'">
|
[label]="'project.page.id'">
|
||||||
</ds-generic-item-page-field>
|
</ds-generic-item-page-field>
|
||||||
<ds-generic-item-page-field [item]="item"
|
<!--<ds-generic-item-page-field [item]="item"-->
|
||||||
[fields]="['project.identifier.expectedcompletion']"
|
<!--[fields]="['project.identifier.expectedcompletion']"-->
|
||||||
[label]="'project.page.expectedcompletion'">
|
<!--[label]="'project.page.expectedcompletion'">-->
|
||||||
</ds-generic-item-page-field>
|
<!--</ds-generic-item-page-field>-->
|
||||||
</div>
|
</div>
|
||||||
<div class="col-xs-12 col-md-6">
|
<div class="col-xs-12 col-md-6">
|
||||||
<ds-related-items
|
<ds-related-items
|
||||||
@@ -41,11 +41,11 @@
|
|||||||
[label]="'relationships.isOrgUnitOf' | translate">
|
[label]="'relationships.isOrgUnitOf' | translate">
|
||||||
</ds-related-items>
|
</ds-related-items>
|
||||||
<ds-generic-item-page-field [item]="item"
|
<ds-generic-item-page-field [item]="item"
|
||||||
[fields]="['project.identifier.description']"
|
[fields]="['dc.description']"
|
||||||
[label]="'project.page.description'">
|
[label]="'project.page.description'">
|
||||||
</ds-generic-item-page-field>
|
</ds-generic-item-page-field>
|
||||||
<ds-generic-item-page-field [item]="item"
|
<ds-generic-item-page-field [item]="item"
|
||||||
[fields]="['project.identifier.keyword']"
|
[fields]="['dc.subject']"
|
||||||
[label]="'project.page.keyword'">
|
[label]="'project.page.keyword'">
|
||||||
</ds-generic-item-page-field>
|
</ds-generic-item-page-field>
|
||||||
<div>
|
<div>
|
||||||
|
@@ -12,31 +12,31 @@ import {
|
|||||||
const mockItem: Item = Object.assign(new Item(), {
|
const mockItem: Item = Object.assign(new Item(), {
|
||||||
bitstreams: observableOf(new RemoteData(false, false, true, null, new PaginatedList(new PageInfo(), []))),
|
bitstreams: observableOf(new RemoteData(false, false, true, null, new PaginatedList(new PageInfo(), []))),
|
||||||
metadata: {
|
metadata: {
|
||||||
'project.identifier.status': [
|
// 'project.identifier.status': [
|
||||||
{
|
// {
|
||||||
language: 'en_US',
|
// language: 'en_US',
|
||||||
value: 'published'
|
// value: 'published'
|
||||||
}
|
// }
|
||||||
],
|
// ],
|
||||||
'project.identifier.id': [
|
'dc.identifier': [
|
||||||
{
|
{
|
||||||
language: 'en_US',
|
language: 'en_US',
|
||||||
value: '1'
|
value: '1'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
'project.identifier.expectedcompletion': [
|
// 'project.identifier.expectedcompletion': [
|
||||||
{
|
// {
|
||||||
language: 'en_US',
|
// language: 'en_US',
|
||||||
value: 'exp comp'
|
// value: 'exp comp'
|
||||||
}
|
// }
|
||||||
],
|
// ],
|
||||||
'project.identifier.description': [
|
'dc.description': [
|
||||||
{
|
{
|
||||||
language: 'en_US',
|
language: 'en_US',
|
||||||
value: 'keyword'
|
value: 'keyword'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
'project.identifier.keyword': [
|
'dc.subject': [
|
||||||
{
|
{
|
||||||
language: 'en_US',
|
language: 'en_US',
|
||||||
value: 'keyword'
|
value: 'keyword'
|
||||||
|
@@ -11,6 +11,7 @@ import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
|||||||
import { Injector, NO_ERRORS_SCHEMA } from '@angular/core';
|
import { Injector, NO_ERRORS_SCHEMA } from '@angular/core';
|
||||||
import { MenuService } from '../shared/menu/menu.service';
|
import { MenuService } from '../shared/menu/menu.service';
|
||||||
import { MenuServiceStub } from '../shared/testing/menu-service-stub';
|
import { MenuServiceStub } from '../shared/testing/menu-service-stub';
|
||||||
|
import { ENV_CONFIG, GLOBAL_CONFIG } from '../../config';
|
||||||
|
|
||||||
let comp: NavbarComponent;
|
let comp: NavbarComponent;
|
||||||
let fixture: ComponentFixture<NavbarComponent>;
|
let fixture: ComponentFixture<NavbarComponent>;
|
||||||
@@ -30,6 +31,7 @@ describe('NavbarComponent', () => {
|
|||||||
{ provide: Injector, useValue: {} },
|
{ provide: Injector, useValue: {} },
|
||||||
{ provide: MenuService, useValue: menuService },
|
{ provide: MenuService, useValue: menuService },
|
||||||
{ provide: HostWindowService, useValue: new HostWindowServiceStub(800) },
|
{ provide: HostWindowService, useValue: new HostWindowServiceStub(800) },
|
||||||
|
{ provide: GLOBAL_CONFIG, useValue: ENV_CONFIG }
|
||||||
],
|
],
|
||||||
schemas: [NO_ERRORS_SCHEMA]
|
schemas: [NO_ERRORS_SCHEMA]
|
||||||
})
|
})
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import { Component, Injector, OnInit } from '@angular/core';
|
import { Component, Inject, Injector, OnInit } from '@angular/core';
|
||||||
import { slideMobileNav } from '../shared/animations/slide';
|
import { slideMobileNav } from '../shared/animations/slide';
|
||||||
import { MenuComponent } from '../shared/menu/menu.component';
|
import { MenuComponent } from '../shared/menu/menu.component';
|
||||||
import { MenuService } from '../shared/menu/menu.service';
|
import { MenuService } from '../shared/menu/menu.service';
|
||||||
@@ -6,6 +6,7 @@ import { MenuID, MenuItemType } from '../shared/menu/initial-menus-state';
|
|||||||
import { TextMenuItemModel } from '../shared/menu/menu-item/models/text.model';
|
import { TextMenuItemModel } from '../shared/menu/menu-item/models/text.model';
|
||||||
import { LinkMenuItemModel } from '../shared/menu/menu-item/models/link.model';
|
import { LinkMenuItemModel } from '../shared/menu/menu-item/models/link.model';
|
||||||
import { HostWindowService } from '../shared/host-window.service';
|
import { HostWindowService } from '../shared/host-window.service';
|
||||||
|
import { GLOBAL_CONFIG, GlobalConfig } from '../../config';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Component representing the public navbar
|
* Component representing the public navbar
|
||||||
@@ -23,7 +24,8 @@ export class NavbarComponent extends MenuComponent implements OnInit {
|
|||||||
*/
|
*/
|
||||||
menuID = MenuID.PUBLIC;
|
menuID = MenuID.PUBLIC;
|
||||||
|
|
||||||
constructor(protected menuService: MenuService,
|
constructor(@Inject(GLOBAL_CONFIG) public config: GlobalConfig,
|
||||||
|
protected menuService: MenuService,
|
||||||
protected injector: Injector,
|
protected injector: Injector,
|
||||||
public windowService: HostWindowService
|
public windowService: HostWindowService
|
||||||
) {
|
) {
|
||||||
@@ -39,7 +41,7 @@ export class NavbarComponent extends MenuComponent implements OnInit {
|
|||||||
* Initialize all menu sections and items for this menu
|
* Initialize all menu sections and items for this menu
|
||||||
*/
|
*/
|
||||||
createMenu() {
|
createMenu() {
|
||||||
const menuList = [
|
const menuList: any[] = [
|
||||||
/* News */
|
/* News */
|
||||||
{
|
{
|
||||||
id: 'browse_global',
|
id: 'browse_global',
|
||||||
@@ -62,50 +64,6 @@ export class NavbarComponent extends MenuComponent implements OnInit {
|
|||||||
// link: '#'
|
// link: '#'
|
||||||
// } as LinkMenuItemModel,
|
// } as LinkMenuItemModel,
|
||||||
// },
|
// },
|
||||||
{
|
|
||||||
id: 'browse_global_global_by_title',
|
|
||||||
parentID: 'browse_global',
|
|
||||||
active: false,
|
|
||||||
visible: true,
|
|
||||||
model: {
|
|
||||||
type: MenuItemType.LINK,
|
|
||||||
text: 'menu.section.browse_global_by_title',
|
|
||||||
link: '/browse/title'
|
|
||||||
} as LinkMenuItemModel,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'browse_global_global_by_issue_date',
|
|
||||||
parentID: 'browse_global',
|
|
||||||
active: false,
|
|
||||||
visible: true,
|
|
||||||
model: {
|
|
||||||
type: MenuItemType.LINK,
|
|
||||||
text: 'menu.section.browse_global_by_issue_date',
|
|
||||||
link: '/browse/dateissued'
|
|
||||||
} as LinkMenuItemModel,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'browse_global_by_author',
|
|
||||||
parentID: 'browse_global',
|
|
||||||
active: false,
|
|
||||||
visible: true,
|
|
||||||
model: {
|
|
||||||
type: MenuItemType.LINK,
|
|
||||||
text: 'menu.section.browse_global_by_author',
|
|
||||||
link: '/browse/author'
|
|
||||||
} as LinkMenuItemModel,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'browse_global_by_subject',
|
|
||||||
parentID: 'browse_global',
|
|
||||||
active: false,
|
|
||||||
visible: true,
|
|
||||||
model: {
|
|
||||||
type: MenuItemType.LINK,
|
|
||||||
text: 'menu.section.browse_global_by_subject',
|
|
||||||
link: '/browse/subject'
|
|
||||||
} as LinkMenuItemModel,
|
|
||||||
},
|
|
||||||
|
|
||||||
/* Statistics */
|
/* Statistics */
|
||||||
{
|
{
|
||||||
@@ -120,6 +78,21 @@ export class NavbarComponent extends MenuComponent implements OnInit {
|
|||||||
index: 2
|
index: 2
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
// Read the different Browse-By types from config and add them to the browse menu
|
||||||
|
const types = this.config.browseBy.types;
|
||||||
|
types.forEach((typeConfig) => {
|
||||||
|
menuList.push({
|
||||||
|
id: `browse_global_by_${typeConfig.id}`,
|
||||||
|
parentID: 'browse_global',
|
||||||
|
active: false,
|
||||||
|
visible: true,
|
||||||
|
model: {
|
||||||
|
type: MenuItemType.LINK,
|
||||||
|
text: `menu.section.browse_global_by_${typeConfig.id}`,
|
||||||
|
link: `/browse/${typeConfig.id}`
|
||||||
|
} as LinkMenuItemModel
|
||||||
|
});
|
||||||
|
});
|
||||||
menuList.forEach((menuSection) => this.menuService.addSection(this.menuID, menuSection));
|
menuList.forEach((menuSection) => this.menuService.addSection(this.menuID, menuSection));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +1,6 @@
|
|||||||
<h3>{{'browse.comcol.head' | translate}}</h3>
|
<h3>{{'browse.comcol.head' | translate}}</h3>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a [routerLink]="['/browse/title']" [queryParams]="{scope: id}">{{'browse.comcol.by.title' | translate}}</a></li>
|
<li *ngFor="let config of types">
|
||||||
<li><a [routerLink]="['/browse/dateissued']" [queryParams]="{scope: id}">{{'browse.comcol.by.dateissued' | translate}}</a></li>
|
<a [routerLink]="['/browse/' + config.id]" [queryParams]="{scope: id}">{{'browse.comcol.by.' + config.id | translate}}</a>
|
||||||
<li><a [routerLink]="['/browse/author']" [queryParams]="{scope: id}">{{'browse.comcol.by.author' | translate}}</a></li>
|
</li>
|
||||||
<li><a [routerLink]="['/browse/subject']" [queryParams]="{scope: id}">{{'browse.comcol.by.subject' | translate}}</a></li>
|
|
||||||
</ul>
|
</ul>
|
||||||
|
@@ -1,4 +1,6 @@
|
|||||||
import { Component, Input } from '@angular/core';
|
import { Component, Inject, Input, OnInit } from '@angular/core';
|
||||||
|
import { GLOBAL_CONFIG, GlobalConfig } from '../../../config';
|
||||||
|
import { BrowseByTypeConfig } from '../../../config/browse-by-type-config.interface';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A component to display the "Browse By" section of a Community or Collection page
|
* A component to display the "Browse By" section of a Community or Collection page
|
||||||
@@ -8,9 +10,22 @@ import { Component, Input } from '@angular/core';
|
|||||||
selector: 'ds-comcol-page-browse-by',
|
selector: 'ds-comcol-page-browse-by',
|
||||||
templateUrl: './comcol-page-browse-by.component.html',
|
templateUrl: './comcol-page-browse-by.component.html',
|
||||||
})
|
})
|
||||||
export class ComcolPageBrowseByComponent {
|
export class ComcolPageBrowseByComponent implements OnInit {
|
||||||
/**
|
/**
|
||||||
* The ID of the Community or Collection
|
* The ID of the Community or Collection
|
||||||
*/
|
*/
|
||||||
@Input() id: string;
|
@Input() id: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of currently active browse configurations
|
||||||
|
*/
|
||||||
|
types: BrowseByTypeConfig[];
|
||||||
|
|
||||||
|
constructor(@Inject(GLOBAL_CONFIG) public config: GlobalConfig) {
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
this.types = this.config.browseBy.types;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import { GenericConstructor } from '../../core/shared/generic-constructor';
|
import { GenericConstructor } from '../../core/shared/generic-constructor';
|
||||||
import { ListableObject } from '../object-collection/shared/listable-object.model';
|
import { ListableObject } from '../object-collection/shared/listable-object.model';
|
||||||
import { isNull } from '../empty.util';
|
import { hasNoValue, isNull } from '../empty.util';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contains the mapping between a search result component and a DSpaceObject
|
* Contains the mapping between a search result component and a DSpaceObject
|
||||||
@@ -34,7 +34,7 @@ export function searchResultFor(domainConstructor: GenericConstructor<ListableOb
|
|||||||
* @returns The component's constructor that matches the given DSpaceObject
|
* @returns The component's constructor that matches the given DSpaceObject
|
||||||
*/
|
*/
|
||||||
export function getSearchResultFor(domainConstructor: GenericConstructor<ListableObject>, configuration: string = null) {
|
export function getSearchResultFor(domainConstructor: GenericConstructor<ListableObject>, configuration: string = null) {
|
||||||
if (isNull(configuration) || configuration === 'default') {
|
if (isNull(configuration) || configuration === 'default' || hasNoValue(searchResultMap.get(configuration))) {
|
||||||
return searchResultMap.get(domainConstructor);
|
return searchResultMap.get(domainConstructor);
|
||||||
} else {
|
} else {
|
||||||
return searchResultMap.get(configuration).get(domainConstructor);
|
return searchResultMap.get(configuration).get(domainConstructor);
|
||||||
|
@@ -45,9 +45,9 @@ export class SearchResultsComponent {
|
|||||||
@Input() viewMode: SetViewMode;
|
@Input() viewMode: SetViewMode;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An optional fixed filter to filter the result on one type
|
* An optional configuration to filter the result on one type
|
||||||
*/
|
*/
|
||||||
@Input() fixedFilter: string;
|
@Input() configuration: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether or not to hide the header of the results
|
* Whether or not to hide the header of the results
|
||||||
@@ -58,19 +58,6 @@ export class SearchResultsComponent {
|
|||||||
@Input() selectable = false;
|
@Input() selectable = false;
|
||||||
|
|
||||||
@Input() selectionConfig: {repeatable: boolean, listId: string};
|
@Input() selectionConfig: {repeatable: boolean, listId: string};
|
||||||
/**
|
|
||||||
* Get the i18n key for the title depending on the fixed filter
|
|
||||||
* Defaults to 'search.results.head' if there's no fixed filter found
|
|
||||||
* @returns {string}
|
|
||||||
*/
|
|
||||||
getTitleKey() {
|
|
||||||
if (isNotEmpty(this.fixedFilter)) {
|
|
||||||
return this.fixedFilter + '.search.results.head'
|
|
||||||
} else {
|
|
||||||
return 'search.results.head';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method to change the given string by surrounding it by quotes if not already present.
|
* Method to change the given string by surrounding it by quotes if not already present.
|
||||||
*/
|
*/
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
import { Config } from './config.interface';
|
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
|
* Config that determines how the dropdown list of years are created for browse-by-date components
|
||||||
@@ -18,4 +19,9 @@ export interface BrowseByConfig extends Config {
|
|||||||
* The absolute lowest year to display in the dropdown when no lowest date can be found for all items
|
* The absolute lowest year to display in the dropdown when no lowest date can be found for all items
|
||||||
*/
|
*/
|
||||||
defaultLowerLimit: number;
|
defaultLowerLimit: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A list of all the active Browse-By pages
|
||||||
|
*/
|
||||||
|
types: BrowseByTypeConfig[];
|
||||||
}
|
}
|
||||||
|
23
src/config/browse-by-type-config.interface.ts
Normal file
23
src/config/browse-by-type-config.interface.ts
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The metadata field to use for rendering starts-with options (only necessary when type is set to BrowseByType.Date)
|
||||||
|
*/
|
||||||
|
metadataField: string;
|
||||||
|
}
|
Reference in New Issue
Block a user