2019-07-19 13:52:08 +02:00
|
|
|
import {
|
2020-02-03 10:24:25 +01:00
|
|
|
isString,
|
|
|
|
isUndefined,
|
|
|
|
find,
|
|
|
|
keys,
|
|
|
|
uniq,
|
|
|
|
some,
|
|
|
|
filter,
|
|
|
|
reduce,
|
|
|
|
cloneDeep,
|
|
|
|
includes,
|
|
|
|
last,
|
|
|
|
} from "lodash/fp"
|
|
|
|
import { types, expandComponentDefinition } from "./types"
|
|
|
|
import { assign } from "lodash"
|
|
|
|
import { pipe } from "../../common/core"
|
|
|
|
import { isRootComponent } from "./searchComponents"
|
|
|
|
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) => {
|
2020-02-03 10:24:25 +01:00
|
|
|
const finalProps = cloneDeep(componentInfo.fullProps)
|
2019-08-14 23:11:59 +02:00
|
|
|
|
2020-02-03 10:24:25 +01:00
|
|
|
for (let p in props) {
|
|
|
|
finalProps[p] = props[p]
|
|
|
|
}
|
2019-08-14 23:11:59 +02:00
|
|
|
|
2020-02-03 10:24:25 +01:00
|
|
|
return finalProps
|
2019-08-14 23:11:59 +02:00
|
|
|
}
|
|
|
|
|
2020-01-18 00:06:42 +01:00
|
|
|
export const getNewComponentInfo = (components, rootComponent, name) => {
|
2020-02-03 10:24:25 +01:00
|
|
|
const component = {
|
|
|
|
name: name || "",
|
|
|
|
description: "",
|
|
|
|
props: {
|
|
|
|
_component: rootComponent,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
return getComponentInfo(components, component)
|
2019-08-14 23:11:59 +02:00
|
|
|
}
|
|
|
|
|
2020-01-18 00:06:42 +01:00
|
|
|
export const getScreenInfo = (components, screen) => {
|
2020-02-03 10:24:25 +01:00
|
|
|
return getComponentInfo(components, screen)
|
2019-08-14 23:11:59 +02:00
|
|
|
}
|
|
|
|
|
2020-01-18 00:06:42 +01:00
|
|
|
export const getComponentInfo = (components, comp) => {
|
2020-02-03 10:24:25 +01:00
|
|
|
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
|
|
|
|
? subComponent.props._component
|
|
|
|
: subComponent._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,
|
|
|
|
}
|
2020-01-18 00:06:42 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
export const createProps = (componentDefinition, derivedFromProps) => {
|
2020-02-03 10:24:25 +01:00
|
|
|
const error = (propName, error) => errors.push({ propName, error })
|
2019-07-20 22:41:06 +02:00
|
|
|
|
2020-02-03 10:24:25 +01:00
|
|
|
const props = {
|
|
|
|
_component: componentDefinition.name,
|
|
|
|
}
|
2019-07-19 13:52:08 +02:00
|
|
|
|
2020-02-03 10:24:25 +01:00
|
|
|
const errors = []
|
2019-07-19 13:52:08 +02:00
|
|
|
|
2020-02-03 10:24:25 +01:00
|
|
|
if (!componentDefinition.name)
|
|
|
|
error("_component", "Component name not supplied")
|
2019-07-20 22:41:06 +02:00
|
|
|
|
2020-02-03 10:24:25 +01:00
|
|
|
const propsDef = componentDefinition.props
|
|
|
|
for (let propDef in propsDef) {
|
|
|
|
const parsedPropDef = parsePropDef(propsDef[propDef])
|
|
|
|
if (parsedPropDef.error) error(propDef, parsedPropDef.error)
|
|
|
|
else props[propDef] = parsedPropDef
|
|
|
|
}
|
2019-07-19 13:52:08 +02:00
|
|
|
|
2020-02-03 10:24:25 +01:00
|
|
|
if (derivedFromProps) {
|
|
|
|
assign(props, derivedFromProps)
|
|
|
|
}
|
2019-07-19 13:52:08 +02:00
|
|
|
|
2020-02-03 10:24:25 +01:00
|
|
|
if (componentDefinition.children !== false && isUndefined(props._children)) {
|
|
|
|
props._children = []
|
|
|
|
}
|
2020-01-18 00:06:42 +01:00
|
|
|
|
2020-02-03 10:24:25 +01:00
|
|
|
return {
|
|
|
|
props,
|
|
|
|
errors,
|
|
|
|
}
|
2019-07-19 13:52:08 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
const parsePropDef = propDef => {
|
2020-02-03 10:24:25 +01:00
|
|
|
const error = message => ({ error: message, propDef })
|
2019-07-19 13:52:08 +02:00
|
|
|
|
2020-02-03 10:24:25 +01:00
|
|
|
if (isString(propDef)) {
|
|
|
|
if (!types[propDef]) return error(`Do not recognise type ${propDef}`)
|
2020-01-24 12:32:13 +01:00
|
|
|
|
2020-02-03 10:24:25 +01:00
|
|
|
return types[propDef].default()
|
|
|
|
}
|
2019-07-19 13:52:08 +02:00
|
|
|
|
2020-02-03 10:24:25 +01:00
|
|
|
if (!propDef.type) return error("Property Definition must declare a type")
|
2020-01-24 12:32:13 +01:00
|
|
|
|
2020-02-03 10:24:25 +01:00
|
|
|
const type = types[propDef.type]
|
|
|
|
if (!type) return error(`Do not recognise type ${propDef.type}`)
|
2019-07-19 13:52:08 +02:00
|
|
|
|
2020-02-03 10:24:25 +01:00
|
|
|
if (isUndefined(propDef.default)) return type.default(propDef)
|
2019-07-19 13:52:08 +02:00
|
|
|
|
2020-02-03 10:24:25 +01:00
|
|
|
if (!type.isOfType(propDef.default))
|
|
|
|
return error(`${propDef.default} is not of type ${type}`)
|
2019-07-19 13:52:08 +02:00
|
|
|
|
2020-02-03 10:24:25 +01:00
|
|
|
return propDef.default
|
2019-07-19 13:52:08 +02:00
|
|
|
}
|
|
|
|
|
2020-01-24 12:32:13 +01:00
|
|
|
export const arrayElementComponentName = (parentComponentName, arrayPropName) =>
|
2020-02-03 10:24:25 +01:00
|
|
|
`${parentComponentName}:${arrayPropName}`
|
2019-09-03 11:42:19 +02:00
|
|
|
|
2019-07-19 19:03:58 +02:00
|
|
|
/*
|
|
|
|
Allowed propDefOptions
|
|
|
|
- type: string, bool, number, array
|
|
|
|
- default: default value, when undefined
|
2020-01-24 12:32:13 +01:00
|
|
|
- required: field is required
|
|
|
|
*/
|