From 29e6f6f72f36c15225007516925f0f6c4ed24030 Mon Sep 17 00:00:00 2001 From: Art Lowel Date: Thu, 2 Apr 2020 10:22:08 +0200 Subject: [PATCH] fix issue where the first relationship of a type wouldn't be added --- .../core/cache/server-sync-buffer.effects.ts | 1 + src/app/core/data/data.service.ts | 10 ++++- .../core/data/relationship-type.service.ts | 8 ++-- src/app/core/data/relationship.service.ts | 1 + .../builder/json-patch-operations-builder.ts | 8 ++++ .../json-patch-operations.reducer.ts | 14 +++++++ ...ynamic-form-control-container.component.ts | 3 ++ ...xisting-metadata-list-element.component.ts | 37 +++++++++++++++++++ ...dynamic-lookup-relation-modal.component.ts | 5 ++- .../relationship.effects.ts | 2 +- 10 files changed, 82 insertions(+), 7 deletions(-) diff --git a/src/app/core/cache/server-sync-buffer.effects.ts b/src/app/core/cache/server-sync-buffer.effects.ts index fd398f2971..f9e65bf23f 100644 --- a/src/app/core/cache/server-sync-buffer.effects.ts +++ b/src/app/core/cache/server-sync-buffer.effects.ts @@ -105,6 +105,7 @@ export class ServerSyncBufferEffects { if (isNotEmpty(entry.patches)) { const flatPatch: Operation[] = [].concat(...entry.patches.map((patch) => patch.operations)); if (isNotEmpty(flatPatch)) { + // if (href.match(/https://dspace7-ben.atmire.com/server/api/core/relationships/\d+/)) this.requestService.configure(new PatchRequest(this.requestService.generateRequestId(), href, flatPatch)); } } diff --git a/src/app/core/data/data.service.ts b/src/app/core/data/data.service.ts index f14f6e30c8..267cc547ea 100644 --- a/src/app/core/data/data.service.ts +++ b/src/app/core/data/data.service.ts @@ -509,7 +509,15 @@ export abstract class DataService { this.requestService.commit(method); } - getLinkPath() { + /** + * Return the links to traverse from the root of the api to the + * endpoint this DataService represents + * + * e.g. if the api root links to 'foo', and the endpoint at 'foo' + * links to 'bar' the linkPath for the BarDataService would be + * 'foo/bar' + */ + getLinkPath(): string { return this.linkPath; } } diff --git a/src/app/core/data/relationship-type.service.ts b/src/app/core/data/relationship-type.service.ts index eefe663209..23e56e31c9 100644 --- a/src/app/core/data/relationship-type.service.ts +++ b/src/app/core/data/relationship-type.service.ts @@ -3,9 +3,9 @@ import { Injectable } from '@angular/core'; import { Store } from '@ngrx/store'; import { combineLatest as observableCombineLatest } from 'rxjs'; import { Observable } from 'rxjs/internal/Observable'; -import { filter, find, map, switchMap } from 'rxjs/operators'; +import { filter, find, map, switchMap, tap, mergeMap } from 'rxjs/operators'; import { AppState } from '../../app.reducer'; -import { isNotUndefined } from '../../shared/empty.util'; +import { isNotUndefined, hasValue, isNotEmpty } from '../../shared/empty.util'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { followLink } from '../../shared/utils/follow-link-config.model'; import { dataService } from '../cache/builders/build-decorators'; @@ -76,7 +76,7 @@ export class RelationshipTypeService extends DataService { getSucceededRemoteData(), /* Flatten the page so we can treat it like an observable */ switchMap((typeListRD: RemoteData>) => typeListRD.payload.page), - switchMap((type: RelationshipType) => { + mergeMap((type: RelationshipType) => { if (type.leftwardType === label) { return this.checkType(type, firstType, secondType); } else if (type.rightwardType === label) { @@ -92,7 +92,7 @@ export class RelationshipTypeService extends DataService { // returns a void observable if there's not match // returns an observable that emits the relationship type when there is a match private checkType(type: RelationshipType, firstType: string, secondType: string): Observable { - const entityTypes = observableCombineLatest(type.leftType.pipe(getSucceededRemoteData()), type.rightType.pipe(getSucceededRemoteData())); + const entityTypes = observableCombineLatest([type.leftType.pipe(getSucceededRemoteData()), type.rightType.pipe(getSucceededRemoteData())]); return entityTypes.pipe( find(([leftTypeRD, rightTypeRD]: [RemoteData, RemoteData]) => leftTypeRD.payload.label === firstType && rightTypeRD.payload.label === secondType), filter((types) => isNotUndefined(types)), diff --git a/src/app/core/data/relationship.service.ts b/src/app/core/data/relationship.service.ts index 9abb8edb3c..3aca9de117 100644 --- a/src/app/core/data/relationship.service.ts +++ b/src/app/core/data/relationship.service.ts @@ -114,6 +114,7 @@ export class RelationshipService extends DataService { * @param rightwardValue The rightward value of the relationship */ addRelationship(typeId: string, item1: Item, item2: Item, leftwardValue?: string, rightwardValue?: string): Observable { + console.log('addRelationship', typeId, item1, item2, leftwardValue, rightwardValue); const options: HttpOptions = Object.create({}); let headers = new HttpHeaders(); headers = headers.append('Content-Type', 'text/uri-list'); diff --git a/src/app/core/json-patch/builder/json-patch-operations-builder.ts b/src/app/core/json-patch/builder/json-patch-operations-builder.ts index dc4b2f7052..c87b78d6bc 100644 --- a/src/app/core/json-patch/builder/json-patch-operations-builder.ts +++ b/src/app/core/json-patch/builder/json-patch-operations-builder.ts @@ -65,6 +65,14 @@ export class JsonPatchOperationsBuilder { } } + /** + * Dispatch a new NewPatchMoveOperationAction + * + * @param path + * the new path tho move to + * @param prevPath + * the original path to move from + */ move(path: JsonPatchOperationPathObject, prevPath: string) { this.store.dispatch( new NewPatchMoveOperationAction( diff --git a/src/app/core/json-patch/json-patch-operations.reducer.ts b/src/app/core/json-patch/json-patch-operations.reducer.ts index aa2010f0d5..648221f512 100644 --- a/src/app/core/json-patch/json-patch-operations.reducer.ts +++ b/src/app/core/json-patch/json-patch-operations.reducer.ts @@ -294,6 +294,20 @@ function flushOperation(state: JsonPatchOperationsState, action: FlushPatchOpera } } +/** + * Add a new operation to a patch + * + * @param body + * The current patch + * @param actionType + * The type of operation to add + * @param targetPath + * The path for the operation + * @param value + * The new value + * @param fromPath + * The previous path (in case of a move operation) + */ function addOperationToList(body: JsonPatchOperationObject[], actionType, targetPath, value?, fromPath?) { const newBody = Array.from(body); switch (actionType) { diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts index 662ba02f93..24cbc488b6 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts @@ -358,6 +358,9 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo .forEach((sub) => sub.unsubscribe()); } + /** + * Initialize this.item$ based on this.model.submissionId + */ private setItem() { const submissionObject$ = this.submissionObjectService .findById(this.model.submissionId, followLink('item'), followLink('collection')).pipe( diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.ts index 5e102e3783..b4c3fe1d96 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.ts @@ -35,17 +35,33 @@ export abstract class Reorderable { constructor(public oldIndex?: number, public newIndex?: number) { } + /** + * Return the id for this Reorderable + */ abstract getId(): string; + /** + * Return the place metadata for this Reorderable + */ abstract getPlace(): number; + /** + * Update the Reorderable + */ abstract update(): Observable; + /** + * Returns true if the oldIndex of this Reorderable + * differs from the newIndex + */ get hasMoved(): boolean { return this.oldIndex !== this.newIndex } } +/** + * A Reorderable representation of a FormFieldMetadataValue + */ export class ReorderableFormFieldMetadataValue extends Reorderable { constructor( @@ -60,6 +76,9 @@ export class ReorderableFormFieldMetadataValue extends Reorderable { this.metadataValue = metadataValue; } + /** + * Return the id for this Reorderable + */ getId(): string { if (hasValue(this.metadataValue.authority)) { return this.metadataValue.authority; @@ -69,10 +88,16 @@ export class ReorderableFormFieldMetadataValue extends Reorderable { } } + /** + * Return the place metadata for this Reorderable + */ getPlace(): number { return this.metadataValue.place; } + /** + * Update the Reorderable + */ update(): Observable { this.oldIndex = this.newIndex; return observableOf(this.metadataValue); @@ -98,10 +123,16 @@ export class ReorderableRelationship extends Reorderable { this.useLeftItem = useLeftItem; } + /** + * Return the id for this Reorderable + */ getId(): string { return this.relationship.id; } + /** + * Return the place metadata for this Reorderable + */ getPlace(): number { if (this.useLeftItem) { return this.relationship.rightPlace @@ -110,6 +141,9 @@ export class ReorderableRelationship extends Reorderable { } } + /** + * Update the Reorderable + */ update(): Observable> { this.store.dispatch(new UpdateRelationshipAction(this.relationship, this.submissionID)) const updatedRelationship$ = this.relationshipService.updatePlace(this).pipe( @@ -154,6 +188,9 @@ export class ExistingMetadataListElementComponent implements OnChanges, OnDestro ) { } + /** + * Change callback for the component + */ ngOnChanges() { if (hasValue(this.reoRel)) { const item$ = this.reoRel.useLeftItem ? diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/dynamic-lookup-relation-modal.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/dynamic-lookup-relation-modal.component.ts index be223f3eac..ed1003bddf 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/dynamic-lookup-relation-modal.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/dynamic-lookup-relation-modal.component.ts @@ -144,6 +144,7 @@ export class DsDynamicLookupRelationModalComponent implements OnInit, OnDestroy * @param selectableObjects */ select(...selectableObjects: Array>) { + console.log('selectableObjects', selectableObjects); this.zone.runOutsideAngular( () => { const obs: Observable = combineLatest(...selectableObjects.map((sri: SearchResult) => { @@ -163,7 +164,9 @@ export class DsDynamicLookupRelationModalComponent implements OnInit, OnDestroy obs .subscribe((arr: any[]) => { return arr.forEach((object: any) => { - this.store.dispatch(new AddRelationshipAction(this.item, object.item, this.relationshipOptions.relationshipType, this.submissionId, object.nameVariant)); + const addRelationshipAction = new AddRelationshipAction(this.item, object.item, this.relationshipOptions.relationshipType, this.submissionId, object.nameVariant); + console.log('addRelationshipAction', addRelationshipAction); + this.store.dispatch(addRelationshipAction); } ); }) diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/relationship.effects.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/relationship.effects.ts index f61eba461a..83787bcdfd 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/relationship.effects.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/relationship.effects.ts @@ -21,7 +21,7 @@ import { ServerSyncBufferActionTypes } from '../../../../../core/cache/server-sy import { CommitPatchOperationsAction, JsonPatchOperationsActionTypes, PatchOperationsActions } from '../../../../../core/json-patch/json-patch-operations.actions'; import { followLink } from '../../../../utils/follow-link-config.model'; -const DEBOUNCE_TIME = 5000; +const DEBOUNCE_TIME = 500; /** * NGRX effects for RelationshipEffects