import React from 'react'; import { Fields, ConditionRule, ConditionGroupValue, Funcs, ExpressionFunc, Func, Field, FieldSimple, ExpressionField, OperatorType, ExpressionComplex } from './types'; import {ThemeProps, themeable} from '../../theme'; import {Icon} from '../icons'; import {autobind, findTree, noop} from '../../utils/helper'; import Expression from './Expression'; import {Config, OperationMap} from './config'; import PopOverContainer from '../PopOverContainer'; import ListRadios from '../ListRadios'; import ResultBox from '../ResultBox'; const option2value = (item: any) => item.value; export interface ConditionItemProps extends ThemeProps { config: Config; fields: Fields; funcs?: Funcs; index?: number; value: ConditionRule; data?: any; disabled?: boolean; onChange: (value: ConditionRule, index?: number) => void; fieldClassName?: string; } export class ConditionItem extends React.Component { @autobind handleLeftFieldSelect(field: any) { const value = {...this.props.value}; const onChange = this.props.onChange; value.left = field; onChange(value, this.props.index); } @autobind handleLeftInputTypeChange(type: 'func' | 'field') { const value = {...this.props.value}; const onChange = this.props.onChange; if (type === 'func') { value.left = {type: 'func'}; } else { value.left = ''; } onChange(value, this.props.index); } @autobind handleLeftChange(leftValue: any) { const value = { ...this.props.value, left: leftValue, op: undefined, right: undefined }; const onChange = this.props.onChange; onChange(value, this.props.index); } @autobind handleOperatorChange(op: OperatorType) { const value = {...this.props.value, op: op, right: undefined}; this.props.onChange(value, this.props.index); } @autobind handleRightChange(rightValue: any) { const value = {...this.props.value, right: rightValue}; const onChange = this.props.onChange; onChange(value, this.props.index); } handleRightSubChange(index: number, rightValue: any) { const origin = Array.isArray(this.props.value?.right) ? this.props.value.right.concat() : []; origin[index] = rightValue; const value = {...this.props.value, right: origin}; const onChange = this.props.onChange; onChange(value, this.props.index); } renderLeft() { const {value, fields, funcs, config, disabled, fieldClassName} = this.props; return ( type === 'field' || type === 'func' ) as any } /> ); } renderOperator() { const {funcs, config, fields, value, classnames: cx, disabled} = this.props; const left = value?.left; let operators: Array = []; if ((left as ExpressionFunc)?.type === 'func') { const func: Func = findTree( funcs!, (i: Func) => i.type === (left as ExpressionFunc).func ) as Func; if (func) { operators = config.types[func.returnType]?.operators; } } else if ((left as ExpressionField)?.type === 'field') { const field: FieldSimple = findTree( fields, (i: FieldSimple) => i.name === (left as ExpressionField).field ) as FieldSimple; if (field) { operators = field.operators || config.types[field.type]?.operators; } } if (Array.isArray(operators) && operators.length) { return ( ( ({ label: OperationMap[operator as keyof typeof OperationMap], value: operator }))} value={value.op} showRadio={false} /> )} > {({onClick, isOpened, ref}) => (
)}
); } return null; } renderRight() { const {value, funcs, fields} = this.props; if (!value?.op) { return null; } const left = value?.left; let leftType = ''; if ((left as ExpressionFunc)?.type === 'func') { const func: Func = findTree( funcs!, (i: Func) => i.type === (left as ExpressionFunc).func ) as Func; if (func) { leftType = func.returnType; } } else if ((left as ExpressionField)?.type === 'field') { const field: FieldSimple = findTree( fields, (i: FieldSimple) => i.name === (left as ExpressionField).field ) as FieldSimple; if (field) { leftType = field.type; } } if (leftType) { return this.renderRightWidgets(leftType, value.op!); } return null; } renderRightWidgets(type: string, op: OperatorType) { const { funcs, value, data, fields, config, classnames: cx, disabled } = this.props; let field = { ...config.types[type], type } as FieldSimple; if ((value?.left as ExpressionField)?.type === 'field') { const leftField: FieldSimple = findTree( fields, (i: FieldSimple) => i.name === (value?.left as ExpressionField).field ) as FieldSimple; if (leftField) { field = { ...field, ...leftField }; } } if (op === 'is_empty' || op === 'is_not_empty') { return null; } else if (op === 'between' || op === 'not_between') { return ( <> )?.[0]} data={data} onChange={this.handleRightSubChange.bind(this, 0)} fields={fields} allowedTypes={ field?.valueTypes || config.valueTypes || ['value', 'field', 'func', 'formula'] } disabled={disabled} /> ~ )?.[1]} data={data} onChange={this.handleRightSubChange.bind(this, 1)} fields={fields} allowedTypes={ field?.valueTypes || config.valueTypes || ['value', 'field', 'func', 'formula'] } disabled={disabled} /> ); } return ( ); } render() { const {classnames: cx} = this.props; return (
{this.renderLeft()} {this.renderOperator()} {this.renderRight()}
); } } export default themeable(ConditionItem);