2019-07-19 13:52:08 +02:00
|
|
|
import {
|
2020-01-18 00:06:42 +01:00
|
|
|
isString, isUndefined, find, keys, uniq,
|
|
|
|
some, filter, reduce, cloneDeep, includes,last
|
2019-07-19 13:52:08 +02:00
|
|
|
} from "lodash/fp";
|
2020-01-18 00:06:42 +01:00
|
|
|
import { types, expandComponentDefinition } 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";
|
2020-01-18 00:06:42 +01:00
|
|
|
import { ensureShardNameIsInShardMap } from "../../../../core/src/indexing/sharding";
|
2019-08-14 23:11:59 +02:00
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2020-01-18 00:06:42 +01:00
|
|
|
export const getNewComponentInfo = (components, rootComponent, name) => {
|
2019-08-14 23:11:59 +02:00
|
|
|
const component = {
|
2020-01-18 00:06:42 +01:00
|
|
|
name: name || "",
|
|
|
|
description:"",
|
|
|
|
props:{
|
|
|
|
_component: rootComponent
|
|
|
|
}
|
2019-08-14 23:11:59 +02:00
|
|
|
};
|
|
|
|
return getComponentInfo(
|
2020-01-18 00:06:42 +01:00
|
|
|
components,
|
|
|
|
component);
|
2019-08-14 23:11:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-01-18 00:06:42 +01:00
|
|
|
export const getScreenInfo = (components, screen) => {
|
2019-08-14 23:11:59 +02:00
|
|
|
return getComponentInfo(
|
2020-01-18 00:06:42 +01:00
|
|
|
components,
|
|
|
|
screen);
|
2019-08-14 23:11:59 +02:00
|
|
|
}
|
|
|
|
|
2020-01-18 00:06:42 +01:00
|
|
|
export const getComponentInfo = (components, comp) => {
|
|
|
|
const targetComponent = isString(comp)
|
|
|
|
? find(c => c.name === comp)(components)
|
|
|
|
: comp;
|
|
|
|
let component;
|
|
|
|
let subComponent;
|
|
|
|
if(isRootComponent(targetComponent)) {
|
|
|
|
component = targetComponent;
|
|
|
|
} else {
|
|
|
|
subComponent = targetComponent;
|
|
|
|
component = find(c => c.name === subComponent.props._component)(
|
|
|
|
components);
|
|
|
|
}
|
|
|
|
|
|
|
|
const subComponentProps = subComponent ? subComponent.props : {};
|
|
|
|
const p = createProps(component, subComponentProps);
|
|
|
|
const rootProps = createProps(component);
|
|
|
|
|
|
|
|
const unsetProps = pipe(p.props, [
|
|
|
|
keys,
|
|
|
|
filter(k => !includes(k)(keys(subComponentProps)) && k !== "_component")
|
|
|
|
]);
|
|
|
|
|
|
|
|
const fullProps = cloneDeep(p.props);
|
|
|
|
fullProps._component = targetComponent.name;
|
|
|
|
|
|
|
|
return ({
|
|
|
|
propsDefinition:expandComponentDefinition(component),
|
|
|
|
rootDefaultProps: rootProps.props,
|
|
|
|
unsetProps,
|
|
|
|
fullProps: fullProps,
|
|
|
|
errors: p.errors,
|
|
|
|
component: targetComponent,
|
|
|
|
rootComponent: component
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
export const createProps = (componentDefinition, derivedFromProps) => {
|
2019-07-20 22:41:06 +02:00
|
|
|
|
|
|
|
const error = (propName, error) =>
|
|
|
|
errors.push({propName, error});
|
|
|
|
|
|
|
|
const props = {
|
2020-01-18 00:06:42 +01:00
|
|
|
_component: componentDefinition.name
|
2019-07-20 22:41:06 +02:00
|
|
|
};
|
2019-07-19 13:52:08 +02:00
|
|
|
|
|
|
|
const errors = [];
|
|
|
|
|
2020-01-18 00:06:42 +01:00
|
|
|
if(!componentDefinition.name)
|
2019-07-20 22:41:06 +02:00
|
|
|
error("_component", "Component name not supplied");
|
|
|
|
|
2020-01-18 00:06:42 +01:00
|
|
|
const propsDef = componentDefinition.props;
|
|
|
|
for(let propDef in propsDef) {
|
|
|
|
const parsedPropDef = parsePropDef(propsDef[propDef]);
|
2019-07-19 13:52:08 +02:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2020-01-18 00:06:42 +01:00
|
|
|
if(componentDefinition.children !== false
|
|
|
|
&& isUndefined(props._children)) {
|
|
|
|
props._children = [];
|
|
|
|
}
|
|
|
|
|
2019-07-19 13:52:08 +02:00
|
|
|
return ({
|
|
|
|
props, errors
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-09-03 11:42:19 +02:00
|
|
|
|
2019-07-19 13:52:08 +02:00
|
|
|
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-09-03 11:42:19 +02:00
|
|
|
export const arrayElementComponentName = (parentComponentName, arrayPropName) =>
|
|
|
|
`${parentComponentName}:${arrayPropName}`;
|
|
|
|
|
2019-07-19 19:03:58 +02:00
|
|
|
/*
|
|
|
|
Allowed propDefOptions
|
|
|
|
- type: string, bool, number, array
|
|
|
|
- default: default value, when undefined
|
|
|
|
- required: field is required
|
|
|
|
*/
|