Skip to content

Commit 10a4e27

Browse files
KasinhouMatus Kasakclaude
authored
Clarin9/Save submission immediately when a type/sponsor/author field changes (#1489)
* Clarin9/Save submission immediately when a type/sponsor/author field changes In the DSpace 9 upgrade, the CLARIN section-form lost the logic that persisted the submission as soon as a type-bind controlling field (e.g. dc.type) or a sponsor/author autocomplete value was picked. In v7, selecting such a value in a dropdown fired an immediate section save (verified live on dev-5: choosing a resource type triggers a PATCH). In v9 nothing was saved until the whole section lost focus, so the choice could be lost. Restore the v7 behaviour in SubmissionSectionFormComponent.onChange: when the changed field is a type-bind controlling field or the sponsor/author field, dispatch a section save immediately. The set of type-bind controlling fields is owned by FormBuilderService in v9 (populated from `submit.type-bind.field`), so expose it via a new getTypeFieldValues() accessor rather than duplicating the map in the component. Form reconfiguration on type change is already handled reactively by v9's type-bind machinery, so only the save is restored here. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * Fix type-bind match to handle multi-segment controlling fields Convert metadata to underscore notation instead of replacing only the first underscore in the field id (addresses Copilot review). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Matus Kasak <matus.kasak@dataquest.sk> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
1 parent f78da0e commit 10a4e27

4 files changed

Lines changed: 45 additions & 0 deletions

File tree

src/app/shared/form/builder/form-builder.service.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -708,4 +708,9 @@ export class FormBuilderService extends DynamicFormService {
708708
return this.getDefaultTypeBindModelId();
709709
}
710710

711+
/** Type-bind controlling fields (underscore notation, e.g. `dc_type`, `edm_type`) from `submit.type-bind.field`. */
712+
getTypeFieldValues(): string[] {
713+
return Array.from(this.typeFields.values());
714+
}
715+
711716
}

src/app/shared/mocks/form-builder-service.mock.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ export function getMockFormBuilderService(): FormBuilderService {
4848
),
4949
getTypeBindModelUpdates: EMPTY,
5050
resolveTypeBindModelId: undefined,
51+
getTypeFieldValues: ['dc_type'],
5152
});
5253

5354
// as the real implementation behaves for a reference the type field map does not remap

src/app/submission/sections/form/section-form.component.spec.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -608,6 +608,36 @@ describe('SubmissionSectionFormComponent test suite', () => {
608608

609609
});
610610

611+
it('should call dispatchSaveSection on form change when a type-bind field (e.g. dc.type) changes', () => {
612+
spyOn(comp, 'hasStoredValue').and.returnValue(false);
613+
formOperationsService.getFieldPathSegmentedFromChangeEvent.and.returnValue('dc.type');
614+
formOperationsService.getFieldValueFromChangeEvent.and.returnValue({ value: 'Corpus' });
615+
616+
comp.onChange(dynamicFormControlEvent);
617+
618+
expect(submissionServiceStub.dispatchSaveSection).toHaveBeenCalledWith(submissionId, sectionObject.id);
619+
});
620+
621+
it('should call dispatchSaveSection on form change when a sponsor value changes', () => {
622+
spyOn(comp, 'hasStoredValue').and.returnValue(false);
623+
formOperationsService.getFieldPathSegmentedFromChangeEvent.and.returnValue('local.sponsor');
624+
formOperationsService.getFieldValueFromChangeEvent.and.returnValue({ value: 'EU' });
625+
626+
comp.onChange(dynamicFormControlEvent);
627+
628+
expect(submissionServiceStub.dispatchSaveSection).toHaveBeenCalledWith(submissionId, sectionObject.id);
629+
});
630+
631+
it('should not call dispatchSaveSection on form change for a regular field', () => {
632+
spyOn(comp, 'hasStoredValue').and.returnValue(false);
633+
formOperationsService.getFieldPathSegmentedFromChangeEvent.and.returnValue('dc.description');
634+
formOperationsService.getFieldValueFromChangeEvent.and.returnValue('some text');
635+
636+
comp.onChange(dynamicFormControlEvent);
637+
638+
expect(submissionServiceStub.dispatchSaveSection).not.toHaveBeenCalled();
639+
});
640+
611641
it('should set previousValue on form focus event', () => {
612642
formBuilderService.hasMappedGroupValue.and.returnValue(false);
613643
formOperationsService.getFieldValueFromChangeEvent.and.returnValue('test');

src/app/submission/sections/form/section-form.component.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ import {
5252
isNotEmpty,
5353
isUndefined,
5454
} from '../../../shared/empty.util';
55+
import { AUTHOR_METADATA_FIELD_NAME } from '../../../shared/form/builder/ds-dynamic-form-ui/models/clarin-name.model';
56+
import { SPONSOR_METADATA_NAME } from '../../../shared/form/builder/ds-dynamic-form-ui/models/ds-dynamic-complex.model';
5557
import { FormBuilderService } from '../../../shared/form/builder/form-builder.service';
5658
import { FormFieldPreviousValueObject } from '../../../shared/form/builder/models/form-field-previous-value-object';
5759
import { FormComponent } from '../../../shared/form/form.component';
@@ -446,6 +448,13 @@ export class SubmissionSectionFormComponent extends SectionModelComponent {
446448
if ((environment.submission.autosave.metadata.indexOf(metadata) !== -1 && isNotEmpty(value)) || this.hasRelatedCustomError(metadata)) {
447449
this.submissionService.dispatchSave(this.submissionId);
448450
}
451+
452+
// Save immediately when a type-bind field (values like `dc_type`, `edm_type`) or a sponsor/author value changes.
453+
const isTypeBindField = this.formBuilderService.getTypeFieldValues()
454+
.some((typeValue) => typeValue === metadata.replace(/\./g, '_'));
455+
if (isTypeBindField || [SPONSOR_METADATA_NAME, AUTHOR_METADATA_FIELD_NAME].includes(metadata)) {
456+
this.submissionService.dispatchSaveSection(this.submissionId, this.sectionData.id);
457+
}
449458
}
450459

451460
private hasRelatedCustomError(medatata): boolean {

0 commit comments

Comments
 (0)