Skip to content
Snippets Groups Projects
Commit 67e5578b authored by Kristof De Langhe's avatar Kristof De Langhe
Browse files

62063: Configurable browse-by

parent 684b74e3
No related branches found
No related tags found
No related merge requests found
Showing
with 128 additions and 15 deletions
......@@ -149,7 +149,26 @@ module.exports = {
// Limit for years to display using jumps of five years (current year - fiveYearLimit)
fiveYearLimit: 30,
// The absolute lowest year to display in the dropdown (only used when no lowest date can be found for all items)
defaultLowerLimit: 1900
defaultLowerLimit: 1900,
types: [
{
metadata: 'title',
type: 'title'
},
{
metadata: 'dateissued',
type: 'date',
metadataField: 'dc.date.issued'
},
{
metadata: 'author',
type: 'metadata'
},
{
metadata: 'subject',
type: 'metadata'
}
]
},
item: {
edit: {
......
......@@ -13,6 +13,7 @@ import { BrowseService } from '../../core/browse/browse.service';
import { DSpaceObjectDataService } from '../../core/data/dspace-object-data.service';
import { GLOBAL_CONFIG, GlobalConfig } from '../../../config';
import { StartsWithType } from '../../shared/starts-with/starts-with-decorator';
import { BrowseByType, rendersBrowseBy } from '../+browse-by-switcher/browse-by-decorator';
@Component({
selector: 'ds-browse-by-date-page',
......@@ -24,6 +25,7 @@ import { StartsWithType } from '../../shared/starts-with/starts-with-decorator';
* A metadata definition is a short term used to describe one or multiple metadata fields.
* An example would be 'dateissued' for 'dc.date.issued'
*/
@rendersBrowseBy(BrowseByType.Date)
export class BrowseByDatePageComponent extends BrowseByMetadataPageComponent {
/**
......@@ -78,8 +80,9 @@ export class BrowseByDatePageComponent extends BrowseByMetadataPageComponent {
let lowerLimit = this.config.browseBy.defaultLowerLimit;
if (hasValue(firstItemRD.payload)) {
const date = firstItemRD.payload.firstMetadataValue(metadataField);
if (hasValue(date) && hasValue(+date.split('-')[0])) {
lowerLimit = +date.split('-')[0];
if (hasValue(date)) {
const dateObj = new Date(date);
lowerLimit = dateObj.getFullYear();
}
}
const options = [];
......
......@@ -15,6 +15,7 @@ import { DSpaceObjectDataService } from '../../core/data/dspace-object-data.serv
import { DSpaceObject } from '../../core/shared/dspace-object.model';
import { take } from 'rxjs/operators';
import { StartsWithType } from '../../shared/starts-with/starts-with-decorator';
import { BrowseByType, rendersBrowseBy } from '../+browse-by-switcher/browse-by-decorator';
@Component({
selector: 'ds-browse-by-metadata-page',
......@@ -26,6 +27,7 @@ import { StartsWithType } from '../../shared/starts-with/starts-with-decorator';
* A metadata definition is a short term used to describe one or multiple metadata fields.
* An example would be 'author' for 'dc.contributor.*'
*/
@rendersBrowseBy(BrowseByType.Metadata)
export class BrowseByMetadataPageComponent implements OnInit {
/**
......
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();
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}"`);
}
};
}
export function getComponentByBrowseByType(browseByType) {
const comp = map.get(browseByType);
if (hasNoValue(comp)) {
map.get(DEFAULT_BROWSE_BY_TYPE);
}
return comp;
}
<ng-container *ngComponentOutlet="getComponent() | async"></ng-container>
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'
})
export class BrowseBySwitcherComponent implements OnInit {
browseByTypeConfig: Observable<BrowseByTypeConfig>;
public constructor(@Inject(GLOBAL_CONFIG) public config: GlobalConfig,
protected route: ActivatedRoute) {
}
ngOnInit(): void {
this.browseByTypeConfig = this.route.params.pipe(
map((params) => {
const metadata = params.metadata;
return this.config.browseBy.types.find((config: BrowseByTypeConfig) => config.metadata === metadata);
})
);
}
getComponent() {
return this.browseByTypeConfig.pipe(
map((config: BrowseByTypeConfig) => getComponentByBrowseByType(config.type))
);
}
}
import { combineLatest as observableCombineLatest } from 'rxjs';
import { Component } from '@angular/core';
import { ItemDataService } from '../../core/data/item-data.service';
import { ActivatedRoute, Router } from '@angular/router';
import { hasValue } from '../../shared/empty.util';
import {
......@@ -11,6 +10,7 @@ import { BrowseEntrySearchOptions } from '../../core/browse/browse-entry-search-
import { DSpaceObjectDataService } from '../../core/data/dspace-object-data.service';
import { BrowseService } from '../../core/browse/browse.service';
import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model';
import { BrowseByType, rendersBrowseBy } from '../+browse-by-switcher/browse-by-decorator';
@Component({
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)
*/
@rendersBrowseBy(BrowseByType.Title)
export class BrowseByTitlePageComponent extends BrowseByMetadataPageComponent {
public constructor(protected route: ActivatedRoute,
......
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 { hasValue } from '../shared/empty.util';
import { hasNoValue, hasValue } from '../shared/empty.util';
import { map } from 'rxjs/operators';
import { getSucceededRemoteData } from '../core/shared/operators';
import { TranslateService } from '@ngx-translate/core';
import { of as observableOf } from 'rxjs';
import { GLOBAL_CONFIG, GlobalConfig } from '../../config';
@Injectable()
/**
......@@ -13,14 +14,21 @@ import { of as observableOf } from 'rxjs';
*/
export class BrowseByGuard implements CanActivate {
constructor(protected dsoService: DSpaceObjectDataService,
constructor(@Inject(GLOBAL_CONFIG) public config: GlobalConfig,
protected dsoService: DSpaceObjectDataService,
protected translate: TranslateService) {
}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
const title = route.data.title;
const metadata = route.params.metadata || route.queryParams.metadata || route.data.metadata;
const metadataField = route.data.metadataField;
let metadataField = route.data.metadataField;
if (hasNoValue(metadataField) && hasValue(metadata)) {
const config = this.config.browseBy.types.find((conf) => conf.metadata === metadata);
if (hasValue(config) && hasValue(config.metadataField)) {
metadataField = config.metadataField;
}
}
const scope = route.queryParams.scope;
const value = route.queryParams.value;
const metadataTranslated = this.translate.instant('browse.metadata.' + metadata);
......
import { RouterModule } from '@angular/router';
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 { BrowseBySwitcherComponent } from './+browse-by-switcher/browse-by-switcher.component';
@NgModule({
imports: [
RouterModule.forChild([
{ path: 'title', component: BrowseByTitlePageComponent, canActivate: [BrowseByGuard], data: { metadata: 'title', 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' } }
{ path: ':metadata', component: BrowseBySwitcherComponent, 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 { BrowseByDatePageComponent } from './+browse-by-date-page/browse-by-date-page.component';
import { BrowseByGuard } from './browse-by-guard';
import { BrowseBySwitcherComponent } from './+browse-by-switcher/browse-by-switcher.component';
@NgModule({
imports: [
......@@ -18,12 +19,18 @@ import { BrowseByGuard } from './browse-by-guard';
declarations: [
BrowseByTitlePageComponent,
BrowseByMetadataPageComponent,
BrowseByDatePageComponent
BrowseByDatePageComponent,
BrowseBySwitcherComponent
],
providers: [
ItemDataService,
BrowseService,
BrowseByGuard
],
entryComponents: [
BrowseByTitlePageComponent,
BrowseByMetadataPageComponent,
BrowseByDatePageComponent
]
})
export class BrowseByModule {
......
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
......@@ -18,4 +19,6 @@ export interface BrowseByConfig extends Config {
* The absolute lowest year to display in the dropdown when no lowest date can be found for all items
*/
defaultLowerLimit: number;
types: BrowseByTypeConfig[];
}
import { Config } from './config.interface';
import { BrowseByType } from '../app/+browse-by/+browse-by-switcher/browse-by-decorator';
export interface BrowseByTypeConfig extends Config {
metadata: string;
type: BrowseByType;
metadataField: string;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment