From 358a6522c0358d2abb251c85f8381ec0d326c7f1 Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Mon, 16 Sep 2019 17:01:03 +0200 Subject: [PATCH] 64961: Update bitstream format --- .../edit-bitstream-page.component.ts | 77 +++++++++++-------- .../core/cache/server-sync-buffer.effects.ts | 5 +- src/app/core/data/bitstream-data.service.ts | 19 +++-- src/app/core/data/data.service.ts | 11 ++- 4 files changed, 71 insertions(+), 41 deletions(-) diff --git a/src/app/+bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts b/src/app/+bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts index 8d29a8111b..2c43257e7f 100644 --- a/src/app/+bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts +++ b/src/app/+bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts @@ -19,11 +19,12 @@ import { DynamicCustomSwitchModel } from '../../shared/form/builder/ds-dynamic-f import { cloneDeep } from 'lodash'; import { BitstreamDataService } from '../../core/data/bitstream-data.service'; import { getRemoteDataPayload, getSucceededRemoteData } from '../../core/shared/operators'; -import { RemoteData } from '../../core/data/remote-data'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { BitstreamFormatDataService } from '../../core/data/bitstream-format-data.service'; import { BitstreamFormat } from '../../core/shared/bitstream-format.model'; import { BitstreamFormatSupportLevel } from '../../core/shared/bitstream-format-support-level'; +import { RestResponse } from '../../core/cache/response.models'; +import { hasValue } from '../../shared/empty.util'; @Component({ selector: 'ds-edit-bitstream-page', @@ -42,9 +43,14 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy { bitstream: Bitstream; /** - * The ID of the originally selected format + * The originally selected format */ - originalFormatID: string; + originalFormat: BitstreamFormat; + + /** + * A list of all available bitstream formats + */ + formats: BitstreamFormat[]; /** * @type {string} Key prefix used to generate form messages @@ -71,11 +77,6 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy { */ findAllOptions = { elementsPerPage: 9999 }; - /** - * List of IDs of unknown formats - */ - unknownFormatIDs: string[] = []; - /** * The Dynamic Input Model for the file's name */ @@ -272,7 +273,8 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy { allFormats$ ).subscribe(([bitstream, allFormats]) => { this.bitstream = bitstream as Bitstream; - this.updateFormatModel(allFormats.page); + this.formats = allFormats.page; + this.updateFormatModel(); this.updateForm(this.bitstream); }); @@ -286,7 +288,6 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy { /** * Update the current form values with bitstream properties * @param bitstream - * @param bitstreamFormat */ updateForm(bitstream: Bitstream) { this.formGroup.patchValue({ @@ -303,7 +304,7 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy { getRemoteDataPayload(), take(1) ).subscribe((format: BitstreamFormat) => { - this.originalFormatID = format.id; + this.originalFormat = format; this.formGroup.patchValue({ formatContainer: { selectedFormat: format.id @@ -315,13 +316,9 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy { /** * Create the list of unknown format IDs an add options to the selectedFormatModel - * @param formats */ - updateFormatModel(formats: BitstreamFormat[]) { - this.unknownFormatIDs = formats - .filter((format: BitstreamFormat) => format.supportLevel === BitstreamFormatSupportLevel.Unknown) - .map((format: BitstreamFormat) => format.id); - this.selectedFormatModel.options = formats.map((format: BitstreamFormat) => + updateFormatModel() { + this.selectedFormatModel.options = this.formats.map((format: BitstreamFormat) => Object.assign({ value: format.id, label: this.isUnknownFormat(format.id) ? this.translate.instant(this.KEY_PREFIX + 'selectedFormat.unknown') : format.shortDescription @@ -345,7 +342,8 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy { * @param id */ isUnknownFormat(id: string): boolean { - return this.unknownFormatIDs.indexOf(id) > -1; + const format = this.formats.find((f: BitstreamFormat) => f.id === id); + return hasValue(format) && format.supportLevel === BitstreamFormatSupportLevel.Unknown; } /** @@ -387,23 +385,40 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy { onSubmit() { const updatedValues = this.formGroup.getRawValue(); const newBitstream = this.formToBitstream(updatedValues); - const selectedFormat = updatedValues.formatContainer.selectedFormat; + const selectedFormat = this.formats.find((f: BitstreamFormat) => f.id === updatedValues.formatContainer.selectedFormat); + const isNewFormat = selectedFormat.id !== this.originalFormat.id; - const updatedBitstream$ = this.bitstreamService.update(newBitstream).pipe( + const extraOperations = []; + if (isNewFormat) { + const operation = Object.assign({op: 'replace', path: '/format', value: selectedFormat.self}); + extraOperations.push(operation); + } + + const updatedBitstream$ = this.bitstreamService.update(newBitstream, extraOperations).pipe( tap(() => this.bitstreamService.commitUpdates()), - getSucceededRemoteData() + getSucceededRemoteData(), + getRemoteDataPayload() ); - const updatedFormatResponse$ = this.bitstreamService.updateFormat(newBitstream, selectedFormat); - observableCombineLatest(updatedBitstream$, updatedFormatResponse$).subscribe(([bitstreamRD, formatResponse]) => { - console.log(formatResponse); - this.bitstream = bitstreamRD.payload; - this.updateForm(this.bitstream); - this.notificationsService.success( - this.translate.instant(this.NOTIFICATIONS_PREFIX + 'saved.title'), - this.translate.instant(this.NOTIFICATIONS_PREFIX + 'saved.content') - ); - }); + if (isNewFormat) { + const updatedFormatResponse$ = this.bitstreamService.updateFormat(newBitstream, selectedFormat); + observableCombineLatest(updatedBitstream$, updatedFormatResponse$).subscribe(([bitstream, formatResponse]) => { + this.onSuccess(bitstream, formatResponse); + }); + } else { + updatedBitstream$.subscribe((bitstream: Bitstream) => { + this.onSuccess(bitstream); + }); + } + } + + onSuccess(bitstream: Bitstream, formatResponse?: RestResponse) { + this.bitstream = bitstream; + this.updateForm(this.bitstream); + this.notificationsService.success( + this.translate.instant(this.NOTIFICATIONS_PREFIX + 'saved.title'), + this.translate.instant(this.NOTIFICATIONS_PREFIX + 'saved.content') + ); } /** diff --git a/src/app/core/cache/server-sync-buffer.effects.ts b/src/app/core/cache/server-sync-buffer.effects.ts index f25923e1f5..f095b99fd8 100644 --- a/src/app/core/cache/server-sync-buffer.effects.ts +++ b/src/app/core/cache/server-sync-buffer.effects.ts @@ -104,7 +104,10 @@ export class ServerSyncBufferEffects { map((entry: ObjectCacheEntry) => { if (isNotEmpty(entry.patches)) { const flatPatch: Operation[] = [].concat(...entry.patches.map((patch) => patch.operations)); - this.requestService.configure(new PatchRequest(this.requestService.generateRequestId(), href, flatPatch)); + const metadataPatch = flatPatch.filter((op: Operation) => op.path.startsWith('/metadata')); + if (isNotEmpty(metadataPatch)) { + this.requestService.configure(new PatchRequest(this.requestService.generateRequestId(), href, metadataPatch)); + } return new ApplyPatchObjectCacheAction(href); } }) diff --git a/src/app/core/data/bitstream-data.service.ts b/src/app/core/data/bitstream-data.service.ts index 896dd49ab2..8c06b126bf 100644 --- a/src/app/core/data/bitstream-data.service.ts +++ b/src/app/core/data/bitstream-data.service.ts @@ -16,10 +16,17 @@ import { FindAllOptions, PutRequest } from './request.models'; import { Observable } from 'rxjs/internal/Observable'; import { RestResponse } from '../cache/response.models'; import { BitstreamFormatDataService } from './bitstream-format-data.service'; -import { map, switchMap } from 'rxjs/operators'; +import { map, mergeMap, switchMap, take } from 'rxjs/operators'; import { combineLatest as observableCombineLatest } from 'rxjs'; import { HttpOptions } from '../dspace-rest-v2/dspace-rest-v2.service'; -import { configureRequest, getResponseFromEntry } from '../shared/operators'; +import { + configureRequest, + getRemoteDataPayload, + getResponseFromEntry, + getSucceededRemoteData +} from '../shared/operators'; +import { RemoteData } from './remote-data'; +import { BitstreamFormat } from '../shared/bitstream-format.model'; /** * A service responsible for fetching/sending data from/to the REST API on the bitstreams endpoint @@ -68,18 +75,18 @@ export class BitstreamDataService extends DataService { } /** - * Set the format of a bitstream by ID + * Set the format of a bitstream * @param bitstream - * @param formatId + * @param format */ - updateFormat(bitstream: Bitstream, formatId: string): Observable { + updateFormat(bitstream: Bitstream, format: BitstreamFormat): Observable { const requestId = this.requestService.generateRequestId(); const bitstreamHref$ = this.getBrowseEndpoint().pipe( map((href: string) => `${href}/${bitstream.id}`), switchMap((href: string) => this.halService.getEndpoint('format', href)) ); const formatHref$ = this.bitstreamFormatService.getBrowseEndpoint().pipe( - map((href: string) => `${href}/${formatId}`) + map((href: string) => `${href}/${format.id}`) ); observableCombineLatest(bitstreamHref$, formatHref$).pipe( map(([bitstreamHref, formatHref]) => { diff --git a/src/app/core/data/data.service.ts b/src/app/core/data/data.service.ts index d1f6444a4f..783613b2c1 100644 --- a/src/app/core/data/data.service.ts +++ b/src/app/core/data/data.service.ts @@ -211,13 +211,18 @@ export abstract class DataService { * Add a new patch to the object cache * The patch is derived from the differences between the given object and its version in the object cache * @param {DSpaceObject} object The given object + * @param extraOperations */ - update(object: T): Observable> { + update(object: T, extraOperations?: Operation[]): Observable> { const oldVersion$ = this.objectCache.getObjectBySelfLink(object.self); return oldVersion$.pipe(take(1), mergeMap((oldVersion: T) => { const operations = this.comparator.diff(oldVersion, object); - if (isNotEmpty(operations)) { - this.objectCache.addPatch(object.self, operations); + let combinedOperations = operations || extraOperations; + if (isNotEmpty(extraOperations)) { + combinedOperations = [...operations, ...extraOperations]; + } + if (isNotEmpty(combinedOperations)) { + this.objectCache.addPatch(object.self, combinedOperations); } return this.findById(object.uuid); }