also add relationships one by one on the edit item relationships tab

(cherry picked from commit 8e59b7d0b0)
This commit is contained in:
Art Lowel
2024-04-11 17:51:59 +02:00
committed by Alexandre Vryghem
parent d8a24686ec
commit 17d1f2e6ac
2 changed files with 120 additions and 77 deletions

View File

@@ -155,8 +155,11 @@ export class RelationshipDataService extends IdentifiableDataService<Relationshi
* @param id the ID of the relationship to delete * @param id the ID of the relationship to delete
* @param copyVirtualMetadata whether to copy this relationship's virtual metadata to the related Items * @param copyVirtualMetadata whether to copy this relationship's virtual metadata to the related Items
* accepted values: none, all, left, right, configured * accepted values: none, all, left, right, configured
* @param shouldRefresh refresh the cache for the items in the relationship after creating
* it. Disable this if you want to add relationships in bulk, and
* want to refresh the cachemanually at the end
*/ */
deleteRelationship(id: string, copyVirtualMetadata: string): Observable<RemoteData<NoContent>> { deleteRelationship(id: string, copyVirtualMetadata: string, shouldRefresh = true): Observable<RemoteData<NoContent>> {
return this.getRelationshipEndpoint(id).pipe( return this.getRelationshipEndpoint(id).pipe(
isNotEmptyOperator(), isNotEmptyOperator(),
take(1), take(1),
@@ -167,7 +170,11 @@ export class RelationshipDataService extends IdentifiableDataService<Relationshi
sendRequest(this.requestService), sendRequest(this.requestService),
switchMap((restRequest: RestRequest) => this.rdbService.buildFromRequestUUID(restRequest.uuid)), switchMap((restRequest: RestRequest) => this.rdbService.buildFromRequestUUID(restRequest.uuid)),
getFirstCompletedRemoteData(), getFirstCompletedRemoteData(),
tap(() => this.refreshRelationshipItemsInCacheByRelationship(id)), tap(() => {
if (shouldRefresh) {
this.refreshRelationshipItemsInCacheByRelationship(id);
}
}),
); );
} }
@@ -178,8 +185,11 @@ export class RelationshipDataService extends IdentifiableDataService<Relationshi
* @param item2 The second item of the relationship * @param item2 The second item of the relationship
* @param leftwardValue The leftward value of the relationship * @param leftwardValue The leftward value of the relationship
* @param rightwardValue The rightward value of the relationship * @param rightwardValue The rightward value of the relationship
* @param shouldRefresh refresh the cache for the items in the relationship after creating it.
* Disable this if you want to add relationships in bulk, and want to refresh
* the cache manually at the end
*/ */
addRelationship(typeId: string, item1: Item, item2: Item, leftwardValue?: string, rightwardValue?: string): Observable<RemoteData<Relationship>> { addRelationship(typeId: string, item1: Item, item2: Item, leftwardValue?: string, rightwardValue?: string, shouldRefresh = true): Observable<RemoteData<Relationship>> {
const options: HttpOptions = Object.create({}); const options: HttpOptions = Object.create({});
let headers = new HttpHeaders(); let headers = new HttpHeaders();
headers = headers.append('Content-Type', 'text/uri-list'); headers = headers.append('Content-Type', 'text/uri-list');
@@ -194,8 +204,12 @@ export class RelationshipDataService extends IdentifiableDataService<Relationshi
sendRequest(this.requestService), sendRequest(this.requestService),
switchMap((restRequest: RestRequest) => this.rdbService.buildFromRequestUUID(restRequest.uuid)), switchMap((restRequest: RestRequest) => this.rdbService.buildFromRequestUUID(restRequest.uuid)),
getFirstCompletedRemoteData(), getFirstCompletedRemoteData(),
tap(() => this.refreshRelationshipItemsInCache(item1)), tap(() => {
tap(() => this.refreshRelationshipItemsInCache(item2)), if (shouldRefresh) {
this.refreshRelationshipItemsInCache(item1);
this.refreshRelationshipItemsInCache(item2);
}
}),
) as Observable<RemoteData<Relationship>>; ) as Observable<RemoteData<Relationship>>;
} }

View File

@@ -17,16 +17,17 @@ import {
TranslateService, TranslateService,
} from '@ngx-translate/core'; } from '@ngx-translate/core';
import { import {
BehaviorSubject,
combineLatest as observableCombineLatest, combineLatest as observableCombineLatest,
EMPTY,
Observable, Observable,
of as observableOf,
zip as observableZip,
} from 'rxjs'; } from 'rxjs';
import { import {
concatMap,
map, map,
startWith,
switchMap, switchMap,
take, take,
toArray,
} from 'rxjs/operators'; } from 'rxjs/operators';
import { ObjectCacheService } from '../../../core/cache/object-cache.service'; import { ObjectCacheService } from '../../../core/cache/object-cache.service';
@@ -91,7 +92,7 @@ export class ItemRelationshipsComponent extends AbstractItemUpdateComponent {
/** /**
* The item's entity type as an observable * The item's entity type as an observable
*/ */
entityType$: Observable<ItemType>; entityType$: BehaviorSubject<ItemType> = new BehaviorSubject(undefined);
constructor( constructor(
public itemService: ItemDataService, public itemService: ItemDataService,
@@ -123,13 +124,13 @@ export class ItemRelationshipsComponent extends AbstractItemUpdateComponent {
map((relationshipTypes: PaginatedList<RelationshipType>) => relationshipTypes.page), map((relationshipTypes: PaginatedList<RelationshipType>) => relationshipTypes.page),
); );
this.entityType$ = this.entityTypeService.getEntityTypeByLabel(label).pipe( this.entityTypeService.getEntityTypeByLabel(label).pipe(
getFirstSucceededRemoteData(), getFirstSucceededRemoteData(),
getRemoteDataPayload(), getRemoteDataPayload(),
); ).subscribe((type) => this.entityType$.next(type));
} else { } else {
this.entityType$ = observableOf(undefined); this.entityType$.next(undefined);
} }
} }
@@ -147,8 +148,7 @@ export class ItemRelationshipsComponent extends AbstractItemUpdateComponent {
public submit(): void { public submit(): void {
// Get all the relationships that should be removed // Get all the relationships that should be removed
const removedRelationshipIDs$: Observable<DeleteRelationship[]> = this.relationshipService.getItemRelationshipsArray(this.item).pipe( const removeUpdates$: Observable<FieldUpdate[]> = this.relationshipService.getItemRelationshipsArray(this.item).pipe(
startWith([]),
map((relationships: Relationship[]) => relationships.map((relationship) => map((relationships: Relationship[]) => relationships.map((relationship) =>
Object.assign(new Relationship(), relationship, { uuid: relationship.id }), Object.assign(new Relationship(), relationship, { uuid: relationship.id }),
)), )),
@@ -157,84 +157,113 @@ export class ItemRelationshipsComponent extends AbstractItemUpdateComponent {
}), }),
map((fieldUpdates: FieldUpdates) => map((fieldUpdates: FieldUpdates) =>
Object.values(fieldUpdates) Object.values(fieldUpdates)
.filter((fieldUpdate: FieldUpdate) => fieldUpdate.changeType === FieldChangeType.REMOVE) .filter((fieldUpdate: FieldUpdate) => fieldUpdate.changeType === FieldChangeType.REMOVE),
.map((fieldUpdate: FieldUpdate) => fieldUpdate.field as DeleteRelationship),
), ),
take(1),
); );
const addRelatedItems$: Observable<RelationshipIdentifiable[]> = this.objectUpdatesService.getFieldUpdates(this.url, []).pipe( const addUpdates$: Observable<FieldUpdate[]> = this.objectUpdatesService.getFieldUpdates(this.url, []).pipe(
map((fieldUpdates: FieldUpdates) => map((fieldUpdates: FieldUpdates) =>
Object.values(fieldUpdates) Object.values(fieldUpdates)
.filter((fieldUpdate: FieldUpdate) => hasValue(fieldUpdate)) .filter((fieldUpdate: FieldUpdate) => hasValue(fieldUpdate))
.filter((fieldUpdate: FieldUpdate) => fieldUpdate.changeType === FieldChangeType.ADD) .filter((fieldUpdate: FieldUpdate) => fieldUpdate.changeType === FieldChangeType.ADD),
.map((fieldUpdate: FieldUpdate) => fieldUpdate.field as RelationshipIdentifiable),
), ),
take(1),
); );
observableCombineLatest( observableCombineLatest([
removedRelationshipIDs$, removeUpdates$,
addRelatedItems$, addUpdates$,
).pipe( ]).pipe(
take(1), take(1),
).subscribe(([removeRelationshipIDs, addRelatedItems]) => { switchMap(([removeUpdates, addUpdates]) => [...removeUpdates, ...addUpdates]),
const actions = [ concatMap((update: FieldUpdate) => {
this.deleteRelationships(removeRelationshipIDs), if (update.changeType === FieldChangeType.REMOVE) {
this.addRelationships(addRelatedItems), return this.deleteRelationship(update.field as DeleteRelationship).pipe(take(1));
]; } else if (update.changeType === FieldChangeType.ADD) {
actions.forEach((action) => return this.addRelationship(update.field as RelationshipIdentifiable).pipe(
action.subscribe((response) => { take(1),
if (response.length > 0) { switchMap((relationshipRD: RemoteData<Relationship>) => {
this.initializeOriginalFields(); if (relationshipRD.hasSucceeded) {
this.cdr.detectChanges(); // Set the newly related item to stale, so its relationships will update to include
this.displayNotifications(response); // the new one. Only set the current item to stale at the very end so we only do it
this.modalService.dismissAll(); // once
} const { leftItem, rightItem } = relationshipRD.payload._links;
}), if (leftItem.href === this.item.self) {
); return this.itemService.invalidateByHref(rightItem.href).pipe(
// when it's invalidated, emit the original relationshipRD for use in the pipe below
map(() => relationshipRD),
);
} else {
return this.itemService.invalidateByHref(leftItem.href).pipe(
// when it's invalidated, emit the original relationshipRD for use in the pipe below
map(() => relationshipRD),
);
}
} else {
return [relationshipRD];
}
}),
);
} else {
return EMPTY;
}
}),
toArray(),
switchMap((responses) => {
// once all relationships are made and all related items have been invalidated, invalidate
// the current item
return this.itemService.invalidateByHref(this.item.self).pipe(
map(() => responses),
);
}),
).subscribe((responses) => {
if (responses.length > 0) {
this.initializeOriginalFields();
this.displayNotifications(responses);
this.modalService.dismissAll();
}
}); });
} }
deleteRelationships(deleteRelationshipIDs: DeleteRelationship[]): Observable<RemoteData<NoContent>[]> { deleteRelationship(deleteRelationship: DeleteRelationship): Observable<RemoteData<NoContent>> {
return observableZip(...deleteRelationshipIDs.map((deleteRelationship) => { let copyVirtualMetadata: string;
let copyVirtualMetadata: string; if (deleteRelationship.keepLeftVirtualMetadata && deleteRelationship.keepRightVirtualMetadata) {
if (deleteRelationship.keepLeftVirtualMetadata && deleteRelationship.keepRightVirtualMetadata) { copyVirtualMetadata = 'all';
copyVirtualMetadata = 'all'; } else if (deleteRelationship.keepLeftVirtualMetadata) {
} else if (deleteRelationship.keepLeftVirtualMetadata) { copyVirtualMetadata = 'left';
copyVirtualMetadata = 'left'; } else if (deleteRelationship.keepRightVirtualMetadata) {
} else if (deleteRelationship.keepRightVirtualMetadata) { copyVirtualMetadata = 'right';
copyVirtualMetadata = 'right'; } else {
} else { copyVirtualMetadata = 'none';
copyVirtualMetadata = 'none'; }
}
return this.relationshipService.deleteRelationship(deleteRelationship.uuid, copyVirtualMetadata); return this.relationshipService.deleteRelationship(deleteRelationship.uuid, copyVirtualMetadata, false);
},
));
} }
addRelationships(addRelatedItems: RelationshipIdentifiable[]): Observable<RemoteData<Relationship>[]> { addRelationship(addRelationship: RelationshipIdentifiable): Observable<RemoteData<Relationship>> {
return observableZip(...addRelatedItems.map((addRelationship) => return this.entityType$.pipe(
this.entityType$.pipe( switchMap((entityType) => this.entityTypeService.isLeftType(addRelationship.type, entityType)),
switchMap((entityType) => this.entityTypeService.isLeftType(addRelationship.type, entityType)), switchMap((isLeftType) => {
switchMap((isLeftType) => { let leftItem: Item;
let leftItem: Item; let rightItem: Item;
let rightItem: Item; let leftwardValue: string;
let leftwardValue: string; let rightwardValue: string;
let rightwardValue: string; if (isLeftType) {
if (isLeftType) { leftItem = this.item;
leftItem = this.item; rightItem = addRelationship.relatedItem;
rightItem = addRelationship.relatedItem; leftwardValue = null;
leftwardValue = null; rightwardValue = addRelationship.nameVariant;
rightwardValue = addRelationship.nameVariant; } else {
} else { leftItem = addRelationship.relatedItem;
leftItem = addRelationship.relatedItem; rightItem = this.item;
rightItem = this.item; leftwardValue = addRelationship.nameVariant;
leftwardValue = addRelationship.nameVariant; rightwardValue = null;
rightwardValue = null; }
} return this.relationshipService.addRelationship(addRelationship.type.id, leftItem, rightItem, leftwardValue, rightwardValue, false);
return this.relationshipService.addRelationship(addRelationship.type.id, leftItem, rightItem, leftwardValue, rightwardValue); }),
}), );
),
));
} }
/** /**