import React from 'react' ; import assign from 'lodash/assign' ; import isFunction from 'lodash/isFunction' ; import isString from 'lodash/isString' ; import isArray from 'lodash/isArray' ; import toLower from 'lodash/toLower' ; import { Space } from 'antd' ; import { LazyPluginCtx , LazyPluginCtxGetter , PluginCtx } from '../types/ctx' ; import { RenderPlugin , ActionPlugin , FieldPlugin , PluginType , ValidatorPlugin , ConvertParamsPlugin , ConverterPlugin , DependencyPlugin , } from '../types/plugin' ; import transformConfig , { SkipOptions } from '../_util/transformConfig' ; import sula from '../core' ; import { toArray } from '../_util/common' ; import Rope from '.' ; import RopeContainer from './RopeContainer' ; export const getLazyCtx = ( ctx ) => { if ( ! ctx ) { return null ; } return Object . keys ( ctx ) . reduce ( ( memo , key ) => { if ( key === 'ctxGetter' ) { const ctxGetter = ctx [ key ] as LazyPluginCtxGetter ; return assign ( isFunction ( ctxGetter ) ? ctxGetter ( ) : Object . keys ( ctxGetter ) . reduce ( ( ctxMemo , ctxKey ) => { const curCtxGetter = ctxGetter [ ctxKey ] as LazyPluginCtxGetter ; assign ( ctxMemo , isFunction ( curCtxGetter ) ? curCtxGetter ( ) : { } ) ; return ctxMemo ; } , { } ) , memo ) ; } memo [ key ] = ctx [ key ] ; return memo ; } , { } as PluginCtx ) ; } ; /**
 * 1. lazyCtx -> ctx
 * 2. 方法 config.type 执行
 * 3. 配置属性转换
 * 4. 如果是render插件则做funcProps与props的合并
 * 5. 触发插件
 */ export const triggerPlugin = ( name , ctx , config , skipOptions ? , isRender ? ) => { const normalizedConfig = normalizeConfig ( config ) ; if ( isFunction ( normalizedConfig . type ) ) { return normalizedConfig . type ( ctx ) ; } let transedConfig = transformConfig ( normalizedConfig , ctx , skipOptions ) ; if ( isRender ) { const funcProps = transedConfig . funcProps ; if ( funcProps ) { transedConfig . props = assign ( { } , transedConfig . props , funcProps ) ; } } return sula [ name ] ( transedConfig . type , ctx , transedConfig ) ; } ; /**
 * 表单插件
 * - skipFuncObjKeys
 *   - props
 * - skipSelector
 */ export const triggerFieldPlugin = ( lazyCtx , config , valuePropName ? ) => { const skipSelector = ( curKey , parentKey ) => parentKey === 'props' && curKey === valuePropName ; return triggerPlugin ( 'field' , getLazyCtx ( lazyCtx ) , config , { skipSelector , skipFuncObjKeys : [ 'props' ] , } , true ) ; } ; export const triggerRenderPlugin = ( lazyCtx , config ) : React . ReactFragment | null => { const ctx = getLazyCtx ( lazyCtx ) as PluginCtx ; const arrayConf = toArray ( config ) . filter ( ( iterConf ) => { const visible = transformConfig ( iterConf . visible , ctx ) ; return visible != false ; } ) ; if ( arrayConf . length === 0 ) { return null ; } else if ( arrayConf . length === 1 ) { return triggerSingleRenderPlugin ( lazyCtx , arrayConf [ 0 ] ) ; } return ( < Space > { arrayConf . map ( ( conf , index ) => { const actionNode = triggerSingleRenderPlugin ( lazyCtx , conf ) ; return React . cloneElement ( actionNode , { key : index } ) ; } ) } < /Space>); } ; /**
 * 针对单个，渲染插件可携带action
 * scope: private
 */ export const triggerSingleRenderPlugin = ( lazyCtx , config ) => { const skipOptions = { skipFuncObjKeys : [ 'props' ] , skipKeys : [ 'action' ] , } ; const normalizedRenderConfig = normalizeConfig ( config ) as RenderPlugin ; const isTwiceTrigger = normalizedRenderConfig . type === 'button' || normalizedRenderConfig . type === 'link' || normalizedRenderConfig . type === 'icon' ; const renderNode = triggerPlugin ( 'render' , isTwiceTrigger ? lazyCtx : getLazyCtx ( lazyCtx ) , normalizedRenderConfig as RenderPlugin , skipOptions , true ) ; const actionsConfig = normalizedRenderConfig . action ; if ( ! actionsConfig || isTwiceTrigger ) { return renderNode ; } const rope = new Rope ( { trigger : ( ctx , config ) => { return triggerActionPlugin ( ctx , config ) ; } , } ) ; const arrayActionsConfig = [ ] as ActionPlugin [ ] ; toArrayActions ( actionsConfig , arrayActionsConfig ) ; const trigger = arrayActionsConfig . reduce ( ( memo , actionConfig ) => { const normalizedActionConfig = normalizeConfig ( actionConfig , 'request' ) ; memo . use ( normalizedActionConfig ) ; return memo ; } , rope ) . proxy ( ) ; const { disabled , confirm , tooltip } = normalizedRenderConfig ; return ( < RopeContainer disabled = { disabled } confirm = { confirm } tooltip = { tooltip } trigger = { ( ) => { const ctx = getLazyCtx ( lazyCtx ) ; trigger ( ctx ) ; } } > { renderNode } < /RopeContainer>); } ; /**
 * 行为插件
 */ const formPluginsName = [ 'submit' , 'back' , 'actionsRender' , 'fields' , 'container' , 'remoteValues' ] ; const actionSkipKeysMap = { request : [ 'convertParams' , 'converter' ] , modalform : formPluginsName , drawerform : formPluginsName , } ; export const triggerActionPlugin = ( lazyCtx , config ) => { const normalizedConfig = normalizeConfig ( config , 'request' ) as ActionPlugin ; let finalSkipOptions ; if ( isString ( normalizedConfig . type ) ) { const pluginName = toLower ( normalizedConfig . type ) ; finalSkipOptions = { skipKeys : actionSkipKeysMap [ pluginName ] , } ; } return triggerPlugin ( 'action' , getLazyCtx ( lazyCtx ) , normalizedConfig , finalSkipOptions ) ; } ; /**
 * 归一化actions
 */ export function toArrayActions ( actions , actionsChain ) { const arrayAction = toArray ( actions ) ; arrayAction . forEach ( ( action ) => { getNextAction ( action , actionsChain ) ; } ) ; } function getNextAction ( action , actionsChain ) { if ( isArray ( action ) ) { toArrayActions ( action , actionsChain ) ; } else if ( action . finish ) { const { finish : nextAction , ... restAction } = action ; actionsChain . push ( restAction ) ; toArrayActions ( nextAction , actionsChain ) ; } else { actionsChain . push ( action ) ; } } /**
 * 归一化配置
 */ export function normalizeConfig ( config , type ? ) { if ( isString ( config ) || isFunction ( config ) ) { return { type : config , } ; } else if ( type ) { return assign ( { type } , config ) ; } return config ; }