diff --git a/src/app/entity-groups/journal-entities/item-list-elements/sidebar-search-list-elements/journal-issue/journal-issue-sidebar-search-list-element.component.spec.ts b/src/app/entity-groups/journal-entities/item-list-elements/sidebar-search-list-elements/journal-issue/journal-issue-sidebar-search-list-element.component.spec.ts index 88ea337f063..88da82b2138 100644 --- a/src/app/entity-groups/journal-entities/item-list-elements/sidebar-search-list-elements/journal-issue/journal-issue-sidebar-search-list-element.component.spec.ts +++ b/src/app/entity-groups/journal-entities/item-list-elements/sidebar-search-list-elements/journal-issue/journal-issue-sidebar-search-list-element.component.spec.ts @@ -32,12 +32,19 @@ const parent = Object.assign(new Collection(), { metadata: { 'dc.title': [ { - value: 'parent title', + value: 'community title > collection title', }, ], }, }); describe('JournalIssueSidebarSearchListElementComponent', - createSidebarSearchListElementTests(JournalIssueSidebarSearchListElementComponent, object, parent, 'parent title', 'title', '5 - 7'), + createSidebarSearchListElementTests( + JournalIssueSidebarSearchListElementComponent, + object, + parent, + 'community title > collection title', + 'title', + '5 - 7', + ), ); diff --git a/src/app/entity-groups/journal-entities/item-list-elements/sidebar-search-list-elements/journal-volume/journal-volume-sidebar-search-list-element.component.spec.ts b/src/app/entity-groups/journal-entities/item-list-elements/sidebar-search-list-elements/journal-volume/journal-volume-sidebar-search-list-element.component.spec.ts index fbfce34ee90..20e6ad746a2 100644 --- a/src/app/entity-groups/journal-entities/item-list-elements/sidebar-search-list-elements/journal-volume/journal-volume-sidebar-search-list-element.component.spec.ts +++ b/src/app/entity-groups/journal-entities/item-list-elements/sidebar-search-list-elements/journal-volume/journal-volume-sidebar-search-list-element.component.spec.ts @@ -35,12 +35,18 @@ const parent = Object.assign(new Collection(), { metadata: { 'dc.title': [ { - value: 'parent title', + value: 'community title > collection title', }, ], }, }); describe('JournalVolumeSidebarSearchListElementComponent', - createSidebarSearchListElementTests(JournalVolumeSidebarSearchListElementComponent, object, parent, 'parent title', 'title', 'journal title (1) (2)'), + createSidebarSearchListElementTests( + JournalVolumeSidebarSearchListElementComponent, + object, parent, + 'community title > collection title', + 'title', + 'journal title (1) (2)'), ); + diff --git a/src/app/entity-groups/journal-entities/item-list-elements/sidebar-search-list-elements/journal/journal-sidebar-search-list-element.component.spec.ts b/src/app/entity-groups/journal-entities/item-list-elements/sidebar-search-list-elements/journal/journal-sidebar-search-list-element.component.spec.ts index b97643041bc..fd0f5c53a1d 100644 --- a/src/app/entity-groups/journal-entities/item-list-elements/sidebar-search-list-elements/journal/journal-sidebar-search-list-element.component.spec.ts +++ b/src/app/entity-groups/journal-entities/item-list-elements/sidebar-search-list-elements/journal/journal-sidebar-search-list-element.component.spec.ts @@ -30,12 +30,19 @@ const parent = Object.assign(new Collection(), { metadata: { 'dc.title': [ { - value: 'parent title', + value: 'parent community-title > parent collection-title', }, ], }, }); describe('JournalSidebarSearchListElementComponent', - createSidebarSearchListElementTests(JournalSidebarSearchListElementComponent, object, parent, 'parent title', 'title', '1234, 5678'), + createSidebarSearchListElementTests( + JournalSidebarSearchListElementComponent, + object, + parent, + 'parent community-title > parent collection-title', + 'title', + '1234, 5678', + ), ); diff --git a/src/app/entity-groups/research-entities/item-list-elements/sidebar-search-list-elements/org-unit/org-unit-sidebar-search-list-element.component.spec.ts b/src/app/entity-groups/research-entities/item-list-elements/sidebar-search-list-elements/org-unit/org-unit-sidebar-search-list-element.component.spec.ts index 843d20c3866..61979dddb2e 100644 --- a/src/app/entity-groups/research-entities/item-list-elements/sidebar-search-list-elements/org-unit/org-unit-sidebar-search-list-element.component.spec.ts +++ b/src/app/entity-groups/research-entities/item-list-elements/sidebar-search-list-elements/org-unit/org-unit-sidebar-search-list-element.component.spec.ts @@ -32,12 +32,12 @@ const parent = Object.assign(new Collection(), { metadata: { 'dc.title': [ { - value: 'parent title', + value: 'community title > collection title', }, ], }, }); describe('OrgUnitSidebarSearchListElementComponent', - createSidebarSearchListElementTests(OrgUnitSidebarSearchListElementComponent, object, parent, 'parent title', 'title', 'description'), + createSidebarSearchListElementTests(OrgUnitSidebarSearchListElementComponent, object, parent, 'community title > collection title', 'title', 'description'), ); diff --git a/src/app/entity-groups/research-entities/item-list-elements/sidebar-search-list-elements/person/person-sidebar-search-list-element.component.spec.ts b/src/app/entity-groups/research-entities/item-list-elements/sidebar-search-list-elements/person/person-sidebar-search-list-element.component.spec.ts index 8856dea4c9e..8ef30a2cbcf 100644 --- a/src/app/entity-groups/research-entities/item-list-elements/sidebar-search-list-elements/person/person-sidebar-search-list-element.component.spec.ts +++ b/src/app/entity-groups/research-entities/item-list-elements/sidebar-search-list-elements/person/person-sidebar-search-list-element.component.spec.ts @@ -37,13 +37,13 @@ const parent = Object.assign(new Collection(), { metadata: { 'dc.title': [ { - value: 'parent title', + value: 'community title > collection title', }, ], }, }); describe('PersonSidebarSearchListElementComponent', - createSidebarSearchListElementTests(PersonSidebarSearchListElementComponent, object, parent, 'parent title', 'family name, given name', 'job title', [ - ]), + createSidebarSearchListElementTests(PersonSidebarSearchListElementComponent, object, parent, 'community title > collection title', 'family name, given name', 'job title', []), ); + diff --git a/src/app/entity-groups/research-entities/item-list-elements/sidebar-search-list-elements/project/project-sidebar-search-list-element.component.spec.ts b/src/app/entity-groups/research-entities/item-list-elements/sidebar-search-list-elements/project/project-sidebar-search-list-element.component.spec.ts index 1166804b841..e68db556b69 100644 --- a/src/app/entity-groups/research-entities/item-list-elements/sidebar-search-list-elements/project/project-sidebar-search-list-element.component.spec.ts +++ b/src/app/entity-groups/research-entities/item-list-elements/sidebar-search-list-elements/project/project-sidebar-search-list-element.component.spec.ts @@ -22,12 +22,13 @@ const parent = Object.assign(new Collection(), { metadata: { 'dc.title': [ { - value: 'parent title', + value: 'community title > collection title', }, ], }, }); describe('ProjectSidebarSearchListElementComponent', - createSidebarSearchListElementTests(ProjectSidebarSearchListElementComponent, object, parent, 'parent title', 'title', undefined), + createSidebarSearchListElementTests(ProjectSidebarSearchListElementComponent, object, parent, 'community title > collection title', 'title', undefined), ); + diff --git a/src/app/shared/object-list/sidebar-search-list-element/collection/collection-sidebar-search-list-element.component.spec.ts b/src/app/shared/object-list/sidebar-search-list-element/collection/collection-sidebar-search-list-element.component.spec.ts index 0ad2ab68250..0d9f43f0072 100644 --- a/src/app/shared/object-list/sidebar-search-list-element/collection/collection-sidebar-search-list-element.component.spec.ts +++ b/src/app/shared/object-list/sidebar-search-list-element/collection/collection-sidebar-search-list-element.component.spec.ts @@ -22,6 +22,8 @@ const object = Object.assign(new CollectionSearchResult(), { }, }), }); +object.indexableObject.getParentLinkKey = () => 'parentCommunity'; + const parent = Object.assign(new Community(), { id: 'test-community', metadata: { diff --git a/src/app/shared/object-list/sidebar-search-list-element/community/community-sidebar-search-list-element.component.spec.ts b/src/app/shared/object-list/sidebar-search-list-element/community/community-sidebar-search-list-element.component.spec.ts index fde593c203f..4acdea66c2e 100644 --- a/src/app/shared/object-list/sidebar-search-list-element/community/community-sidebar-search-list-element.component.spec.ts +++ b/src/app/shared/object-list/sidebar-search-list-element/community/community-sidebar-search-list-element.component.spec.ts @@ -21,6 +21,8 @@ const object = Object.assign(new CommunitySearchResult(), { }, }), }); +object.indexableObject.getParentLinkKey = () => 'parentCommunity'; + const parent = Object.assign(new Community(), { id: 'test-parent-community', metadata: { diff --git a/src/app/shared/object-list/sidebar-search-list-element/item-types/publication/publication-sidebar-search-list-element.component.spec.ts b/src/app/shared/object-list/sidebar-search-list-element/item-types/publication/publication-sidebar-search-list-element.component.spec.ts index 2ddec2bbdb8..92ea36fc7c1 100644 --- a/src/app/shared/object-list/sidebar-search-list-element/item-types/publication/publication-sidebar-search-list-element.component.spec.ts +++ b/src/app/shared/object-list/sidebar-search-list-element/item-types/publication/publication-sidebar-search-list-element.component.spec.ts @@ -37,12 +37,12 @@ const parent = Object.assign(new Collection(), { metadata: { 'dc.title': [ { - value: 'parent title', + value: 'communtity title > collection title', }, ], }, }); describe('PublicationSidebarSearchListElementComponent', - createSidebarSearchListElementTests(PublicationSidebarSearchListElementComponent, object, parent, 'parent title', 'title', '(publisher, date) author'), + createSidebarSearchListElementTests(PublicationSidebarSearchListElementComponent, object, parent, 'communtity title > collection title', 'title', '(publisher, date) author'), ); diff --git a/src/app/shared/object-list/sidebar-search-list-element/sidebar-search-list-element.component.html b/src/app/shared/object-list/sidebar-search-list-element/sidebar-search-list-element.component.html index 55f8b6d4e94..2df71dae7f1 100644 --- a/src/app/shared/object-list/sidebar-search-list-element/sidebar-search-list-element.component.html +++ b/src/app/shared/object-list/sidebar-search-list-element/sidebar-search-list-element.component.html @@ -1,6 +1,6 @@ - +
+ [innerHTML]="(hierarchicalTitle$ && hierarchicalTitle$ | async) ? (hierarchicalTitle$ | async) : ('home.breadcrumbs' | translate)">
, parent: DSpaceObject, - expectedParentTitle: string, + expectedHierarchicalTitle: string, expectedTitle: string, expectedDescription: string, extraProviders: any[] = [], @@ -39,6 +39,7 @@ export function createSidebarSearchListElementTests( [object.indexableObject.getParentLinkKey()]: createSuccessfulRemoteDataObject$(parent), }), }); + TestBed.configureTestingModule({ imports: [TranslateModule.forRoot(), RouterTestingModule.withRoutes([]), VarDirective], providers: [ @@ -59,10 +60,16 @@ export function createSidebarSearchListElementTests( fixture.detectChanges(); }); - it('should contain the correct parent title', (done) => { - component.parentTitle$.subscribe((title) => { - expect(title).toEqual(expectedParentTitle); - done(); + it('should contain the correct hierarchical title', (done) => { + component.hierarchicalTitle$.subscribe({ + next: (title) => { + expect(title).toEqual(expectedHierarchicalTitle); + done(); + }, + error: (err) => { + fail('hierarchicalTitle$ threw an error: ' + err); + done(); + }, }); }); @@ -75,3 +82,4 @@ export function createSidebarSearchListElementTests( }); }; } + diff --git a/src/app/shared/object-list/sidebar-search-list-element/sidebar-search-list-element.component.ts b/src/app/shared/object-list/sidebar-search-list-element/sidebar-search-list-element.component.ts index 34aaf0d74ea..c73be6daa03 100644 --- a/src/app/shared/object-list/sidebar-search-list-element/sidebar-search-list-element.component.ts +++ b/src/app/shared/object-list/sidebar-search-list-element/sidebar-search-list-element.component.ts @@ -20,12 +20,14 @@ import { } from '@dspace/shared/utils/empty.util'; import { TranslateModule } from '@ngx-translate/core'; import { + from, Observable, of, } from 'rxjs'; import { + catchError, find, - map, + switchMap, } from 'rxjs/operators'; import { TruncatableService } from '../../truncatable/truncatable.service'; @@ -49,9 +51,9 @@ import { SearchResultListElementComponent } from '../search-result-list-element/ */ export class SidebarSearchListElementComponent, K extends DSpaceObject> extends SearchResultListElementComponent implements OnInit { /** - * Observable for the title of the parent object (displayed above the object's title) + * Observable for the hierarchical title i.e community > subcommunity > collection */ - parentTitle$: Observable; + hierarchicalTitle$: Observable; /** * A description to display below the title @@ -71,7 +73,7 @@ export class SidebarSearchListElementComponent, K exte ngOnInit(): void { super.ngOnInit(); if (hasValue(this.dso)) { - this.parentTitle$ = this.getParentTitle(); + this.hierarchicalTitle$ = this.getHierarchicalName(); this.description = this.getDescription(); } } @@ -85,25 +87,66 @@ export class SidebarSearchListElementComponent, K exte /** * Get the title of the object's parent - * Retrieve the parent by using the object's parent link and retrieving its 'dc.title' metadata + * keep on Retrieving recursively the parent by using the object's parent link and retrieving its 'dc.title' metadata + * and build a heirarchical name by concating the parent's names */ - getParentTitle(): Observable { + getHierarchicalName(): Observable { return this.getParent().pipe( - map((parentRD: RemoteData) => { - return hasValue(parentRD) && hasValue(parentRD.payload) ? this.dsoNameService.getName(parentRD.payload, true) : undefined; + switchMap((initialRD: RemoteData) => { + if (!hasValue(initialRD) || !initialRD.hasSucceeded || !hasValue(initialRD.payload)) { + return of(''); + } + + return from((async () => { + const names: string[] = []; + let current: DSpaceObject | null = initialRD.payload; + + const visited = new Set(); // prevent cycles + + while (current && !visited.has(current.id)) { + visited.add(current.id); + const name = this.dsoNameService.getName(current); + if (name) { + names.unshift(name); + } + + const instance = this.createInstanceFromDSpaceObject(current); + const parentRD: RemoteData = await instance.getParent().toPromise().catch(() => null); + + if (hasValue(parentRD) && parentRD.hasSucceeded && hasValue(parentRD.payload)) { + current = parentRD.payload; + } else { + current = null; + } + } + + return names.join(' > '); + })()); }), + catchError(() => of('')), ); } + /** + * Utility method to create an instance of the current class from a DSpaceObject + */ + private createInstanceFromDSpaceObject(dso: DSpaceObject): this { + const instance = Object.create(this); + instance.dso = dso; + return instance; + } + /** * Get the parent of the object */ getParent(): Observable> { if (typeof (this.dso as any).getParentLinkKey === 'function') { const propertyName = (this.dso as any).getParentLinkKey(); - return this.linkService.resolveLink(this.dso, followLink(propertyName))[propertyName].pipe( - find((parentRD: RemoteData) => parentRD.hasSucceeded || parentRD.statusCode === 204), - ); + if (this.linkService.resolveLink(this.dso, followLink(propertyName))[propertyName]) { + return this.linkService.resolveLink(this.dso, followLink(propertyName))[propertyName].pipe( + find((parentRD: RemoteData) => parentRD.hasSucceeded || parentRD.statusCode === 204), + ); + } } return of(undefined); } diff --git a/src/app/shared/truncatable/truncatable-part/truncatable-part.component.scss b/src/app/shared/truncatable/truncatable-part/truncatable-part.component.scss index e045b197d28..5602606a5c2 100644 --- a/src/app/shared/truncatable/truncatable-part/truncatable-part.component.scss +++ b/src/app/shared/truncatable/truncatable-part/truncatable-part.component.scss @@ -9,3 +9,8 @@ .removeFaded.content::after { display: none; } + +.content { + white-space: normal; + overflow: visible; +}