mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 10:04:11 +00:00
64574: relationship-service's getRelatedItemsByLabel returns paginated list using new REST API search endpoint + test cases on publication pages
This commit is contained in:
@@ -4,8 +4,10 @@ import { Observable } from 'rxjs/internal/Observable';
|
|||||||
import { FieldUpdate, FieldUpdates } from '../../../../core/data/object-updates/object-updates.reducer';
|
import { FieldUpdate, FieldUpdates } from '../../../../core/data/object-updates/object-updates.reducer';
|
||||||
import { RelationshipService } from '../../../../core/data/relationship.service';
|
import { RelationshipService } from '../../../../core/data/relationship.service';
|
||||||
import { Item } from '../../../../core/shared/item.model';
|
import { Item } from '../../../../core/shared/item.model';
|
||||||
import { switchMap } from 'rxjs/operators';
|
import { map, switchMap } from 'rxjs/operators';
|
||||||
import { hasValue } from '../../../../shared/empty.util';
|
import { hasValue } from '../../../../shared/empty.util';
|
||||||
|
import { RemoteData } from '../../../../core/data/remote-data';
|
||||||
|
import { PaginatedList } from '../../../../core/data/paginated-list';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ds-edit-relationship-list',
|
selector: 'ds-edit-relationship-list',
|
||||||
@@ -63,7 +65,7 @@ export class EditRelationshipListComponent implements OnInit, OnChanges {
|
|||||||
* Transform the item's relationships of a specific type into related items
|
* Transform the item's relationships of a specific type into related items
|
||||||
* @param label The relationship type's label
|
* @param label The relationship type's label
|
||||||
*/
|
*/
|
||||||
public getRelatedItemsByLabel(label: string): Observable<Item[]> {
|
public getRelatedItemsByLabel(label: string): Observable<RemoteData<PaginatedList<Item>>> {
|
||||||
return this.relationshipService.getRelatedItemsByLabel(this.item, label);
|
return this.relationshipService.getRelatedItemsByLabel(this.item, label);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,7 +75,7 @@ export class EditRelationshipListComponent implements OnInit, OnChanges {
|
|||||||
*/
|
*/
|
||||||
public getUpdatesByLabel(label: string): Observable<FieldUpdates> {
|
public getUpdatesByLabel(label: string): Observable<FieldUpdates> {
|
||||||
return this.getRelatedItemsByLabel(label).pipe(
|
return this.getRelatedItemsByLabel(label).pipe(
|
||||||
switchMap((items: Item[]) => this.objectUpdatesService.getFieldUpdatesExclusive(this.url, items))
|
switchMap((itemsRD) => this.objectUpdatesService.getFieldUpdatesExclusive(this.url, itemsRD.payload.page))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -32,15 +32,15 @@
|
|||||||
[representations]="authors$ | async">
|
[representations]="authors$ | async">
|
||||||
</ds-metadata-representation-list>
|
</ds-metadata-representation-list>
|
||||||
<ds-related-items
|
<ds-related-items
|
||||||
[items]="projects$ | async"
|
[items]="(projects$ | async)?.payload?.page"
|
||||||
[label]="'relationships.isProjectOf' | translate">
|
[label]="'relationships.isProjectOf' | translate">
|
||||||
</ds-related-items>
|
</ds-related-items>
|
||||||
<ds-related-items
|
<ds-related-items
|
||||||
[items]="orgUnits$ | async"
|
[items]="(orgUnits$ | async)?.payload?.page"
|
||||||
[label]="'relationships.isOrgUnitOf' | translate">
|
[label]="'relationships.isOrgUnitOf' | translate">
|
||||||
</ds-related-items>
|
</ds-related-items>
|
||||||
<ds-related-items
|
<ds-related-items
|
||||||
[items]="journalIssues$ | async"
|
[items]="(journalIssues$ | async)?.payload?.page"
|
||||||
[label]="'relationships.isJournalIssueOf' | translate">
|
[label]="'relationships.isJournalIssueOf' | translate">
|
||||||
</ds-related-items>
|
</ds-related-items>
|
||||||
<ds-item-page-abstract-field [item]="item"></ds-item-page-abstract-field>
|
<ds-item-page-abstract-field [item]="item"></ds-item-page-abstract-field>
|
||||||
|
@@ -8,6 +8,8 @@ import {
|
|||||||
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 { getRelatedItemsByTypeLabel } from '../shared/item-relationships-utils';
|
import { getRelatedItemsByTypeLabel } from '../shared/item-relationships-utils';
|
||||||
|
import { RemoteData } from '../../../../core/data/remote-data';
|
||||||
|
import { PaginatedList } from '../../../../core/data/paginated-list';
|
||||||
|
|
||||||
@rendersItemType('Publication', ItemViewMode.Full)
|
@rendersItemType('Publication', ItemViewMode.Full)
|
||||||
@rendersItemType(DEFAULT_ITEM_TYPE, ItemViewMode.Full)
|
@rendersItemType(DEFAULT_ITEM_TYPE, ItemViewMode.Full)
|
||||||
@@ -26,17 +28,17 @@ export class PublicationComponent extends ItemComponent implements OnInit {
|
|||||||
/**
|
/**
|
||||||
* The projects related to this publication
|
* The projects related to this publication
|
||||||
*/
|
*/
|
||||||
projects$: Observable<Item[]>;
|
projects$: Observable<RemoteData<PaginatedList<Item>>>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The organisation units related to this publication
|
* The organisation units related to this publication
|
||||||
*/
|
*/
|
||||||
orgUnits$: Observable<Item[]>;
|
orgUnits$: Observable<RemoteData<PaginatedList<Item>>>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The journal issues related to this publication
|
* The journal issues related to this publication
|
||||||
*/
|
*/
|
||||||
journalIssues$: Observable<Item[]>;
|
journalIssues$: Observable<RemoteData<PaginatedList<Item>>>;
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
super.ngOnInit();
|
super.ngOnInit();
|
||||||
@@ -45,17 +47,9 @@ export class PublicationComponent extends ItemComponent implements OnInit {
|
|||||||
|
|
||||||
this.authors$ = this.buildRepresentations('Person', 'dc.contributor.author');
|
this.authors$ = this.buildRepresentations('Person', 'dc.contributor.author');
|
||||||
|
|
||||||
this.projects$ = this.resolvedRelsAndTypes$.pipe(
|
this.projects$ = this.relationshipService.getRelatedItemsByLabel(this.item, 'isProjectOfPublication');
|
||||||
getRelatedItemsByTypeLabel(this.item.id, 'isProjectOfPublication')
|
this.orgUnits$ = this.relationshipService.getRelatedItemsByLabel(this.item, 'isOrgUnitOfPublication');
|
||||||
);
|
this.journalIssues$ = this.relationshipService.getRelatedItemsByLabel(this.item, 'isJournalIssueOfPublication');
|
||||||
|
|
||||||
this.orgUnits$ = this.resolvedRelsAndTypes$.pipe(
|
|
||||||
getRelatedItemsByTypeLabel(this.item.id, 'isOrgUnitOfPublication')
|
|
||||||
);
|
|
||||||
|
|
||||||
this.journalIssues$ = this.resolvedRelsAndTypes$.pipe(
|
|
||||||
getRelatedItemsByTypeLabel(this.item.id, 'isJournalIssueOfPublication')
|
|
||||||
);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -13,6 +13,7 @@ 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';
|
import { RemoteData } from '../../../../core/data/remote-data';
|
||||||
import { RelationshipService } from '../../../../core/data/relationship.service';
|
import { RelationshipService } from '../../../../core/data/relationship.service';
|
||||||
|
import { PaginatedList } from '../../../../core/data/paginated-list';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Operator for comparing arrays using a mapping function
|
* Operator for comparing arrays using a mapping function
|
||||||
@@ -99,6 +100,34 @@ export const relationsToItems = (thisId: string) =>
|
|||||||
distinctUntilChanged(compareArraysUsingIds()),
|
distinctUntilChanged(compareArraysUsingIds()),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export const paginatedRelationsToItems = (thisId: string) =>
|
||||||
|
(source: Observable<RemoteData<PaginatedList<Relationship>>>): Observable<RemoteData<PaginatedList<Item>>> =>
|
||||||
|
source.pipe(
|
||||||
|
getSucceededRemoteData(),
|
||||||
|
switchMap((relationshipsRD: RemoteData<PaginatedList<Relationship>>) => {
|
||||||
|
return observableZip(
|
||||||
|
...relationshipsRD.payload.page.map((rel: Relationship) => observableCombineLatest(rel.leftItem, rel.rightItem))
|
||||||
|
).pipe(
|
||||||
|
map((arr) =>
|
||||||
|
arr
|
||||||
|
.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;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.filter((item: Item) => hasValue(item))
|
||||||
|
),
|
||||||
|
distinctUntilChanged(compareArraysUsingIds()),
|
||||||
|
map((relatedItems: Item[]) =>
|
||||||
|
Object.assign(relationshipsRD, { payload: { page: relatedItems } })
|
||||||
|
)
|
||||||
|
)
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Operator for turning a list of relationships and their relationship-types into a list of relevant items by relationship label
|
* 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 thisId The item's id of which the relations belong to
|
||||||
|
@@ -15,6 +15,7 @@ import { MetadatumRepresentation } from '../../../../core/shared/metadata-repres
|
|||||||
import { of } from 'rxjs/internal/observable/of';
|
import { of } from 'rxjs/internal/observable/of';
|
||||||
import { MetadataValue } from '../../../../core/shared/metadata.models';
|
import { MetadataValue } from '../../../../core/shared/metadata.models';
|
||||||
import { compareArraysUsingIds } from './item-relationships-utils';
|
import { compareArraysUsingIds } from './item-relationships-utils';
|
||||||
|
import { RelationshipService } from '../../../../core/data/relationship.service';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Operator for turning a list of relationships into a list of metadatarepresentations given the original metadata
|
* Operator for turning a list of relationships into a list of metadatarepresentations given the original metadata
|
||||||
@@ -68,7 +69,8 @@ export class ItemComponent implements OnInit {
|
|||||||
resolvedRelsAndTypes$: Observable<[Relationship[], RelationshipType[]]>;
|
resolvedRelsAndTypes$: Observable<[Relationship[], RelationshipType[]]>;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(ITEM) public item: Item
|
@Inject(ITEM) public item: Item,
|
||||||
|
public relationshipService: RelationshipService
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
|
@@ -10,7 +10,7 @@ import {
|
|||||||
getRemoteDataPayload, getResponseFromEntry,
|
getRemoteDataPayload, getResponseFromEntry,
|
||||||
getSucceededRemoteData
|
getSucceededRemoteData
|
||||||
} from '../shared/operators';
|
} from '../shared/operators';
|
||||||
import { DeleteRequest, RestRequest } from './request.models';
|
import { DeleteRequest, FindAllOptions, RestRequest } from './request.models';
|
||||||
import { Observable } from 'rxjs/internal/Observable';
|
import { Observable } from 'rxjs/internal/Observable';
|
||||||
import { RestResponse } from '../cache/response.models';
|
import { RestResponse } from '../cache/response.models';
|
||||||
import { Item } from '../shared/item.model';
|
import { Item } from '../shared/item.model';
|
||||||
@@ -22,23 +22,42 @@ import { zip as observableZip } from 'rxjs';
|
|||||||
import { PaginatedList } from './paginated-list';
|
import { PaginatedList } from './paginated-list';
|
||||||
import { ItemDataService } from './item-data.service';
|
import { ItemDataService } from './item-data.service';
|
||||||
import {
|
import {
|
||||||
compareArraysUsingIds, filterRelationsByTypeLabel,
|
compareArraysUsingIds, filterRelationsByTypeLabel, paginatedRelationsToItems,
|
||||||
relationsToItems
|
relationsToItems
|
||||||
} from '../../+item-page/simple/item-types/shared/item-relationships-utils';
|
} from '../../+item-page/simple/item-types/shared/item-relationships-utils';
|
||||||
import { ObjectCacheService } from '../cache/object-cache.service';
|
import { ObjectCacheService } from '../cache/object-cache.service';
|
||||||
|
import { DataService } from './data.service';
|
||||||
|
import { NormalizedObjectBuildService } from '../cache/builders/normalized-object-build.service';
|
||||||
|
import { Store } from '@ngrx/store';
|
||||||
|
import { CoreState } from '../core.reducers';
|
||||||
|
import { NotificationsService } from '../../shared/notifications/notifications.service';
|
||||||
|
import { HttpClient } from '@angular/common/http';
|
||||||
|
import { DefaultChangeAnalyzer } from './default-change-analyzer.service';
|
||||||
|
import { SearchParam } from '../cache/models/search-param.model';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The service handling all relationship requests
|
* The service handling all relationship requests
|
||||||
*/
|
*/
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class RelationshipService {
|
export class RelationshipService extends DataService<Relationship> {
|
||||||
protected linkPath = 'relationships';
|
protected linkPath = 'relationships';
|
||||||
|
protected forceBypassCache = false;
|
||||||
|
|
||||||
constructor(protected requestService: RequestService,
|
constructor(protected itemService: ItemDataService,
|
||||||
protected halService: HALEndpointService,
|
protected requestService: RequestService,
|
||||||
protected rdbService: RemoteDataBuildService,
|
protected rdbService: RemoteDataBuildService,
|
||||||
protected itemService: ItemDataService,
|
protected dataBuildService: NormalizedObjectBuildService,
|
||||||
protected objectCache: ObjectCacheService) {
|
protected store: Store<CoreState>,
|
||||||
|
protected halService: HALEndpointService,
|
||||||
|
protected objectCache: ObjectCacheService,
|
||||||
|
protected notificationsService: NotificationsService,
|
||||||
|
protected http: HttpClient,
|
||||||
|
protected comparator: DefaultChangeAnalyzer<Relationship>) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
getBrowseEndpoint(options: FindAllOptions = {}, linkPath: string = this.linkPath): Observable<string> {
|
||||||
|
return this.halService.getEndpoint(linkPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -208,11 +227,20 @@ export class RelationshipService {
|
|||||||
* @param item
|
* @param item
|
||||||
* @param label
|
* @param label
|
||||||
*/
|
*/
|
||||||
getRelatedItemsByLabel(item: Item, label: string): Observable<Item[]> {
|
getRelatedItemsByLabel(item: Item, label: string): Observable<RemoteData<PaginatedList<Item>>> {
|
||||||
return this.getItemResolvedRelsAndTypes(item).pipe(
|
return this.getItemRelationshipsByLabel(item, label).pipe(paginatedRelationsToItems(item.uuid));
|
||||||
filterRelationsByTypeLabel(label),
|
}
|
||||||
relationsToItems(item.uuid)
|
|
||||||
);
|
/**
|
||||||
|
* Resolve a given item's relationships into related items, filtered by a relationship label
|
||||||
|
* and return the items as an array
|
||||||
|
* @param item
|
||||||
|
* @param label
|
||||||
|
*/
|
||||||
|
getItemRelationshipsByLabel(item: Item, label: string): Observable<RemoteData<PaginatedList<Relationship>>> {
|
||||||
|
const options = new FindAllOptions();
|
||||||
|
options.searchParams = [ new SearchParam('label', label), new SearchParam('dso', item.id) ];
|
||||||
|
return this.searchBy('byLabel', options);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -7,6 +7,7 @@ import { SearchFixedFilterService } from '../../../../+search-page/search-filter
|
|||||||
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 { getRelatedItemsByTypeLabel } from '../../../../+item-page/simple/item-types/shared/item-relationships-utils';
|
import { getRelatedItemsByTypeLabel } from '../../../../+item-page/simple/item-types/shared/item-relationships-utils';
|
||||||
|
import { RelationshipService } from '../../../../core/data/relationship.service';
|
||||||
|
|
||||||
@rendersItemType('Person', ItemViewMode.Full)
|
@rendersItemType('Person', ItemViewMode.Full)
|
||||||
@Component({
|
@Component({
|
||||||
@@ -45,9 +46,10 @@ export class PersonComponent extends ItemComponent {
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(ITEM) public item: Item,
|
@Inject(ITEM) public item: Item,
|
||||||
|
public relationshipService: RelationshipService,
|
||||||
private fixedFilterService: SearchFixedFilterService
|
private fixedFilterService: SearchFixedFilterService
|
||||||
) {
|
) {
|
||||||
super(item);
|
super(item, relationshipService);
|
||||||
}
|
}
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
super.ngOnInit();
|
super.ngOnInit();
|
||||||
|
Reference in New Issue
Block a user