2019-07-19 13:52:08 +02:00
|
|
|
import {
|
|
|
|
isString,
|
2019-08-04 23:21:16 +02:00
|
|
|
isUndefined,
|
|
|
|
find,
|
|
|
|
keys,
|
|
|
|
uniq,
|
|
|
|
some,
|
2019-08-07 10:03:49 +02:00
|
|
|
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) => {
|
2019-08-07 10:03:49 +02:00
|
|
|
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],
|
|
|
|
{});
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-08-19 09:51:01 +02:00
|
|
|
export const getComponentInfo = (allComponents, comp, stack=[], subComponentProps=null) => {
|
|
|
|
const component = isString(comp)
|
|
|
|
? find(c => c.name === comp)(allComponents)
|
|
|
|
: comp;
|
|
|
|
const cname = isString(comp) ? comp : comp.name;
|
2019-08-14 23:11:59 +02:00
|
|
|
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,
|
2019-08-19 22:18:23 +02:00
|
|
|
component: stack.length > 0 ? stack[0] : component,
|
|
|
|
rootComponent: component
|
2019-08-14 23:11:59 +02:00
|
|
|
});
|
|
|
|
}
|
|
|
|
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
|
|
|
|
*/
|