client/app/components/dynamic-form/dynamicFormHelper.js (128 lines of code) (raw):
import React from "react";
import { each, includes, isUndefined, isEmpty, isNil, map, get, some } from "lodash";
function orderedInputs(properties, order, targetOptions) {
const inputs = new Array(order.length);
Object.keys(properties).forEach(key => {
const position = order.indexOf(key);
const input = {
name: key,
title: properties[key].title,
type: properties[key].type,
placeholder: isNil(properties[key].default) ? null : properties[key].default.toString(),
required: properties[key].required,
extra: properties[key].extra,
initialValue: targetOptions[key],
};
if (input.type === "select") {
input.placeholder = "Select an option";
input.options = properties[key].options;
}
if (position > -1) {
inputs[position] = input;
} else {
inputs.push(input);
}
});
return inputs;
}
function normalizeSchema(configurationSchema) {
each(configurationSchema.properties, (prop, name) => {
if (name === "password" || name === "passwd") {
prop.type = "password";
}
if (name.endsWith("File")) {
prop.type = "file";
}
if (prop.type === "boolean") {
prop.type = "checkbox";
}
if (prop.type === "string") {
prop.type = "text";
}
if (!isEmpty(prop.enum)) {
prop.type = "select";
prop.options = map(prop.enum, value => ({ value, name: value }));
}
if (!isEmpty(prop.extendedEnum)) {
prop.type = "select";
prop.options = prop.extendedEnum;
}
prop.required = includes(configurationSchema.required, name);
prop.extra = includes(configurationSchema.extra_options, name);
});
configurationSchema.order = configurationSchema.order || [];
}
function setDefaultValueToFields(configurationSchema, options = {}) {
const properties = configurationSchema.properties;
Object.keys(properties).forEach(key => {
const property = properties[key];
// set default value for checkboxes
if (!isUndefined(property.default) && property.type === "checkbox") {
options[key] = property.default;
}
// set default or first value when value has predefined options
if (property.type === "select") {
const optionValues = map(property.options, option => option.value);
options[key] = includes(optionValues, property.default) ? property.default : optionValues[0];
}
});
}
function getFields(type = {}, target = { options: {} }) {
const configurationSchema = type.configuration_schema;
normalizeSchema(configurationSchema);
const hasTargetObject = Object.keys(target.options).length > 0;
if (!hasTargetObject) {
setDefaultValueToFields(configurationSchema, target.options);
}
const isNewTarget = !target.id;
const inputs = [
{
name: "name",
title: "Name",
type: "text",
required: true,
initialValue: target.name,
contentAfter: React.createElement("hr"),
placeholder: `My ${type.name}`,
autoFocus: isNewTarget,
},
{
name: "description",
title: "Description",
type: "text",
required: false,
initialValue: target.description,
},
...orderedInputs(configurationSchema.properties, configurationSchema.order, target.options),
];
return inputs;
}
function updateTargetWithValues(target, values) {
target.name = values.name;
target.description = values.description;
Object.keys(values).forEach(key => {
if (key !== "name") {
target.options[key] = values[key];
}
});
}
function getBase64(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => resolve(reader.result.substr(reader.result.indexOf(",") + 1));
reader.onerror = error => reject(error);
});
}
function hasFilledExtraField(type, target) {
const extraOptions = get(type, "configuration_schema.extra_options", []);
return some(extraOptions, optionName => {
const defaultOptionValue = get(type, ["configuration_schema", "properties", optionName, "default"]);
const targetOptionValue = get(target, ["options", optionName]);
return !isNil(targetOptionValue) && targetOptionValue !== defaultOptionValue;
});
}
export default {
getFields,
updateTargetWithValues,
getBase64,
hasFilledExtraField,
};