This commit is contained in:
lotte
2020-02-27 16:53:47 +01:00
parent d2fe506299
commit 3d1e93f5ef
21 changed files with 213 additions and 33 deletions

View File

@@ -196,6 +196,14 @@
"browse.metadata.title": "Title", "browse.metadata.title": "Title",
"browse.metadata.author.breadcrumbs": "Browse by Author",
"browse.metadata.dateissued.breadcrumbs": "Browse by Date",
"browse.metadata.subject.breadcrumbs": "Browse by Subject",
"browse.metadata.title.breadcrumbs": "Browse by Title",
"browse.startsWith.choose_start": "(Choose start)", "browse.startsWith.choose_start": "(Choose start)",
"browse.startsWith.choose_year": "(Choose year)", "browse.startsWith.choose_year": "(Choose year)",
@@ -237,7 +245,6 @@
"browse.title": "Browsing {{ collection }} by {{ field }} {{ value }}", "browse.title": "Browsing {{ collection }} by {{ field }} {{ value }}",
"chips.remove": "Remove chip", "chips.remove": "Remove chip",

View File

@@ -20,7 +20,6 @@ import { Item } from '../../core/shared/item.model';
import { DSpaceObjectDataService } from '../../core/data/dspace-object-data.service'; import { DSpaceObjectDataService } from '../../core/data/dspace-object-data.service';
import { Community } from '../../core/shared/community.model'; import { Community } from '../../core/shared/community.model';
import { MockRouter } from '../../shared/mocks/mock-router'; import { MockRouter } from '../../shared/mocks/mock-router';
import { ResourceType } from '../../core/shared/resource-type';
import { createSuccessfulRemoteDataObject$ } from '../../shared/testing/utils'; import { createSuccessfulRemoteDataObject$ } from '../../shared/testing/utils';
import { BrowseEntry } from '../../core/shared/browse-entry.model'; import { BrowseEntry } from '../../core/shared/browse-entry.model';
import { VarDirective } from '../../shared/utils/var.directive'; import { VarDirective } from '../../shared/utils/var.directive';

View File

@@ -0,0 +1,41 @@
import { Injectable } from '@angular/core';
import { Community } from '../core/shared/community.model';
import { DSpaceObjectDataService } from '../core/data/dspace-object-data.service';
import { DSOBreadcrumbsService } from '../core/breadcrumbs/dso-breadcrumbs.service';
import { Collection } from '../core/shared/collection.model';
import { ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { BreadcrumbConfig } from '../breadcrumbs/breadcrumb/breadcrumb-config.model';
import { Observable } from 'rxjs';
import { getRemoteDataPayload, getSucceededRemoteData } from '../core/shared/operators';
import { map } from 'rxjs/operators';
import { hasValue } from '../shared/empty.util';
import { getDSOPath } from '../app-routing.module';
/**
* The class that resolves the BreadcrumbConfig object for a DSpaceObject on a browse by page
*/
@Injectable()
export class BrowseByDSOBreadcrumbResolver {
constructor(protected breadcrumbService: DSOBreadcrumbsService, protected dataService: DSpaceObjectDataService) {
}
/**
* Method for resolving a breadcrumb config object
* @param {ActivatedRouteSnapshot} route The current ActivatedRouteSnapshot
* @param {RouterStateSnapshot} state The current RouterStateSnapshot
* @returns BreadcrumbConfig object
*/
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<BreadcrumbConfig<Community | Collection>> {
const uuid = route.queryParams.scope;
if (hasValue(uuid)) {
return this.dataService.findById(uuid).pipe(
getSucceededRemoteData(),
getRemoteDataPayload(),
map((object: Community | Collection) => {
return { provider: this.breadcrumbService, key: object, url: getDSOPath(object) };
})
);
}
return undefined;
}
}

View File

@@ -37,24 +37,24 @@ export class BrowseByGuard implements CanActivate {
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, id, metadataField, name, metadataTranslated, value); route.data = this.createData(title, id, metadataField, name, metadataTranslated, value, route);
return true; return true;
}) })
); );
} else { } else {
route.data = this.createData(title, id, metadataField, '', metadataTranslated, value); route.data = this.createData(title, id, metadataField, '', metadataTranslated, value, route);
return observableOf(true); return observableOf(true);
} }
} }
private createData(title, id, metadataField, collection, field, value) { private createData(title, id, metadataField, collection, field, value, route) {
return { return Object.assign({}, route.data, {
title: title, title: title,
id: id, id: id,
metadataField: metadataField, metadataField: metadataField,
collection: collection, collection: collection,
field: field, field: field,
value: hasValue(value) ? `"${value}"` : '' value: hasValue(value) ? `"${value}"` : ''
} });
} }
} }

View File

@@ -0,0 +1,28 @@
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, Resolve, RouterStateSnapshot } from '@angular/router';
import { I18nBreadcrumbsService } from '../core/breadcrumbs/i18n-breadcrumbs.service';
import { BreadcrumbConfig } from '../breadcrumbs/breadcrumb/breadcrumb-config.model';
import { I18nBreadcrumbResolver } from '../core/breadcrumbs/i18n-breadcrumb.resolver';
/**
* This class resolves a BreadcrumbConfig object with an i18n key string for a route
* It adds the metadata field of the current browse-by page
*/
@Injectable()
export class BrowseByI18nBreadcrumbResolver extends I18nBreadcrumbResolver {
constructor(protected breadcrumbService: I18nBreadcrumbsService) {
super(breadcrumbService);
}
/**
* Method for resolving a browse-by i18n breadcrumb configuration object
* @param {ActivatedRouteSnapshot} route The current ActivatedRouteSnapshot
* @param {RouterStateSnapshot} state The current RouterStateSnapshot
* @returns BreadcrumbConfig object for a browse-by page
*/
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): BreadcrumbConfig<string> {
const extendedBreadcrumbKey = route.data.breadcrumbKey + '.' + route.params.id;
route.data = Object.assign({}, route.data, { breadcrumbKey: extendedBreadcrumbKey });
return super.resolve(route, state);
}
}

View File

@@ -2,12 +2,29 @@ import { RouterModule } from '@angular/router';
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { BrowseByGuard } from './browse-by-guard'; import { BrowseByGuard } from './browse-by-guard';
import { BrowseBySwitcherComponent } from './+browse-by-switcher/browse-by-switcher.component'; import { BrowseBySwitcherComponent } from './+browse-by-switcher/browse-by-switcher.component';
import { BrowseByDSOBreadcrumbResolver } from './browse-by-dso-breadcrumb.resolver';
import { BrowseByI18nBreadcrumbResolver } from './browse-by-i18n-breadcrumb.resolver';
@NgModule({ @NgModule({
imports: [ imports: [
RouterModule.forChild([ RouterModule.forChild([
{ path: ':id', component: BrowseBySwitcherComponent, canActivate: [BrowseByGuard], data: { title: 'browse.title' } } {
]) path: '',
resolve: { breadcrumb: BrowseByDSOBreadcrumbResolver },
children: [
{
path: ':id',
component: BrowseBySwitcherComponent,
canActivate: [BrowseByGuard],
resolve: { breadcrumb: BrowseByI18nBreadcrumbResolver },
data: { title: 'browse.title', breadcrumbKey: 'browse.metadata' }
}
]
}])
],
providers: [
BrowseByI18nBreadcrumbResolver,
BrowseByDSOBreadcrumbResolver
] ]
}) })
export class BrowseByRoutingModule { export class BrowseByRoutingModule {

View File

@@ -31,23 +31,24 @@ import { I18nBreadcrumbResolver } from '../../core/breadcrumbs/i18n-breadcrumb.r
component: CollectionMetadataComponent, component: CollectionMetadataComponent,
data: { data: {
title: 'collection.edit.tabs.metadata.title', title: 'collection.edit.tabs.metadata.title',
hideReturnButton: true hideReturnButton: true,
showBreadcrumbs: true
} }
}, },
{ {
path: 'roles', path: 'roles',
component: CollectionRolesComponent, component: CollectionRolesComponent,
data: { title: 'collection.edit.tabs.roles.title' } data: { title: 'collection.edit.tabs.roles.title', showBreadcrumbs: true }
}, },
{ {
path: 'source', path: 'source',
component: CollectionSourceComponent, component: CollectionSourceComponent,
data: { title: 'collection.edit.tabs.source.title' } data: { title: 'collection.edit.tabs.source.title', showBreadcrumbs: true }
}, },
{ {
path: 'curate', path: 'curate',
component: CollectionCurateComponent, component: CollectionCurateComponent,
data: { title: 'collection.edit.tabs.curate.title' } data: { title: 'collection.edit.tabs.curate.title', showBreadcrumbs: true }
} }
] ]
} }

View File

@@ -31,18 +31,19 @@ import { I18nBreadcrumbResolver } from '../../core/breadcrumbs/i18n-breadcrumb.r
component: CommunityMetadataComponent, component: CommunityMetadataComponent,
data: { data: {
title: 'community.edit.tabs.metadata.title', title: 'community.edit.tabs.metadata.title',
hideReturnButton: true hideReturnButton: true,
showBreadcrumbs: true
} }
}, },
{ {
path: 'roles', path: 'roles',
component: CommunityRolesComponent, component: CommunityRolesComponent,
data: { title: 'community.edit.tabs.roles.title' } data: { title: 'community.edit.tabs.roles.title', showBreadcrumbs: true }
}, },
{ {
path: 'curate', path: 'curate',
component: CommunityCurateComponent, component: CommunityCurateComponent,
data: { title: 'community.edit.tabs.curate.title' } data: { title: 'community.edit.tabs.curate.title', showBreadcrumbs: true }
} }
] ]
} }

View File

@@ -47,34 +47,34 @@ const ITEM_EDIT_MOVE_PATH = 'move';
{ {
path: 'status', path: 'status',
component: ItemStatusComponent, component: ItemStatusComponent,
data: { title: 'item.edit.tabs.status.title' } data: { title: 'item.edit.tabs.status.title', showBreadcrumbs: true }
}, },
{ {
path: 'bitstreams', path: 'bitstreams',
component: ItemBitstreamsComponent, component: ItemBitstreamsComponent,
data: { title: 'item.edit.tabs.bitstreams.title' } data: { title: 'item.edit.tabs.bitstreams.title', showBreadcrumbs: true }
}, },
{ {
path: 'metadata', path: 'metadata',
component: ItemMetadataComponent, component: ItemMetadataComponent,
data: { title: 'item.edit.tabs.metadata.title' } data: { title: 'item.edit.tabs.metadata.title', showBreadcrumbs: true }
}, },
{ {
path: 'relationships', path: 'relationships',
component: ItemRelationshipsComponent, component: ItemRelationshipsComponent,
data: { title: 'item.edit.tabs.relationships.title' } data: { title: 'item.edit.tabs.relationships.title', showBreadcrumbs: true }
}, },
{ {
path: 'view', path: 'view',
/* TODO - change when view page exists */ /* TODO - change when view page exists */
component: ItemBitstreamsComponent, component: ItemBitstreamsComponent,
data: { title: 'item.edit.tabs.view.title' } data: { title: 'item.edit.tabs.view.title', showBreadcrumbs: true }
}, },
{ {
path: 'curate', path: 'curate',
/* TODO - change when curate page exists */ /* TODO - change when curate page exists */
component: ItemBitstreamsComponent, component: ItemBitstreamsComponent,
data: { title: 'item.edit.tabs.curate.title' } data: { title: 'item.edit.tabs.curate.title', showBreadcrumbs: true }
} }
] ]
}, },

View File

@@ -27,7 +27,7 @@ export class ItemPageResolver implements Resolve<RemoteData<Item>> {
return this.itemService.findById(route.params.id, return this.itemService.findById(route.params.id,
followLink('owningCollection'), followLink('owningCollection'),
followLink('bundles'), followLink('bundles'),
followLink('relationships') followLink('relationships'),
).pipe( ).pipe(
find((RD) => hasValue(RD.error) || RD.hasSucceeded), find((RD) => hasValue(RD.error) || RD.hasSucceeded),
); );

View File

@@ -11,6 +11,7 @@ import { Collection } from './core/shared/collection.model';
import { Item } from './core/shared/item.model'; import { Item } from './core/shared/item.model';
import { getItemPageRoute } from './+item-page/item-page-routing.module'; import { getItemPageRoute } from './+item-page/item-page-routing.module';
import { getCollectionPageRoute } from './+collection-page/collection-page-routing.module'; import { getCollectionPageRoute } from './+collection-page/collection-page-routing.module';
import { BrowseByDSOBreadcrumbResolver } from './+browse-by/browse-by-dso-breadcrumb.resolver';
const ITEM_MODULE_PATH = 'items'; const ITEM_MODULE_PATH = 'items';

View File

@@ -1,7 +1,21 @@
import { BreadcrumbsService } from '../../core/breadcrumbs/breadcrumbs.service'; import { BreadcrumbsService } from '../../core/breadcrumbs/breadcrumbs.service';
/**
* Interface for breadcrumb configuration objects
*/
export interface BreadcrumbConfig<T> { export interface BreadcrumbConfig<T> {
/**
* The service used to calculate the breadcrumb object
*/
provider: BreadcrumbsService<T>; provider: BreadcrumbsService<T>;
/**
* The key that is used to calculate the breadcrumb display value
*/
key: T; key: T;
/**
* The url of the breadcrumb
*/
url?: string; url?: string;
} }

View File

@@ -1,6 +1,15 @@
/**
* Class representing a single breadcrumb
*/
export class Breadcrumb { export class Breadcrumb {
constructor( constructor(
/**
* The display value of the breadcrumb
*/
public text: string, public text: string,
/**
* The optional url of the breadcrumb
*/
public url?: string) { public url?: string) {
} }
} }

View File

@@ -1,7 +1,7 @@
import { Component, OnDestroy, OnInit } from '@angular/core'; import { Component, OnDestroy, OnInit } from '@angular/core';
import { ActivatedRoute, NavigationEnd, Router } from '@angular/router'; import { ActivatedRoute, NavigationEnd, Router } from '@angular/router';
import { Breadcrumb } from './breadcrumb/breadcrumb.model'; import { Breadcrumb } from './breadcrumb/breadcrumb.model';
import { hasNoValue, hasValue, isNotUndefined } from '../shared/empty.util'; import { hasNoValue, hasValue, isNotUndefined, isUndefined } from '../shared/empty.util';
import { filter, map, switchMap, tap } from 'rxjs/operators'; import { filter, map, switchMap, tap } from 'rxjs/operators';
import { combineLatest, Observable, Subscription, of as observableOf } from 'rxjs'; import { combineLatest, Observable, Subscription, of as observableOf } from 'rxjs';
@@ -58,8 +58,12 @@ export class BreadcrumbsComponent implements OnInit, OnDestroy {
const routeConfig = route.snapshot.routeConfig; const routeConfig = route.snapshot.routeConfig;
const last: boolean = hasNoValue(route.firstChild); const last: boolean = hasNoValue(route.firstChild);
if (last && isNotUndefined(data.showBreadcrumbs)) { if (last) {
if (hasValue(data.showBreadcrumbs)) {
this.showBreadcrumbs = data.showBreadcrumbs; this.showBreadcrumbs = data.showBreadcrumbs;
} else if (isUndefined(data.breadcrumb)) {
this.showBreadcrumbs = false;
}
} }
if ( if (

View File

@@ -3,6 +3,7 @@ import { DSOBreadcrumbsService } from './dso-breadcrumbs.service';
import { DSOBreadcrumbResolver } from './dso-breadcrumb.resolver'; import { DSOBreadcrumbResolver } from './dso-breadcrumb.resolver';
import { Collection } from '../shared/collection.model'; import { Collection } from '../shared/collection.model';
import { CollectionDataService } from '../data/collection-data.service'; import { CollectionDataService } from '../data/collection-data.service';
import { followLink, FollowLinkConfig } from '../../shared/utils/follow-link-config.model';
/** /**
* The class that resolves the BreadcrumbConfig object for a Collection * The class that resolves the BreadcrumbConfig object for a Collection
@@ -12,4 +13,17 @@ export class CollectionBreadcrumbResolver extends DSOBreadcrumbResolver<Collecti
constructor(protected breadcrumbService: DSOBreadcrumbsService, protected dataService: CollectionDataService) { constructor(protected breadcrumbService: DSOBreadcrumbsService, protected dataService: CollectionDataService) {
super(breadcrumbService, dataService); super(breadcrumbService, dataService);
} }
/**
* Method that returns the follow links to already resolve
* The self links defined in this list are expected to be requested somewhere in the near future
* Requesting them as embeds will limit the number of requests
*/
get followLinks(): Array<FollowLinkConfig<Collection>> {
return [
followLink('parentCommunity', undefined,
followLink('parentCommunity')
)
];
}
} }

View File

@@ -3,6 +3,7 @@ import { DSOBreadcrumbsService } from './dso-breadcrumbs.service';
import { DSOBreadcrumbResolver } from './dso-breadcrumb.resolver'; import { DSOBreadcrumbResolver } from './dso-breadcrumb.resolver';
import { CommunityDataService } from '../data/community-data.service'; import { CommunityDataService } from '../data/community-data.service';
import { Community } from '../shared/community.model'; import { Community } from '../shared/community.model';
import { followLink, FollowLinkConfig } from '../../shared/utils/follow-link-config.model';
/** /**
* The class that resolves the BreadcrumbConfig object for a Community * The class that resolves the BreadcrumbConfig object for a Community
@@ -12,4 +13,15 @@ export class CommunityBreadcrumbResolver extends DSOBreadcrumbResolver<Community
constructor(protected breadcrumbService: DSOBreadcrumbsService, protected dataService: CommunityDataService) { constructor(protected breadcrumbService: DSOBreadcrumbsService, protected dataService: CommunityDataService) {
super(breadcrumbService, dataService); super(breadcrumbService, dataService);
} }
/**
* Method that returns the follow links to already resolve
* The self links defined in this list are expected to be requested somewhere in the near future
* Requesting them as embeds will limit the number of requests
*/
get followLinks(): Array<FollowLinkConfig<Community>> {
return [
followLink('parentCommunity')
];
}
} }

View File

@@ -2,6 +2,7 @@ import { DSOBreadcrumbResolver } from './dso-breadcrumb.resolver';
import { Collection } from '../shared/collection.model'; import { Collection } from '../shared/collection.model';
import { createSuccessfulRemoteDataObject$ } from '../../shared/testing/utils'; import { createSuccessfulRemoteDataObject$ } from '../../shared/testing/utils';
import { getTestScheduler } from 'jasmine-marbles'; import { getTestScheduler } from 'jasmine-marbles';
import { CollectionBreadcrumbResolver } from './collection-breadcrumb.resolver';
describe('DSOBreadcrumbResolver', () => { describe('DSOBreadcrumbResolver', () => {
describe('resolve', () => { describe('resolve', () => {
@@ -22,7 +23,7 @@ describe('DSOBreadcrumbResolver', () => {
collectionService = { collectionService = {
findById: (id: string) => createSuccessfulRemoteDataObject$(testCollection) findById: (id: string) => createSuccessfulRemoteDataObject$(testCollection)
}; };
resolver = new DSOBreadcrumbResolver(dsoBreadcrumbService, collectionService); resolver = new CollectionBreadcrumbResolver(dsoBreadcrumbService, collectionService);
}); });
it('should resolve a breadcrumb config for the correct DSO', () => { it('should resolve a breadcrumb config for the correct DSO', () => {

View File

@@ -8,12 +8,13 @@ import { map } from 'rxjs/operators';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { DSpaceObject } from '../shared/dspace-object.model'; import { DSpaceObject } from '../shared/dspace-object.model';
import { ChildHALResource } from '../shared/child-hal-resource.model'; import { ChildHALResource } from '../shared/child-hal-resource.model';
import { FollowLinkConfig } from '../../shared/utils/follow-link-config.model';
/** /**
* The class that resolves the BreadcrumbConfig object for a DSpaceObject * The class that resolves the BreadcrumbConfig object for a DSpaceObject
*/ */
@Injectable() @Injectable()
export class DSOBreadcrumbResolver<T extends ChildHALResource & DSpaceObject> implements Resolve<BreadcrumbConfig<T>> { export abstract class DSOBreadcrumbResolver<T extends ChildHALResource & DSpaceObject> implements Resolve<BreadcrumbConfig<T>> {
constructor(protected breadcrumbService: DSOBreadcrumbsService, protected dataService: DataService<T>) { constructor(protected breadcrumbService: DSOBreadcrumbsService, protected dataService: DataService<T>) {
} }
@@ -25,7 +26,7 @@ export class DSOBreadcrumbResolver<T extends ChildHALResource & DSpaceObject> im
*/ */
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<BreadcrumbConfig<T>> { resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<BreadcrumbConfig<T>> {
const uuid = route.params.id; const uuid = route.params.id;
return this.dataService.findById(uuid).pipe( return this.dataService.findById(uuid, ...this.followLinks).pipe(
getSucceededRemoteData(), getSucceededRemoteData(),
getRemoteDataPayload(), getRemoteDataPayload(),
map((object: T) => { map((object: T) => {
@@ -34,6 +35,12 @@ export class DSOBreadcrumbResolver<T extends ChildHALResource & DSpaceObject> im
return { provider: this.breadcrumbService, key: object, url: url }; return { provider: this.breadcrumbService, key: object, url: url };
}) })
); );
}
} /**
* Method that returns the follow links to already resolve
* The self links defined in this list are expected to be requested somewhere in the near future
* Requesting them as embeds will limit the number of requests
*/
abstract get followLinks(): Array<FollowLinkConfig<T>>;
} }

View File

@@ -9,11 +9,11 @@ import { hasNoValue } from '../../shared/empty.util';
*/ */
@Injectable() @Injectable()
export class I18nBreadcrumbResolver implements Resolve<BreadcrumbConfig<string>> { export class I18nBreadcrumbResolver implements Resolve<BreadcrumbConfig<string>> {
constructor(private breadcrumbService: I18nBreadcrumbsService) { constructor(protected breadcrumbService: I18nBreadcrumbsService) {
} }
/** /**
* Method for resolving a site object * Method for resolving an I18n breadcrumb configuration object
* @param {ActivatedRouteSnapshot} route The current ActivatedRouteSnapshot * @param {ActivatedRouteSnapshot} route The current ActivatedRouteSnapshot
* @param {RouterStateSnapshot} state The current RouterStateSnapshot * @param {RouterStateSnapshot} state The current RouterStateSnapshot
* @returns BreadcrumbConfig object * @returns BreadcrumbConfig object

View File

@@ -3,6 +3,7 @@ import { DSOBreadcrumbsService } from './dso-breadcrumbs.service';
import { ItemDataService } from '../data/item-data.service'; import { ItemDataService } from '../data/item-data.service';
import { Item } from '../shared/item.model'; import { Item } from '../shared/item.model';
import { DSOBreadcrumbResolver } from './dso-breadcrumb.resolver'; import { DSOBreadcrumbResolver } from './dso-breadcrumb.resolver';
import { followLink, FollowLinkConfig } from '../../shared/utils/follow-link-config.model';
/** /**
* The class that resolves the BreadcrumbConfig object for an Item * The class that resolves the BreadcrumbConfig object for an Item
@@ -12,4 +13,20 @@ export class ItemBreadcrumbResolver extends DSOBreadcrumbResolver<Item> {
constructor(protected breadcrumbService: DSOBreadcrumbsService, protected dataService: ItemDataService) { constructor(protected breadcrumbService: DSOBreadcrumbsService, protected dataService: ItemDataService) {
super(breadcrumbService, dataService); super(breadcrumbService, dataService);
} }
/**
* Method that returns the follow links to already resolve
* The self links defined in this list are expected to be requested somewhere in the near future
* Requesting them as embeds will limit the number of requests
*/
get followLinks(): Array<FollowLinkConfig<Item>> {
return [
followLink('owningCollection', undefined,
followLink('parentCommunity', undefined,
followLink('parentCommunity'))
),
followLink('bundles'),
followLink('relationships')
];
}
} }

View File

@@ -1,5 +1,12 @@
import { HALResource } from './hal-resource.model'; import { HALResource } from './hal-resource.model';
/**
* Interface for HALResources with a parent object link
*/
export interface ChildHALResource extends HALResource { export interface ChildHALResource extends HALResource {
/**
* Returns the key of the parent link
*/
getParentLinkKey(): keyof this['_links']; getParentLinkKey(): keyof this['_links'];
} }