64961: Update bitstream format

This commit is contained in:
Kristof De Langhe
2019-09-16 17:01:03 +02:00
parent 6230fef6b9
commit 358a6522c0
4 changed files with 71 additions and 41 deletions

View File

@@ -19,11 +19,12 @@ import { DynamicCustomSwitchModel } from '../../shared/form/builder/ds-dynamic-f
import { cloneDeep } from 'lodash'; import { cloneDeep } from 'lodash';
import { BitstreamDataService } from '../../core/data/bitstream-data.service'; import { BitstreamDataService } from '../../core/data/bitstream-data.service';
import { getRemoteDataPayload, getSucceededRemoteData } from '../../core/shared/operators'; import { getRemoteDataPayload, getSucceededRemoteData } from '../../core/shared/operators';
import { RemoteData } from '../../core/data/remote-data';
import { NotificationsService } from '../../shared/notifications/notifications.service'; import { NotificationsService } from '../../shared/notifications/notifications.service';
import { BitstreamFormatDataService } from '../../core/data/bitstream-format-data.service'; import { BitstreamFormatDataService } from '../../core/data/bitstream-format-data.service';
import { BitstreamFormat } from '../../core/shared/bitstream-format.model'; import { BitstreamFormat } from '../../core/shared/bitstream-format.model';
import { BitstreamFormatSupportLevel } from '../../core/shared/bitstream-format-support-level'; import { BitstreamFormatSupportLevel } from '../../core/shared/bitstream-format-support-level';
import { RestResponse } from '../../core/cache/response.models';
import { hasValue } from '../../shared/empty.util';
@Component({ @Component({
selector: 'ds-edit-bitstream-page', selector: 'ds-edit-bitstream-page',
@@ -42,9 +43,14 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy {
bitstream: Bitstream; 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 * @type {string} Key prefix used to generate form messages
@@ -71,11 +77,6 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy {
*/ */
findAllOptions = { elementsPerPage: 9999 }; findAllOptions = { elementsPerPage: 9999 };
/**
* List of IDs of unknown formats
*/
unknownFormatIDs: string[] = [];
/** /**
* The Dynamic Input Model for the file's name * The Dynamic Input Model for the file's name
*/ */
@@ -272,7 +273,8 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy {
allFormats$ allFormats$
).subscribe(([bitstream, allFormats]) => { ).subscribe(([bitstream, allFormats]) => {
this.bitstream = bitstream as Bitstream; this.bitstream = bitstream as Bitstream;
this.updateFormatModel(allFormats.page); this.formats = allFormats.page;
this.updateFormatModel();
this.updateForm(this.bitstream); this.updateForm(this.bitstream);
}); });
@@ -286,7 +288,6 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy {
/** /**
* Update the current form values with bitstream properties * Update the current form values with bitstream properties
* @param bitstream * @param bitstream
* @param bitstreamFormat
*/ */
updateForm(bitstream: Bitstream) { updateForm(bitstream: Bitstream) {
this.formGroup.patchValue({ this.formGroup.patchValue({
@@ -303,7 +304,7 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy {
getRemoteDataPayload(), getRemoteDataPayload(),
take(1) take(1)
).subscribe((format: BitstreamFormat) => { ).subscribe((format: BitstreamFormat) => {
this.originalFormatID = format.id; this.originalFormat = format;
this.formGroup.patchValue({ this.formGroup.patchValue({
formatContainer: { formatContainer: {
selectedFormat: format.id 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 * Create the list of unknown format IDs an add options to the selectedFormatModel
* @param formats
*/ */
updateFormatModel(formats: BitstreamFormat[]) { updateFormatModel() {
this.unknownFormatIDs = formats this.selectedFormatModel.options = this.formats.map((format: BitstreamFormat) =>
.filter((format: BitstreamFormat) => format.supportLevel === BitstreamFormatSupportLevel.Unknown)
.map((format: BitstreamFormat) => format.id);
this.selectedFormatModel.options = formats.map((format: BitstreamFormat) =>
Object.assign({ Object.assign({
value: format.id, value: format.id,
label: this.isUnknownFormat(format.id) ? this.translate.instant(this.KEY_PREFIX + 'selectedFormat.unknown') : format.shortDescription 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 * @param id
*/ */
isUnknownFormat(id: string): boolean { 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() { onSubmit() {
const updatedValues = this.formGroup.getRawValue(); const updatedValues = this.formGroup.getRawValue();
const newBitstream = this.formToBitstream(updatedValues); 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()), tap(() => this.bitstreamService.commitUpdates()),
getSucceededRemoteData() getSucceededRemoteData(),
getRemoteDataPayload()
); );
const updatedFormatResponse$ = this.bitstreamService.updateFormat(newBitstream, selectedFormat);
observableCombineLatest(updatedBitstream$, updatedFormatResponse$).subscribe(([bitstreamRD, formatResponse]) => { if (isNewFormat) {
console.log(formatResponse); const updatedFormatResponse$ = this.bitstreamService.updateFormat(newBitstream, selectedFormat);
this.bitstream = bitstreamRD.payload; observableCombineLatest(updatedBitstream$, updatedFormatResponse$).subscribe(([bitstream, formatResponse]) => {
this.updateForm(this.bitstream); this.onSuccess(bitstream, formatResponse);
this.notificationsService.success( });
this.translate.instant(this.NOTIFICATIONS_PREFIX + 'saved.title'), } else {
this.translate.instant(this.NOTIFICATIONS_PREFIX + 'saved.content') 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')
);
} }
/** /**

View File

@@ -104,7 +104,10 @@ export class ServerSyncBufferEffects {
map((entry: ObjectCacheEntry) => { map((entry: ObjectCacheEntry) => {
if (isNotEmpty(entry.patches)) { if (isNotEmpty(entry.patches)) {
const flatPatch: Operation[] = [].concat(...entry.patches.map((patch) => patch.operations)); 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); return new ApplyPatchObjectCacheAction(href);
} }
}) })

View File

@@ -16,10 +16,17 @@ import { FindAllOptions, PutRequest } from './request.models';
import { Observable } from 'rxjs/internal/Observable'; import { Observable } from 'rxjs/internal/Observable';
import { RestResponse } from '../cache/response.models'; import { RestResponse } from '../cache/response.models';
import { BitstreamFormatDataService } from './bitstream-format-data.service'; 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 { combineLatest as observableCombineLatest } from 'rxjs';
import { HttpOptions } from '../dspace-rest-v2/dspace-rest-v2.service'; 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 * 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<Bitstream> {
} }
/** /**
* Set the format of a bitstream by ID * Set the format of a bitstream
* @param bitstream * @param bitstream
* @param formatId * @param format
*/ */
updateFormat(bitstream: Bitstream, formatId: string): Observable<RestResponse> { updateFormat(bitstream: Bitstream, format: BitstreamFormat): Observable<RestResponse> {
const requestId = this.requestService.generateRequestId(); const requestId = this.requestService.generateRequestId();
const bitstreamHref$ = this.getBrowseEndpoint().pipe( const bitstreamHref$ = this.getBrowseEndpoint().pipe(
map((href: string) => `${href}/${bitstream.id}`), map((href: string) => `${href}/${bitstream.id}`),
switchMap((href: string) => this.halService.getEndpoint('format', href)) switchMap((href: string) => this.halService.getEndpoint('format', href))
); );
const formatHref$ = this.bitstreamFormatService.getBrowseEndpoint().pipe( const formatHref$ = this.bitstreamFormatService.getBrowseEndpoint().pipe(
map((href: string) => `${href}/${formatId}`) map((href: string) => `${href}/${format.id}`)
); );
observableCombineLatest(bitstreamHref$, formatHref$).pipe( observableCombineLatest(bitstreamHref$, formatHref$).pipe(
map(([bitstreamHref, formatHref]) => { map(([bitstreamHref, formatHref]) => {

View File

@@ -211,13 +211,18 @@ export abstract class DataService<T extends CacheableObject> {
* Add a new patch to the object cache * 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 * 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 {DSpaceObject} object The given object
* @param extraOperations
*/ */
update(object: T): Observable<RemoteData<T>> { update(object: T, extraOperations?: Operation[]): Observable<RemoteData<T>> {
const oldVersion$ = this.objectCache.getObjectBySelfLink(object.self); const oldVersion$ = this.objectCache.getObjectBySelfLink(object.self);
return oldVersion$.pipe(take(1), mergeMap((oldVersion: T) => { return oldVersion$.pipe(take(1), mergeMap((oldVersion: T) => {
const operations = this.comparator.diff(oldVersion, object); const operations = this.comparator.diff(oldVersion, object);
if (isNotEmpty(operations)) { let combinedOperations = operations || extraOperations;
this.objectCache.addPatch(object.self, operations); if (isNotEmpty(extraOperations)) {
combinedOperations = [...operations, ...extraOperations];
}
if (isNotEmpty(combinedOperations)) {
this.objectCache.addPatch(object.self, combinedOperations);
} }
return this.findById(object.uuid); return this.findById(object.uuid);
} }