budibase/packages/core/src/templateApi/fields.js

95 lines
2.8 KiB
JavaScript
Raw Normal View History

import { some, map, filter, keys, includes, countBy, flatten } from "lodash/fp"
2019-07-15 08:12:52 +02:00
import {
isSomething,
$,
2019-07-15 08:12:52 +02:00
isNonEmptyString,
isNothingOrEmpty,
isNothing,
} from "../common"
import { all, getDefaultOptions } from "../types"
import { applyRuleSet, makerule } from "../common/validationCommon"
import { BadRequestError } from "../common/errors"
2019-07-15 08:12:52 +02:00
export const fieldErrors = {
AddFieldValidationFailed: "Add field validation: ",
}
2019-07-15 08:12:52 +02:00
export const allowedTypes = () => keys(all)
2019-07-15 08:12:52 +02:00
export const getNewField = type => ({
name: "", // how field is referenced internally
2019-07-15 08:12:52 +02:00
type,
typeOptions: getDefaultOptions(type),
label: "", // how field is displayed
getInitialValue: "default", // function that gets value when initially created
getUndefinedValue: "default", // function that gets value when field undefined on record
})
2019-07-15 08:12:52 +02:00
const fieldRules = allFields => [
makerule("name", "field name is not set", f => isNonEmptyString(f.name)),
makerule("type", "field type is not set", f => isNonEmptyString(f.type)),
makerule("label", "field label is not set", f => isNonEmptyString(f.label)),
makerule("getInitialValue", "getInitialValue function is not set", f =>
isNonEmptyString(f.getInitialValue)
),
makerule("getUndefinedValue", "getUndefinedValue function is not set", f =>
isNonEmptyString(f.getUndefinedValue)
),
makerule(
"name",
"field name is duplicated",
f => isNothingOrEmpty(f.name) || countBy("name")(allFields)[f.name] === 1
),
makerule(
"type",
"type is unknown",
f => isNothingOrEmpty(f.type) || some(t => f.type === t)(allowedTypes())
),
]
2019-07-15 08:12:52 +02:00
const typeOptionsRules = field => {
const type = all[field.type]
if (isNothing(type)) return []
2019-07-15 08:12:52 +02:00
const def = optName => type.optionDefinitions[optName]
2019-07-15 08:12:52 +02:00
return $(field.typeOptions, [
keys,
filter(o => isSomething(def(o)) && isSomething(def(o).isValid)),
map(o =>
makerule(`typeOptions.${o}`, `${def(o).requirementDescription}`, field =>
def(o).isValid(field.typeOptions[o])
)
),
])
}
2019-07-15 08:12:52 +02:00
export const validateField = allFields => field => {
const everySingleField = includes(field)(allFields)
? allFields
: [...allFields, field]
return applyRuleSet([
...fieldRules(everySingleField),
...typeOptionsRules(field),
])(field)
}
2019-07-15 08:12:52 +02:00
export const validateAllFields = recordNode =>
$(recordNode.fields, [map(validateField(recordNode.fields)), flatten])
2019-07-15 08:12:52 +02:00
export const addField = (recordTemplate, field) => {
if (isNothingOrEmpty(field.label)) {
field.label = field.name
2019-07-15 08:12:52 +02:00
}
const validationMessages = validateField([...recordTemplate.fields, field])(
field
)
2019-07-15 08:12:52 +02:00
if (validationMessages.length > 0) {
const errors = map(m => m.error)(validationMessages)
throw new BadRequestError(
`${fieldErrors.AddFieldValidationFailed} ${errors.join(", ")}`
)
2019-07-15 08:12:52 +02:00
}
recordTemplate.fields.push(field)
}