github.com/stampzilla/stampzilla-go@v2.0.0-rc9+incompatible/nodes/stampzilla-server/web/src/routes/dashboard/Device.js (about) 1 import React, { Component } from 'react'; 2 import { 3 mdiLightbulb, 4 mdiPower, 5 mdiPulse, 6 } from '@mdi/js'; 7 import Icon from '@mdi/react'; 8 import classnames from 'classnames'; 9 10 import './device.scss'; 11 import { write } from '../../components/Websocket'; 12 import Trait from './Trait'; 13 14 export const traitPriority = [ 15 'OnOff', 16 'Brightness', 17 'ColorSetting', 18 ]; 19 20 export const traitNames = { 21 Brightness: 'Brightness', 22 OnOff: 'Power', 23 ColorSetting: 'Temperature', 24 }; 25 26 export const traitStates = { 27 Brightness: 'brightness', 28 OnOff: 'on', 29 ColorSetting: 'temperature', 30 }; 31 32 const icons = { 33 light: mdiLightbulb, 34 switch: mdiPower, 35 sensor: mdiPulse, 36 }; 37 38 const guessType = (device) => { 39 const traits = (device.get('traits') && device.get('traits').toJS()) || []; 40 41 if (traits.length === 0) { 42 return 'sensor'; 43 } 44 45 if (traits.indexOf('Brightness') !== -1) { 46 return 'light'; 47 } 48 if (traits.indexOf('ColorSetting') !== -1) { 49 return 'light'; 50 } 51 if (traits.indexOf('OnOff') !== -1) { 52 return 'switch'; 53 } 54 55 return null; 56 }; 57 58 class Device extends Component { 59 onChange = (device, trait) => (value) => { 60 const clone = device.toJS(); 61 clone.state[traitStates[trait]] = value; 62 63 write({ 64 type: 'state-change', 65 body: { 66 [clone.id]: clone, 67 }, 68 }); 69 } 70 71 render() { 72 const { device } = this.props; 73 74 const sortedTraits = device.get('traits') && device.get('traits').sort((a, b) => { 75 const prioA = traitPriority.findIndex(trait => trait === a); 76 const prioB = traitPriority.findIndex(trait => trait === b); 77 return prioA - prioB; 78 }); 79 80 const primaryTrait = sortedTraits && sortedTraits.first(); 81 const secondaryTraits = sortedTraits && sortedTraits.shift(); 82 83 const type = device.get('type') || guessType(device); 84 const icon = icons[type]; 85 86 return ( 87 <div className={classnames({ 88 'd-flex flex-column': true, 89 offline: !device.get('online'), 90 })} 91 > 92 <div className="d-flex align-items-center py-1"> 93 <div style={{ width: '1.5rem' }}> 94 { icon && 95 <Icon 96 path={icon} 97 size={1} 98 /> 99 } 100 </div> 101 <div className="flex-grow-1 mr-2"> 102 {device.get('name')}<br /> 103 </div> 104 {primaryTrait && 105 <Trait 106 trait={primaryTrait} 107 device={device} 108 state={traitStates[primaryTrait] && device.getIn(['state', traitStates[primaryTrait]])} 109 onChange={this.onChange(device, primaryTrait)} 110 /> 111 } 112 {!primaryTrait && 113 <span>{JSON.stringify(device.get('state'))}</span> 114 } 115 </div> 116 <div className="d-flex flex-column ml-4"> 117 {secondaryTraits && secondaryTraits.map(trait => ( 118 <div className="d-flex ml-3" key={trait}> 119 <div className="mr-2">{traitNames[trait] || trait}</div> 120 <div className="flex-grow-1 d-flex align-items-center"> 121 <Trait 122 trait={trait} 123 device={device} 124 state={traitStates[trait] && device.getIn(['state', traitStates[trait]])} 125 onChange={this.onChange(device, trait)} 126 /> 127 </div> 128 </div> 129 ))} 130 </div> 131 </div> 132 ); 133 } 134 } 135 136 export default Device;