mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-08 02:24:11 +00:00
[835] Auto-save in new Item Submission form breaks the form
Store additions: 1. Form AdditionalData: contains the list of the touched metadata 2. Submission metadata: contains the list of the metadata ids assignable for each section We keep also track whether a section ha focused fields or not.
This commit is contained in:
@@ -7,7 +7,7 @@ import {
|
||||
DYNAMIC_FORM_CONTROL_TYPE_GROUP,
|
||||
DYNAMIC_FORM_CONTROL_TYPE_INPUT,
|
||||
DYNAMIC_FORM_CONTROL_TYPE_RADIO_GROUP,
|
||||
DynamicFormArrayModel,
|
||||
DynamicFormArrayModel, DynamicFormControlEvent,
|
||||
DynamicFormControlModel,
|
||||
DynamicFormGroupModel,
|
||||
DynamicFormService, DynamicFormValidationService,
|
||||
@@ -26,6 +26,7 @@ import { DsDynamicInputModel } from './ds-dynamic-form-ui/models/ds-dynamic-inpu
|
||||
import { FormFieldMetadataValueObject } from './models/form-field-metadata-value.model';
|
||||
import { isNgbDateStruct } from '../../date.util';
|
||||
import { DYNAMIC_FORM_CONTROL_TYPE_RELATION_GROUP } from './ds-dynamic-form-ui/ds-dynamic-form-constants';
|
||||
import { CONCAT_GROUP_SUFFIX, DynamicConcatModel } from './ds-dynamic-form-ui/models/ds-dynamic-concat.model';
|
||||
|
||||
@Injectable()
|
||||
export class FormBuilderService extends DynamicFormService {
|
||||
@@ -54,6 +55,15 @@ export class FormBuilderService extends DynamicFormService {
|
||||
break;
|
||||
}
|
||||
|
||||
if (this.isConcatGroup(controlModel)) {
|
||||
const concatGroupId = controlModel.id.replace(CONCAT_GROUP_SUFFIX, '');
|
||||
// if (concatGroupId === findId) {
|
||||
if (concatGroupId.includes(findId)) {
|
||||
result = (controlModel as DynamicConcatModel).group[0];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.isGroup(controlModel)) {
|
||||
findByIdFn(findId, (controlModel as DynamicFormGroupModel).group, findArrayIndex);
|
||||
}
|
||||
@@ -247,6 +257,10 @@ export class FormBuilderService extends DynamicFormService {
|
||||
return model && ((model as any).type === DYNAMIC_FORM_CONTROL_TYPE_GROUP && (model as any).isCustomGroup === true);
|
||||
}
|
||||
|
||||
isConcatGroup(model: DynamicFormControlModel): boolean {
|
||||
return this.isCustomGroup(model) && (model.id.indexOf(CONCAT_GROUP_SUFFIX) !== -1);
|
||||
}
|
||||
|
||||
isRowGroup(model: DynamicFormControlModel): boolean {
|
||||
return model && ((model as any).type === DYNAMIC_FORM_CONTROL_TYPE_GROUP && (model as any).isRowGroup === true);
|
||||
}
|
||||
@@ -303,4 +317,76 @@ export class FormBuilderService extends DynamicFormService {
|
||||
return (tempModel.id !== tempModel.name) ? tempModel.name : tempModel.id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the metadata list related to the event.
|
||||
* @param event
|
||||
*/
|
||||
getMetadataIdsFromEvent(event: DynamicFormControlEvent): string[] {
|
||||
|
||||
let model = event.model;
|
||||
while (model.parent) {
|
||||
model = model.parent as any;
|
||||
}
|
||||
|
||||
const iterateControlModels = (findGroupModel: DynamicFormControlModel[], controlModelIndex: number = 0): void => {
|
||||
let iterateResult = Object.create({});
|
||||
|
||||
// Iterate over all group's controls
|
||||
for (const controlModel of findGroupModel) {
|
||||
|
||||
if (this.isRowGroup(controlModel) && !this.isCustomOrListGroup(controlModel)) {
|
||||
iterateResult = mergeWith(iterateResult, iterateControlModels((controlModel as DynamicFormGroupModel).group));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (this.isGroup(controlModel) && !this.isCustomOrListGroup(controlModel)) {
|
||||
iterateResult[controlModel.name] = iterateControlModels((controlModel as DynamicFormGroupModel).group);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (this.isRowArrayGroup(controlModel)) {
|
||||
for (const arrayItemModel of (controlModel as DynamicRowArrayModel).groups) {
|
||||
iterateResult = mergeWith(iterateResult, iterateControlModels(arrayItemModel.group, arrayItemModel.index));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (this.isArrayGroup(controlModel)) {
|
||||
iterateResult[controlModel.name] = [];
|
||||
for (const arrayItemModel of (controlModel as DynamicFormArrayModel).groups) {
|
||||
iterateResult[controlModel.name].push(iterateControlModels(arrayItemModel.group, arrayItemModel.index));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
let controlId;
|
||||
// Get the field's name
|
||||
if (this.isQualdropGroup(controlModel)) {
|
||||
// If is instance of DynamicQualdropModel take the qualdrop id as field's name
|
||||
controlId = (controlModel as DynamicQualdropModel).qualdropId;
|
||||
} else {
|
||||
controlId = controlModel.name;
|
||||
}
|
||||
|
||||
if (this.isRelationGroup(controlModel)) {
|
||||
const values = (controlModel as DynamicRelationGroupModel).getGroupValue();
|
||||
values.forEach((groupValue, groupIndex) => {
|
||||
Object.keys(groupValue).forEach((key) => {
|
||||
iterateResult[key] = true;
|
||||
});
|
||||
});
|
||||
} else {
|
||||
iterateResult[controlId] = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return iterateResult;
|
||||
};
|
||||
|
||||
const result = iterateControlModels([model]);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -13,6 +13,7 @@ import { type } from '../ngrx/type';
|
||||
export const FormActionTypes = {
|
||||
FORM_INIT: type('dspace/form/FORM_INIT'),
|
||||
FORM_CHANGE: type('dspace/form/FORM_CHANGE'),
|
||||
FORM_ADDITIONAL: type('dspace/form/FORM_ADDITIONAL'),
|
||||
FORM_REMOVE: type('dspace/form/FORM_REMOVE'),
|
||||
FORM_STATUS_CHANGE: type('dspace/form/FORM_STATUS_CHANGE'),
|
||||
FORM_ADD_ERROR: type('dspace/form/FORM_ADD_ERROR'),
|
||||
@@ -27,6 +28,7 @@ export class FormInitAction implements Action {
|
||||
formId: string;
|
||||
formData: any;
|
||||
valid: boolean;
|
||||
formAdditional: any;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -39,8 +41,8 @@ export class FormInitAction implements Action {
|
||||
* @param valid
|
||||
* the Form validation status
|
||||
*/
|
||||
constructor(formId: string, formData: any, valid: boolean) {
|
||||
this.payload = {formId, formData, valid};
|
||||
constructor(formId: string, formData: any, valid: boolean, formAdditional?: any) {
|
||||
this.payload = {formId, formData, valid, formAdditional};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,7 +54,7 @@ export class FormChangeAction implements Action {
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a new FormInitAction
|
||||
* Create a new FormChangeAction
|
||||
*
|
||||
* @param formId
|
||||
* the Form's ID
|
||||
@@ -64,6 +66,26 @@ export class FormChangeAction implements Action {
|
||||
}
|
||||
}
|
||||
|
||||
export class FormSetAdditionalAction implements Action {
|
||||
type = FormActionTypes.FORM_ADDITIONAL;
|
||||
payload: {
|
||||
formId: string;
|
||||
additionalData: any;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a new FormSetAdditionalAction
|
||||
*
|
||||
* @param formId
|
||||
* the Form's ID
|
||||
* @param additionalData
|
||||
* the additionalData Object
|
||||
*/
|
||||
constructor(formId: string, additionalData: any) {
|
||||
this.payload = {formId, additionalData};
|
||||
}
|
||||
}
|
||||
|
||||
export class FormRemoveAction implements Action {
|
||||
type = FormActionTypes.FORM_REMOVE;
|
||||
payload: {
|
||||
@@ -147,6 +169,7 @@ export class FormClearErrorsAction implements Action {
|
||||
*/
|
||||
export type FormAction = FormInitAction
|
||||
| FormChangeAction
|
||||
| FormSetAdditionalAction
|
||||
| FormRemoveAction
|
||||
| FormStatusChangeAction
|
||||
| FormAddError
|
||||
|
@@ -5,7 +5,7 @@ import {
|
||||
FormChangeAction, FormClearErrorsAction,
|
||||
FormInitAction,
|
||||
FormRemoveAction,
|
||||
FormRemoveErrorAction,
|
||||
FormRemoveErrorAction, FormSetAdditionalAction,
|
||||
FormStatusChangeAction
|
||||
} from './form.actions';
|
||||
import { hasValue } from '../empty.util';
|
||||
@@ -21,6 +21,7 @@ export interface FormEntry {
|
||||
data: any;
|
||||
valid: boolean;
|
||||
errors: FormError[];
|
||||
additional: any;
|
||||
}
|
||||
|
||||
export interface FormState {
|
||||
@@ -40,6 +41,10 @@ export function formReducer(state = initialState, action: FormAction): FormState
|
||||
return changeDataForm(state, action as FormChangeAction);
|
||||
}
|
||||
|
||||
case FormActionTypes.FORM_ADDITIONAL: {
|
||||
return additionalData(state, action as FormSetAdditionalAction);
|
||||
}
|
||||
|
||||
case FormActionTypes.FORM_REMOVE: {
|
||||
return removeForm(state, action as FormRemoveAction);
|
||||
}
|
||||
@@ -127,7 +132,8 @@ function initForm(state: FormState, action: FormInitAction): FormState {
|
||||
const formState = {
|
||||
data: action.payload.formData,
|
||||
valid: action.payload.valid,
|
||||
errors: []
|
||||
errors: [],
|
||||
additional: action.payload.formAdditional
|
||||
};
|
||||
if (!hasValue(state[action.payload.formId])) {
|
||||
return Object.assign({}, state, {
|
||||
@@ -212,3 +218,30 @@ function removeForm(state: FormState, action: FormRemoveAction): FormState {
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the additional data state of the form. New touched fields are merged with the previous ones.
|
||||
* @param state
|
||||
* @param action
|
||||
*/
|
||||
function additionalData(state: FormState, action: FormSetAdditionalAction): FormState {
|
||||
if (hasValue(state[action.payload.formId])) {
|
||||
|
||||
const newState = Object.assign({}, state);
|
||||
|
||||
const newAdditional = newState[action.payload.formId].additional ? {...newState[action.payload.formId].additional} : {};
|
||||
|
||||
const newTouchedValue = newAdditional.touched ? {...newAdditional.touched,
|
||||
...action.payload.additionalData.touched} : { ...action.payload.additionalData.touched};
|
||||
newAdditional.touched = newTouchedValue;
|
||||
|
||||
newState[action.payload.formId] = Object.assign({}, newState[action.payload.formId], {
|
||||
additional: newAdditional
|
||||
}
|
||||
);
|
||||
|
||||
return newState;
|
||||
} else {
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
@@ -7,13 +7,13 @@ import { select, Store } from '@ngrx/store';
|
||||
import { AppState } from '../../app.reducer';
|
||||
import { formObjectFromIdSelector } from './selectors';
|
||||
import { FormBuilderService } from './builder/form-builder.service';
|
||||
import { DynamicFormControlModel } from '@ng-dynamic-forms/core';
|
||||
import {DynamicFormControlEvent, DynamicFormControlModel} from '@ng-dynamic-forms/core';
|
||||
import { isEmpty, isNotUndefined } from '../empty.util';
|
||||
import { uniqueId } from 'lodash';
|
||||
import {
|
||||
FormChangeAction,
|
||||
FormInitAction,
|
||||
FormRemoveAction, FormRemoveErrorAction,
|
||||
FormRemoveAction, FormRemoveErrorAction, FormSetAdditionalAction,
|
||||
FormStatusChangeAction
|
||||
} from './form.actions';
|
||||
import { FormEntry } from './form.reducer';
|
||||
@@ -51,6 +51,18 @@ export class FormService {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to retrieve form's additional data from state
|
||||
*/
|
||||
public getFormAdditionalData(formId: string): Observable<any> {
|
||||
return this.store.pipe(
|
||||
select(formObjectFromIdSelector(formId)),
|
||||
filter((state) => isNotUndefined(state)),
|
||||
map((state) => state.additional),
|
||||
distinctUntilChanged()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to retrieve form's errors from state
|
||||
*/
|
||||
@@ -149,8 +161,8 @@ export class FormService {
|
||||
return (environment.form.validatorMap.hasOwnProperty(validator)) ? environment.form.validatorMap[validator] : validator;
|
||||
}
|
||||
|
||||
public initForm(formId: string, model: DynamicFormControlModel[], valid: boolean) {
|
||||
this.store.dispatch(new FormInitAction(formId, this.formBuilderService.getValueFromModel(model), valid));
|
||||
public initForm(formId: string, model: DynamicFormControlModel[], valid: boolean, additional?: any) {
|
||||
this.store.dispatch(new FormInitAction(formId, this.formBuilderService.getValueFromModel(model), valid, additional));
|
||||
}
|
||||
|
||||
public setStatusChanged(formId: string, valid: boolean) {
|
||||
@@ -169,6 +181,11 @@ export class FormService {
|
||||
this.store.dispatch(new FormChangeAction(formId, this.formBuilderService.getValueFromModel(model)));
|
||||
}
|
||||
|
||||
public setTouched(formId: string, model: DynamicFormControlModel[], event: DynamicFormControlEvent) {
|
||||
const ids = this.formBuilderService.getMetadataIdsFromEvent(event);
|
||||
this.store.dispatch(new FormSetAdditionalAction(formId, { touched: ids}));
|
||||
}
|
||||
|
||||
public removeError(formId: string, eventModelId: string, fieldIndex: number) {
|
||||
this.store.dispatch(new FormRemoveErrorAction(formId, eventModelId, fieldIndex));
|
||||
}
|
||||
|
@@ -206,6 +206,7 @@ export class UpdateSectionDataAction implements Action {
|
||||
sectionId: string;
|
||||
data: WorkspaceitemSectionDataType;
|
||||
errors: SubmissionSectionError[];
|
||||
metadata: string[];
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -219,12 +220,15 @@ export class UpdateSectionDataAction implements Action {
|
||||
* the section's data
|
||||
* @param errors
|
||||
* the section's errors
|
||||
* @param metadata
|
||||
* the section's metadata
|
||||
*/
|
||||
constructor(submissionId: string,
|
||||
sectionId: string,
|
||||
data: WorkspaceitemSectionDataType,
|
||||
errors: SubmissionSectionError[]) {
|
||||
this.payload = { submissionId, sectionId, data, errors };
|
||||
errors: SubmissionSectionError[],
|
||||
metadata?: string[]) {
|
||||
this.payload = { submissionId, sectionId, data, errors, metadata };
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -292,7 +292,7 @@ export class SubmissionObjectEffects {
|
||||
return item$.pipe(
|
||||
map((item: Item) => item.metadata),
|
||||
filter((metadata) => !isEqual(action.payload.data, metadata)),
|
||||
map((metadata: any) => new UpdateSectionDataAction(action.payload.submissionId, action.payload.sectionId, metadata, action.payload.errors))
|
||||
map((metadata: any) => new UpdateSectionDataAction(action.payload.submissionId, action.payload.sectionId, metadata, action.payload.errors, action.payload.metadata))
|
||||
);
|
||||
} else {
|
||||
return observableOf(new UpdateSectionDataSuccessAction());
|
||||
|
@@ -85,6 +85,11 @@ export interface SubmissionSectionObject {
|
||||
*/
|
||||
enabled: boolean;
|
||||
|
||||
/**
|
||||
* The list of the metadata ids of the section.
|
||||
*/
|
||||
metadata: string[];
|
||||
|
||||
/**
|
||||
* The section data object
|
||||
*/
|
||||
@@ -660,7 +665,8 @@ function updateSectionData(state: SubmissionObjectState, action: UpdateSectionDa
|
||||
[ action.payload.sectionId ]: Object.assign({}, state[ action.payload.submissionId ].sections [ action.payload.sectionId ], {
|
||||
enabled: true,
|
||||
data: action.payload.data,
|
||||
errors: action.payload.errors
|
||||
errors: action.payload.errors,
|
||||
metadata: reduceSectionMetadata(action.payload.metadata, state[ action.payload.submissionId ].sections [ action.payload.sectionId ].metadata)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -670,6 +676,22 @@ function updateSectionData(state: SubmissionObjectState, action: UpdateSectionDa
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the state of the section metadata only when a new value is provided.
|
||||
* Keep the existent otherwise.
|
||||
* @param newMetadata
|
||||
* @param oldMetadata
|
||||
*/
|
||||
function reduceSectionMetadata(newMetadata: string[], oldMetadata: string[]) {
|
||||
if (newMetadata) {
|
||||
return newMetadata;
|
||||
}
|
||||
if (oldMetadata) {
|
||||
return [...oldMetadata];
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a section state.
|
||||
*
|
||||
|
@@ -2,7 +2,9 @@
|
||||
<ds-form *ngIf="!isLoading && formModel" #formRef="formComponent"
|
||||
[formId]="formId"
|
||||
[formModel]="formModel"
|
||||
[formAdditional]="formAdditionalData"
|
||||
[displaySubmit]="false"
|
||||
(dfBlur)="onBlur($event)"
|
||||
(dfChange)="onChange($event)"
|
||||
(dfFocus)="onFocus($event)"
|
||||
(remove)="onRemove($event)"
|
||||
|
@@ -20,7 +20,7 @@ import { FormComponent } from '../../../shared/form/form.component';
|
||||
import { FormService } from '../../../shared/form/form.service';
|
||||
import { SectionModelComponent } from '../models/section.model';
|
||||
import { SubmissionFormsConfigService } from '../../../core/config/submission-forms-config.service';
|
||||
import { hasNoValue, hasValue, isNotEmpty, isUndefined } from '../../../shared/empty.util';
|
||||
import { hasNoValue, hasValue, isEmpty, isNotEmpty, isUndefined } from '../../../shared/empty.util';
|
||||
import { JsonPatchOperationPathCombiner } from '../../../core/json-patch/builder/json-patch-operation-path-combiner';
|
||||
import { SubmissionFormsModel } from '../../../core/config/models/config-submission-forms.model';
|
||||
import {
|
||||
@@ -101,6 +101,18 @@ export class SubmissionSectionformComponent extends SectionModelComponent {
|
||||
*/
|
||||
protected formData: any = Object.create({});
|
||||
|
||||
/**
|
||||
* Store the current form additional data
|
||||
* @protected
|
||||
*/
|
||||
protected formAdditionalData: any = Object.create({});
|
||||
|
||||
/**
|
||||
* Store the
|
||||
* @protected
|
||||
*/
|
||||
protected sectionMetadata: string[];
|
||||
|
||||
/**
|
||||
* The [JsonPatchOperationPathCombiner] object
|
||||
* @type {JsonPatchOperationPathCombiner}
|
||||
@@ -125,6 +137,12 @@ export class SubmissionSectionformComponent extends SectionModelComponent {
|
||||
*/
|
||||
@ViewChild('formRef', {static: false}) private formRef: FormComponent;
|
||||
|
||||
/**
|
||||
* Keep track whether the section is focused or not.
|
||||
* @protected
|
||||
*/
|
||||
protected isFocused = false;
|
||||
|
||||
/**
|
||||
* Initialize instance variables
|
||||
*
|
||||
@@ -230,16 +248,24 @@ export class SubmissionSectionformComponent extends SectionModelComponent {
|
||||
* the section data retrieved from the server
|
||||
*/
|
||||
hasMetadataEnrichment(sectionData: WorkspaceitemSectionFormObject): boolean {
|
||||
|
||||
const sectionDataToCheck = {};
|
||||
Object.keys(sectionData).forEach((key) => {
|
||||
if (this.sectionMetadata.includes(key)) {
|
||||
sectionDataToCheck[key] = sectionData[key];
|
||||
}
|
||||
})
|
||||
|
||||
const diffResult = [];
|
||||
|
||||
// compare current form data state with section data retrieved from store
|
||||
const diffObj = difference(sectionData, this.formData);
|
||||
const diffObj = difference(sectionDataToCheck, this.formData);
|
||||
|
||||
// iterate over differences to check whether they are actually different
|
||||
Object.keys(diffObj)
|
||||
.forEach((key) => {
|
||||
diffObj[key].forEach((value) => {
|
||||
if (value.hasOwnProperty('value')) {
|
||||
if (value.hasOwnProperty('value') && !isEmpty(value.value)) {
|
||||
diffResult.push(value);
|
||||
}
|
||||
});
|
||||
@@ -262,6 +288,9 @@ export class SubmissionSectionformComponent extends SectionModelComponent {
|
||||
sectionData,
|
||||
this.submissionService.getSubmissionScope()
|
||||
);
|
||||
this.formBuilderService.enrichWithAdditionalData(this.formModel, this.formAdditionalData);
|
||||
this.sectionMetadata = this.sectionService.computeSectionConfiguredMetadata(this.formConfig);
|
||||
|
||||
} catch (e) {
|
||||
const msg: string = this.translate.instant('error.submission.sections.init-form-error') + e.toString();
|
||||
const sectionError: SubmissionSectionError = {
|
||||
@@ -283,8 +312,9 @@ export class SubmissionSectionformComponent extends SectionModelComponent {
|
||||
*/
|
||||
updateForm(sectionData: WorkspaceitemSectionFormObject, errors: SubmissionSectionError[]): void {
|
||||
|
||||
if (hasValue(sectionData) && !isEqual(sectionData, this.sectionData.data)) {
|
||||
if (isNotEmpty(sectionData) && !isEqual(sectionData, this.sectionData.data)) {
|
||||
this.sectionData.data = sectionData;
|
||||
if (this.hasMetadataEnrichment(sectionData)) {
|
||||
this.isUpdating = true;
|
||||
this.formModel = null;
|
||||
this.cdr.detectChanges();
|
||||
@@ -295,6 +325,9 @@ export class SubmissionSectionformComponent extends SectionModelComponent {
|
||||
} else if (isNotEmpty(errors) || isNotEmpty(this.sectionData.errors)) {
|
||||
this.checksForErrors(errors);
|
||||
}
|
||||
} else if (isNotEmpty(errors) || isNotEmpty(this.sectionData.errors)) {
|
||||
this.checksForErrors(errors);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -308,6 +341,9 @@ export class SubmissionSectionformComponent extends SectionModelComponent {
|
||||
this.formService.isFormInitialized(this.formId).pipe(
|
||||
find((status: boolean) => status === true && !this.isUpdating))
|
||||
.subscribe(() => {
|
||||
|
||||
// TODO: filter these errors to only those that had been touched
|
||||
|
||||
this.sectionService.checkSectionErrors(this.submissionId, this.sectionData.id, this.formId, errors, this.sectionData.errors);
|
||||
this.sectionData.errors = errors;
|
||||
this.cdr.detectChanges();
|
||||
@@ -328,6 +364,12 @@ export class SubmissionSectionformComponent extends SectionModelComponent {
|
||||
this.formData = formData;
|
||||
}),
|
||||
|
||||
this.formService.getFormAdditionalData(this.formId).pipe(
|
||||
distinctUntilChanged())
|
||||
.subscribe((formAdditional) => {
|
||||
this.formAdditionalData = formAdditional;
|
||||
}),
|
||||
|
||||
/**
|
||||
* Subscribe to section state
|
||||
*/
|
||||
@@ -375,6 +417,7 @@ export class SubmissionSectionformComponent extends SectionModelComponent {
|
||||
* the [[DynamicFormControlEvent]] emitted
|
||||
*/
|
||||
onFocus(event: DynamicFormControlEvent): void {
|
||||
this.isFocused = true;
|
||||
const value = this.formOperationsService.getFieldValueFromChangeEvent(event);
|
||||
const path = this.formBuilderService.getPath(event.model);
|
||||
if (this.formBuilderService.hasMappedGroupValue(event.model)) {
|
||||
@@ -386,6 +429,17 @@ export class SubmissionSectionformComponent extends SectionModelComponent {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method called when a form dfBlur event is fired.
|
||||
*
|
||||
* @param event
|
||||
* the [[DynamicFormControlEvent]] emitted
|
||||
*/
|
||||
|
||||
onBlur(event: DynamicFormControlEvent): void {
|
||||
this.isFocused = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method called when a form remove event is fired.
|
||||
* Dispatch form operations based on changes.
|
||||
|
@@ -8,7 +8,7 @@ import { ScrollToConfigOptions, ScrollToService } from '@nicky-lenaers/ngx-scrol
|
||||
import { isEqual } from 'lodash';
|
||||
|
||||
import { SubmissionState } from '../submission.reducers';
|
||||
import { hasValue, isEmpty, isNotEmpty, isNotUndefined } from '../../shared/empty.util';
|
||||
import { hasValue, isEmpty, isNotEmpty, isNotNull, isNotUndefined } from '../../shared/empty.util';
|
||||
import {
|
||||
DisableSectionAction,
|
||||
EnableSectionAction,
|
||||
@@ -36,6 +36,8 @@ import { SubmissionService } from '../submission.service';
|
||||
import { WorkspaceitemSectionDataType } from '../../core/submission/models/workspaceitem-sections.model';
|
||||
import { SectionsType } from './sections-type';
|
||||
import { normalizeSectionData } from '../../core/submission/submission-response-parsing.service';
|
||||
import { SubmissionFormsModel } from '../../core/config/models/config-submission-forms.model';
|
||||
import { parseReviver } from '@ng-dynamic-forms/core';
|
||||
|
||||
/**
|
||||
* A service that provides methods used in submission process.
|
||||
@@ -335,8 +337,10 @@ export class SectionsService {
|
||||
* The section data
|
||||
* @param errors
|
||||
* The list of section errors
|
||||
* @param metadata
|
||||
* The section metadata
|
||||
*/
|
||||
public updateSectionData(submissionId: string, sectionId: string, data: WorkspaceitemSectionDataType, errors: SubmissionSectionError[] = []) {
|
||||
public updateSectionData(submissionId: string, sectionId: string, data: WorkspaceitemSectionDataType, errors: SubmissionSectionError[] = [], metadata?: string[]) {
|
||||
if (isNotEmpty(data)) {
|
||||
const isAvailable$ = this.isSectionAvailable(submissionId, sectionId);
|
||||
const isEnabled$ = this.isSectionEnabled(submissionId, sectionId);
|
||||
@@ -345,7 +349,7 @@ export class SectionsService {
|
||||
take(1),
|
||||
filter(([available, enabled]: [boolean, boolean]) => available))
|
||||
.subscribe(([available, enabled]: [boolean, boolean]) => {
|
||||
this.store.dispatch(new UpdateSectionDataAction(submissionId, sectionId, data, errors));
|
||||
this.store.dispatch(new UpdateSectionDataAction(submissionId, sectionId, data, errors, metadata));
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -377,4 +381,30 @@ export class SectionsService {
|
||||
public setSectionStatus(submissionId: string, sectionId: string, status: boolean) {
|
||||
this.store.dispatch(new SectionStatusChangeAction(submissionId, sectionId, status));
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the list of selectable metadata for the section configuration.
|
||||
* @param formConfig
|
||||
*/
|
||||
public computeSectionConfiguredMetadata(formConfig: string | SubmissionFormsModel): string[] {
|
||||
const metadata = [];
|
||||
const rawData = typeof formConfig === 'string' ? JSON.parse(formConfig, parseReviver) : formConfig;
|
||||
if (rawData.rows && !isEmpty(rawData.rows)) {
|
||||
rawData.rows.forEach((currentRow) => {
|
||||
if (currentRow.fields && !isEmpty(currentRow.fields)) {
|
||||
currentRow.fields.forEach((field) => {
|
||||
if (field.selectableMetadata && !isEmpty(field.selectableMetadata)) {
|
||||
field.selectableMetadata.forEach((selectableMetadata) => {
|
||||
if (!metadata.includes(selectableMetadata.metadata)) {
|
||||
metadata.push(selectableMetadata.metadata);
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
}
|
||||
return metadata;
|
||||
}
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user