function OutputFormula()

in client/src/components/special/cellprofiler/model/parameters/define-results/renderer/output-formula.js [212:365]


function OutputFormula (props) {
  const {
    formula,
    pipeline,
    onChange = () => {},
    onRemove = () => {}
  } = props || {};
  if (!formula || !pipeline) {
    return null;
  }
  const {
    name,
    value,
    variables = {}
  } = formula;
  const onChangeFormulaName = (e) => {
    onChange({
      ...formula,
      name: e.target.value
    });
  };
  const onChangeFormula = (e) => {
    const {
      expression,
      variables: parsedVariables = [],
      error: parsingError
    } = parseFormula(e.target.value);
    const newVariables = parsingError
      ? variables
      : parsedVariables
        .map(variable => ({[variable]: variables[variable]}))
        .reduce((r, c) => ({...r, ...c}), {});
    onChange({
      ...formula,
      expression,
      variables: newVariables,
      value: e.target.value,
      error: parsingError
    });
  };
  const {error} = parseFormula(value);
  const sortedVariables = Object.keys(variables || {}).sort();
  const properties = getVariableOptions(pipeline);
  const getProperty = value => properties.find(o => getVariableOptionValue(o) === value);
  const onChangeFormulaVariable = (variable) => (property) => {
    onChange({
      ...formula,
      variables: {
        ...variables,
        [variable]: getProperty(property)
      }
    });
  };
  return (
    <div>
      <div
        className={styles.row}
      >
        <span className={styles.title}>
          Formula:
        </span>
        <Input
          className={
            classNames(
              styles.value,
              {'cp-error': !!error}
            )
          }
          value={value}
          onChange={onChangeFormula}
        />
        <Button
          type="danger"
          size="small"
          style={{marginLeft: 5}}
          onClick={onRemove}
        >
          <Icon type="delete" />
        </Button>
      </div>
      {
        sortedVariables.map((variable) => (
          <div
            key={variable}
            className={styles.row}
            style={{paddingRight: 33}}
          >
            <span className={styles.title}>
              Variable <b>{variable}</b>:
            </span>
            <Select
              showSearch
              value={getVariableOptionValue(variables[variable])}
              className={styles.value}
              onChange={onChangeFormulaVariable(variable)}
              filterOption={(input, option) =>
                [option.props.object, option.props.property, option.props.statistics]
                  .filter(Boolean)
                  .some(o => o.toLowerCase().includes((input || '').toLowerCase()))
              }
            >
              {
                properties.map(property => (
                  <Select.Option
                    key={getVariableOptionValue(property)}
                    value={getVariableOptionValue(property)}
                    object={property.object}
                    property={ObjectPropertyName[property.property]}
                    statistics={
                      property.function
                        ? PropertyFunctionNames[property.function]
                        : undefined
                    }
                    title={
                      `${property.object}: ${ObjectPropertyName[property.property]}`
                        .concat(
                          property.function
                            ? ` - ${PropertyFunctionNames[property.function]}`
                            : ''
                        )
                    }
                  >
                    <b>{property.object}</b>: {ObjectPropertyName[property.property]}
                    {
                      property.function && (
                        <span style={{whiteSpace: 'pre'}}>
                          {' - '}
                          {PropertyFunctionNames[property.function]}
                        </span>
                      )
                    }
                  </Select.Option>
                ))
              }
            </Select>
          </div>
        ))
      }
      <div
        className={styles.row}
        style={{paddingRight: 33}}
      >
        <span className={styles.title}>
          Name:
        </span>
        <Input
          className={styles.value}
          value={name}
          onChange={onChangeFormulaName}
        />
      </div>
    </div>
  );
}