Skip to content

Commit

Permalink
Merge 080ea9e into e179596
Browse files Browse the repository at this point in the history
  • Loading branch information
Atmire-Kristof committed Jun 17, 2019
2 parents e179596 + 080ea9e commit cc9e95d
Show file tree
Hide file tree
Showing 12 changed files with 126 additions and 134 deletions.
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import { ChangeDetectionStrategy, Component, Inject, OnInit } from '@angular/core';
import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
import { Observable } from 'rxjs';
import { ItemDataService } from '../../../../core/data/item-data.service';
import { Item } from '../../../../core/shared/item.model';
import {
DEFAULT_ITEM_TYPE, ItemViewMode,
rendersItemType
} from '../../../../shared/items/item-type-decorator';
import { ITEM } from '../../../../shared/items/switcher/item-type-switcher.component';
import { ItemComponent } from '../shared/item.component';
import { MetadataRepresentation } from '../../../../core/shared/metadata-representation/metadata-representation.model';
import { filterRelationsByTypeLabel, relationsToItems } from '../shared/item-relationships-utils';
Expand Down Expand Up @@ -40,33 +38,26 @@ export class PublicationComponent extends ItemComponent implements OnInit {
*/
journalIssues$: Observable<Item[]>;

constructor(
@Inject(ITEM) public item: Item,
private ids: ItemDataService
) {
super(item);
}

ngOnInit(): void {
super.ngOnInit();

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(
filterRelationsByTypeLabel('isProjectOfPublication'),
relationsToItems(this.item.id, this.ids)
relationsToItems(this.item.id)
);

this.orgUnits$ = this.resolvedRelsAndTypes$.pipe(
filterRelationsByTypeLabel('isOrgUnitOfPublication'),
relationsToItems(this.item.id, this.ids)
relationsToItems(this.item.id)
);

this.journalIssues$ = this.resolvedRelsAndTypes$.pipe(
filterRelationsByTypeLabel('isJournalIssueOfPublication'),
relationsToItems(this.item.id, this.ids)
relationsToItems(this.item.id)
);

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ 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 { of as observableOf, zip as observableZip } from 'rxjs';
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';
Expand Down Expand Up @@ -60,27 +60,26 @@ export const filterRelationsByTypeLabel = (label: string) =>
/**
* 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 {ItemDataService} ids The ItemDataService to fetch items from the REST API
* @returns {(source: Observable<Relationship[]>) => Observable<Item[]>}
*/
export const relationsToItems = (thisId: string, ids: ItemDataService) =>
export const relationsToItems = (thisId: string) =>
(source: Observable<Relationship[]>): Observable<Item[]> =>
source.pipe(
flatMap((rels: Relationship[]) =>
observableZip(
...rels.map((rel: Relationship) => {
let queryId = rel.leftId;
if (rel.leftId === thisId) {
queryId = rel.rightId;
}
return ids.findById(queryId);
})
...rels.map((rel: Relationship) => observableCombineLatest(rel.leftItem, rel.rightItem))
)
),
map((arr: Array<RemoteData<Item>>) =>
map((arr) =>
arr
.filter((d: RemoteData<Item>) => d.hasSucceeded)
.map((d: RemoteData<Item>) => d.payload)),
.filter(([leftItem, rightItem]) => leftItem.hasSucceeded && rightItem.hasSucceeded)
.map(([leftItem, rightItem]) => {
if (leftItem.payload.id === thisId) {
return rightItem.payload;
} else if (rightItem.payload.id === thisId) {
return leftItem.payload;
}
})),
distinctUntilChanged(compareArraysUsingIds()),
);

Expand All @@ -103,13 +102,15 @@ export const relationsToRepresentations = (parentId: string, itemType: string, m
const matchingRels = rels.filter((rel: Relationship) => ('' + rel.id) === metadatum.virtualValue);
if (matchingRels.length > 0) {
const matchingRel = matchingRels[0];
let queryId = matchingRel.leftId;
if (matchingRel.leftId === parentId) {
queryId = matchingRel.rightId;
}
return ids.findById(queryId).pipe(
getSucceededRemoteData(),
map((d: RemoteData<Item>) => Object.assign(new ItemMetadataRepresentation(), d.payload))
return observableCombineLatest(matchingRel.leftItem, matchingRel.rightItem).pipe(
map(([leftItem, rightItem]) => {
if (leftItem.payload.id === parentId) {
return rightItem.payload;
} else if (rightItem.payload.id === parentId) {
return leftItem.payload;
}
}),
map((item: Item) => Object.assign(new ItemMetadataRepresentation(), item))
);
}
} else {
Expand Down
44 changes: 22 additions & 22 deletions src/app/+item-page/simple/item-types/shared/item.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -319,20 +319,31 @@ describe('ItemComponent', () => {
let fixture: ComponentFixture<ItemComponent>;

const metadataField = 'dc.contributor.author';
const relatedItem = Object.assign(new Item(), {
id: '2',
metadata: Object.assign(new MetadataMap(), {
'dc.title': [
{
language: 'en_US',
value: 'related item'
}
]
})
});
const mockItem = Object.assign(new Item(), {
id: '1',
uuid: '1',
metadata: new MetadataMap(),
relationships: observableOf(new RemoteData(false, false, true, null, new PaginatedList(new PageInfo(), [
Object.assign(new Relationship(), {
uuid: '123',
id: '123',
leftId: '1',
rightId: '2',
relationshipType: observableOf(new RemoteData(false, false, true, null, new RelationshipType()))
})
])))
metadata: new MetadataMap()
});
mockItem.relationships = observableOf(new RemoteData(false, false, true, null, new PaginatedList(new PageInfo(), [
Object.assign(new Relationship(), {
uuid: '123',
id: '123',
leftItem: observableOf(new RemoteData(false, false, true, null, mockItem)),
rightItem: observableOf(new RemoteData(false, false, true, null, relatedItem)),
relationshipType: observableOf(new RemoteData(false, false, true, null, new RelationshipType()))
})
])));
mockItem.metadata[metadataField] = [
{
value: 'Second value',
Expand All @@ -353,17 +364,6 @@ describe('ItemComponent', () => {
authority: '123'
}
] as MetadataValue[];
const relatedItem = Object.assign(new Item(), {
id: '2',
metadata: Object.assign(new MetadataMap(), {
'dc.title': [
{
language: 'en_US',
value: 'related item'
}
]
})
});
const mockItemDataService = Object.assign({
findById: (id) => {
if (id === relatedItem.id) {
Expand Down Expand Up @@ -397,7 +397,7 @@ describe('ItemComponent', () => {
fixture = TestBed.createComponent(ItemComponent);
comp = fixture.componentInstance;
fixture.detectChanges();
representations = comp.buildRepresentations('bogus', metadataField, mockItemDataService);
representations = comp.buildRepresentations('bogus', metadataField);
}));

it('should contain exactly 4 metadata-representations', () => {
Expand Down
53 changes: 47 additions & 6 deletions src/app/+item-page/simple/item-types/shared/item.component.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,58 @@
import { Component, Inject, OnInit } from '@angular/core';
import { combineLatest as observableCombineLatest, Observable, zip as observableZip } from 'rxjs';
import { Observable , zip as observableZip, combineLatest as observableCombineLatest } from 'rxjs';
import { distinctUntilChanged, filter, flatMap, map } from 'rxjs/operators';
import { ItemDataService } from '../../../../core/data/item-data.service';
import { PaginatedList } from '../../../../core/data/paginated-list';
import { RemoteData } from '../../../../core/data/remote-data';
import { RelationshipType } from '../../../../core/shared/item-relationships/relationship-type.model';
import { Relationship } from '../../../../core/shared/item-relationships/relationship.model';
import { Item } from '../../../../core/shared/item.model';
import { MetadataRepresentation } from '../../../../core/shared/metadata-representation/metadata-representation.model';
import { getRemoteDataPayload, getSucceededRemoteData } from '../../../../core/shared/operators';
import { ITEM } from '../../../../shared/items/switcher/item-type-switcher.component';
import { compareArraysUsingIds, relationsToRepresentations } from './item-relationships-utils';
import { MetadataRepresentation } from '../../../../core/shared/metadata-representation/metadata-representation.model';
import { ItemMetadataRepresentation } from '../../../../core/shared/metadata-representation/item/item-metadata-representation.model';
import { MetadatumRepresentation } from '../../../../core/shared/metadata-representation/metadatum/metadatum-representation.model';
import { of } from 'rxjs/internal/observable/of';
import { MetadataValue } from '../../../../core/shared/metadata.models';
import { compareArraysUsingIds } from './item-relationships-utils';

/**
* Operator for turning a list of relationships into a list of metadatarepresentations given the original metadata
* @param thisId The id of the parent item
* @param itemType The type of relation this list resembles (for creating representations)
* @param metadata The list of original Metadatum objects
*/
export const relationsToRepresentations = (thisId: string, itemType: string, metadata: MetadataValue[]) =>
(source: Observable<Relationship[]>): Observable<MetadataRepresentation[]> =>
source.pipe(
flatMap((rels: Relationship[]) =>
observableZip(
...metadata
.map((metadatum: any) => Object.assign(new MetadataValue(), metadatum))
.map((metadatum: MetadataValue) => {
if (metadatum.isVirtual) {
const matchingRels = rels.filter((rel: Relationship) => ('' + rel.id) === metadatum.virtualValue);
if (matchingRels.length > 0) {
const matchingRel = matchingRels[0];
return observableCombineLatest(matchingRel.leftItem, matchingRel.rightItem).pipe(
filter(([leftItem, rightItem]) => leftItem.hasSucceeded && rightItem.hasSucceeded),
map(([leftItem, rightItem]) => {
if (leftItem.payload.id === thisId) {
return rightItem.payload;
} else if (rightItem.payload.id === thisId) {
return leftItem.payload;
}
}),
map((item: Item) => Object.assign(new ItemMetadataRepresentation(), item))
);
}
} else {
return of(Object.assign(new MetadatumRepresentation(itemType), metadatum));
}
})
)
)
);

@Component({
selector: 'ds-item',
Expand Down Expand Up @@ -60,9 +102,8 @@ export class ItemComponent implements OnInit {
* certain type.
* @param itemType The type of item we're building representations of. Used for matching templates.
* @param metadataField The metadata field that resembles the item type.
* @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 relsCurrentPage$ = this.item.relationships.pipe(
getSucceededRemoteData(),
Expand All @@ -72,7 +113,7 @@ export class ItemComponent implements OnInit {
);

return relsCurrentPage$.pipe(
relationsToRepresentations(this.item.id, itemType, metadata, itemDataService)
relationsToRepresentations(this.item.id, itemType, metadata)
);
}

Expand Down
10 changes: 6 additions & 4 deletions src/app/core/cache/models/items/normalized-relationship.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,18 @@ export class NormalizedRelationship extends NormalizedObject<Relationship> {
id: string;

/**
* The identifier of the Item to the left side of this Relationship
* The item to the left of this relationship
*/
@autoserialize
leftId: string;
@relationship(ResourceType.Item, false)
leftItem: string;

/**
* The identifier of the Item to the right side of this Relationship
* The item to the right of this relationship
*/
@autoserialize
rightId: string;
@relationship(ResourceType.Item, false)
rightItem: string;

/**
* The place of the Item to the left side of this Relationship
Expand Down
9 changes: 5 additions & 4 deletions src/app/core/shared/item-relationships/relationship.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { CacheableObject } from '../../cache/object-cache.reducer';
import { RemoteData } from '../../data/remote-data';
import { ResourceType } from '../resource-type';
import { RelationshipType } from './relationship-type.model';
import { Item } from '../item.model';

/**
* Describes a Relationship between two Items
Expand All @@ -29,14 +30,14 @@ export class Relationship implements CacheableObject {
id: string;

/**
* The identifier of the Item to the left side of this Relationship
* The item to the left of this relationship
*/
leftId: string;
leftItem: Observable<RemoteData<Item>>;

/**
* The identifier of the Item to the right side of this Relationship
* The item to the right of this relationship
*/
rightId: string;
rightItem: Observable<RemoteData<Item>>;

/**
* The place of the Item to the left side of this Relationship
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import { Component, Inject } from '@angular/core';
import { Component } from '@angular/core';
import { Observable } from 'rxjs';
import { ItemDataService } from '../../../../core/data/item-data.service';
import { Item } from '../../../../core/shared/item.model';
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 { ItemComponent } from '../../../../+item-page/simple/item-types/shared/item.component';
import {
Expand Down Expand Up @@ -31,23 +29,17 @@ export class JournalIssueComponent extends ItemComponent {
*/
publications$: Observable<Item[]>;

constructor(
@Inject(ITEM) public item: Item,
private ids: ItemDataService
) {
super(item);
}
ngOnInit(): void {
super.ngOnInit();

if (isNotEmpty(this.resolvedRelsAndTypes$)) {
this.volumes$ = this.resolvedRelsAndTypes$.pipe(
filterRelationsByTypeLabel('isJournalVolumeOfIssue'),
relationsToItems(this.item.id, this.ids)
relationsToItems(this.item.id)
);
this.publications$ = this.resolvedRelsAndTypes$.pipe(
filterRelationsByTypeLabel('isPublicationOfJournalIssue'),
relationsToItems(this.item.id, this.ids)
relationsToItems(this.item.id)
);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import { Component, Inject } from '@angular/core';
import { Component } from '@angular/core';
import { Observable } from 'rxjs';
import { ItemDataService } from '../../../../core/data/item-data.service';
import { Item } from '../../../../core/shared/item.model';
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 { ItemComponent } from '../../../../+item-page/simple/item-types/shared/item.component';
import {
Expand Down Expand Up @@ -31,23 +29,17 @@ export class JournalVolumeComponent extends ItemComponent {
*/
issues$: Observable<Item[]>;

constructor(
@Inject(ITEM) public item: Item,
private ids: ItemDataService
) {
super(item);
}
ngOnInit(): void {
super.ngOnInit();

if (isNotEmpty(this.resolvedRelsAndTypes$)) {
this.journals$ = this.resolvedRelsAndTypes$.pipe(
filterRelationsByTypeLabel('isJournalOfVolume'),
relationsToItems(this.item.id, this.ids)
relationsToItems(this.item.id)
);
this.issues$ = this.resolvedRelsAndTypes$.pipe(
filterRelationsByTypeLabel('isIssueOfJournalVolume'),
relationsToItems(this.item.id, this.ids)
relationsToItems(this.item.id)
);
}
}
Expand Down

0 comments on commit cc9e95d

Please sign in to comment.