github.com/stampzilla/stampzilla-go@v2.0.0-rc9+incompatible/nodes/stampzilla-server/web/src/routes/automation/Rule.js (about)

     1  import React, { Component } from 'react';
     2  import { Button } from 'reactstrap';
     3  import { connect } from 'react-redux';
     4  import Form from 'react-jsonschema-form';
     5  
     6  import { add, save } from '../../ducks/rules';
     7  import Card from '../../components/Card';
     8  import SavedStateWidget from './components/SavedStatePicker';
     9  import {
    10    ArrayFieldTemplate,
    11    CustomCheckbox,
    12    ObjectFieldTemplate,
    13    ConnectedRuleConditions,
    14  } from './components/formComponents';
    15  
    16  const schema = {
    17    type: 'object',
    18    required: ['name'],
    19    properties: {
    20      name: {
    21        type: 'string',
    22        title: 'Name',
    23      },
    24      enabled: {
    25        type: 'boolean',
    26        title: 'Enabled',
    27        description: 'Turn on and off this rule',
    28      },
    29      expression: {
    30        type: 'string',
    31        title: 'Expression',
    32        description:
    33          'The main expression that describes the state that should activate the rule',
    34      },
    35      for: {
    36        type: 'string',
    37        title: 'Delay',
    38        description:
    39          'The expression must be fullfilled this amount of time before the actions are carried out',
    40      },
    41      actions: {
    42        type: 'array',
    43        title: 'Actions',
    44        items: {
    45          type: 'string',
    46        },
    47      },
    48      conditions: {
    49        type: 'object',
    50        title: 'Conditions',
    51        description:
    52          'This is the conditions for the rule to be evaluated. Here you can depend one rule on an other by selecting if the parent rule has to be active or not.',
    53        properties: {},
    54      },
    55    },
    56  };
    57  const uiSchema = {
    58    config: {
    59      'ui:options': {
    60        rows: 15,
    61      },
    62    },
    63    actions: {
    64      items: {
    65        'ui:widget': 'SavedStateWidget',
    66      },
    67    },
    68    conditions: {
    69      'ui:field': 'ConnectedRuleConditions',
    70    },
    71  };
    72  
    73  const loadFromProps = (props) => {
    74    const { rules, match } = props;
    75    const rule = rules.find(n => n.get('uuid') === match.params.uuid);
    76    const formData = rule && rule.toJS();
    77  
    78    if (rule) {
    79      formData.actions = formData.actions || [];
    80    }
    81    return { formData };
    82  };
    83  
    84  class Automation extends Component {
    85    constructor(props) {
    86      super();
    87  
    88      this.state = {
    89        isValid: true,
    90        isModified: false,
    91        ...loadFromProps(props),
    92      };
    93    }
    94  
    95    componentWillReceiveProps(nextProps) {
    96      const { rules, match } = nextProps;
    97      if (
    98        !this.props ||
    99        match.params.uuid !== this.props.match.params.uuid ||
   100        rules !== this.props.rules
   101      ) {
   102        this.setState({
   103          ...loadFromProps(nextProps),
   104          isModified: false,
   105        });
   106      }
   107    }
   108  
   109    onChange = () => (data) => {
   110      const { errors, formData } = data;
   111      this.setState({
   112        isValid: errors.length === 0,
   113        formData,
   114        isModified: true,
   115      });
   116    };
   117  
   118    onSubmit = () => ({ formData }) => {
   119      const { dispatch } = this.props;
   120  
   121      if (formData.uuid) {
   122        dispatch(save(formData));
   123      } else {
   124        dispatch(add(formData));
   125      }
   126    };
   127  
   128    onBackClick = () => () => {
   129      const { history } = this.props;
   130      history.push('/aut');
   131    };
   132  
   133    render() {
   134      const { match, devices, state } = this.props;
   135      const { isModified } = this.state;
   136  
   137      const params = devices.reduce((acc, dev) => {
   138        (dev.get('state') || []).forEach((value, key) => {
   139          acc[`devices["${dev.get('id')}"].${key}`] = value;
   140        });
   141        return acc;
   142      }, {});
   143  
   144      const patchedSchema = Object.assign({}, schema);
   145      const patchedUiSchema = Object.assign({}, uiSchema);
   146      patchedUiSchema.conditions.current = match.params.uuid;
   147  
   148      return (
   149        <React.Fragment>
   150          <div className="row">
   151            <div className="col-md-12">
   152              {state.getIn([match.params.uuid, 'error']) && (
   153                <div className="alert alert-danger">
   154                  {state.getIn([match.params.uuid, 'error'])}
   155                </div>
   156              )}
   157              <Card
   158                title={match.params.uuid ? 'Edit rule ' : 'New rule'}
   159                bodyClassName="p-0"
   160              >
   161                <div className="card-body">
   162                  <Form
   163                    schema={patchedSchema}
   164                    uiSchema={patchedUiSchema}
   165                    showErrorList={false}
   166                    liveValidate
   167                    onChange={this.onChange()}
   168                    formData={this.state.formData}
   169                    onSubmit={this.onSubmit()}
   170                    // onError={log('errors')}
   171                    // disabled={this.props.disabled}
   172                    // transformErrors={this.props.transformErrors}
   173                    ObjectFieldTemplate={ObjectFieldTemplate}
   174                    ArrayFieldTemplate={ArrayFieldTemplate}
   175                    widgets={{
   176                      CheckboxWidget: CustomCheckbox,
   177                      SavedStateWidget,
   178                    }}
   179                    fields={{
   180                      ConnectedRuleConditions,
   181                    }}
   182                  >
   183                    <button
   184                      ref={(btn) => {
   185                        this.submitButton = btn;
   186                      }}
   187                      style={{ display: 'none' }}
   188                      type="submit"
   189                    />
   190                  </Form>
   191                </div>
   192                <div className="card-footer">
   193                  <Button color="secondary" onClick={this.onBackClick()}>
   194                    {'Back'}
   195                  </Button>
   196                  <Button
   197                    color={isModified ? 'primary' : 'secondary'}
   198                    disabled={!this.state.isValid || this.props.disabled}
   199                    onClick={() => this.submitButton.click()}
   200                    className="float-right"
   201                  >
   202                    {'Save'}
   203                  </Button>
   204                </div>
   205              </Card>
   206  
   207              <pre>
   208                {Object.keys(params).map(key => (
   209                  <div key={key}>
   210                    {key}: <strong>{JSON.stringify(params[key])}</strong>
   211                  </div>
   212                ))}
   213              </pre>
   214            </div>
   215          </div>
   216        </React.Fragment>
   217      );
   218    }
   219  }
   220  
   221  const mapToProps = state => ({
   222    rules: state.getIn(['rules', 'list']),
   223    state: state.getIn(['rules', 'state']),
   224    devices: state.getIn(['devices', 'list']),
   225  });
   226  
   227  export default connect(mapToProps)(Automation);