breadcrumbs for DSOs

This commit is contained in:
lotte
2020-02-21 17:06:50 +01:00
committed by Art Lowel
parent 4ea264dd7f
commit 725f20a9d0
18 changed files with 197 additions and 39 deletions

View File

@@ -7,6 +7,9 @@ import { ItemPageResolver } from './item-page.resolver';
import { URLCombiner } from '../core/url-combiner/url-combiner'; import { URLCombiner } from '../core/url-combiner/url-combiner';
import { getItemModulePath } from '../app-routing.module'; import { getItemModulePath } from '../app-routing.module';
import { AuthenticatedGuard } from '../core/auth/authenticated.guard'; import { AuthenticatedGuard } from '../core/auth/authenticated.guard';
import { ItemBreadcrumbResolver } from '../core/breadcrumbs/item-breadcrumb.resolver';
import { DSOBreadcrumbsService } from '../core/breadcrumbs/dso-breadcrumbs.service';
import { LinkService } from '../core/cache/builders/link.service';
export function getItemPageRoute(itemId: string) { export function getItemPageRoute(itemId: string) {
return new URLCombiner(getItemModulePath(), itemId).toString(); return new URLCombiner(getItemModulePath(), itemId).toString();
@@ -25,14 +28,16 @@ const ITEM_EDIT_PATH = ':id/edit';
component: ItemPageComponent, component: ItemPageComponent,
pathMatch: 'full', pathMatch: 'full',
resolve: { resolve: {
item: ItemPageResolver item: ItemPageResolver,
breadcrumb: ItemBreadcrumbResolver
} }
}, },
{ {
path: ':id/full', path: ':id/full',
component: FullItemPageComponent, component: FullItemPageComponent,
resolve: { resolve: {
item: ItemPageResolver item: ItemPageResolver,
breadcrumb: ItemBreadcrumbResolver
} }
}, },
{ {
@@ -44,6 +49,9 @@ const ITEM_EDIT_PATH = ':id/edit';
], ],
providers: [ providers: [
ItemPageResolver, ItemPageResolver,
ItemBreadcrumbResolver,
DSOBreadcrumbsService,
LinkService
] ]
}) })
export class ItemPageRoutingModule { export class ItemPageRoutingModule {

View File

@@ -4,14 +4,19 @@ import { RouterModule } from '@angular/router';
import { ConfigurationSearchPageGuard } from './configuration-search-page.guard'; import { ConfigurationSearchPageGuard } from './configuration-search-page.guard';
import { ConfigurationSearchPageComponent } from './configuration-search-page.component'; import { ConfigurationSearchPageComponent } from './configuration-search-page.component';
import { SearchPageComponent } from './search-page.component'; import { SearchPageComponent } from './search-page.component';
import { Breadcrumb } from '../breadcrumbs/breadcrumb/breadcrumb.model'; import { I18nBreadcrumbResolver } from '../core/breadcrumbs/i18n-breadcrumb.resolver';
import { I18nBreadcrumbsService } from '../core/breadcrumbs/i18n-breadcrumbs.service';
@NgModule({ @NgModule({
imports: [ imports: [
RouterModule.forChild([ RouterModule.forChild([
{ path: '', component: SearchPageComponent, data: { title: 'search.title', breadcrumb: new Breadcrumb('Search', '/search') } }, { path: '', component: SearchPageComponent, resolve: { breadcrumb: I18nBreadcrumbResolver }, data: { title: 'search.title', breadcrumbKey: 'Search' } },
{ path: ':configuration', component: ConfigurationSearchPageComponent, canActivate: [ConfigurationSearchPageGuard] } { path: ':configuration', component: ConfigurationSearchPageComponent, canActivate: [ConfigurationSearchPageGuard] }
]) ])
],
providers: [
I18nBreadcrumbResolver,
I18nBreadcrumbsService
] ]
}) })
export class SearchPageRoutingModule { export class SearchPageRoutingModule {

View File

@@ -4,6 +4,13 @@ import { RouterModule } from '@angular/router';
import { PageNotFoundComponent } from './pagenotfound/pagenotfound.component'; import { PageNotFoundComponent } from './pagenotfound/pagenotfound.component';
import { AuthenticatedGuard } from './core/auth/authenticated.guard'; import { AuthenticatedGuard } from './core/auth/authenticated.guard';
import { Breadcrumb } from './breadcrumbs/breadcrumb/breadcrumb.model'; import { Breadcrumb } from './breadcrumbs/breadcrumb/breadcrumb.model';
import { DSpaceObject } from './core/shared/dspace-object.model';
import { Community } from './core/shared/community.model';
import { getCommunityPageRoute } from './+community-page/community-page-routing.module';
import { Collection } from './core/shared/collection.model';
import { Item } from './core/shared/item.model';
import { getItemPageRoute } from './+item-page/item-page-routing.module';
import { getCollectionPageRoute } from './+collection-page/collection-page-routing.module';
const ITEM_MODULE_PATH = 'items'; const ITEM_MODULE_PATH = 'items';
@@ -29,6 +36,17 @@ export function getAdminModulePath() {
return `/${ADMIN_MODULE_PATH}`; return `/${ADMIN_MODULE_PATH}`;
} }
export function getDSOPath(dso: DSpaceObject): string {
switch ((dso as any).type) {
case Community.type.value:
return getCommunityPageRoute(dso.uuid);
case Collection.type.value:
return getCollectionPageRoute(dso.uuid);
case Item.type.value:
return getItemPageRoute(dso.uuid);
}
}
@NgModule({ @NgModule({
imports: [ imports: [
RouterModule.forRoot([ RouterModule.forRoot([
@@ -41,7 +59,7 @@ export function getAdminModulePath() {
{ path: COLLECTION_MODULE_PATH, loadChildren: './+collection-page/collection-page.module#CollectionPageModule' }, { path: COLLECTION_MODULE_PATH, loadChildren: './+collection-page/collection-page.module#CollectionPageModule' },
{ path: ITEM_MODULE_PATH, loadChildren: './+item-page/item-page.module#ItemPageModule' }, { path: ITEM_MODULE_PATH, loadChildren: './+item-page/item-page.module#ItemPageModule' },
{ path: 'mydspace', loadChildren: './+my-dspace-page/my-dspace-page.module#MyDSpacePageModule', canActivate: [AuthenticatedGuard] }, { path: 'mydspace', loadChildren: './+my-dspace-page/my-dspace-page.module#MyDSpacePageModule', canActivate: [AuthenticatedGuard] },
{ path: 'search', loadChildren: './+search-page/search-page.module#SearchPageModule', data: { breadcrumb: new Breadcrumb('Search', '/search') } }, { path: 'search', loadChildren: './+search-page/search-page.module#SearchPageModule' },
{ path: 'browse', loadChildren: './+browse-by/browse-by.module#BrowseByModule' }, { path: 'browse', loadChildren: './+browse-by/browse-by.module#BrowseByModule' },
{ path: ADMIN_MODULE_PATH, loadChildren: './+admin/admin.module#AdminModule', canActivate: [AuthenticatedGuard] }, { path: ADMIN_MODULE_PATH, loadChildren: './+admin/admin.module#AdminModule', canActivate: [AuthenticatedGuard] },
{ path: 'login', loadChildren: './+login-page/login-page.module#LoginPageModule' }, { path: 'login', loadChildren: './+login-page/login-page.module#LoginPageModule' },

View File

@@ -1,7 +1,7 @@
import { BreadcrumbsService } from '../../core/breadcrumbs/breadcrumbs.service'; import { BreadcrumbsService } from '../../core/breadcrumbs/breadcrumbs.service';
export interface BreadcrumbConfig { export interface BreadcrumbConfig<T> {
provider: BreadcrumbsService; provider: BreadcrumbsService<T>;
key: string; key: T;
url?: string; url?: string;
} }

View File

@@ -3,7 +3,7 @@ import { ActivatedRoute, NavigationEnd, Router } from '@angular/router';
import { Breadcrumb } from './breadcrumb/breadcrumb.model'; import { Breadcrumb } from './breadcrumb/breadcrumb.model';
import { hasValue, isNotUndefined } from '../shared/empty.util'; import { hasValue, isNotUndefined } from '../shared/empty.util';
import { filter, map, switchMap, tap } from 'rxjs/operators'; import { filter, map, switchMap, tap } from 'rxjs/operators';
import { combineLatest, Observable, Subscription } from 'rxjs'; import { combineLatest, Observable, Subscription, of as observableOf } from 'rxjs';
import { BreadcrumbConfig } from './breadcrumb/breadcrumb-config.model'; import { BreadcrumbConfig } from './breadcrumb/breadcrumb-config.model';
@Component({ @Component({
@@ -32,22 +32,22 @@ export class BreadcrumbsComponent implements OnDestroy {
resolveBreadcrumb(route: ActivatedRoute): Observable<Breadcrumb[]> { resolveBreadcrumb(route: ActivatedRoute): Observable<Breadcrumb[]> {
const data = route.snapshot.data; const data = route.snapshot.data;
const last: boolean = route.children.length === 0;
if (last && isNotUndefined(data.showBreadcrumbs)) {
this.showBreadcrumbs = data.showBreadcrumbs;
}
if (hasValue(data) && hasValue(data.breadcrumb)) { if (hasValue(data) && hasValue(data.breadcrumb)) {
const { provider, key, url }: BreadcrumbConfig = data.breadcrumb; const { provider, key, url } = data.breadcrumb;
if (route.children.length > 0) { if (!last) {
return combineLatest(provider.getBreadcrumbs(key, url), this.resolveBreadcrumb(route.firstChild)) return combineLatest(provider.getBreadcrumbs(key, url), this.resolveBreadcrumb(route.firstChild))
.pipe(map((crumbs) => [].concat.apply([], crumbs))); .pipe(map((crumbs) => [].concat.apply([], crumbs)));
} else { } else {
if (isNotUndefined(data.showBreadcrumbs)) {
this.showBreadcrumbs = data.showBreadcrumbs;
}
return provider.getBreadcrumbs(key, url); return provider.getBreadcrumbs(key, url);
} }
} }
if (route.children.length > 0) { return !last ? this.resolveBreadcrumb(route.firstChild) : observableOf([]);
return this.resolveBreadcrumb(route.firstChild)
}
} }
ngOnDestroy(): void { ngOnDestroy(): void {

View File

@@ -1,6 +1,6 @@
import { Breadcrumb } from '../../breadcrumbs/breadcrumb/breadcrumb.model'; import { Breadcrumb } from '../../breadcrumbs/breadcrumb/breadcrumb.model';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
export interface BreadcrumbsService { export interface BreadcrumbsService<T> {
getBreadcrumbs(key: string, url: string): Observable<Breadcrumb[]>; getBreadcrumbs(key: T, url: string): Observable<Breadcrumb[]>;
} }

View File

@@ -0,0 +1,17 @@
import { Injectable } from '@angular/core';
import { DSOBreadcrumbsService } from './dso-breadcrumbs.service';
import { ItemDataService } from '../data/item-data.service';
import { Item } from '../shared/item.model';
import { DSOBreadcrumbResolver } from './dso-breadcrumb.resolver';
import { Collection } from '../shared/collection.model';
import { CollectionDataService } from '../data/collection-data.service';
/**
* The class that resolve the BreadcrumbConfig object for a route
*/
@Injectable()
export class CollectionBreadcrumbResolver extends DSOBreadcrumbResolver<Collection> {
constructor(protected breadcrumbService: DSOBreadcrumbsService, protected dataService: CollectionDataService) {
super(breadcrumbService, dataService);
}
}

View File

@@ -0,0 +1,15 @@
import { Injectable } from '@angular/core';
import { DSOBreadcrumbsService } from './dso-breadcrumbs.service';
import { DSOBreadcrumbResolver } from './dso-breadcrumb.resolver';
import { CommunityDataService } from '../data/community-data.service';
import { Community } from '../shared/community.model';
/**
* The class that resolve the BreadcrumbConfig object for a route
*/
@Injectable()
export class CommunityBreadcrumbResolver extends DSOBreadcrumbResolver<Community> {
constructor(protected breadcrumbService: DSOBreadcrumbsService, protected dataService: CommunityDataService) {
super(breadcrumbService, dataService);
}
}

View File

@@ -2,13 +2,19 @@ import { BreadcrumbConfig } from '../../breadcrumbs/breadcrumb/breadcrumb-config
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, Resolve, RouterStateSnapshot } from '@angular/router'; import { ActivatedRouteSnapshot, Resolve, RouterStateSnapshot } from '@angular/router';
import { DSOBreadcrumbsService } from './dso-breadcrumbs.service'; import { DSOBreadcrumbsService } from './dso-breadcrumbs.service';
import { DataService } from '../data/data.service';
import { getRemoteDataPayload, getSucceededRemoteData } from '../shared/operators';
import { map } from 'rxjs/operators';
import { Observable } from 'rxjs';
import { DSpaceObject } from '../shared/dspace-object.model';
import { ChildHALResource } from '../shared/child-hal-resource.model';
/** /**
* The class that resolve the BreadcrumbConfig object for a route * The class that resolve the BreadcrumbConfig object for a route
*/ */
@Injectable() @Injectable()
export class DSOBreadcrumbResolver implements Resolve<BreadcrumbConfig> { export class DSOBreadcrumbResolver<T extends ChildHALResource & DSpaceObject> implements Resolve<BreadcrumbConfig<T>> {
constructor(private breadcrumbService: DSOBreadcrumbsService) { constructor(protected breadcrumbService: DSOBreadcrumbsService, protected dataService: DataService<T>) {
} }
/** /**
@@ -17,10 +23,17 @@ export class DSOBreadcrumbResolver implements Resolve<BreadcrumbConfig> {
* @param {RouterStateSnapshot} state The current RouterStateSnapshot * @param {RouterStateSnapshot} state The current RouterStateSnapshot
* @returns BreadcrumbConfig object * @returns BreadcrumbConfig object
*/ */
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): BreadcrumbConfig { resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<BreadcrumbConfig<T>> {
const uuid = route.params.id; const uuid = route.params.id;
const fullPath = route.url.join(''); return this.dataService.findById(uuid).pipe(
const url = fullPath.substr(0, fullPath.indexOf(uuid)) + uuid; getSucceededRemoteData(),
return { provider: this.breadcrumbService, key: uuid, url: url }; getRemoteDataPayload(),
map((object: T) => {
const fullPath = route.url.join('');
const url = fullPath.substr(0, fullPath.indexOf(uuid)) + uuid;
return { provider: this.breadcrumbService, key: object, url: url };
})
);
} }
} }

View File

@@ -1,9 +1,36 @@
import { Breadcrumb } from '../../breadcrumbs/breadcrumb/breadcrumb.model'; import { Breadcrumb } from '../../breadcrumbs/breadcrumb/breadcrumb.model';
import { BreadcrumbsService } from './breadcrumbs.service'; import { BreadcrumbsService } from './breadcrumbs.service';
import { Observable } from 'rxjs'; import { Observable, of as observableOf } from 'rxjs';
import { ChildHALResource } from '../shared/child-hal-resource.model';
import { LinkService } from '../cache/builders/link.service';
import { DSpaceObject } from '../shared/dspace-object.model';
import { followLink } from '../../shared/utils/follow-link-config.model';
import { filter, find, map, switchMap } from 'rxjs/operators';
import { getDSOPath } from '../../app-routing.module';
import { RemoteData } from '../data/remote-data';
import { hasValue } from '../../shared/empty.util';
import { Injectable } from '@angular/core';
export class DSOBreadcrumbsService implements BreadcrumbsService { @Injectable()
getBreadcrumbs(key: string, url: string): Observable<Breadcrumb[]> { export class DSOBreadcrumbsService implements BreadcrumbsService<ChildHALResource & DSpaceObject> {
return undefined; constructor(private linkService: LinkService) {
}
getBreadcrumbs(key: ChildHALResource & DSpaceObject, url: string): Observable<Breadcrumb[]> {
const crumb = new Breadcrumb(key.name, url);
const propertyName = key.getParentLinkKey();
return this.linkService.resolveLink(key, followLink(propertyName))[propertyName].pipe(
filter((childRD: RemoteData<ChildHALResource & DSpaceObject>) => childRD.isSuccessful === true && childRD.requestPending === false && childRD.responsePending === false),
switchMap((childRD: RemoteData<ChildHALResource & DSpaceObject>) => {
if (hasValue(childRD.payload)) {
const child = childRD.payload;
return this.getBreadcrumbs(child, getDSOPath(child))
}
return observableOf([]);
}),
map((breadcrumbs: Breadcrumb[]) => [...breadcrumbs, crumb])
);
} }
} }

View File

@@ -8,7 +8,7 @@ import { hasNoValue } from '../../shared/empty.util';
* The class that resolve the BreadcrumbConfig object for a route * The class that resolve the BreadcrumbConfig object for a route
*/ */
@Injectable() @Injectable()
export class I18nBreadcrumbResolver implements Resolve<BreadcrumbConfig> { export class I18nBreadcrumbResolver implements Resolve<BreadcrumbConfig<string>> {
constructor(private breadcrumbService: I18nBreadcrumbsService) { constructor(private breadcrumbService: I18nBreadcrumbsService) {
} }
@@ -18,7 +18,7 @@ export class I18nBreadcrumbResolver implements Resolve<BreadcrumbConfig> {
* @param {RouterStateSnapshot} state The current RouterStateSnapshot * @param {RouterStateSnapshot} state The current RouterStateSnapshot
* @returns BreadcrumbConfig object * @returns BreadcrumbConfig object
*/ */
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): BreadcrumbConfig { resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): BreadcrumbConfig<string> {
const key = route.data.breadcrumbKey; const key = route.data.breadcrumbKey;
if (hasNoValue(key)) { if (hasNoValue(key)) {
throw new Error('You provided an i18nBreadcrumbResolver for url \"' + route.url + '\" but no breadcrumbKey in the route\'s data') throw new Error('You provided an i18nBreadcrumbResolver for url \"' + route.url + '\" but no breadcrumbKey in the route\'s data')

View File

@@ -1,10 +1,12 @@
import { Breadcrumb } from '../../breadcrumbs/breadcrumb/breadcrumb.model'; import { Breadcrumb } from '../../breadcrumbs/breadcrumb/breadcrumb.model';
import { BreadcrumbsService } from './breadcrumbs.service'; import { BreadcrumbsService } from './breadcrumbs.service';
import { Observable, of as observableOf } from 'rxjs'; import { Observable, of as observableOf } from 'rxjs';
import { Injectable } from '@angular/core';
export const BREADCRUMB_MESSAGE_PREFIX = 'breadcrumbs.'; export const BREADCRUMB_MESSAGE_PREFIX = 'breadcrumbs.';
export class I18nBreadcrumbsService implements BreadcrumbsService { @Injectable()
export class I18nBreadcrumbsService implements BreadcrumbsService<string> {
getBreadcrumbs(key: string, url: string): Observable<Breadcrumb[]> { getBreadcrumbs(key: string, url: string): Observable<Breadcrumb[]> {
return observableOf([new Breadcrumb(BREADCRUMB_MESSAGE_PREFIX + key, url)]); return observableOf([new Breadcrumb(BREADCRUMB_MESSAGE_PREFIX + key, url)]);
} }

View File

@@ -0,0 +1,15 @@
import { Injectable } from '@angular/core';
import { DSOBreadcrumbsService } from './dso-breadcrumbs.service';
import { ItemDataService } from '../data/item-data.service';
import { Item } from '../shared/item.model';
import { DSOBreadcrumbResolver } from './dso-breadcrumb.resolver';
/**
* The class that resolve the BreadcrumbConfig object for a route
*/
@Injectable()
export class ItemBreadcrumbResolver extends DSOBreadcrumbResolver<Item> {
constructor(protected breadcrumbService: DSOBreadcrumbsService, protected dataService: ItemDataService) {
super(breadcrumbService, dataService);
}
}

View File

@@ -13,9 +13,9 @@ export enum RemoteDataState {
*/ */
export class RemoteData<T> { export class RemoteData<T> {
constructor( constructor(
private requestPending?: boolean, public requestPending?: boolean,
private responsePending?: boolean, public responsePending?: boolean,
private isSuccessful?: boolean, public isSuccessful?: boolean,
public error?: RemoteDataError, public error?: RemoteDataError,
public payload?: T public payload?: T
) { ) {

View File

@@ -0,0 +1,5 @@
import { HALResource } from './hal-resource.model';
export interface ChildHALResource extends HALResource {
getParentLinkKey(): keyof this['_links'];
}

View File

@@ -12,10 +12,13 @@ import { License } from './license.model';
import { LICENSE } from './license.resource-type'; import { LICENSE } from './license.resource-type';
import { ResourcePolicy } from './resource-policy.model'; import { ResourcePolicy } from './resource-policy.model';
import { RESOURCE_POLICY } from './resource-policy.resource-type'; import { RESOURCE_POLICY } from './resource-policy.resource-type';
import { COMMUNITY } from './community.resource-type';
import { Community } from './community.model';
import { ChildHALResource } from './child-hal-resource.model';
@typedObject @typedObject
@inheritSerialization(DSpaceObject) @inheritSerialization(DSpaceObject)
export class Collection extends DSpaceObject { export class Collection extends DSpaceObject implements ChildHALResource {
static type = COLLECTION; static type = COLLECTION;
/** /**
@@ -35,6 +38,7 @@ export class Collection extends DSpaceObject {
itemtemplate: HALLink; itemtemplate: HALLink;
defaultAccessConditions: HALLink; defaultAccessConditions: HALLink;
logo: HALLink; logo: HALLink;
parentCommunity: HALLink;
self: HALLink; self: HALLink;
}; };
@@ -59,6 +63,13 @@ export class Collection extends DSpaceObject {
@link(RESOURCE_POLICY, true) @link(RESOURCE_POLICY, true)
defaultAccessConditions?: Observable<RemoteData<PaginatedList<ResourcePolicy>>>; defaultAccessConditions?: Observable<RemoteData<PaginatedList<ResourcePolicy>>>;
/**
* The Community that is a direct parent of this Collection
* Will be undefined unless the parent community HALLink has been resolved.
*/
@link(COMMUNITY, false)
parentCommunity?: Observable<RemoteData<Community>>;
/** /**
* The introductory text of this Collection * The introductory text of this Collection
* Corresponds to the metadata field dc.description * Corresponds to the metadata field dc.description
@@ -98,4 +109,8 @@ export class Collection extends DSpaceObject {
get sidebarText(): string { get sidebarText(): string {
return this.firstMetadataValue('dc.description.tableofcontents'); return this.firstMetadataValue('dc.description.tableofcontents');
} }
getParentLinkKey(): keyof this['_links'] {
return 'parentCommunity';
}
} }

View File

@@ -10,10 +10,11 @@ import { COLLECTION } from './collection.resource-type';
import { COMMUNITY } from './community.resource-type'; import { COMMUNITY } from './community.resource-type';
import { DSpaceObject } from './dspace-object.model'; import { DSpaceObject } from './dspace-object.model';
import { HALLink } from './hal-link.model'; import { HALLink } from './hal-link.model';
import { ChildHALResource } from './child-hal-resource.model';
@typedObject @typedObject
@inheritSerialization(DSpaceObject) @inheritSerialization(DSpaceObject)
export class Community extends DSpaceObject { export class Community extends DSpaceObject implements ChildHALResource {
static type = COMMUNITY; static type = COMMUNITY;
/** /**
@@ -30,6 +31,7 @@ export class Community extends DSpaceObject {
collections: HALLink; collections: HALLink;
logo: HALLink; logo: HALLink;
subcommunities: HALLink; subcommunities: HALLink;
parentCommunity: HALLink;
self: HALLink; self: HALLink;
}; };
@@ -54,6 +56,13 @@ export class Community extends DSpaceObject {
@link(COMMUNITY, true) @link(COMMUNITY, true)
subcommunities?: Observable<RemoteData<PaginatedList<Community>>>; subcommunities?: Observable<RemoteData<PaginatedList<Community>>>;
/**
* The Community that is a direct parent of this Community
* Will be undefined unless the parent community HALLink has been resolved.
*/
@link(COMMUNITY, false)
parentCommunity?: Observable<RemoteData<Community>>;
/** /**
* The introductory text of this Community * The introductory text of this Community
* Corresponds to the metadata field dc.description * Corresponds to the metadata field dc.description
@@ -85,4 +94,8 @@ export class Community extends DSpaceObject {
get sidebarText(): string { get sidebarText(): string {
return this.firstMetadataValue('dc.description.tableofcontents'); return this.firstMetadataValue('dc.description.tableofcontents');
} }
getParentLinkKey(): keyof this['_links'] {
return 'parentCommunity';
}
} }

View File

@@ -17,13 +17,14 @@ import { HALLink } from './hal-link.model';
import { Relationship } from './item-relationships/relationship.model'; import { Relationship } from './item-relationships/relationship.model';
import { RELATIONSHIP } from './item-relationships/relationship.resource-type'; import { RELATIONSHIP } from './item-relationships/relationship.resource-type';
import { ITEM } from './item.resource-type'; import { ITEM } from './item.resource-type';
import { ChildHALResource } from './child-hal-resource.model';
/** /**
* Class representing a DSpace Item * Class representing a DSpace Item
*/ */
@typedObject @typedObject
@inheritSerialization(DSpaceObject) @inheritSerialization(DSpaceObject)
export class Item extends DSpaceObject { export class Item extends DSpaceObject implements ChildHALResource {
static type = ITEM; static type = ITEM;
/** /**
@@ -100,4 +101,8 @@ export class Item extends DSpaceObject {
} }
return [entityType, ...super.getRenderTypes()]; return [entityType, ...super.getRenderTypes()];
} }
getParentLinkKey(): keyof this['_links'] {
return 'owningCollection';
}
} }