Merge pull request #430 from atmire/One-Sided-Relationship-Filtering

One-sided relationship filtering and refactoring
This commit is contained in:
benbosman
2019-07-25 15:59:24 +02:00
committed by GitHub
9 changed files with 67 additions and 73 deletions

View File

@@ -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')
);
}

View File

@@ -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,17 +42,30 @@ export const compareArraysUsingIds = <T extends { id: string }>() =>
/**
* 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<Relationship[]>}
*/
export const filterRelationsByTypeLabel = (label: string) =>
export const filterRelationsByTypeLabel = (label: string, thisId?: string) =>
(source: Observable<[Relationship[], RelationshipType[]]>): Observable<Relationship[]> =>
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())
);
@@ -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<Item[]> =>
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

View File

@@ -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()))
})
])));
}

View File

@@ -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')
);
}
}

View File

@@ -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')
);
}
}

View File

@@ -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')
);
}
}

View File

@@ -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')
);
}
}}

View File

@@ -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);

View File

@@ -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')
);
}
}