mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 01:54:15 +00:00
61142: RelationshipService
This commit is contained in:
@@ -1,22 +1,16 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { Component, Inject } from '@angular/core';
|
||||
import { Item } from '../../../core/shared/item.model';
|
||||
import { FieldUpdates } from '../../../core/data/object-updates/object-updates.reducer';
|
||||
import { Observable } from 'rxjs/internal/Observable';
|
||||
import { distinctUntilChanged, first, flatMap, map, switchMap } from 'rxjs/operators';
|
||||
import { zip as observableZip } from 'rxjs';
|
||||
import { RemoteData } from '../../../core/data/remote-data';
|
||||
import { PaginatedList } from '../../../core/data/paginated-list';
|
||||
import { Relationship } from '../../../core/shared/item-relationships/relationship.model';
|
||||
import { hasValue, hasValueOperator } from '../../../shared/empty.util';
|
||||
import { getRemoteDataPayload, getSucceededRemoteData } from '../../../core/shared/operators';
|
||||
import { RelationshipType } from '../../../core/shared/item-relationships/relationship-type.model';
|
||||
import {
|
||||
compareArraysUsingIds,
|
||||
filterRelationsByTypeLabel,
|
||||
relationsToItems
|
||||
} from '../../simple/item-types/shared/item.component';
|
||||
import { combineLatest as observableCombineLatest } from 'rxjs/internal/observable/combineLatest';
|
||||
import { switchMap, take } from 'rxjs/operators';
|
||||
import { AbstractItemUpdateComponent } from '../abstract-item-update/abstract-item-update.component';
|
||||
import { ItemDataService } from '../../../core/data/item-data.service';
|
||||
import { ObjectUpdatesService } from '../../../core/data/object-updates/object-updates.service';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { NotificationsService } from '../../../shared/notifications/notifications.service';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { GLOBAL_CONFIG, GlobalConfig } from '../../../../config';
|
||||
import { RelationshipService } from '../../../core/data/relationship.service';
|
||||
|
||||
@Component({
|
||||
selector: 'ds-item-relationships',
|
||||
@@ -33,49 +27,32 @@ export class ItemRelationshipsComponent extends AbstractItemUpdateComponent {
|
||||
*/
|
||||
relationLabels$: Observable<string[]>;
|
||||
|
||||
/**
|
||||
* Resolved relationships and types together in one observable
|
||||
*/
|
||||
resolvedRelsAndTypes$: Observable<[Relationship[], RelationshipType[]]>;
|
||||
constructor(
|
||||
protected itemService: ItemDataService,
|
||||
protected objectUpdatesService: ObjectUpdatesService,
|
||||
protected router: Router,
|
||||
protected notificationsService: NotificationsService,
|
||||
protected translateService: TranslateService,
|
||||
@Inject(GLOBAL_CONFIG) protected EnvConfig: GlobalConfig,
|
||||
protected route: ActivatedRoute,
|
||||
protected relationshipService: RelationshipService
|
||||
) {
|
||||
super(itemService, objectUpdatesService, router, notificationsService, translateService, EnvConfig, route);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up and initialize all fields
|
||||
*/
|
||||
ngOnInit(): void {
|
||||
super.ngOnInit();
|
||||
this.initRelationshipObservables();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the item's relationship observables for easier access across the component
|
||||
*/
|
||||
initRelationshipObservables() {
|
||||
const relationships$ = this.getRelationships();
|
||||
|
||||
const relationshipTypes$ = relationships$.pipe(
|
||||
flatMap((rels: Relationship[]) =>
|
||||
observableZip(...rels.map((rel: Relationship) => rel.relationshipType)).pipe(
|
||||
map(([...arr]: Array<RemoteData<RelationshipType>>) => arr.map((d: RemoteData<RelationshipType>) => d.payload).filter((type) => hasValue(type)))
|
||||
)
|
||||
),
|
||||
distinctUntilChanged(compareArraysUsingIds())
|
||||
);
|
||||
|
||||
this.resolvedRelsAndTypes$ = observableCombineLatest(
|
||||
relationships$,
|
||||
relationshipTypes$
|
||||
);
|
||||
this.relationLabels$ = relationshipTypes$.pipe(
|
||||
map((types: RelationshipType[]) => Array.from(new Set(types.map((type) => type.leftLabel))))
|
||||
);
|
||||
this.relationLabels$ = this.relationshipService.getItemRelationshipLabels(this.item);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the values and updates of the current item's relationship fields
|
||||
*/
|
||||
public initializeUpdates(): void {
|
||||
this.updates$ = this.getRelationships().pipe(
|
||||
relationsToItems(this.item.id, this.itemService),
|
||||
this.updates$ = this.relationshipService.getRelatedItems(this.item).pipe(
|
||||
switchMap((items: Item[]) => this.objectUpdatesService.getFieldUpdates(this.url, items))
|
||||
);
|
||||
}
|
||||
@@ -88,9 +65,7 @@ export class ItemRelationshipsComponent extends AbstractItemUpdateComponent {
|
||||
}
|
||||
|
||||
public submit(): void {
|
||||
const updatedItems$ = this.getRelationships().pipe(
|
||||
first(),
|
||||
relationsToItems(this.item.id, this.itemService),
|
||||
const updatedItems$ = this.relationshipService.getRelatedItems(this.item).pipe(
|
||||
switchMap((items: Item[]) => this.objectUpdatesService.getUpdatedFields(this.url, items) as Observable<Item[]>)
|
||||
);
|
||||
// TODO: Delete relationships
|
||||
@@ -100,36 +75,17 @@ export class ItemRelationshipsComponent extends AbstractItemUpdateComponent {
|
||||
* Sends all initial values of this item to the object updates service
|
||||
*/
|
||||
public initializeOriginalFields() {
|
||||
this.getRelationships().pipe(
|
||||
first(),
|
||||
relationsToItems(this.item.id, this.itemService)
|
||||
).subscribe((items: Item[]) => {
|
||||
this.relationshipService.getRelatedItems(this.item).pipe(take(1)).subscribe((items: Item[]) => {
|
||||
this.objectUpdatesService.initialize(this.url, items, this.item.lastModified);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch all the relationships of the item
|
||||
*/
|
||||
public getRelationships(): Observable<Relationship[]> {
|
||||
return this.item.relationships.pipe(
|
||||
getSucceededRemoteData(),
|
||||
getRemoteDataPayload(),
|
||||
map((rels: PaginatedList<Relationship>) => rels.page),
|
||||
hasValueOperator(),
|
||||
distinctUntilChanged(compareArraysUsingIds())
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform the item's relationships of a specific type into related items
|
||||
* @param label The relationship type's label
|
||||
*/
|
||||
public getRelatedItemsByLabel(label: string): Observable<Item[]> {
|
||||
return this.resolvedRelsAndTypes$.pipe(
|
||||
filterRelationsByTypeLabel(label),
|
||||
relationsToItems(this.item.id, this.itemService)
|
||||
);
|
||||
return this.relationshipService.getRelatedItemsByLabel(this.item, label);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -81,6 +81,7 @@ import { DSOChangeAnalyzer } from './data/dso-change-analyzer.service';
|
||||
import { ObjectUpdatesService } from './data/object-updates/object-updates.service';
|
||||
import { DefaultChangeAnalyzer } from './data/default-change-analyzer.service';
|
||||
import { SearchService } from '../+search-page/search-service/search.service';
|
||||
import { RelationshipService } from './data/relationship.service';
|
||||
|
||||
const IMPORTS = [
|
||||
CommonModule,
|
||||
@@ -163,6 +164,7 @@ const PROVIDERS = [
|
||||
MenuService,
|
||||
ObjectUpdatesService,
|
||||
SearchService,
|
||||
RelationshipService,
|
||||
// register AuthInterceptor as HttpInterceptor
|
||||
{
|
||||
provide: HTTP_INTERCEPTORS,
|
||||
|
121
src/app/core/data/relationship.service.ts
Normal file
121
src/app/core/data/relationship.service.ts
Normal file
@@ -0,0 +1,121 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { RequestService } from './request.service';
|
||||
import { HALEndpointService } from '../shared/hal-endpoint.service';
|
||||
import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service';
|
||||
import { hasValue, hasValueOperator, isNotEmptyOperator } from '../../shared/empty.util';
|
||||
import { distinctUntilChanged, flatMap, map, take } from 'rxjs/operators';
|
||||
import {
|
||||
configureRequest,
|
||||
filterSuccessfulResponses,
|
||||
getRemoteDataPayload,
|
||||
getSucceededRemoteData
|
||||
} from '../shared/operators';
|
||||
import { DeleteRequest, RestRequest } from './request.models';
|
||||
import { Observable } from 'rxjs/internal/Observable';
|
||||
import { RestResponse } from '../cache/response.models';
|
||||
import { Item } from '../shared/item.model';
|
||||
import { Relationship } from '../shared/item-relationships/relationship.model';
|
||||
import { RelationshipType } from '../shared/item-relationships/relationship-type.model';
|
||||
import { RemoteData } from './remote-data';
|
||||
import {
|
||||
compareArraysUsingIds,
|
||||
filterRelationsByTypeLabel, relationsToItems
|
||||
} from '../../+item-page/simple/item-types/shared/item.component';
|
||||
import { combineLatest as observableCombineLatest } from 'rxjs/internal/observable/combineLatest';
|
||||
import { zip as observableZip } from 'rxjs';
|
||||
import { PaginatedList } from './paginated-list';
|
||||
import { ItemDataService } from './item-data.service';
|
||||
|
||||
/**
|
||||
* The service handling all relationship requests
|
||||
*/
|
||||
@Injectable()
|
||||
export class RelationshipService {
|
||||
protected linkPath = 'relationships';
|
||||
|
||||
constructor(protected requestService: RequestService,
|
||||
protected halService: HALEndpointService,
|
||||
protected rdbService: RemoteDataBuildService,
|
||||
protected itemService: ItemDataService) {
|
||||
}
|
||||
|
||||
getRelationshipEndpoint(uuid: string) {
|
||||
return this.halService.getEndpoint(this.linkPath).pipe(
|
||||
map((href: string) => `${href}/${uuid}`)
|
||||
);
|
||||
}
|
||||
|
||||
deleteRelationship(uuid: string): Observable<RestResponse> {
|
||||
const requestUuid = this.requestService.generateRequestId();
|
||||
|
||||
this.getRelationshipEndpoint(uuid).pipe(
|
||||
isNotEmptyOperator(),
|
||||
distinctUntilChanged(),
|
||||
map((endpointURL: string) => new DeleteRequest(requestUuid, endpointURL)),
|
||||
configureRequest(this.requestService),
|
||||
take(1)
|
||||
).subscribe();
|
||||
|
||||
return this.requestService.getByUUID(requestUuid).pipe(
|
||||
filterSuccessfulResponses()
|
||||
);
|
||||
}
|
||||
|
||||
getItemResolvedRelsAndTypes(item: Item): Observable<[Relationship[], RelationshipType[]]> {
|
||||
const relationships$ = this.getItemRelationshipsArray(item);
|
||||
|
||||
const relationshipTypes$ = relationships$.pipe(
|
||||
flatMap((rels: Relationship[]) =>
|
||||
observableZip(...rels.map((rel: Relationship) => rel.relationshipType)).pipe(
|
||||
map(([...arr]: Array<RemoteData<RelationshipType>>) => arr.map((d: RemoteData<RelationshipType>) => d.payload).filter((type) => hasValue(type)))
|
||||
)
|
||||
),
|
||||
distinctUntilChanged(compareArraysUsingIds())
|
||||
);
|
||||
|
||||
return observableCombineLatest(
|
||||
relationships$,
|
||||
relationshipTypes$
|
||||
);
|
||||
}
|
||||
|
||||
getItemRelationshipsArray(item: Item): Observable<Relationship[]> {
|
||||
return item.relationships.pipe(
|
||||
getSucceededRemoteData(),
|
||||
getRemoteDataPayload(),
|
||||
map((rels: PaginatedList<Relationship>) => rels.page),
|
||||
hasValueOperator(),
|
||||
distinctUntilChanged(compareArraysUsingIds())
|
||||
);
|
||||
}
|
||||
|
||||
getItemRelationshipLabels(item: Item): Observable<string[]> {
|
||||
return this.getItemResolvedRelsAndTypes(item).pipe(
|
||||
map(([relsCurrentPage, relTypesCurrentPage]) => {
|
||||
return relTypesCurrentPage.map((type, index) => {
|
||||
const relationship = relsCurrentPage[index];
|
||||
if (relationship.leftId === item.uuid) {
|
||||
return type.leftLabel;
|
||||
} else {
|
||||
return type.rightLabel;
|
||||
}
|
||||
});
|
||||
}),
|
||||
map((labels: string[]) => Array.from(new Set(labels)))
|
||||
)
|
||||
}
|
||||
|
||||
getRelatedItems(item: Item): Observable<Item[]> {
|
||||
return this.getItemRelationshipsArray(item).pipe(
|
||||
relationsToItems(item.uuid, this.itemService)
|
||||
);
|
||||
}
|
||||
|
||||
getRelatedItemsByLabel(item: Item, label: string): Observable<Item[]> {
|
||||
return this.getItemResolvedRelsAndTypes(item).pipe(
|
||||
filterRelationsByTypeLabel(label),
|
||||
relationsToItems(item.uuid, this.itemService)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user