diff --git a/src/app/core/shared/operators.ts b/src/app/core/shared/operators.ts index ea2a0283eb..2a68e44af8 100644 --- a/src/app/core/shared/operators.ts +++ b/src/app/core/shared/operators.ts @@ -349,7 +349,7 @@ export const metadataFieldsToString = () => map((schema: MetadataSchema) => ({ field, schema })) ); }); - return observableCombineLatest(fieldSchemaArray); + return isNotEmpty(fieldSchemaArray) ? observableCombineLatest(fieldSchemaArray) : [[]]; }), map((fieldSchemaArray: { field: MetadataField, schema: MetadataSchema }[]): string[] => { return fieldSchemaArray.map((fieldSchema: { field: MetadataField, schema: MetadataSchema }) => fieldSchema.schema.prefix + '.' + fieldSchema.field.toString()); diff --git a/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata-form.ts b/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata-form.ts index c059f5064f..220a4561f6 100644 --- a/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata-form.ts +++ b/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata-form.ts @@ -1,5 +1,10 @@ import { MetadataMap, MetadataValue } from '../../core/shared/metadata.models'; import { hasNoValue, hasValue, isEmpty, isNotEmpty } from '../../shared/empty.util'; +import { Operation } from 'fast-json-patch'; +import { MetadataPatchReplaceOperation } from '../../core/data/object-updates/patch-operation-service/operations/metadata/metadata-patch-replace-operation.model'; +import { MetadataPatchRemoveOperation } from '../../core/data/object-updates/patch-operation-service/operations/metadata/metadata-patch-remove-operation.model'; +import { MetadataPatchAddOperation } from '../../core/data/object-updates/patch-operation-service/operations/metadata/metadata-patch-add-operation.model'; +import { MetadataPatchOperation } from '../../core/data/object-updates/patch-operation-service/operations/metadata/metadata-patch-operation.model'; export enum DsoEditMetadataChangeType { UPDATE = 1, @@ -55,10 +60,14 @@ export class DsoEditMetadataValue { } reinstate(): void { - this.newValue = this.reinstatableValue; - this.reinstatableValue = undefined; - this.change = this.reinstatableChange; - this.reinstatableChange = undefined; + if (hasValue(this.reinstatableValue)) { + this.newValue = this.reinstatableValue; + this.reinstatableValue = undefined; + } + if (hasValue(this.reinstatableChange)) { + this.change = this.reinstatableChange; + this.reinstatableChange = undefined; + } } isReinstatable(): boolean { @@ -67,16 +76,23 @@ export class DsoEditMetadataValue { } export class DsoEditMetadataForm { + originalFieldKeys: string[]; fieldKeys: string[]; fields: { [mdField: string]: DsoEditMetadataValue[], }; + reinstatableNewValues: { + [mdField: string]: DsoEditMetadataValue[], + }; newValue: DsoEditMetadataValue; constructor(metadata: MetadataMap) { + this.originalFieldKeys = []; this.fieldKeys = []; this.fields = {}; + this.reinstatableNewValues = {}; Object.entries(metadata).forEach(([mdField, values]: [string, MetadataValue[]]) => { + this.originalFieldKeys.push(mdField); this.fieldKeys.push(mdField); this.fields[mdField] = values.map((value) => new DsoEditMetadataValue(value)); }); @@ -89,12 +105,17 @@ export class DsoEditMetadataForm { } setMetadataField(mdField: string) { + this.newValue.editing = false; + this.addValueToField(this.newValue, mdField); + this.newValue = undefined; + } + + private addValueToField(value: DsoEditMetadataValue, mdField: string) { if (isEmpty(this.fields[mdField])) { this.fieldKeys.push(mdField); this.fields[mdField] = []; } - this.fields[mdField].push(this.newValue); - this.newValue = undefined; + this.fields[mdField].push(value); } remove(mdField: string, index: number) { @@ -112,11 +133,31 @@ export class DsoEditMetadataForm { } discard(): void { - Object.values(this.fields).forEach((values) => { - values.forEach((value) => { - value.discard(); + Object.entries(this.fields).forEach(([field, values]) => { + let removeFromIndex = -1; + values.forEach((value, index) => { + if (value.change === DsoEditMetadataChangeType.ADD) { + if (isEmpty(this.reinstatableNewValues[field])) { + this.reinstatableNewValues[field] = []; + } + this.reinstatableNewValues[field].push(value); + if (removeFromIndex === -1) { + removeFromIndex = index; + } + } else { + value.discardAndMarkReinstatable(); + } }); + if (removeFromIndex > -1) { + this.fields[field].splice(removeFromIndex, this.fields[field].length - removeFromIndex); + } }); + this.fieldKeys.forEach((field) => { + if (this.originalFieldKeys.indexOf(field) < 0) { + delete this.fields[field]; + } + }); + this.fieldKeys = [...this.originalFieldKeys]; } reinstate(): void { @@ -125,9 +166,48 @@ export class DsoEditMetadataForm { value.reinstate(); }); }); + Object.entries(this.reinstatableNewValues).forEach(([field, values]) => { + values.forEach((value) => { + this.addValueToField(value, field); + }); + }); + this.reinstatableNewValues = {}; } isReinstatable(): boolean { - return Object.values(this.fields).some((values) => values.some((value) => value.isReinstatable())); + return isNotEmpty(this.reinstatableNewValues) || + Object.values(this.fields) + .some((values) => values + .some((value) => value.isReinstatable())); + } + + getOperations(): Operation[] { + const operations: Operation[] = []; + Object.entries(this.fields).forEach(([field, values]) => { + values.forEach((value, place) => { + if (value.hasChanges()) { + let operation: MetadataPatchOperation; + if (value.change === DsoEditMetadataChangeType.UPDATE) { + operation = new MetadataPatchReplaceOperation(field, place, { + value: value.newValue.value, + language: value.newValue.language, + }); + } else if (value.change === DsoEditMetadataChangeType.REMOVE) { + operation = new MetadataPatchRemoveOperation(field, place); + } else if (value.change === DsoEditMetadataChangeType.ADD) { + operation = new MetadataPatchAddOperation(field, { + value: value.newValue.value, + language: value.newValue.language, + }); + } else { + console.warn('Illegal metadata change state detected for', value); + } + if (hasValue(operation)) { + operations.push(operation.toOperation()); + } + } + }); + }); + return operations; } } diff --git a/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata.component.html b/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata.component.html index abe671e6f3..27cf706a1a 100644 --- a/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata.component.html +++ b/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata.component.html @@ -1,19 +1,19 @@