diff --git a/src/app/core/cache/server-sync-buffer.effects.ts b/src/app/core/cache/server-sync-buffer.effects.ts index f9e65bf23f..029bee31a8 100644 --- a/src/app/core/cache/server-sync-buffer.effects.ts +++ b/src/app/core/cache/server-sync-buffer.effects.ts @@ -25,6 +25,7 @@ import { Observable } from 'rxjs/internal/Observable'; import { RestRequestMethod } from '../data/rest-request-method'; import { ObjectCacheEntry } from './object-cache.reducer'; import { Operation } from 'fast-json-patch'; +import { RESTURLCombiner } from '../url-combiner/rest-url-combiner'; @Injectable() export class ServerSyncBufferEffects { @@ -98,22 +99,49 @@ export class ServerSyncBufferEffects { * @returns {Observable} ApplyPatchObjectCacheAction to be dispatched */ private applyPatch(href: string): Observable { - const patchObject = this.objectCache.getBySelfLink(href).pipe(take(1)); + if (isNotEmpty(href.match(/^http.*\/core\/relationships\/\d+$/))) { + return this.sendPatchAsPut(href); + } else { + const patchObject = this.objectCache.getBySelfLink(href).pipe(take(1)); + + return patchObject.pipe( + map((entry: ObjectCacheEntry) => { + if (isNotEmpty(entry.patches)) { + const flatPatch: Operation[] = [].concat(...entry.patches.map((patch) => patch.operations)); + if (isNotEmpty(flatPatch)) { + this.requestService.configure(new PatchRequest(this.requestService.generateRequestId(), href, flatPatch)); + } + } + return new ApplyPatchObjectCacheAction(href); + }) + ); + } + } + + + /** + * Send a list of PATCH operations made by the UI as a PUT request to the REST API + * This allows us to use PATCH in the UI while PATCH support for the endpoint is still + * under developent. + * + * @param {string} href The self link of the cache entry + * @returns {Observable} ApplyPatchObjectCacheAction to be dispatched + */ + private sendPatchAsPut(href: string): Observable { + const patchObject = this.objectCache.getObjectBySelfLink(href).pipe(take(1)); return patchObject.pipe( - map((entry: ObjectCacheEntry) => { - 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)); - } - } - return new ApplyPatchObjectCacheAction(href); + map((object) => { + const serializedObject = new DSpaceSerializer(object.constructor as GenericConstructor<{}>).serialize(object); + + this.requestService.configure(new PutRequest(this.requestService.generateRequestId(), href, serializedObject)); + + return new ApplyPatchObjectCacheAction(href) }) - ); + ) } + constructor(private actions$: Actions, private store: Store, private requestService: RequestService, diff --git a/src/app/core/data/relationship.service.ts b/src/app/core/data/relationship.service.ts index 3aca9de117..0b8d569ce2 100644 --- a/src/app/core/data/relationship.service.ts +++ b/src/app/core/data/relationship.service.ts @@ -3,7 +3,16 @@ import { Injectable } from '@angular/core'; import { MemoizedSelector, select, Store } from '@ngrx/store'; import { combineLatest as observableCombineLatest } from 'rxjs'; import { Observable } from 'rxjs/internal/Observable'; -import { distinctUntilChanged, filter, map, startWith, switchMap, take, tap } from 'rxjs/operators'; +import { + distinctUntilChanged, + filter, + map, + startWith, + switchMap, + take, + tap, + mergeMap +} from 'rxjs/operators'; import { compareArraysUsingIds, paginatedRelationsToItems, @@ -306,7 +315,7 @@ export class RelationshipService extends DataService { getSucceededRemoteData(), isNotEmptyOperator(), map((relationshipListRD: RemoteData>) => relationshipListRD.payload.page), - switchMap((relationships: Relationship[]) => { + mergeMap((relationships: Relationship[]) => { return observableCombineLatest(...relationships.map((relationship: Relationship) => { return observableCombineLatest( this.isItemMatchWithItemRD(this.itemService.findByHref(relationship._links.leftItem.href), item2), @@ -378,6 +387,7 @@ export class RelationshipService extends DataService { let count = 0 const update$: Observable> = this.getRelationshipByItemsAndLabel(item1, item2, relationshipLabel) .pipe( + tap((v) => console.log('updateNameVariant after getRelationshipByItemsAndLabel', v)), filter((relation: Relationship) => hasValue(relation)), switchMap((relation: Relationship) => relation.relationshipType.pipe( @@ -389,6 +399,7 @@ export class RelationshipService extends DataService { ) ), switchMap((relationshipAndType: { relation: Relationship, type: RelationshipType }) => { + console.log('updateNameVariant switchMap', relationshipAndType); const { relation, type } = relationshipAndType; let updatedRelationship; if (relationshipLabel === type.leftwardType) { 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 b4c3fe1d96..c0d3e5ea3d 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 @@ -167,14 +167,14 @@ export class ReorderableRelationship extends Reorderable { templateUrl: './existing-metadata-list-element.component.html', styleUrls: ['./existing-metadata-list-element.component.scss'] }) -export class ExistingMetadataListElementComponent implements OnChanges, OnDestroy { +export class ExistingMetadataListElementComponent implements OnInit, OnChanges, OnDestroy { @Input() listId: string; @Input() submissionItem: Item; @Input() reoRel: ReorderableRelationship; @Input() metadataFields: string[]; @Input() relationshipOptions: RelationshipOptions; @Input() submissionId: string; - metadataRepresentation$: BehaviorSubject; + metadataRepresentation$: BehaviorSubject = new BehaviorSubject(undefined); relatedItem: Item; /** @@ -188,6 +188,10 @@ export class ExistingMetadataListElementComponent implements OnChanges, OnDestro ) { } + ngOnInit(): void { + this.ngOnChanges(); + } + /** * Change callback for the component */ @@ -208,11 +212,7 @@ export class ExistingMetadataListElementComponent implements OnChanges, OnDestro new ItemMetadataRepresentation(metadataRepresentationMD), this.relatedItem ); - if (hasValue(this.metadataRepresentation$)) { - this.metadataRepresentation$.next(nextValue); - } else { - this.metadataRepresentation$ = new BehaviorSubject(nextValue); - } + this.metadataRepresentation$.next(nextValue); } })); } 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 ed1003bddf..953227c161 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 @@ -2,7 +2,7 @@ import { Component, EventEmitter, NgZone, OnDestroy, OnInit, Output } from '@ang import { combineLatest, Observable, Subscription, zip as observableZip } from 'rxjs'; import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; import { hasValue } from '../../../../empty.util'; -import { map, skip, switchMap, take } from 'rxjs/operators'; +import { map, skip, switchMap, take, tap, filter } from 'rxjs/operators'; import { SEARCH_CONFIG_SERVICE } from '../../../../../+my-dspace-page/my-dspace-page.component'; import { SearchConfigurationService } from '../../../../../core/shared/search/search-configuration.service'; import { SelectableListService } from '../../../../object-list/selectable-list/selectable-list.service'; @@ -165,7 +165,6 @@ export class DsDynamicLookupRelationModalComponent implements OnInit, OnDestroy .subscribe((arr: any[]) => { return arr.forEach((object: any) => { 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 83787bcdfd..d6f8103814 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 @@ -98,7 +98,7 @@ export class RelationshipEffects { const { item1, item2, relationshipType, submissionId, nameVariant } = action.payload; const identifier: string = this.createIdentifier(item1, item2, relationshipType); const inProgress = hasValue(this.debounceMap[identifier]); - if (inProgress) { + if (inProgress) { this.nameVariantUpdates[identifier] = nameVariant; } else { this.relationshipService.updateNameVariant(item1, item2, relationshipType, nameVariant).pipe(take(1))