budibase/packages/builder/src/userInterface/pagesParsing/createProps.js

170 lines
4.3 KiB
JavaScript
Raw Normal View History

2019-07-19 13:52:08 +02:00
import {
isString,
2019-08-04 23:21:16 +02:00
isUndefined,
find,
keys,
uniq,
some,
filter,
2019-08-14 23:11:59 +02:00
reduce,
cloneDeep,
includes
2019-07-19 13:52:08 +02:00
} from "lodash/fp";
2019-08-14 23:11:59 +02:00
import { types, expandPropsDefinition } from "./types";
2019-07-19 13:52:08 +02:00
import { assign } from "lodash";
2019-08-04 23:21:16 +02:00
import { pipe } from "../../common/core";
import { isRootComponent } from "./searchComponents";
export const createPropDefinitionForDerived = (allComponents, componentName) => {
2019-08-14 23:11:59 +02:00
2019-08-04 23:21:16 +02:00
2019-08-14 23:11:59 +02:00
const {propDef, derivedProps} = getComponentInfo(allComponents, componentName);
2019-08-04 23:21:16 +02:00
const hasDerivedProp = k => pipe(derivedProps, [
keys,
uniq,
some(key => key === k)
]);
return pipe(propDef, [
keys,
filter(k => !hasDerivedProp(k)),
reduce((obj, k) => {
obj[k] = propDef[k];
return obj;
2019-08-14 23:11:59 +02:00
}, {}),
expandPropsDefinition
2019-08-04 23:21:16 +02:00
])
}
2019-07-19 13:52:08 +02:00
2019-08-14 23:11:59 +02:00
export const traverseForProps = getComponentInfo;
2019-08-16 16:48:45 +02:00
export const getInstanceProps = (componentInfo, props) => {
2019-08-14 23:11:59 +02:00
const finalProps = cloneDeep(componentInfo.fullProps);
for(let p in props) {
finalProps[p] = props[p];
}
return finalProps;
}
export const getNewComponentInfo = (allComponents, inherits) => {
const parentcomponent = find(c => c.name === inherits)(allComponents);
const component = {
name:"",
description:"",
inherits,
2019-08-15 09:49:15 +02:00
props:{},
2019-08-14 23:11:59 +02:00
tags:parentcomponent.tags
};
return getComponentInfo(
allComponents,
inherits,
[component],
{});
}
export const getComponentInfo = (allComponents, cname, stack=[], subComponentProps=null) => {
const component = find(c => c.name === cname)(allComponents);
if(isRootComponent(component)) {
subComponentProps = subComponentProps||{};
const p = createProps(cname, component.props, subComponentProps);
const inheritedProps = [];
if(stack.length > 0) {
const targetComponent = stack[0];
for(let prop in subComponentProps) {
const hasProp = pipe(targetComponent.props, [
keys,
includes(prop)]);
if(!hasProp)
inheritedProps.push(prop);
}
}
const unsetProps = pipe(p.props, [
keys,
2019-08-15 09:49:15 +02:00
filter(k => !includes(k)(keys(subComponentProps)))
2019-08-14 23:11:59 +02:00
]);
return ({
2019-08-16 16:48:45 +02:00
propsDefinition:expandPropsDefinition(component.props),
2019-08-14 23:11:59 +02:00
inheritedProps,
rootDefaultProps: p.props,
unsetProps,
fullProps: p.props,
errors: p.errors,
component: stack.length > 0 ? stack[0] : component
});
}
return getComponentInfo(
allComponents,
component.inherits,
[...stack, component],
{...component.props, ...subComponentProps});
}
2019-07-20 22:41:06 +02:00
export const createProps = (componentName, propsDefinition, derivedFromProps) => {
const error = (propName, error) =>
errors.push({propName, error});
const props = {
_component: componentName
};
2019-07-19 13:52:08 +02:00
const errors = [];
2019-07-20 22:41:06 +02:00
if(!componentName)
error("_component", "Component name not supplied");
2019-07-19 13:52:08 +02:00
for(let propDef in propsDefinition) {
const parsedPropDef = parsePropDef(propsDefinition[propDef]);
if(parsedPropDef.error)
2019-07-20 22:41:06 +02:00
error(propDef, parsedPropDef.error);
2019-07-19 13:52:08 +02:00
else
props[propDef] = parsedPropDef;
}
if(derivedFromProps) {
2019-08-14 23:11:59 +02:00
assign(props, derivedFromProps);
2019-07-19 13:52:08 +02:00
}
return ({
props, errors
});
}
const parsePropDef = propDef => {
2019-07-19 19:03:58 +02:00
const error = message => ({error:message, propDef});
2019-07-19 13:52:08 +02:00
if(isString(propDef)) {
if(!types[propDef])
return error(`Do not recognise type ${propDef}`);
return types[propDef].default();
}
if(!propDef.type)
return error("Property Definition must declare a type");
const type = types[propDef.type];
if(!type)
return error(`Do not recognise type ${propDef.type}`);
if(isUndefined(propDef.default))
return type.default(propDef);
if(!type.isOfType(propDef.default))
return error(`${propDef.default} is not of type ${type}`);
return propDef.default;
}
2019-07-19 19:03:58 +02:00
/*
Allowed propDefOptions
- type: string, bool, number, array
- default: default value, when undefined
- required: field is required
*/