diff --git a/src/app/+item-page/simple/item-types/publication/publication.component.ts b/src/app/+item-page/simple/item-types/publication/publication.component.ts index 3647e23367..81e2726e0c 100644 --- a/src/app/+item-page/simple/item-types/publication/publication.component.ts +++ b/src/app/+item-page/simple/item-types/publication/publication.component.ts @@ -7,7 +7,7 @@ import { } from '../../../../shared/items/item-type-decorator'; import { ItemComponent } from '../shared/item.component'; import { MetadataRepresentation } from '../../../../core/shared/metadata-representation/metadata-representation.model'; -import { filterRelationsByTypeLabel, relationsToItems } from '../shared/item-relationships-utils'; +import { getRelatedItemsByTypeLabel } from '../shared/item-relationships-utils'; @rendersItemType('Publication', ItemViewMode.Full) @rendersItemType(DEFAULT_ITEM_TYPE, ItemViewMode.Full) @@ -46,18 +46,15 @@ export class PublicationComponent extends ItemComponent implements OnInit { this.authors$ = this.buildRepresentations('Person', 'dc.contributor.author'); this.projects$ = this.resolvedRelsAndTypes$.pipe( - filterRelationsByTypeLabel('isProjectOfPublication'), - relationsToItems(this.item.id) + getRelatedItemsByTypeLabel(this.item.id, 'isProjectOfPublication') ); this.orgUnits$ = this.resolvedRelsAndTypes$.pipe( - filterRelationsByTypeLabel('isOrgUnitOfPublication'), - relationsToItems(this.item.id) + getRelatedItemsByTypeLabel(this.item.id, 'isOrgUnitOfPublication') ); this.journalIssues$ = this.resolvedRelsAndTypes$.pipe( - filterRelationsByTypeLabel('isJournalIssueOfPublication'), - relationsToItems(this.item.id) + getRelatedItemsByTypeLabel(this.item.id, 'isJournalIssueOfPublication') ); } diff --git a/src/app/+item-page/simple/item-types/shared/item-relationships-utils.ts b/src/app/+item-page/simple/item-types/shared/item-relationships-utils.ts index 91f7c52bb8..65ad743245 100644 --- a/src/app/+item-page/simple/item-types/shared/item-relationships-utils.ts +++ b/src/app/+item-page/simple/item-types/shared/item-relationships-utils.ts @@ -2,16 +2,15 @@ import { ItemMetadataRepresentation } from '../../../../core/shared/metadata-rep import { MetadataRepresentation } from '../../../../core/shared/metadata-representation/metadata-representation.model'; import { MetadatumRepresentation } from '../../../../core/shared/metadata-representation/metadatum/metadatum-representation.model'; import { MetadataValue } from '../../../../core/shared/metadata.models'; -import { getSucceededRemoteData } from '../../../../core/shared/operators'; -import { hasValue } from '../../../../shared/empty.util'; +import { getRemoteDataPayload, getSucceededRemoteData } from '../../../../core/shared/operators'; +import { hasNoValue, hasValue } from '../../../../shared/empty.util'; import { Observable } from 'rxjs/internal/Observable'; import { Relationship } from '../../../../core/shared/item-relationships/relationship.model'; import { RelationshipType } from '../../../../core/shared/item-relationships/relationship-type.model'; -import { distinctUntilChanged, flatMap, map } from 'rxjs/operators'; +import { distinctUntilChanged, flatMap, map, switchMap } from 'rxjs/operators'; import { of as observableOf, zip as observableZip, combineLatest as observableCombineLatest } from 'rxjs'; import { ItemDataService } from '../../../../core/data/item-data.service'; import { Item } from '../../../../core/shared/item.model'; -import { RemoteData } from '../../../../core/data/remote-data'; /** * Operator for comparing arrays using a mapping function @@ -43,23 +42,36 @@ export const compareArraysUsingIds = () => /** * Fetch the relationships which match the type label given * @param {string} label Type label + * @param thisId The item's id of which the relations belong to * @returns {(source: Observable<[Relationship[] , RelationshipType[]]>) => Observable} */ -export const filterRelationsByTypeLabel = (label: string) => +export const filterRelationsByTypeLabel = (label: string, thisId?: string) => (source: Observable<[Relationship[], RelationshipType[]]>): Observable => source.pipe( - map(([relsCurrentPage, relTypesCurrentPage]) => - relsCurrentPage.filter((rel: Relationship, idx: number) => - hasValue(relTypesCurrentPage[idx]) && (relTypesCurrentPage[idx].leftLabel === label || - relTypesCurrentPage[idx].rightLabel === label) - ) - ), + switchMap(([relsCurrentPage, relTypesCurrentPage]) => { + const relatedItems$ = observableZip(...relsCurrentPage.map((rel: Relationship) => + observableCombineLatest( + rel.leftItem.pipe(getSucceededRemoteData(), getRemoteDataPayload()), + rel.rightItem.pipe(getSucceededRemoteData(), getRemoteDataPayload())) + ) + ); + return relatedItems$.pipe( + map((arr) => relsCurrentPage.filter((rel: Relationship, idx: number) => + hasValue(relTypesCurrentPage[idx]) && ( + (hasNoValue(thisId) && (relTypesCurrentPage[idx].leftLabel === label || + relTypesCurrentPage[idx].rightLabel === label)) || + (thisId === arr[idx][0].id && relTypesCurrentPage[idx].leftLabel === label) || + (thisId === arr[idx][1].id && relTypesCurrentPage[idx].rightLabel === label) + ) + )) + ); + }), distinctUntilChanged(compareArraysUsingIds()) ); /** * Operator for turning a list of relationships into a list of the relevant items - * @param {string} thisId The item's id of which the relations belong to + * @param {string} thisId The item's id of which the relations belong to * @returns {(source: Observable) => Observable} */ export const relationsToItems = (thisId: string) => @@ -79,10 +91,25 @@ export const relationsToItems = (thisId: string) => } else if (rightItem.payload.id === thisId) { return leftItem.payload; } - })), + }) + .filter((item: Item) => hasValue(item)) + ), distinctUntilChanged(compareArraysUsingIds()), ); +/** + * Operator for turning a list of relationships and their relationship-types into a list of relevant items by relationship label + * @param thisId The item's id of which the relations belong to + * @param label The label of the relationship-type to filter on + * @param side Filter only on one side of the relationship (for example: child-parent relationships) + */ +export const getRelatedItemsByTypeLabel = (thisId: string, label: string) => + (source: Observable<[Relationship[], RelationshipType[]]>): Observable => + source.pipe( + filterRelationsByTypeLabel(label, thisId), + relationsToItems(thisId) + ); + /** * Operator for turning a list of relationships into a list of metadatarepresentations given the original metadata * @param parentId The id of the parent item diff --git a/src/app/+item-page/simple/item-types/shared/item.component.spec.ts b/src/app/+item-page/simple/item-types/shared/item.component.spec.ts index 95235c5a72..12312656f6 100644 --- a/src/app/+item-page/simple/item-types/shared/item.component.spec.ts +++ b/src/app/+item-page/simple/item-types/shared/item.component.spec.ts @@ -104,7 +104,9 @@ export function containsFieldInput(fields: DebugElement[], metadataKey: string): export function createRelationshipsObservable() { return observableOf(new RemoteData(false, false, true, null, new PaginatedList(new PageInfo(), [ Object.assign(new Relationship(), { - relationshipType: observableOf(new RemoteData(false, false, true, null, new RelationshipType())) + relationshipType: observableOf(new RemoteData(false, false, true, null, new RelationshipType())), + leftItem: observableOf(new RemoteData(false, false, true, null, new Item())), + rightItem: observableOf(new RemoteData(false, false, true, null, new Item())) }) ]))); } diff --git a/src/app/entity-groups/journal-entities/item-pages/journal-issue/journal-issue.component.ts b/src/app/entity-groups/journal-entities/item-pages/journal-issue/journal-issue.component.ts index a355431100..b584fa3285 100644 --- a/src/app/entity-groups/journal-entities/item-pages/journal-issue/journal-issue.component.ts +++ b/src/app/entity-groups/journal-entities/item-pages/journal-issue/journal-issue.component.ts @@ -4,10 +4,7 @@ import { Item } from '../../../../core/shared/item.model'; import { ItemViewMode, rendersItemType } from '../../../../shared/items/item-type-decorator'; import { isNotEmpty } from '../../../../shared/empty.util'; import { ItemComponent } from '../../../../+item-page/simple/item-types/shared/item.component'; -import { - filterRelationsByTypeLabel, - relationsToItems -} from '../../../../+item-page/simple/item-types/shared/item-relationships-utils'; +import { getRelatedItemsByTypeLabel } from '../../../../+item-page/simple/item-types/shared/item-relationships-utils'; @rendersItemType('JournalIssue', ItemViewMode.Full) @Component({ @@ -34,12 +31,10 @@ export class JournalIssueComponent extends ItemComponent { if (isNotEmpty(this.resolvedRelsAndTypes$)) { this.volumes$ = this.resolvedRelsAndTypes$.pipe( - filterRelationsByTypeLabel('isJournalVolumeOfIssue'), - relationsToItems(this.item.id) + getRelatedItemsByTypeLabel(this.item.id, 'isJournalVolumeOfIssue') ); this.publications$ = this.resolvedRelsAndTypes$.pipe( - filterRelationsByTypeLabel('isPublicationOfJournalIssue'), - relationsToItems(this.item.id) + getRelatedItemsByTypeLabel(this.item.id, 'isPublicationOfJournalIssue') ); } } diff --git a/src/app/entity-groups/journal-entities/item-pages/journal-volume/journal-volume.component.ts b/src/app/entity-groups/journal-entities/item-pages/journal-volume/journal-volume.component.ts index a851bfebbe..66df0b8104 100644 --- a/src/app/entity-groups/journal-entities/item-pages/journal-volume/journal-volume.component.ts +++ b/src/app/entity-groups/journal-entities/item-pages/journal-volume/journal-volume.component.ts @@ -4,10 +4,7 @@ import { Item } from '../../../../core/shared/item.model'; import { ItemViewMode, rendersItemType } from '../../../../shared/items/item-type-decorator'; import { isNotEmpty } from '../../../../shared/empty.util'; import { ItemComponent } from '../../../../+item-page/simple/item-types/shared/item.component'; -import { - filterRelationsByTypeLabel, - relationsToItems -} from '../../../../+item-page/simple/item-types/shared/item-relationships-utils'; +import { getRelatedItemsByTypeLabel } from '../../../../+item-page/simple/item-types/shared/item-relationships-utils'; @rendersItemType('JournalVolume', ItemViewMode.Full) @Component({ @@ -34,12 +31,10 @@ export class JournalVolumeComponent extends ItemComponent { if (isNotEmpty(this.resolvedRelsAndTypes$)) { this.journals$ = this.resolvedRelsAndTypes$.pipe( - filterRelationsByTypeLabel('isJournalOfVolume'), - relationsToItems(this.item.id) + getRelatedItemsByTypeLabel(this.item.id, 'isJournalOfVolume') ); this.issues$ = this.resolvedRelsAndTypes$.pipe( - filterRelationsByTypeLabel('isIssueOfJournalVolume'), - relationsToItems(this.item.id) + getRelatedItemsByTypeLabel(this.item.id, 'isIssueOfJournalVolume') ); } } diff --git a/src/app/entity-groups/journal-entities/item-pages/journal/journal.component.ts b/src/app/entity-groups/journal-entities/item-pages/journal/journal.component.ts index 99183651e1..a8f071d78a 100644 --- a/src/app/entity-groups/journal-entities/item-pages/journal/journal.component.ts +++ b/src/app/entity-groups/journal-entities/item-pages/journal/journal.component.ts @@ -4,10 +4,7 @@ import { Item } from '../../../../core/shared/item.model'; import { ItemViewMode, rendersItemType } from '../../../../shared/items/item-type-decorator'; import { isNotEmpty } from '../../../../shared/empty.util'; import { ItemComponent } from '../../../../+item-page/simple/item-types/shared/item.component'; -import { - filterRelationsByTypeLabel, - relationsToItems -} from '../../../../+item-page/simple/item-types/shared/item-relationships-utils'; +import { getRelatedItemsByTypeLabel } from '../../../../+item-page/simple/item-types/shared/item-relationships-utils'; @rendersItemType('Journal', ItemViewMode.Full) @Component({ @@ -29,8 +26,7 @@ export class JournalComponent extends ItemComponent { if (isNotEmpty(this.resolvedRelsAndTypes$)) { this.volumes$ = this.resolvedRelsAndTypes$.pipe( - filterRelationsByTypeLabel('isVolumeOfJournal'), - relationsToItems(this.item.id) + getRelatedItemsByTypeLabel(this.item.id, 'isVolumeOfJournal') ); } } diff --git a/src/app/entity-groups/research-entities/item-pages/orgunit/orgunit.component.ts b/src/app/entity-groups/research-entities/item-pages/orgunit/orgunit.component.ts index 7101f05d35..031ca14ebb 100644 --- a/src/app/entity-groups/research-entities/item-pages/orgunit/orgunit.component.ts +++ b/src/app/entity-groups/research-entities/item-pages/orgunit/orgunit.component.ts @@ -4,10 +4,7 @@ import { Item } from '../../../../core/shared/item.model'; import { ItemViewMode, rendersItemType } from '../../../../shared/items/item-type-decorator'; import { isNotEmpty } from '../../../../shared/empty.util'; import { ItemComponent } from '../../../../+item-page/simple/item-types/shared/item.component'; -import { - filterRelationsByTypeLabel, - relationsToItems -} from '../../../../+item-page/simple/item-types/shared/item-relationships-utils'; +import { getRelatedItemsByTypeLabel } from '../../../../+item-page/simple/item-types/shared/item-relationships-utils'; @rendersItemType('OrgUnit', ItemViewMode.Full) @Component({ @@ -39,18 +36,15 @@ export class OrgunitComponent extends ItemComponent implements OnInit { if (isNotEmpty(this.resolvedRelsAndTypes$)) { this.people$ = this.resolvedRelsAndTypes$.pipe( - filterRelationsByTypeLabel('isPersonOfOrgUnit'), - relationsToItems(this.item.id) + getRelatedItemsByTypeLabel(this.item.id, 'isPersonOfOrgUnit') ); this.projects$ = this.resolvedRelsAndTypes$.pipe( - filterRelationsByTypeLabel('isProjectOfOrgUnit'), - relationsToItems(this.item.id) + getRelatedItemsByTypeLabel(this.item.id, 'isProjectOfOrgUnit') ); this.publications$ = this.resolvedRelsAndTypes$.pipe( - filterRelationsByTypeLabel('isPublicationOfOrgUnit'), - relationsToItems(this.item.id) + getRelatedItemsByTypeLabel(this.item.id, 'isPublicationOfOrgUnit') ); } }} diff --git a/src/app/entity-groups/research-entities/item-pages/person/person.component.ts b/src/app/entity-groups/research-entities/item-pages/person/person.component.ts index ec91561eb9..8b36175b96 100644 --- a/src/app/entity-groups/research-entities/item-pages/person/person.component.ts +++ b/src/app/entity-groups/research-entities/item-pages/person/person.component.ts @@ -6,10 +6,7 @@ import { ITEM } from '../../../../shared/items/switcher/item-type-switcher.compo import { SearchFixedFilterService } from '../../../../+search-page/search-filters/search-filter/search-fixed-filter.service'; import { isNotEmpty } from '../../../../shared/empty.util'; import { ItemComponent } from '../../../../+item-page/simple/item-types/shared/item.component'; -import { - filterRelationsByTypeLabel, - relationsToItems -} from '../../../../+item-page/simple/item-types/shared/item-relationships-utils'; +import { getRelatedItemsByTypeLabel } from '../../../../+item-page/simple/item-types/shared/item-relationships-utils'; @rendersItemType('Person', ItemViewMode.Full) @Component({ @@ -57,18 +54,15 @@ export class PersonComponent extends ItemComponent { if (isNotEmpty(this.resolvedRelsAndTypes$)) { this.publications$ = this.resolvedRelsAndTypes$.pipe( - filterRelationsByTypeLabel('isPublicationOfAuthor'), - relationsToItems(this.item.id) + getRelatedItemsByTypeLabel(this.item.id, 'isPublicationOfAuthor') ); this.projects$ = this.resolvedRelsAndTypes$.pipe( - filterRelationsByTypeLabel('isProjectOfPerson'), - relationsToItems(this.item.id) + getRelatedItemsByTypeLabel(this.item.id, 'isProjectOfPerson') ); this.orgUnits$ = this.resolvedRelsAndTypes$.pipe( - filterRelationsByTypeLabel('isOrgUnitOfPerson'), - relationsToItems(this.item.id) + getRelatedItemsByTypeLabel(this.item.id, 'isOrgUnitOfPerson') ); this.fixedFilterQuery = this.fixedFilterService.getQueryByRelations('isAuthorOfPublication', this.item.id); diff --git a/src/app/entity-groups/research-entities/item-pages/project/project.component.ts b/src/app/entity-groups/research-entities/item-pages/project/project.component.ts index 46bc7c9f88..13c2b54ba4 100644 --- a/src/app/entity-groups/research-entities/item-pages/project/project.component.ts +++ b/src/app/entity-groups/research-entities/item-pages/project/project.component.ts @@ -5,10 +5,7 @@ import { MetadataRepresentation } from '../../../../core/shared/metadata-represe import { ItemViewMode, rendersItemType } from '../../../../shared/items/item-type-decorator'; import { isNotEmpty } from '../../../../shared/empty.util'; import { ItemComponent } from '../../../../+item-page/simple/item-types/shared/item.component'; -import { - filterRelationsByTypeLabel, - relationsToItems -} from '../../../../+item-page/simple/item-types/shared/item-relationships-utils'; +import { getRelatedItemsByTypeLabel } from '../../../../+item-page/simple/item-types/shared/item-relationships-utils'; @rendersItemType('Project', ItemViewMode.Full) @Component({ @@ -47,18 +44,15 @@ export class ProjectComponent extends ItemComponent implements OnInit { this.contributors$ = this.buildRepresentations('OrgUnit', 'project.contributor.other'); this.people$ = this.resolvedRelsAndTypes$.pipe( - filterRelationsByTypeLabel('isPersonOfProject'), - relationsToItems(this.item.id) + getRelatedItemsByTypeLabel(this.item.id, 'isPersonOfProject') ); this.publications$ = this.resolvedRelsAndTypes$.pipe( - filterRelationsByTypeLabel('isPublicationOfProject'), - relationsToItems(this.item.id) + getRelatedItemsByTypeLabel(this.item.id, 'isPublicationOfProject') ); this.orgUnits$ = this.resolvedRelsAndTypes$.pipe( - filterRelationsByTypeLabel('isOrgUnitOfProject'), - relationsToItems(this.item.id) + getRelatedItemsByTypeLabel(this.item.id, 'isOrgUnitOfProject') ); } }