Merge branch '43-frontend-device-with-backend' into 'dev'

initial setup for device with backend

Closes #43

See merge request sa4-2020/the-sanmarinoes/frontend!42
This commit is contained in:
Claudio Maggioni 2020-03-21 00:00:19 +01:00
commit 8ac12ac8bf
9 changed files with 172 additions and 37 deletions

View file

@ -62,6 +62,7 @@ class App extends Component {
.then(res => { .then(res => {
if (res.data && res.status === 200) { if (res.data && res.status === 200) {
localStorage.setItem("token", res.data.jwttoken); localStorage.setItem("token", res.data.jwttoken);
call.setToken(res.data.jwttoken);
this.setState( this.setState(
{ {
user: data.params.user, user: data.params.user,

View file

@ -1,7 +1,7 @@
import axios from 'axios'; import axios from 'axios';
let config = 'http://localhost:8080/'; let config = 'http://localhost:8080/';
const tkn = localStorage.getItem("token"); var tkn = localStorage.getItem("token");
// requests data devices // requests data devices
/* /*
@ -12,9 +12,23 @@ const tkn = localStorage.getItem("token");
id: se serve id: se serve
} }
device routes:
- buttonDimmer
- dimmableLight
- knobDimmer
- motionSensor
- regularLight
- sensor
- smartPlug
- switch
*/ */
export var call = { export var call = {
setToken: function(token) {
tkn = token;
},
login: function(data, headers) { login: function(data, headers) {
return axios.post(config +'auth/login', data) return axios.post(config +'auth/login', data)
}, },
@ -58,10 +72,10 @@ export var call = {
return axios.post(config + data.device, data.params, { headers: { Authorization : "Bearer " + tkn } }) return axios.post(config + data.device, data.params, { headers: { Authorization : "Bearer " + tkn } })
}, },
deviceUpdate: function(data, headers) { deviceUpdate: function(data, headers) {
return axios.put(config + data.device, data.params) return axios.put(config + 'device', data, { headers: { Authorization : "Bearer " + tkn } })
}, },
deviceDelete: function(data, headers) { deviceDelete: function(data, headers) {
return axios.delete(config + data.device + '/' + data.id, data.params) return axios.delete(config + data.device + '/' + data.id, {}, { headers: { Authorization : "Bearer " + tkn } })
}, },
deviceGetById: function(data, headers) { deviceGetById: function(data, headers) {
return axios.get(config + data.device + '/' + data.id) return axios.get(config + data.device + '/' + data.id)

View file

@ -6,6 +6,8 @@ import {editButtonStyle, panelStyle} from "./devices/styleComponents";
import {checkMaxLength, DEVICE_NAME_MAX_LENGTH} from "./devices/constants"; import {checkMaxLength, DEVICE_NAME_MAX_LENGTH} from "./devices/constants";
import DeviceType from './devices/DeviceTypeController'; import DeviceType from './devices/DeviceTypeController';
import NewDevice from "./devices/NewDevice"; import NewDevice from "./devices/NewDevice";
import SettingsModal from "./devices/SettingsModal";
import { call } from '../../client_server';
export default class DevicePanel extends Component { export default class DevicePanel extends Component {
@ -20,6 +22,13 @@ export default class DevicePanel extends Component {
editModeController = (e) => this.setState((prevState) => ({ editMode: !prevState.editMode })); editModeController = (e) => this.setState((prevState) => ({ editMode: !prevState.editMode }));
openModal = (settingsDeviceId) => {
this.setState(prevState => ({
openSettingsModal: !prevState.openSettingsModal,
settingsDeviceId: settingsDeviceId
}))
}
changeDeviceData = (deviceId, newSettings) => { changeDeviceData = (deviceId, newSettings) => {
console.log(newSettings.name, " <-- new name --> ", deviceId ); console.log(newSettings.name, " <-- new name --> ", deviceId );
@ -46,35 +55,116 @@ export default class DevicePanel extends Component {
this.forceUpdate(); this.forceUpdate();
}; };
addDevice(data) { getDevices() {
const ds = this.props.addDevice(data); if (this.props.activeItem === -1) {
call.getAllDevices()
.then(res => {
if ( res.status === 200) {
this.setState({
devices: res.data
});
}
}).catch(err => {
console.log(err);
});
} else {
call.getAllDevicesByRoom(this.state.settingsDeviceId)
.then(res => {
if (res.status === 200) {
this.setState({
devices: res.data
});
}
}).catch(err => {
});
}
}
async addDevice(data) {
const ds = await this.props.addDevice(data);
this.setState({ this.setState({
devices: ds devices: ds
}); });
this.forceUpdate();
}
updateDevice = (data) => {
const roomId = this.props.devices.filter(d => d.id === this.state.settingsDeviceId)[0].roomId;
console.log(roomId)
data["id"] = this.state.settingsDeviceId;
data["roomId"] = roomId;
call.deviceUpdate(data)
.then(res => {
if (res.status === 200) {
this.getDevices();
}
}).catch(err => {
})
}
removeDevice = () => {
const item = this.props.devices.filter(d => d.id === this.state.settingsDeviceId)[0];
console.log(item)
const data = {
device: item.kind,
id: this.state.settingsDeviceId
};
call.deviceDelete(data)
.then(res => {
console.log(res)
if (res.status === 200) {
this.getDevices();
}
}).catch(err => {
});
} }
render() { render() {
const edit = {
mode: this.state.editMode,
openModal: this.openModal,
};
const ds = this.state.devices ? this.state.devices : this.props.devices; const ds = this.state.devices ? this.state.devices : this.props.devices;
return ( return (
<div style={panelStyle}> <div style={panelStyle}>
<button style={editButtonStyle} onClick={this.editModeController}>Edit</button> <button style={editButtonStyle} onClick={this.editModeController}>Edit</button>
<Grid doubling columns={ds.length > 0 ? ds.length : 1} divided="vertically"> <Grid doubling columns={4} divided="vertically">
{this.state.openSettingsModal ?
<SettingsModal openModal={this.openModal}
updateDevice={this.updateDevice}
removeDevice={this.removeDevice}
device={ds.filter(d => d.id === this.state.settingsDeviceId)[0]}/> : ""
}
{ {
ds ? ds ?
ds.map((e, i) => { ds.map((e, i) => {
return ( return (
<Grid.Column key={i}> <Grid.Column key={i}>
<DeviceType type={e.kind} onChangeData={this.changeDeviceData} device={e} edit={this.state.editMode}/> <DeviceType type={e.kind} onChangeData={this.changeDeviceData} device={e} edit={edit}/>
</Grid.Column> </Grid.Column>
) )
}) })
: :
null null
} }
<Grid.Column> {
<NewDevice addDevice={this.addDevice} devices={ds}/> this.props.activeItem !== -1 ?
</Grid.Column> <Grid.Column>
<NewDevice addDevice={this.addDevice} devices={ds}/>
</Grid.Column>
:
null
}
</Grid> </Grid>
</div> </div>
) )

View file

@ -6,7 +6,6 @@ import DefaultDimmer from "./Dimmer";
import Switcher from "./Switch"; import Switcher from "./Switch";
const DeviceType = (props) => { const DeviceType = (props) => {
switch(props.type) { switch(props.type) {
case "regular-light": case "regular-light":
@ -20,7 +19,7 @@ const DeviceType = (props) => {
case "switch": case "switch":
return <Switcher onChangeData={props.changeDeviceData} device={props.device} edit={props.edit} /> return <Switcher onChangeData={props.changeDeviceData} device={props.device} edit={props.edit} />
case "light": case "light":
return <Light onChangeData={props.changeDeviceData} device={props.device} edit={props.edit} /> return (<Light onChangeData={props.changeDeviceData} device={props.device} edit={props.edit} />)
default: default:
return "" return ""
} }

View file

@ -18,7 +18,6 @@ export default class Light extends Component {
super(props); super(props);
this.state = { this.state = {
turnedOn: false, turnedOn: false,
hasIntensity: false
}; };
this.iconOn = "/img/lightOn.svg"; this.iconOn = "/img/lightOn.svg";
this.iconOff = "/img/lightOff.svg" this.iconOff = "/img/lightOff.svg"
@ -29,7 +28,7 @@ export default class Light extends Component {
}; };
setIntensity = (newValue) => { setIntensity = (newValue) => {
this.setState({intensityLevel: newValue}); this.setState({intensity: newValue});
}; };
getIcon = () => { getIcon = () => {
@ -40,10 +39,9 @@ export default class Light extends Component {
}; };
componentDidMount() { componentDidMount() {
if (this.props.device.hasOwnProperty("hasIntensity") && this.props.device.hasOwnProperty("intensityLevel")) { if (this.props.device.hasOwnProperty("intensity")) {
this.setState({ this.setState({
hasIntensity: this.props.device.hasIntensity, intensity: this.props.device.intensity
intensityLevel: this.props.device.intensityLevel
}); });
} }
// Get the state and update it // Get the state and update it
@ -54,7 +52,7 @@ export default class Light extends Component {
render() { render() {
const intensityLightView = ( const intensityLightView = (
<CircularInput <CircularInput
value={this.state.intensityLevel} value={this.state.intensity}
onChange={this.setIntensity} onChange={this.setIntensity}
style={style} style={style}
> >
@ -63,7 +61,7 @@ export default class Light extends Component {
<CircularThumb/> <CircularThumb/>
<text style={valueStyle} x={100} y={100} textAnchor="middle" dy="0.3em" fontWeight="bold"> <text style={valueStyle} x={100} y={100} textAnchor="middle" dy="0.3em" fontWeight="bold">
{Math.round(this.state.intensityLevel * 100)}% {Math.round(this.state.intensity * 100)}%
</text> </text>
<text style={intensityLightStyle} x={100} y={150} textAnchor="middle" dy="0.3em" fontWeight="bold"> <text style={intensityLightStyle} x={100} y={150} textAnchor="middle" dy="0.3em" fontWeight="bold">
{this.props.device.name} {this.props.device.name}
@ -78,14 +76,14 @@ export default class Light extends Component {
<h5 style={nameStyle}>{this.props.device.name}</h5> <h5 style={nameStyle}>{this.props.device.name}</h5>
</div> </div>
); );
return ( return (
<StyledDiv> <StyledDiv>
<Settings <Settings
deviceId={this.props.device.id} deviceId={this.props.device.id}
edit={this.props.edit} edit={this.props.edit}
onChangeData={(id, newSettings) => this.props.onChangeData(id, newSettings)}/> onChangeData={(id, newSettings) => this.props.onChangeData(id, newSettings)}/>
{this.state.hasIntensity ? (intensityLightView) : (normalLightView)} {this.state.intensity ? (intensityLightView) : (normalLightView)}
</StyledDiv> </StyledDiv>
) )
} }

View file

@ -45,7 +45,12 @@ export default class NewDevice extends Component {
}; };
setTypeOfDevice = (e, d) => { setTypeOfDevice = (e, d) => {
this.setState({typeOfDevice: d.value}); if (d.value === "dimmableLight"){
this.setState({typeOfDevice: d.value,
intensity: 0,});
} else {
this.setState({typeOfDevice: d.value,});
}
}; };
setDeviceName = (e, d) => { setDeviceName = (e, d) => {
@ -69,6 +74,14 @@ export default class NewDevice extends Component {
device: this.state.typeOfDevice device: this.state.typeOfDevice
} }
switch(this.state.typeOfDevice) {
case "dimmableLight":
data.params["intensity"] = 1;
break;
default:
break;
}
this.props.addDevice(data); this.props.addDevice(data);
this.resetState(); this.resetState();
}; };
@ -85,13 +98,13 @@ export default class NewDevice extends Component {
{ {
key: 'intensity-light', key: 'intensity-light',
text: 'Intensity Light', text: 'Intensity Light',
value: 'intensity-light', value: 'dimmableLight',
image: {avatar: true, src: '/img/intensity-light.svg'}, image: {avatar: true, src: '/img/intensity-light.svg'},
}, },
{ {
key: 'smart-plug', key: 'smart-plug',
text: 'Smart Plug', text: 'Smart Plug',
value: 'smart-plug', value: 'smartPlug',
image: {avatar: true, src: '/img/smart-plug.svg'}, image: {avatar: true, src: '/img/smart-plug.svg'},
}, },
{ {
@ -117,25 +130,25 @@ export default class NewDevice extends Component {
{ {
key: "temperature", key: "temperature",
text: "Temperature Sensor", text: "Temperature Sensor",
value: "temperature", value: "TEMPERATURE",
image: {avatar: true, src: '/img/temperature-sensor.svg'}, image: {avatar: true, src: '/img/temperature-sensor.svg'},
}, },
{ {
key: "humidity", key: "humidity",
text: "Humidity Sensor", text: "Humidity Sensor",
value: "humidity", value: "HUMIDITY",
image: {avatar: true, src: '/img/humidity-sensor.svg'}, image: {avatar: true, src: '/img/humidity-sensor.svg'},
}, },
{ {
key: "light", key: "light",
text: "Light Sensor", text: "Light Sensor",
value: "light", value: "LIGHT",
image: {avatar: true, src: '/img/light-sensor.svg'}, image: {avatar: true, src: '/img/light-sensor.svg'},
}, },
{ {
key: "motion", key: "motion",
text: "Motion Sensor", text: "Motion Sensor",
value: "motion", value: "motionSensor",
image: {avatar: true, src: '/img/sensorOn.svg'}, image: {avatar: true, src: '/img/sensorOn.svg'},
} }
]; ];

View file

@ -1,5 +1,19 @@
import React, {Component, useState} from 'react'; import React, {Component, useState} from 'react';
import {Button, Checkbox, Form, Modal} from "semantic-ui-react"; import {Button, Checkbox, Form, Icon, Header, Modal} from "semantic-ui-react";
const DeleteModal = (props) => (
<Modal trigger={<Button color='red'>Remove</Button>} closeIcon>
<Header icon='archive' content='Are you sure ?' />
<Modal.Actions>
<Button color='red'>
<Icon name='remove' /> No
</Button>
<Button onClick={() => props.removeDevice()} color='green'>
<Icon name='checkmark' /> Yes
</Button>
</Modal.Actions>
</Modal>
)
const SettingsForm = (props) => { const SettingsForm = (props) => {
@ -21,11 +35,15 @@ const SettingsForm = (props) => {
<label>New Name: </label> <label>New Name: </label>
<input autoComplete="off" name="name" onChange={handleInputChange} value={values.name} placeholder='Device name'/> <input autoComplete="off" name="name" onChange={handleInputChange} value={values.name} placeholder='Device name'/>
</Form.Field> </Form.Field>
{props.type === "smart-plug" ? ( {props.type === "smart-plug" ? (
<Form.Field> <Form.Field>
<Checkbox slider name={"reset"} onClick={handleCheckboxChange} label='Reset Energy Consumption'/> <Checkbox slider name={"reset"} onClick={handleCheckboxChange} label='Reset Energy Consumption'/>
</Form.Field> </Form.Field>
) : ""} ) : ""}
<Form.Field>
<DeleteModal removeDevice={() => props.removeDevice(values)} />
</Form.Field>
<Button onClick={() => props.saveFunction(values)} color="blue" type='submit'>Save</Button> <Button onClick={() => props.saveFunction(values)} color="blue" type='submit'>Save</Button>
</Form> </Form>
) )
@ -47,16 +65,20 @@ export default class SettingsModal extends Component {
saveSettings = (device) => { saveSettings = (device) => {
// TODO Here there should be all the connections to save the data in the backend // TODO Here there should be all the connections to save the data in the backend
console.log("SAVED: ", device); console.log("SAVED: ", device);
if (device.name.length > 0) {
this.props.updateDevice(device);
}
this.props.openModal(); this.props.openModal();
}; };
render() { render() {
const SettingsModal = () => ( const SettingsModal = () => (
<Modal open={true} onOpen={this.props.openModal} onClose={this.props.openModal}> <Modal open={true} onOpen={this.props.openModal} onClose={this.props.openModal}>
<Modal.Header>Settings of {this.props.device.name}</Modal.Header> <Modal.Header>Settings of {this.props.device.name}</Modal.Header>
<Modal.Content> <Modal.Content>
<SettingsForm type={this.props.device.type} saveFunction={this.saveSettings}/> <SettingsForm type={this.props.device.type} removeDevice={this.props.removeDevice} saveFunction={this.saveSettings}/>
</Modal.Content> </Modal.Content>
</Modal> </Modal>
); );

View file

@ -33,12 +33,8 @@ export default class Switch extends Component {
return this.iconOff; return this.iconOff;
}; };
resetEnergyConsumedValue = () => {
// In the settings form there must be an option to restore this value
// along with the rename feature.
}
componentDidMount() { componentDidMount() {
} }
render(){ render(){

View file

@ -99,6 +99,7 @@ export default class Dashboard extends Component{
call.getAllDevicesByRoom(id, this.props.tkn) call.getAllDevicesByRoom(id, this.props.tkn)
.then(res => { .then(res => {
if (res.status === 200) { if (res.status === 200) {
console.log(res.data);
this.setState({ this.setState({
devices: res.data devices: res.data
}); });
@ -116,12 +117,13 @@ export default class Dashboard extends Component{
this.setState(state => ({ this.setState(state => ({
devices: state.devices.concat([res.data]) devices: state.devices.concat([res.data])
})); }));
return this.state.devices;
}).catch(err => { }).catch(err => {
}); });
return this.state.devices;
} }
render () { render () {
return( return(
<div style={{height : "110vh", background: '#1b1c1d'}}> <div style={{height : "110vh", background: '#1b1c1d'}}>
@ -137,7 +139,7 @@ export default class Dashboard extends Component{
</Grid.Column> </Grid.Column>
<Grid.Column width={13}> <Grid.Column width={13}>
<DevicePanel addDevice={this.addDevice} devices={this.state.devices} /> <DevicePanel tkn={this.props.tkn} activeItem={this.state.activeItem} addDevice={this.addDevice} devices={this.state.devices} />
</Grid.Column> </Grid.Column>
</Grid.Row> </Grid.Row>
</Grid> </Grid>