62339: itemIds to item remotedata in relationships

This commit is contained in:
Kristof De Langhe
2019-05-10 13:44:58 +02:00
parent 7ef769431a
commit 38625d2cd5
11 changed files with 56 additions and 118 deletions

View File

@@ -1,12 +1,10 @@
import { ChangeDetectionStrategy, Component, Inject, OnInit } from '@angular/core'; import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { ItemDataService } from '../../../../core/data/item-data.service';
import { Item } from '../../../../core/shared/item.model'; import { Item } from '../../../../core/shared/item.model';
import { import {
DEFAULT_ITEM_TYPE, ItemViewMode, DEFAULT_ITEM_TYPE, ItemViewMode,
rendersItemType rendersItemType
} from '../../../../shared/items/item-type-decorator'; } from '../../../../shared/items/item-type-decorator';
import { ITEM } from '../../../../shared/items/switcher/item-type-switcher.component';
import { ItemComponent } from '../shared/item.component'; import { ItemComponent } from '../shared/item.component';
import { MetadataRepresentation } from '../../../../core/shared/metadata-representation/metadata-representation.model'; import { MetadataRepresentation } from '../../../../core/shared/metadata-representation/metadata-representation.model';
import { filterRelationsByTypeLabel, relationsToItems } from '../shared/item-relationships-utils'; import { filterRelationsByTypeLabel, relationsToItems } from '../shared/item-relationships-utils';
@@ -40,33 +38,26 @@ export class PublicationComponent extends ItemComponent implements OnInit {
*/ */
journalIssues$: Observable<Item[]>; journalIssues$: Observable<Item[]>;
constructor(
@Inject(ITEM) public item: Item,
private ids: ItemDataService
) {
super(item);
}
ngOnInit(): void { ngOnInit(): void {
super.ngOnInit(); super.ngOnInit();
if (this.resolvedRelsAndTypes$) { if (this.resolvedRelsAndTypes$) {
this.authors$ = this.buildRepresentations('Person', 'dc.contributor.author', this.ids); this.authors$ = this.buildRepresentations('Person', 'dc.contributor.author');
this.projects$ = this.resolvedRelsAndTypes$.pipe( this.projects$ = this.resolvedRelsAndTypes$.pipe(
filterRelationsByTypeLabel('isProjectOfPublication'), filterRelationsByTypeLabel('isProjectOfPublication'),
relationsToItems(this.item.id, this.ids) relationsToItems(this.item.id)
); );
this.orgUnits$ = this.resolvedRelsAndTypes$.pipe( this.orgUnits$ = this.resolvedRelsAndTypes$.pipe(
filterRelationsByTypeLabel('isOrgUnitOfPublication'), filterRelationsByTypeLabel('isOrgUnitOfPublication'),
relationsToItems(this.item.id, this.ids) relationsToItems(this.item.id)
); );
this.journalIssues$ = this.resolvedRelsAndTypes$.pipe( this.journalIssues$ = this.resolvedRelsAndTypes$.pipe(
filterRelationsByTypeLabel('isJournalIssueOfPublication'), filterRelationsByTypeLabel('isJournalIssueOfPublication'),
relationsToItems(this.item.id, this.ids) relationsToItems(this.item.id)
); );
} }

View File

@@ -3,10 +3,8 @@ import { Observable } from 'rxjs/internal/Observable';
import { Relationship } from '../../../../core/shared/item-relationships/relationship.model'; import { Relationship } from '../../../../core/shared/item-relationships/relationship.model';
import { RelationshipType } from '../../../../core/shared/item-relationships/relationship-type.model'; import { RelationshipType } from '../../../../core/shared/item-relationships/relationship-type.model';
import { distinctUntilChanged, flatMap, map } from 'rxjs/operators'; import { distinctUntilChanged, flatMap, map } from 'rxjs/operators';
import { zip as observableZip } from 'rxjs'; import { zip as observableZip, combineLatest as observableCombineLatest } from 'rxjs';
import { ItemDataService } from '../../../../core/data/item-data.service';
import { Item } from '../../../../core/shared/item.model'; import { Item } from '../../../../core/shared/item.model';
import { RemoteData } from '../../../../core/data/remote-data';
/** /**
* Operator for comparing arrays using a mapping function * Operator for comparing arrays using a mapping function
@@ -55,26 +53,25 @@ export const filterRelationsByTypeLabel = (label: string) =>
/** /**
* Operator for turning a list of relationships into a list of the relevant items * 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
* @param {ItemDataService} ids The ItemDataService to fetch items from the REST API
* @returns {(source: Observable<Relationship[]>) => Observable<Item[]>} * @returns {(source: Observable<Relationship[]>) => Observable<Item[]>}
*/ */
export const relationsToItems = (thisId: string, ids: ItemDataService) => export const relationsToItems = (thisId: string) =>
(source: Observable<Relationship[]>): Observable<Item[]> => (source: Observable<Relationship[]>): Observable<Item[]> =>
source.pipe( source.pipe(
flatMap((rels: Relationship[]) => flatMap((rels: Relationship[]) =>
observableZip( observableZip(
...rels.map((rel: Relationship) => { ...rels.map((rel: Relationship) => observableCombineLatest(rel.leftItem, rel.rightItem))
let queryId = rel.leftId;
if (rel.leftId === thisId) {
queryId = rel.rightId;
}
return ids.findById(queryId);
})
) )
), ),
map((arr: Array<RemoteData<Item>>) => map((arr) =>
arr arr
.filter((d: RemoteData<Item>) => d.hasSucceeded) .filter(([leftItem, rightItem]) => leftItem.hasSucceeded && rightItem.hasSucceeded)
.map((d: RemoteData<Item>) => d.payload)), .map(([leftItem, rightItem]) => {
if (leftItem.payload.id === thisId) {
return rightItem.payload;
} else if (rightItem.payload.id === thisId) {
return leftItem.payload;
}
})),
distinctUntilChanged(compareArraysUsingIds()), distinctUntilChanged(compareArraysUsingIds()),
); );

View File

@@ -23,7 +23,7 @@ import { compareArraysUsingIds } from './item-relationships-utils';
* @param metadata The list of original Metadatum objects * @param metadata The list of original Metadatum objects
* @param ids The ItemDataService to use for fetching Items from the Rest API * @param ids The ItemDataService to use for fetching Items from the Rest API
*/ */
export const relationsToRepresentations = (thisId: string, itemType: string, metadata: MetadataValue[], ids: ItemDataService) => export const relationsToRepresentations = (thisId: string, itemType: string, metadata: MetadataValue[]) =>
(source: Observable<Relationship[]>): Observable<MetadataRepresentation[]> => (source: Observable<Relationship[]>): Observable<MetadataRepresentation[]> =>
source.pipe( source.pipe(
flatMap((rels: Relationship[]) => flatMap((rels: Relationship[]) =>
@@ -35,13 +35,16 @@ export const relationsToRepresentations = (thisId: string, itemType: string, met
const matchingRels = rels.filter((rel: Relationship) => ('' + rel.id) === metadatum.virtualValue); const matchingRels = rels.filter((rel: Relationship) => ('' + rel.id) === metadatum.virtualValue);
if (matchingRels.length > 0) { if (matchingRels.length > 0) {
const matchingRel = matchingRels[0]; const matchingRel = matchingRels[0];
let queryId = matchingRel.leftId; return observableCombineLatest(matchingRel.leftItem, matchingRel.rightItem).pipe(
if (matchingRel.leftId === thisId) { filter(([leftItem, rightItem]) => leftItem.hasSucceeded && rightItem.hasSucceeded),
queryId = matchingRel.rightId; map(([leftItem, rightItem]) => {
} if (leftItem.payload.id === thisId) {
return ids.findById(queryId).pipe( return rightItem.payload;
getSucceededRemoteData(), } else if (rightItem.payload.id === thisId) {
map((d: RemoteData<Item>) => Object.assign(new ItemMetadataRepresentation(), d.payload)) return leftItem.payload;
}
}),
map((item: Item) => Object.assign(new ItemMetadataRepresentation(), item))
); );
} }
} else { } else {
@@ -102,7 +105,7 @@ export class ItemComponent implements OnInit {
* @param metadataField The metadata field that resembles the item type. * @param metadataField The metadata field that resembles the item type.
* @param itemDataService ItemDataService to turn relations into items. * @param itemDataService ItemDataService to turn relations into items.
*/ */
buildRepresentations(itemType: string, metadataField: string, itemDataService: ItemDataService): Observable<MetadataRepresentation[]> { buildRepresentations(itemType: string, metadataField: string): Observable<MetadataRepresentation[]> {
const metadata = this.item.findMetadataSortedByPlace(metadataField); const metadata = this.item.findMetadataSortedByPlace(metadataField);
const relsCurrentPage$ = this.item.relationships.pipe( const relsCurrentPage$ = this.item.relationships.pipe(
getSucceededRemoteData(), getSucceededRemoteData(),
@@ -112,7 +115,7 @@ export class ItemComponent implements OnInit {
); );
return relsCurrentPage$.pipe( return relsCurrentPage$.pipe(
relationsToRepresentations(this.item.id, itemType, metadata, itemDataService) relationsToRepresentations(this.item.id, itemType, metadata)
); );
} }

View File

@@ -18,17 +18,13 @@ export class NormalizedRelationship extends NormalizedObject<Relationship> {
@autoserialize @autoserialize
id: string; id: string;
/**
* The identifier of the Item to the left side of this Relationship
*/
@autoserialize @autoserialize
leftId: string; @relationship(ResourceType.Item, false)
leftItem: string;
/**
* The identifier of the Item to the right side of this Relationship
*/
@autoserialize @autoserialize
rightId: string; @relationship(ResourceType.Item, false)
rightItem: string;
/** /**
* The place of the Item to the left side of this Relationship * The place of the Item to the left side of this Relationship

View File

@@ -3,6 +3,7 @@ import { CacheableObject } from '../../cache/object-cache.reducer';
import { RemoteData } from '../../data/remote-data'; import { RemoteData } from '../../data/remote-data';
import { ResourceType } from '../resource-type'; import { ResourceType } from '../resource-type';
import { RelationshipType } from './relationship-type.model'; import { RelationshipType } from './relationship-type.model';
import { Item } from '../item.model';
/** /**
* Describes a Relationship between two Items * Describes a Relationship between two Items
@@ -28,15 +29,9 @@ export class Relationship implements CacheableObject {
*/ */
id: string; id: string;
/** leftItem: Observable<RemoteData<Item>>;
* The identifier of the Item to the left side of this Relationship
*/
leftId: string;
/** rightItem: Observable<RemoteData<Item>>;
* The identifier of the Item to the right side of this Relationship
*/
rightId: string;
/** /**
* The place of the Item to the left side of this Relationship * The place of the Item to the left side of this Relationship

View File

@@ -1,9 +1,7 @@
import { Component, Inject } from '@angular/core'; import { Component } from '@angular/core';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { ItemDataService } from '../../../../core/data/item-data.service';
import { Item } from '../../../../core/shared/item.model'; import { Item } from '../../../../core/shared/item.model';
import { ItemViewMode, rendersItemType } from '../../../../shared/items/item-type-decorator'; import { ItemViewMode, rendersItemType } from '../../../../shared/items/item-type-decorator';
import { ITEM } from '../../../../shared/items/switcher/item-type-switcher.component';
import { isNotEmpty } from '../../../../shared/empty.util'; import { isNotEmpty } from '../../../../shared/empty.util';
import { ItemComponent } from '../../../../+item-page/simple/item-types/shared/item.component'; import { ItemComponent } from '../../../../+item-page/simple/item-types/shared/item.component';
import { import {
@@ -31,23 +29,17 @@ export class JournalIssueComponent extends ItemComponent {
*/ */
publications$: Observable<Item[]>; publications$: Observable<Item[]>;
constructor(
@Inject(ITEM) public item: Item,
private ids: ItemDataService
) {
super(item);
}
ngOnInit(): void { ngOnInit(): void {
super.ngOnInit(); super.ngOnInit();
if (isNotEmpty(this.resolvedRelsAndTypes$)) { if (isNotEmpty(this.resolvedRelsAndTypes$)) {
this.volumes$ = this.resolvedRelsAndTypes$.pipe( this.volumes$ = this.resolvedRelsAndTypes$.pipe(
filterRelationsByTypeLabel('isJournalVolumeOfIssue'), filterRelationsByTypeLabel('isJournalVolumeOfIssue'),
relationsToItems(this.item.id, this.ids) relationsToItems(this.item.id)
); );
this.publications$ = this.resolvedRelsAndTypes$.pipe( this.publications$ = this.resolvedRelsAndTypes$.pipe(
filterRelationsByTypeLabel('isPublicationOfJournalIssue'), filterRelationsByTypeLabel('isPublicationOfJournalIssue'),
relationsToItems(this.item.id, this.ids) relationsToItems(this.item.id)
); );
} }
} }

View File

@@ -1,9 +1,7 @@
import { Component, Inject } from '@angular/core'; import { Component } from '@angular/core';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { ItemDataService } from '../../../../core/data/item-data.service';
import { Item } from '../../../../core/shared/item.model'; import { Item } from '../../../../core/shared/item.model';
import { ItemViewMode, rendersItemType } from '../../../../shared/items/item-type-decorator'; import { ItemViewMode, rendersItemType } from '../../../../shared/items/item-type-decorator';
import { ITEM } from '../../../../shared/items/switcher/item-type-switcher.component';
import { isNotEmpty } from '../../../../shared/empty.util'; import { isNotEmpty } from '../../../../shared/empty.util';
import { ItemComponent } from '../../../../+item-page/simple/item-types/shared/item.component'; import { ItemComponent } from '../../../../+item-page/simple/item-types/shared/item.component';
import { import {
@@ -31,23 +29,17 @@ export class JournalVolumeComponent extends ItemComponent {
*/ */
issues$: Observable<Item[]>; issues$: Observable<Item[]>;
constructor(
@Inject(ITEM) public item: Item,
private ids: ItemDataService
) {
super(item);
}
ngOnInit(): void { ngOnInit(): void {
super.ngOnInit(); super.ngOnInit();
if (isNotEmpty(this.resolvedRelsAndTypes$)) { if (isNotEmpty(this.resolvedRelsAndTypes$)) {
this.journals$ = this.resolvedRelsAndTypes$.pipe( this.journals$ = this.resolvedRelsAndTypes$.pipe(
filterRelationsByTypeLabel('isJournalOfVolume'), filterRelationsByTypeLabel('isJournalOfVolume'),
relationsToItems(this.item.id, this.ids) relationsToItems(this.item.id)
); );
this.issues$ = this.resolvedRelsAndTypes$.pipe( this.issues$ = this.resolvedRelsAndTypes$.pipe(
filterRelationsByTypeLabel('isIssueOfJournalVolume'), filterRelationsByTypeLabel('isIssueOfJournalVolume'),
relationsToItems(this.item.id, this.ids) relationsToItems(this.item.id)
); );
} }
} }

View File

@@ -1,9 +1,7 @@
import { Component, Inject } from '@angular/core'; import { Component } from '@angular/core';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { ItemDataService } from '../../../../core/data/item-data.service';
import { Item } from '../../../../core/shared/item.model'; import { Item } from '../../../../core/shared/item.model';
import { ItemViewMode, rendersItemType } from '../../../../shared/items/item-type-decorator'; import { ItemViewMode, rendersItemType } from '../../../../shared/items/item-type-decorator';
import { ITEM } from '../../../../shared/items/switcher/item-type-switcher.component';
import { isNotEmpty } from '../../../../shared/empty.util'; import { isNotEmpty } from '../../../../shared/empty.util';
import { ItemComponent } from '../../../../+item-page/simple/item-types/shared/item.component'; import { ItemComponent } from '../../../../+item-page/simple/item-types/shared/item.component';
import { import {
@@ -26,19 +24,13 @@ export class JournalComponent extends ItemComponent {
*/ */
volumes$: Observable<Item[]>; volumes$: Observable<Item[]>;
constructor(
@Inject(ITEM) public item: Item,
private ids: ItemDataService
) {
super(item);
}
ngOnInit(): void { ngOnInit(): void {
super.ngOnInit(); super.ngOnInit();
if (isNotEmpty(this.resolvedRelsAndTypes$)) { if (isNotEmpty(this.resolvedRelsAndTypes$)) {
this.volumes$ = this.resolvedRelsAndTypes$.pipe( this.volumes$ = this.resolvedRelsAndTypes$.pipe(
filterRelationsByTypeLabel('isVolumeOfJournal'), filterRelationsByTypeLabel('isVolumeOfJournal'),
relationsToItems(this.item.id, this.ids) relationsToItems(this.item.id)
); );
} }
} }

View File

@@ -1,9 +1,7 @@
import { Component, Inject, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { ItemDataService } from '../../../../core/data/item-data.service';
import { Item } from '../../../../core/shared/item.model'; import { Item } from '../../../../core/shared/item.model';
import { ItemViewMode, rendersItemType } from '../../../../shared/items/item-type-decorator'; import { ItemViewMode, rendersItemType } from '../../../../shared/items/item-type-decorator';
import { ITEM } from '../../../../shared/items/switcher/item-type-switcher.component';
import { isNotEmpty } from '../../../../shared/empty.util'; import { isNotEmpty } from '../../../../shared/empty.util';
import { ItemComponent } from '../../../../+item-page/simple/item-types/shared/item.component'; import { ItemComponent } from '../../../../+item-page/simple/item-types/shared/item.component';
import { import {
@@ -36,30 +34,23 @@ export class OrgunitComponent extends ItemComponent implements OnInit {
*/ */
publications$: Observable<Item[]>; publications$: Observable<Item[]>;
constructor(
@Inject(ITEM) public item: Item,
private ids: ItemDataService
) {
super(item);
}
ngOnInit(): void { ngOnInit(): void {
super.ngOnInit(); super.ngOnInit();
if (isNotEmpty(this.resolvedRelsAndTypes$)) { if (isNotEmpty(this.resolvedRelsAndTypes$)) {
this.people$ = this.resolvedRelsAndTypes$.pipe( this.people$ = this.resolvedRelsAndTypes$.pipe(
filterRelationsByTypeLabel('isPersonOfOrgUnit'), filterRelationsByTypeLabel('isPersonOfOrgUnit'),
relationsToItems(this.item.id, this.ids) relationsToItems(this.item.id)
); );
this.projects$ = this.resolvedRelsAndTypes$.pipe( this.projects$ = this.resolvedRelsAndTypes$.pipe(
filterRelationsByTypeLabel('isProjectOfOrgUnit'), filterRelationsByTypeLabel('isProjectOfOrgUnit'),
relationsToItems(this.item.id, this.ids) relationsToItems(this.item.id)
); );
this.publications$ = this.resolvedRelsAndTypes$.pipe( this.publications$ = this.resolvedRelsAndTypes$.pipe(
filterRelationsByTypeLabel('isPublicationOfOrgUnit'), filterRelationsByTypeLabel('isPublicationOfOrgUnit'),
relationsToItems(this.item.id, this.ids) relationsToItems(this.item.id)
); );
} }
}} }}

View File

@@ -1,6 +1,5 @@
import { Component, Inject } from '@angular/core'; import { Component, Inject } from '@angular/core';
import { Observable , of as observableOf } from 'rxjs'; import { Observable , of as observableOf } from 'rxjs';
import { ItemDataService } from '../../../../core/data/item-data.service';
import { Item } from '../../../../core/shared/item.model'; import { Item } from '../../../../core/shared/item.model';
import { ItemViewMode, rendersItemType } from '../../../../shared/items/item-type-decorator'; import { ItemViewMode, rendersItemType } from '../../../../shared/items/item-type-decorator';
import { ITEM } from '../../../../shared/items/switcher/item-type-switcher.component'; import { ITEM } from '../../../../shared/items/switcher/item-type-switcher.component';
@@ -49,7 +48,6 @@ export class PersonComponent extends ItemComponent {
constructor( constructor(
@Inject(ITEM) public item: Item, @Inject(ITEM) public item: Item,
private ids: ItemDataService,
private fixedFilterService: SearchFixedFilterService private fixedFilterService: SearchFixedFilterService
) { ) {
super(item); super(item);
@@ -60,17 +58,17 @@ export class PersonComponent extends ItemComponent {
if (isNotEmpty(this.resolvedRelsAndTypes$)) { if (isNotEmpty(this.resolvedRelsAndTypes$)) {
this.publications$ = this.resolvedRelsAndTypes$.pipe( this.publications$ = this.resolvedRelsAndTypes$.pipe(
filterRelationsByTypeLabel('isPublicationOfAuthor'), filterRelationsByTypeLabel('isPublicationOfAuthor'),
relationsToItems(this.item.id, this.ids) relationsToItems(this.item.id)
); );
this.projects$ = this.resolvedRelsAndTypes$.pipe( this.projects$ = this.resolvedRelsAndTypes$.pipe(
filterRelationsByTypeLabel('isProjectOfPerson'), filterRelationsByTypeLabel('isProjectOfPerson'),
relationsToItems(this.item.id, this.ids) relationsToItems(this.item.id)
); );
this.orgUnits$ = this.resolvedRelsAndTypes$.pipe( this.orgUnits$ = this.resolvedRelsAndTypes$.pipe(
filterRelationsByTypeLabel('isOrgUnitOfPerson'), filterRelationsByTypeLabel('isOrgUnitOfPerson'),
relationsToItems(this.item.id, this.ids) relationsToItems(this.item.id)
); );
this.fixedFilterQuery = this.fixedFilterService.getQueryByRelations('isAuthorOfPublication', this.item.id); this.fixedFilterQuery = this.fixedFilterService.getQueryByRelations('isAuthorOfPublication', this.item.id);

View File

@@ -1,9 +1,7 @@
import { Component, Inject, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { ItemDataService } from '../../../../core/data/item-data.service';
import { Item } from '../../../../core/shared/item.model'; import { Item } from '../../../../core/shared/item.model';
import { ItemViewMode, rendersItemType } from '../../../../shared/items/item-type-decorator'; import { ItemViewMode, rendersItemType } from '../../../../shared/items/item-type-decorator';
import { ITEM } from '../../../../shared/items/switcher/item-type-switcher.component';
import { isNotEmpty } from '../../../../shared/empty.util'; import { isNotEmpty } from '../../../../shared/empty.util';
import { ItemComponent } from '../../../../+item-page/simple/item-types/shared/item.component'; import { ItemComponent } from '../../../../+item-page/simple/item-types/shared/item.component';
import { import {
@@ -36,30 +34,23 @@ export class ProjectComponent extends ItemComponent implements OnInit {
*/ */
orgUnits$: Observable<Item[]>; orgUnits$: Observable<Item[]>;
constructor(
@Inject(ITEM) public item: Item,
private ids: ItemDataService
) {
super(item);
}
ngOnInit(): void { ngOnInit(): void {
super.ngOnInit(); super.ngOnInit();
if (isNotEmpty(this.resolvedRelsAndTypes$)) { if (isNotEmpty(this.resolvedRelsAndTypes$)) {
this.people$ = this.resolvedRelsAndTypes$.pipe( this.people$ = this.resolvedRelsAndTypes$.pipe(
filterRelationsByTypeLabel('isPersonOfProject'), filterRelationsByTypeLabel('isPersonOfProject'),
relationsToItems(this.item.id, this.ids) relationsToItems(this.item.id)
); );
this.publications$ = this.resolvedRelsAndTypes$.pipe( this.publications$ = this.resolvedRelsAndTypes$.pipe(
filterRelationsByTypeLabel('isPublicationOfProject'), filterRelationsByTypeLabel('isPublicationOfProject'),
relationsToItems(this.item.id, this.ids) relationsToItems(this.item.id)
); );
this.orgUnits$ = this.resolvedRelsAndTypes$.pipe( this.orgUnits$ = this.resolvedRelsAndTypes$.pipe(
filterRelationsByTypeLabel('isOrgUnitOfProject'), filterRelationsByTypeLabel('isOrgUnitOfProject'),
relationsToItems(this.item.id, this.ids) relationsToItems(this.item.id)
); );
} }
} }