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);