mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 01:54:15 +00:00
398 lines
15 KiB
TypeScript
398 lines
15 KiB
TypeScript
import { Injectable } from '@angular/core';
|
|
import { AbstractControl, FormGroup } from '@angular/forms';
|
|
|
|
import {
|
|
DYNAMIC_FORM_CONTROL_TYPE_ARRAY,
|
|
DYNAMIC_FORM_CONTROL_TYPE_CHECKBOX_GROUP,
|
|
DYNAMIC_FORM_CONTROL_TYPE_GROUP,
|
|
DYNAMIC_FORM_CONTROL_TYPE_INPUT,
|
|
DYNAMIC_FORM_CONTROL_TYPE_RADIO_GROUP,
|
|
DynamicFormArrayModel,
|
|
DynamicFormComponentService,
|
|
DynamicFormControlEvent,
|
|
DynamicFormControlModel,
|
|
DynamicFormGroupModel,
|
|
DynamicFormService,
|
|
DynamicFormValidationService,
|
|
DynamicPathable,
|
|
parseReviver,
|
|
} from '@ng-dynamic-forms/core';
|
|
import { isObject, isString, mergeWith } from 'lodash';
|
|
|
|
import { hasValue, isEmpty, isNotEmpty, isNotNull, isNotUndefined, isNull } from '../../empty.util';
|
|
import { DynamicQualdropModel } from './ds-dynamic-form-ui/models/ds-dynamic-qualdrop.model';
|
|
import { SubmissionFormsModel } from '../../../core/config/models/config-submission-forms.model';
|
|
import { DYNAMIC_FORM_CONTROL_TYPE_TAG } from './ds-dynamic-form-ui/models/tag/dynamic-tag.model';
|
|
import { RowParser } from './parsers/row-parser';
|
|
import { DynamicRelationGroupModel } from './ds-dynamic-form-ui/models/relation-group/dynamic-relation-group.model';
|
|
import { DynamicRowArrayModel } from './ds-dynamic-form-ui/models/ds-dynamic-row-array-model';
|
|
import { DsDynamicInputModel } from './ds-dynamic-form-ui/models/ds-dynamic-input.model';
|
|
import { FormFieldMetadataValueObject } from './models/form-field-metadata-value.model';
|
|
import { dateToString, 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 {
|
|
|
|
constructor(
|
|
componentService: DynamicFormComponentService,
|
|
validationService: DynamicFormValidationService,
|
|
protected rowParser: RowParser
|
|
) {
|
|
super(componentService, validationService);
|
|
}
|
|
|
|
findById(id: string, groupModel: DynamicFormControlModel[], arrayIndex = null): DynamicFormControlModel | null {
|
|
|
|
let result = null;
|
|
const findByIdFn = (findId: string, findGroupModel: DynamicFormControlModel[], findArrayIndex): void => {
|
|
|
|
for (const controlModel of findGroupModel) {
|
|
|
|
if (controlModel.id === findId) {
|
|
|
|
if (this.isArrayGroup(controlModel) && isNotNull(findArrayIndex)) {
|
|
result = (controlModel as DynamicFormArrayModel).get(findArrayIndex);
|
|
} else {
|
|
result = controlModel;
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (this.isConcatGroup(controlModel)) {
|
|
if (controlModel.id.match(new RegExp(findId + CONCAT_GROUP_SUFFIX + `_\\d+$`))) {
|
|
result = (controlModel as DynamicConcatModel).group[0];
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (this.isGroup(controlModel)) {
|
|
findByIdFn(findId, (controlModel as DynamicFormGroupModel).group, findArrayIndex);
|
|
}
|
|
|
|
if (this.isArrayGroup(controlModel)
|
|
&& (isNull(findArrayIndex) || (controlModel as DynamicFormArrayModel).size > (findArrayIndex))) {
|
|
const index = (isNull(findArrayIndex)) ? 0 : findArrayIndex;
|
|
findByIdFn(findId, (controlModel as DynamicFormArrayModel).get(index).group, index);
|
|
}
|
|
}
|
|
};
|
|
|
|
findByIdFn(id, groupModel, arrayIndex);
|
|
|
|
return result;
|
|
}
|
|
|
|
clearAllModelsValue(groupModel: DynamicFormControlModel[]): void {
|
|
|
|
const iterateControlModels = (findGroupModel: DynamicFormControlModel[]): void => {
|
|
|
|
for (const controlModel of findGroupModel) {
|
|
|
|
if (this.isGroup(controlModel)) {
|
|
iterateControlModels((controlModel as DynamicFormGroupModel).group);
|
|
continue;
|
|
}
|
|
|
|
if (this.isArrayGroup(controlModel)) {
|
|
iterateControlModels((controlModel as DynamicFormArrayModel).groupFactory());
|
|
continue;
|
|
}
|
|
|
|
if (controlModel.hasOwnProperty('valueChanges')) {
|
|
(controlModel as any).value = undefined;
|
|
}
|
|
}
|
|
};
|
|
|
|
iterateControlModels(groupModel);
|
|
}
|
|
|
|
getValueFromModel(groupModel: DynamicFormControlModel[]): void {
|
|
|
|
let result = Object.create({});
|
|
|
|
const customizer = (objValue, srcValue) => {
|
|
if (Array.isArray(objValue)) {
|
|
return objValue.concat(srcValue);
|
|
}
|
|
};
|
|
|
|
const normalizeValue = (controlModel, controlValue, controlModelIndex) => {
|
|
const controlLanguage = (controlModel as DsDynamicInputModel).hasLanguages ? (controlModel as DsDynamicInputModel).language : null;
|
|
if (isString(controlValue)) {
|
|
return new FormFieldMetadataValueObject(controlValue, controlLanguage, null, null, controlModelIndex);
|
|
} else if (isNgbDateStruct(controlValue)) {
|
|
return new FormFieldMetadataValueObject(dateToString(controlValue));
|
|
} else if (isObject(controlValue)) {
|
|
const authority = (controlValue as any).authority || (controlValue as any).id || null;
|
|
const place = controlModelIndex || (controlValue as any).place;
|
|
if (isNgbDateStruct(controlValue)) {
|
|
return new FormFieldMetadataValueObject(controlValue, controlLanguage, authority, controlValue as any, place);
|
|
} else {
|
|
return new FormFieldMetadataValueObject((controlValue as any).value, controlLanguage, authority, (controlValue as any).display, place, (controlValue as any).confidence);
|
|
}
|
|
}
|
|
};
|
|
|
|
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), customizer);
|
|
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), customizer);
|
|
}
|
|
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) => {
|
|
const newGroupValue = Object.create({});
|
|
Object.keys(groupValue)
|
|
.forEach((key) => {
|
|
const normValue = normalizeValue(controlModel, groupValue[key], groupIndex);
|
|
if (isNotEmpty(normValue) && normValue.hasValue()) {
|
|
if (iterateResult.hasOwnProperty(key)) {
|
|
iterateResult[key].push(normValue);
|
|
} else {
|
|
iterateResult[key] = [normValue];
|
|
}
|
|
}
|
|
});
|
|
});
|
|
} else if (isNotUndefined((controlModel as any).value) && isNotEmpty((controlModel as any).value)) {
|
|
const controlArrayValue = [];
|
|
// Normalize control value as an array of FormFieldMetadataValueObject
|
|
const values = Array.isArray((controlModel as any).value) ? (controlModel as any).value : [(controlModel as any).value];
|
|
values.forEach((controlValue) => {
|
|
controlArrayValue.push(normalizeValue(controlModel, controlValue, controlModelIndex));
|
|
});
|
|
|
|
if (controlId && iterateResult.hasOwnProperty(controlId) && isNotNull(iterateResult[controlId])) {
|
|
iterateResult[controlId] = iterateResult[controlId].concat(controlArrayValue);
|
|
} else {
|
|
iterateResult[controlId] = isNotEmpty(controlArrayValue) ? controlArrayValue : null;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
return iterateResult;
|
|
};
|
|
|
|
result = iterateControlModels(groupModel);
|
|
|
|
return result;
|
|
}
|
|
|
|
modelFromConfiguration(submissionId: string, json: string | SubmissionFormsModel, scopeUUID: string, sectionData: any = {}, submissionScope?: string, readOnly = false): DynamicFormControlModel[] | never {
|
|
let rows: DynamicFormControlModel[] = [];
|
|
const rawData = typeof json === 'string' ? JSON.parse(json, parseReviver) : json;
|
|
|
|
if (rawData.rows && !isEmpty(rawData.rows)) {
|
|
rawData.rows.forEach((currentRow) => {
|
|
const rowParsed = this.rowParser.parse(submissionId, currentRow, scopeUUID, sectionData, submissionScope, readOnly);
|
|
if (isNotNull(rowParsed)) {
|
|
if (Array.isArray(rowParsed)) {
|
|
rows = rows.concat(rowParsed);
|
|
} else {
|
|
rows.push(rowParsed);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
return rows;
|
|
}
|
|
|
|
isModelInCustomGroup(model: DynamicFormControlModel): boolean {
|
|
return this.isCustomGroup((model as any).parent);
|
|
}
|
|
|
|
hasArrayGroupValue(model: DynamicFormControlModel): boolean {
|
|
return model && (this.isListGroup(model) || model.type === DYNAMIC_FORM_CONTROL_TYPE_TAG);
|
|
}
|
|
|
|
hasMappedGroupValue(model: DynamicFormControlModel): boolean {
|
|
return (this.isQualdropGroup((model as any).parent)
|
|
|| this.isRelationGroup((model as any).parent));
|
|
}
|
|
|
|
isGroup(model: DynamicFormControlModel): boolean {
|
|
return model && (model.type === DYNAMIC_FORM_CONTROL_TYPE_GROUP || model.type === DYNAMIC_FORM_CONTROL_TYPE_CHECKBOX_GROUP);
|
|
}
|
|
|
|
isQualdropGroup(model: DynamicFormControlModel): boolean {
|
|
return (model && model.type === DYNAMIC_FORM_CONTROL_TYPE_GROUP && hasValue((model as any).qualdropId));
|
|
}
|
|
|
|
isCustomGroup(model: DynamicFormControlModel): boolean {
|
|
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);
|
|
}
|
|
|
|
isCustomOrListGroup(model: DynamicFormControlModel): boolean {
|
|
return model &&
|
|
(this.isCustomGroup(model)
|
|
|| this.isListGroup(model));
|
|
}
|
|
|
|
isListGroup(model: DynamicFormControlModel): boolean {
|
|
return model &&
|
|
((model.type === DYNAMIC_FORM_CONTROL_TYPE_CHECKBOX_GROUP && (model as any).isListGroup === true)
|
|
|| (model.type === DYNAMIC_FORM_CONTROL_TYPE_RADIO_GROUP && (model as any).isListGroup === true));
|
|
}
|
|
|
|
isRelationGroup(model: DynamicFormControlModel): boolean {
|
|
return model && model.type === DYNAMIC_FORM_CONTROL_TYPE_RELATION_GROUP;
|
|
}
|
|
|
|
isRowArrayGroup(model: DynamicFormControlModel): boolean {
|
|
return model.type === DYNAMIC_FORM_CONTROL_TYPE_ARRAY && (model as any).isRowArray === true;
|
|
}
|
|
|
|
isArrayGroup(model: DynamicFormControlModel): boolean {
|
|
return model.type === DYNAMIC_FORM_CONTROL_TYPE_ARRAY;
|
|
}
|
|
|
|
isInputModel(model: DynamicFormControlModel): boolean {
|
|
return model.type === DYNAMIC_FORM_CONTROL_TYPE_INPUT;
|
|
}
|
|
|
|
getFormControlById(id: string, formGroup: FormGroup, groupModel: DynamicFormControlModel[], index = 0): AbstractControl {
|
|
const fieldModel = this.findById(id, groupModel, index);
|
|
return isNotEmpty(fieldModel) ? formGroup.get(this.getPath(fieldModel)) : null;
|
|
}
|
|
|
|
/**
|
|
* Note (discovered while debugging) this is not the ID as used in the form,
|
|
* but the first part of the path needed in a patch operation:
|
|
* e.g. add foo/0 -> the id is 'foo'
|
|
*/
|
|
getId(model: DynamicPathable): string {
|
|
let tempModel: DynamicFormControlModel;
|
|
|
|
if (this.isArrayGroup(model as DynamicFormControlModel)) {
|
|
return model.index.toString();
|
|
} else if (this.isModelInCustomGroup(model as DynamicFormControlModel)) {
|
|
tempModel = (model as any).parent;
|
|
} else {
|
|
tempModel = (model as any);
|
|
}
|
|
|
|
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): string[] => {
|
|
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 Object.keys(result);
|
|
}
|
|
|
|
}
|