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 => {
if (res.data && res.status === 200) {
localStorage.setItem("token", res.data.jwttoken);
call.setToken(res.data.jwttoken);
this.setState(
{
user: data.params.user,

View file

@ -1,7 +1,7 @@
import axios from 'axios';
let config = 'http://localhost:8080/';
const tkn = localStorage.getItem("token");
var tkn = localStorage.getItem("token");
// requests data devices
/*
@ -12,9 +12,23 @@ const tkn = localStorage.getItem("token");
id: se serve
}
device routes:
- buttonDimmer
- dimmableLight
- knobDimmer
- motionSensor
- regularLight
- sensor
- smartPlug
- switch
*/
export var call = {
setToken: function(token) {
tkn = token;
},
login: function(data, headers) {
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 } })
},
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) {
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) {
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 DeviceType from './devices/DeviceTypeController';
import NewDevice from "./devices/NewDevice";
import SettingsModal from "./devices/SettingsModal";
import { call } from '../../client_server';
export default class DevicePanel extends Component {
@ -20,6 +22,13 @@ export default class DevicePanel extends Component {
editModeController = (e) => this.setState((prevState) => ({ editMode: !prevState.editMode }));
openModal = (settingsDeviceId) => {
this.setState(prevState => ({
openSettingsModal: !prevState.openSettingsModal,
settingsDeviceId: settingsDeviceId
}))
}
changeDeviceData = (deviceId, newSettings) => {
console.log(newSettings.name, " <-- new name --> ", deviceId );
@ -46,35 +55,116 @@ export default class DevicePanel extends Component {
this.forceUpdate();
};
addDevice(data) {
const ds = this.props.addDevice(data);
getDevices() {
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({
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() {
const edit = {
mode: this.state.editMode,
openModal: this.openModal,
};
const ds = this.state.devices ? this.state.devices : this.props.devices;
return (
<div style={panelStyle}>
<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.map((e, i) => {
return (
<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>
)
})
:
null
}
<Grid.Column>
<NewDevice addDevice={this.addDevice} devices={ds}/>
</Grid.Column>
{
this.props.activeItem !== -1 ?
<Grid.Column>
<NewDevice addDevice={this.addDevice} devices={ds}/>
</Grid.Column>
:
null
}
</Grid>
</div>
)

View file

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

View file

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

View file

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

View file

@ -1,5 +1,19 @@
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) => {
@ -21,11 +35,15 @@ const SettingsForm = (props) => {
<label>New Name: </label>
<input autoComplete="off" name="name" onChange={handleInputChange} value={values.name} placeholder='Device name'/>
</Form.Field>
{props.type === "smart-plug" ? (
<Form.Field>
<Checkbox slider name={"reset"} onClick={handleCheckboxChange} label='Reset Energy Consumption'/>
</Form.Field>
) : ""}
<Form.Field>
<DeleteModal removeDevice={() => props.removeDevice(values)} />
</Form.Field>
<Button onClick={() => props.saveFunction(values)} color="blue" type='submit'>Save</Button>
</Form>
)
@ -47,16 +65,20 @@ export default class SettingsModal extends Component {
saveSettings = (device) => {
// TODO Here there should be all the connections to save the data in the backend
console.log("SAVED: ", device);
if (device.name.length > 0) {
this.props.updateDevice(device);
}
this.props.openModal();
};
render() {
const SettingsModal = () => (
<Modal open={true} onOpen={this.props.openModal} onClose={this.props.openModal}>
<Modal.Header>Settings of {this.props.device.name}</Modal.Header>
<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>
);

View file

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

View file

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