github.com/stampzilla/stampzilla-go@v2.0.0-rc9+incompatible/nodes/stampzilla-server/web/src/routes/automation/components/formComponents.js (about) 1 import PropTypes from 'prop-types'; 2 import React from 'react'; 3 import classnames from 'classnames'; 4 import { connect } from 'react-redux'; 5 6 export const ObjectFieldTemplate = (props) => { 7 if (props.title !== undefined) { 8 return ( 9 <div className="card mb-4 bg-dark text-white"> 10 <div className="card-header"> 11 <div> 12 <strong>{props.title}</strong> 13 </div> 14 <small>{props.description}</small> 15 </div> 16 <div 17 className={classnames({ 18 'card-body': true, 19 })} 20 > 21 {props.properties.map(prop => prop.content)} 22 </div> 23 </div> 24 ); 25 } 26 27 return typeof props.uiSchema.tableMode !== 'undefined' ? ( 28 <div className="row"> 29 {props.properties.map(prop => ( 30 <div key={prop.name} className="col-sm-6"> 31 {prop.content} 32 </div> 33 ))} 34 </div> 35 ) : ( 36 <React.Fragment> 37 {props.properties.map(prop => prop.content)} 38 </React.Fragment> 39 ); 40 }; 41 ObjectFieldTemplate.propTypes = { 42 title: PropTypes.string, 43 description: PropTypes.string, 44 properties: PropTypes.arrayOf( 45 PropTypes.shape({ 46 content: PropTypes.node, 47 }), 48 ), 49 uiSchema: PropTypes.shape({ 50 tableMode: PropTypes.bool, 51 }), 52 }; 53 54 export const CustomCheckbox = (props) => { 55 const { 56 id, 57 value, 58 required, 59 disabled, 60 readonly, 61 label, 62 autofocus, 63 onChange, 64 } = props; 65 return ( 66 <div 67 className={`checkbox custom-control custom-checkbox ${ 68 disabled || readonly ? 'disabled' : '' 69 }`} 70 > 71 <input 72 type="checkbox" 73 className="custom-control-input" 74 id={id} 75 checked={typeof value === 'undefined' ? false : value} 76 required={required} 77 disabled={disabled || readonly} 78 autoFocus={autofocus} 79 onChange={event => onChange(event.target.checked)} 80 /> 81 <label className="custom-control-label" htmlFor={id}> 82 <span>{label}</span> 83 </label> 84 </div> 85 ); 86 }; 87 CustomCheckbox.propTypes = { 88 id: PropTypes.string, 89 value: PropTypes.bool, 90 required: PropTypes.bool, 91 disabled: PropTypes.bool, 92 readonly: PropTypes.bool, 93 label: PropTypes.string, 94 autofocus: PropTypes.bool, 95 onChange: PropTypes.func, 96 }; 97 98 const IconButton = (props) => { 99 const { 100 type = 'default', icon, className, ...otherProps 101 } = props; 102 return ( 103 <button 104 type="button" 105 className={`btn btn-${type} ${className}`} 106 {...otherProps} 107 > 108 <i className={`fa fa-${icon}`} /> 109 </button> 110 ); 111 }; 112 IconButton.propTypes = { 113 type: PropTypes.string, 114 icon: PropTypes.string, 115 className: PropTypes.string, 116 }; 117 118 const DefaultArrayItem = (props) => { 119 const btnStyle = { 120 flex: 1, 121 paddingLeft: 6, 122 paddingRight: 6, 123 fontWeight: 'bold', 124 }; 125 return ( 126 <div 127 key={props.index} 128 className={classnames(['row mb-3', props.className])} 129 > 130 <div className={props.hasToolbar ? 'col-sm-9' : 'col-sm-12'}> 131 {props.children} 132 </div> 133 134 {props.hasToolbar && ( 135 <div className="col-sm-3 array-item-toolbox"> 136 <div 137 className="btn-group" 138 style={{ 139 display: 'flex', 140 justifyContent: 'space-around', 141 }} 142 > 143 {(props.hasMoveUp || props.hasMoveDown) && ( 144 <IconButton 145 type="secondary" 146 icon="arrow-up" 147 className="array-item-move-up" 148 tabIndex="-1" 149 style={btnStyle} 150 disabled={props.disabled || props.readonly || !props.hasMoveUp} 151 onClick={props.onReorderClick(props.index, props.index - 1)} 152 /> 153 )} 154 {(props.hasMoveUp || props.hasMoveDown) && ( 155 <IconButton 156 type="secondary" 157 icon="arrow-down" 158 className="array-item-move-down" 159 tabIndex="-1" 160 style={btnStyle} 161 disabled={ 162 props.disabled || props.readonly || !props.hasMoveDown 163 } 164 onClick={props.onReorderClick(props.index, props.index + 1)} 165 /> 166 )} 167 {props.hasRemove && ( 168 <IconButton 169 type="danger" 170 icon="trash" 171 className="array-item-remove" 172 tabIndex="-1" 173 style={btnStyle} 174 disabled={props.disabled || props.readonly} 175 onClick={props.onDropIndexClick(props.index)} 176 /> 177 )} 178 </div> 179 </div> 180 )} 181 </div> 182 ); 183 }; 184 185 DefaultArrayItem.propTypes = { 186 // schema: PropTypes.object.isRequired, 187 uiSchema: PropTypes.shape({ 188 'ui:options': PropTypes.shape({ 189 addable: PropTypes.bool, 190 orderable: PropTypes.bool, 191 removable: PropTypes.bool, 192 }), 193 }), 194 // idSchema: PropTypes.object, 195 // errorSchema: PropTypes.object, 196 // onChange: PropTypes.func.isRequired, 197 // onBlur: PropTypes.func, 198 // onFocus: PropTypes.func, 199 // formData: PropTypes.array, 200 // required: PropTypes.bool, 201 disabled: PropTypes.bool, 202 readonly: PropTypes.bool, 203 // autofocus: PropTypes.bool, 204 registry: PropTypes.shape({ 205 widgets: PropTypes.objectOf( 206 PropTypes.oneOfType([PropTypes.func, PropTypes.shape({})]), 207 ).isRequired, 208 fields: PropTypes.objectOf(PropTypes.func).isRequired, 209 definitions: PropTypes.object.isRequired, 210 formContext: PropTypes.object.isRequired, 211 }), 212 onDropIndexClick: PropTypes.func, 213 hasRemove: PropTypes.bool, 214 hasMoveUp: PropTypes.bool, 215 hasMoveDown: PropTypes.bool, 216 children: PropTypes.node, 217 hasToolbar: PropTypes.bool, 218 className: PropTypes.string, 219 index: PropTypes.string, 220 onReorderClick: PropTypes.func, 221 }; 222 223 export const ArrayFieldTemplate = (props) => { 224 const { title } = props; 225 return ( 226 <div> 227 <label> 228 <span>{title}</span> 229 </label> 230 {props.items && props.items.map(DefaultArrayItem)} 231 {props.canAdd && ( 232 <IconButton 233 icon="plus" 234 className="btn-block btn-success" 235 onClick={props.onAddClick} 236 /> 237 )} 238 </div> 239 ); 240 }; 241 ArrayFieldTemplate.propTypes = { 242 title: PropTypes.string, 243 canAdd: PropTypes.bool, 244 onAddClick: PropTypes.func, 245 items: PropTypes.arrayOf(PropTypes.shape({})), 246 }; 247 248 const stateToTextColor = (status) => { 249 if (!status) { 250 return 'text-secondary'; 251 } 252 253 if (status.get('error')) { 254 return 'text-danger'; 255 } 256 257 if (status.get('active')) { 258 return 'text-success'; 259 } 260 261 return ''; 262 }; 263 264 export class RuleConditions extends React.Component { 265 constructor(props) { 266 super(props); 267 this.state = { ...props.formData }; 268 } 269 270 componentWillReceiveProps(props) { 271 if (props.formData !== this.state) { 272 this.setState({ ...props.formData }); 273 } 274 } 275 276 onChange = (name, value) => (checked) => { 277 this.setState( 278 { 279 [name]: checked ? value : undefined, 280 }, 281 () => this.props.onChange(this.state), 282 ); 283 }; 284 285 render() { 286 const { 287 rules, schema, uiSchema, status, 288 } = this.props; 289 const { 290 id, title, required, description, 291 } = schema; 292 return ( 293 <div> 294 <label htmlFor={id}> 295 {title} 296 {required ? '*' : null} 297 </label> 298 <p id="root_for__description" className="field-description"> 299 {description} 300 </p> 301 <table> 302 <thead> 303 <tr> 304 <th>Active</th> 305 <th>Standby</th> 306 <th>Rule</th> 307 </tr> 308 </thead> 309 <tbody> 310 {rules 311 .filter(rule => rule.get('uuid') !== uiSchema.current) 312 .map(rule => ( 313 <tr key={rule.get('uuid')}> 314 <td className="text-center"> 315 <CustomCheckbox 316 id={`${rule.get('uuid')}-true`} 317 value={this.state[rule.get('uuid')] === true} 318 onChange={this.onChange(rule.get('uuid'), true)} 319 /> 320 </td> 321 <td className="text-center"> 322 <CustomCheckbox 323 id={`${rule.get('uuid')}-false`} 324 value={this.state[rule.get('uuid')] === false} 325 onChange={this.onChange(rule.get('uuid'), false)} 326 /> 327 </td> 328 <td 329 className={stateToTextColor(status.get(rule.get('uuid')))} 330 > 331 {rule.get('name')} 332 </td> 333 </tr> 334 )) 335 .toArray()} 336 </tbody> 337 </table> 338 </div> 339 ); 340 // <input type="number" value={lon} onChange={this.onChange('lon')} /> 341 } 342 } 343 344 const mapStateToProps = state => ({ 345 rules: state.getIn(['rules', 'list']), 346 status: state.getIn(['rules', 'state']), 347 }); 348 349 export const ConnectedRuleConditions = connect(mapStateToProps)(RuleConditions);