Merge branch 'frontend-userstory1-fil' into 'dev'
Frontend userstory1 fil See merge request sa4-2020/the-sanmarinoes/frontend!151
90
smart-hut/package-lock.json
generated
|
@ -4,6 +4,11 @@
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@ant-design/css-animation": {
|
||||||
|
"version": "1.7.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@ant-design/css-animation/-/css-animation-1.7.2.tgz",
|
||||||
|
"integrity": "sha512-bvVOe7A+r7lws58B7r+fgnQDK90cV45AXuvGx6i5CCSX1W/M3AJnHsNggDANBxEtWdNdFWcDd5LorB+RdSIlBw=="
|
||||||
|
},
|
||||||
"@babel/code-frame": {
|
"@babel/code-frame": {
|
||||||
"version": "7.8.3",
|
"version": "7.8.3",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz",
|
||||||
|
@ -1999,6 +2004,14 @@
|
||||||
"resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.2.0.tgz",
|
||||||
"integrity": "sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA=="
|
"integrity": "sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA=="
|
||||||
},
|
},
|
||||||
|
"add-dom-event-listener": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/add-dom-event-listener/-/add-dom-event-listener-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-WCxx1ixHT0GQU9hb0KI/mhgRQhnU+U3GvwY6ZvVjYq8rsihIGoaIOUbY0yMPBxLH5MDtr0kz3fisWGNcbWW7Jw==",
|
||||||
|
"requires": {
|
||||||
|
"object-assign": "4.x"
|
||||||
|
}
|
||||||
|
},
|
||||||
"address": {
|
"address": {
|
||||||
"version": "1.1.2",
|
"version": "1.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/address/-/address-1.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/address/-/address-1.1.2.tgz",
|
||||||
|
@ -4600,6 +4613,11 @@
|
||||||
"esutils": "^2.0.2"
|
"esutils": "^2.0.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"dom-align": {
|
||||||
|
"version": "1.11.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/dom-align/-/dom-align-1.11.1.tgz",
|
||||||
|
"integrity": "sha512-hN42DmUgtweBx0iBjDLO4WtKOMcK8yBmPx/fgdsgQadLuzPu/8co3oLdK5yMmeM/vnUd3yDyV6qV8/NzxBexQg=="
|
||||||
|
},
|
||||||
"dom-converter": {
|
"dom-converter": {
|
||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz",
|
||||||
|
@ -11427,6 +11445,73 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"rc-align": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/rc-align/-/rc-align-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-/T/4LOlKJLFe8EwsORuc3pFWOJ8caUpj2vtKIHWea4PhakoleM7KDQsx0n1WDQENIeSfrP9P1FowVxAdvhjsvw==",
|
||||||
|
"requires": {
|
||||||
|
"classnames": "2.x",
|
||||||
|
"dom-align": "^1.7.0",
|
||||||
|
"rc-util": "^4.12.0",
|
||||||
|
"resize-observer-polyfill": "^1.5.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"rc-animate": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/rc-animate/-/rc-animate-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-+ANeyCei4lWSJHWTcocywdYAy6lpRdBva/7Fs3nBBiAngW/W+Gmx+gQEcsmcgQBqziWUYnR91Bk12ltR3GBHPA==",
|
||||||
|
"requires": {
|
||||||
|
"@ant-design/css-animation": "^1.7.2",
|
||||||
|
"classnames": "^2.2.6",
|
||||||
|
"raf": "^3.4.0",
|
||||||
|
"rc-util": "^4.15.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"rc-slider": {
|
||||||
|
"version": "9.2.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/rc-slider/-/rc-slider-9.2.4.tgz",
|
||||||
|
"integrity": "sha512-wSr7vz+WtzzGqsGU2rTQ4mmLz9fkuIDMPYMYm8ygYFvxQ2Rh4uRhOWHYI0R8krNK5k1bGycckYxmQqUIvLAh3w==",
|
||||||
|
"requires": {
|
||||||
|
"babel-runtime": "6.x",
|
||||||
|
"classnames": "^2.2.5",
|
||||||
|
"rc-tooltip": "^4.0.0",
|
||||||
|
"rc-util": "^4.0.4",
|
||||||
|
"shallowequal": "^1.1.0",
|
||||||
|
"warning": "^4.0.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"rc-tooltip": {
|
||||||
|
"version": "4.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/rc-tooltip/-/rc-tooltip-4.0.3.tgz",
|
||||||
|
"integrity": "sha512-HNyBh9/fPdds0DXja8JQX0XTIHmZapB3lLzbdn74aNSxXG1KUkt+GK4X1aOTRY5X9mqm4uUKdeFrn7j273H8gw==",
|
||||||
|
"requires": {
|
||||||
|
"rc-trigger": "^4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"rc-trigger": {
|
||||||
|
"version": "4.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/rc-trigger/-/rc-trigger-4.1.0.tgz",
|
||||||
|
"integrity": "sha512-EyQjO6aHDAPRvJeyPmg/yVL/8Bp7oA6Lf+4Ay2OyOwhZLzHHN8m+F2XrVWKpjg04eBXbuGBNiucIqv1d/ddE3w==",
|
||||||
|
"requires": {
|
||||||
|
"classnames": "^2.2.6",
|
||||||
|
"raf": "^3.4.1",
|
||||||
|
"rc-align": "^3.0.0-rc.0",
|
||||||
|
"rc-animate": "^3.0.0",
|
||||||
|
"rc-util": "^4.20.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"rc-util": {
|
||||||
|
"version": "4.20.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/rc-util/-/rc-util-4.20.5.tgz",
|
||||||
|
"integrity": "sha512-f67s4Dt1quBYhrVPq5QMKmK3eS2hN1NNIAyhaiG0HmvqiGYAXMQ7SP2AlGqv750vnzhJs38JklbkWT1/wjhFPg==",
|
||||||
|
"requires": {
|
||||||
|
"add-dom-event-listener": "^1.1.0",
|
||||||
|
"prop-types": "^15.5.10",
|
||||||
|
"react-is": "^16.12.0",
|
||||||
|
"react-lifecycles-compat": "^3.0.4",
|
||||||
|
"shallowequal": "^1.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"react": {
|
"react": {
|
||||||
"version": "16.12.0",
|
"version": "16.12.0",
|
||||||
"resolved": "https://registry.npmjs.org/react/-/react-16.12.0.tgz",
|
"resolved": "https://registry.npmjs.org/react/-/react-16.12.0.tgz",
|
||||||
|
@ -11654,6 +11739,11 @@
|
||||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.12.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.12.0.tgz",
|
||||||
"integrity": "sha512-rPCkf/mWBtKc97aLL9/txD8DZdemK0vkA3JMLShjlJB3Pj3s+lpf1KaBzMfQrAmhMQB0n1cU/SUGgKKBCe837Q=="
|
"integrity": "sha512-rPCkf/mWBtKc97aLL9/txD8DZdemK0vkA3JMLShjlJB3Pj3s+lpf1KaBzMfQrAmhMQB0n1cU/SUGgKKBCe837Q=="
|
||||||
},
|
},
|
||||||
|
"react-lifecycles-compat": {
|
||||||
|
"version": "3.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
|
||||||
|
"integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
|
||||||
|
},
|
||||||
"react-modal": {
|
"react-modal": {
|
||||||
"version": "2.2.2",
|
"version": "2.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/react-modal/-/react-modal-2.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/react-modal/-/react-modal-2.2.2.tgz",
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
"classnames": "^2.2.6",
|
"classnames": "^2.2.6",
|
||||||
"immutability-helper": "^3.0.2",
|
"immutability-helper": "^3.0.2",
|
||||||
"material-ui-image": "^3.2.3",
|
"material-ui-image": "^3.2.3",
|
||||||
|
"rc-slider": "^9.2.4",
|
||||||
"react": "^16.12.0",
|
"react": "^16.12.0",
|
||||||
"react-axios": "^2.0.3",
|
"react-axios": "^2.0.3",
|
||||||
"react-circular-input": "^0.1.6",
|
"react-circular-input": "^0.1.6",
|
||||||
|
|
BIN
smart-hut/public/img/camera-icon-simulation.png
Normal file
After Width: | Height: | Size: 34 KiB |
BIN
smart-hut/public/img/humidity-simulation.png
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
smart-hut/public/img/insensity-light-simulation.png
Normal file
After Width: | Height: | Size: 28 KiB |
BIN
smart-hut/public/img/intensity-icon-simulation-2.png
Normal file
After Width: | Height: | Size: 35 KiB |
BIN
smart-hut/public/img/light-simulation.png
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
smart-hut/public/img/motion-simulation.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
smart-hut/public/img/thermo-simulation.png
Normal file
After Width: | Height: | Size: 34 KiB |
15
smart-hut/src/components/DropdownSimulation.js
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { Dropdown } from 'semantic-ui-react';
|
||||||
|
|
||||||
|
const options = [
|
||||||
|
{ key: 'Living Room', text: 'Living Room', value: 'Living Room' },
|
||||||
|
{ key: 'Kitchen', text: 'Kitchen', value: 'Kitchen' },
|
||||||
|
{ key: 'Garden', text: 'Garden', value: 'Garden' },
|
||||||
|
{ key: 'Bedroom 1', text: 'Bedroom 1', value: 'Bedroom 1' },
|
||||||
|
];
|
||||||
|
|
||||||
|
const DropdownSimulation = () => (
|
||||||
|
<Dropdown placeholder="Skills" fluid multiple selection options={options} />
|
||||||
|
);
|
||||||
|
|
||||||
|
export default DropdownSimulation;
|
|
@ -8,10 +8,10 @@ import {
|
||||||
Checkbox,
|
Checkbox,
|
||||||
Segment, Image,
|
Segment, Image,
|
||||||
} from 'semantic-ui-react';
|
} from 'semantic-ui-react';
|
||||||
|
|
||||||
import { withRouter } from 'react-router-dom';
|
import { withRouter } from 'react-router-dom';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { RemoteService } from '../remote';
|
import { RemoteService } from '../remote';
|
||||||
|
import SimulationPanel from './SimulationPanel';
|
||||||
|
|
||||||
const IconHomeImage = () => (
|
const IconHomeImage = () => (
|
||||||
<Image
|
<Image
|
||||||
|
@ -25,10 +25,10 @@ const IconHomeImage = () => (
|
||||||
|
|
||||||
const TitleImage = () => <Image src="sm_logo.png" size="medium" centered />;
|
const TitleImage = () => <Image src="sm_logo.png" size="medium" centered />;
|
||||||
|
|
||||||
export class MyHeader extends React.Component {
|
class MyHeader extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
this.state = { simulationPanel: undefined };
|
||||||
this.getInfo();
|
this.getInfo();
|
||||||
this.logout = this.logout.bind(this);
|
this.logout = this.logout.bind(this);
|
||||||
}
|
}
|
||||||
|
@ -53,16 +53,37 @@ export class MyHeader extends React.Component {
|
||||||
.catch((err) => console.error('Camera enabled', err));
|
.catch((err) => console.error('Camera enabled', err));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
openSimulationPanel = () => {
|
||||||
|
this.setState((state) => ({ simulationPanel: true }));
|
||||||
|
};
|
||||||
|
|
||||||
|
closeSimulationPanel = () => {
|
||||||
|
this.setState((state) => ({ simulationPanel: undefined }));
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
<SimulationPanel
|
||||||
|
simulationPanel={this.state.simulationPanel}
|
||||||
|
closeSimulationPanel={this.closeSimulationPanel}
|
||||||
|
/>
|
||||||
<Responsive minWidth={768}>
|
<Responsive minWidth={768}>
|
||||||
<Grid columns="equal" divided inverted padded>
|
<Grid columns="equal" divided inverted padded>
|
||||||
<Grid.Row color="black" textAlign="center">
|
<Grid.Row color="black" textAlign="center">
|
||||||
<Grid.Column width={4} height={0.5}>
|
<Grid.Column width={4} height={0.5}>
|
||||||
<Segment color="black" inverted>
|
<Grid.Row>
|
||||||
<IconHomeImage />
|
<Segment color="black" inverted>
|
||||||
</Segment>
|
<IconHomeImage />
|
||||||
|
</Segment>
|
||||||
|
</Grid.Row>
|
||||||
|
<Divider />
|
||||||
|
<Grid.Row>
|
||||||
|
<div onClick={this.openSimulationPanel}>
|
||||||
|
<Button> Similuation Panel </Button>
|
||||||
|
</div>
|
||||||
|
</Grid.Row>
|
||||||
</Grid.Column>
|
</Grid.Column>
|
||||||
<Grid.Column>
|
<Grid.Column>
|
||||||
<Segment color="black" inverted>
|
<Segment color="black" inverted>
|
||||||
|
@ -78,6 +99,7 @@ export class MyHeader extends React.Component {
|
||||||
<Button basic inverted onClick={this.logout}>
|
<Button basic inverted onClick={this.logout}>
|
||||||
Logout
|
Logout
|
||||||
</Button>
|
</Button>
|
||||||
|
<Divider />
|
||||||
<Segment
|
<Segment
|
||||||
compact
|
compact
|
||||||
style={{
|
style={{
|
||||||
|
@ -89,7 +111,6 @@ export class MyHeader extends React.Component {
|
||||||
<Checkbox
|
<Checkbox
|
||||||
label={<label>Share cameras</label>}
|
label={<label>Share cameras</label>}
|
||||||
checked={this.props.cameraEnabled}
|
checked={this.props.cameraEnabled}
|
||||||
toggle
|
|
||||||
onChange={(e, val) => this.setCameraEnabled(val.checked)}
|
onChange={(e, val) => this.setCameraEnabled(val.checked)}
|
||||||
/>
|
/>
|
||||||
</Segment>
|
</Segment>
|
||||||
|
@ -106,30 +127,43 @@ export class MyHeader extends React.Component {
|
||||||
</Grid.Row>
|
</Grid.Row>
|
||||||
<Grid.Row color="black" textAlign="center">
|
<Grid.Row color="black" textAlign="center">
|
||||||
<Grid.Column>
|
<Grid.Column>
|
||||||
<IconHomeImage />
|
<Grid.Row>
|
||||||
</Grid.Column>
|
<IconHomeImage />
|
||||||
<Grid.Column>
|
</Grid.Row>
|
||||||
<Label as="a" image color="black">
|
|
||||||
<img alt="SmartHut logo" src="smart-home.png" />
|
|
||||||
{this.props.username}
|
|
||||||
</Label>
|
|
||||||
<Divider />
|
<Divider />
|
||||||
<Button onClick={this.logout}>Logout</Button>
|
<Grid.Row>
|
||||||
<Segment
|
<div onClick={this.openSimulationPanel}>
|
||||||
compact
|
<Button> Similuation Panel </Button>
|
||||||
style={{
|
</div>
|
||||||
|
</Grid.Row>
|
||||||
|
</Grid.Column>
|
||||||
|
<Divider />
|
||||||
|
<Grid.Column>
|
||||||
|
<Grid.Column width={4} heigth={1}>
|
||||||
|
<Label as="a" image color="black">
|
||||||
|
<img alt="SmartHut logo" src="smart-home.png" />
|
||||||
|
{this.props.username}
|
||||||
|
</Label>
|
||||||
|
<Divider />
|
||||||
|
<Button basic inverted onClick={this.logout}>
|
||||||
|
Logout
|
||||||
|
</Button>
|
||||||
|
<Divider />
|
||||||
|
<Segment
|
||||||
|
compact
|
||||||
|
style={{
|
||||||
margin: 'auto',
|
margin: 'auto',
|
||||||
marginTop: '1em',
|
marginTop: '1em',
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
label={<label>Share cameras</label>}
|
label={<label>Share cameras</label>}
|
||||||
checked={this.props.cameraEnabled}
|
checked={this.props.cameraEnabled}
|
||||||
toggle
|
onChange={(e, val) => this.setCameraEnabled(val.checked)}
|
||||||
onChange={(e, val) => this.setCameraEnabled(val.checked)}
|
/>
|
||||||
/>
|
</Segment>
|
||||||
</Segment>
|
</Grid.Column>
|
||||||
</Grid.Column>
|
</Grid.Column>
|
||||||
</Grid.Row>
|
</Grid.Row>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
428
smart-hut/src/components/SimulationPanel.js
Normal file
|
@ -0,0 +1,428 @@
|
||||||
|
import React, { Component } from 'react';
|
||||||
|
import {
|
||||||
|
Grid,
|
||||||
|
Divider,
|
||||||
|
Image,
|
||||||
|
Modal,
|
||||||
|
Button,
|
||||||
|
} from 'semantic-ui-react';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import { RemoteService } from '../remote';
|
||||||
|
import SimulationPanelSlider from './SimulationPanelSlider.js';
|
||||||
|
|
||||||
|
/*
|
||||||
|
const SimulationPanel = (props) => (
|
||||||
|
<Modal
|
||||||
|
isOpen={!!props.simulationPanel}
|
||||||
|
contentLabel="Simulation Panel"
|
||||||
|
onRequestClose={props.closeSimulationPanel}
|
||||||
|
// style={ReactModalPortal,ReactModal__Overlay, modal}
|
||||||
|
style={{
|
||||||
|
overlay: {
|
||||||
|
position: 'fixed',
|
||||||
|
top: 0,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
bottom: 0,
|
||||||
|
backgroundColor: 'rgba(0,0,0,0.5)',
|
||||||
|
},
|
||||||
|
content: {
|
||||||
|
position: 'absolute',
|
||||||
|
top: '40px',
|
||||||
|
left: '40px',
|
||||||
|
right: '40px',
|
||||||
|
bottom: '40px',
|
||||||
|
border: '1px solid #ccc',
|
||||||
|
background: '#fff',
|
||||||
|
overflow: 'auto',
|
||||||
|
WebkitOverflowScrolling: 'touch',
|
||||||
|
borderRadius: '4px',
|
||||||
|
outline: 'none',
|
||||||
|
padding: '20px',
|
||||||
|
backgroundColor: 'rgb(65, 67, 69)',
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{props.simulationPanel}
|
||||||
|
<Grid celled>
|
||||||
|
|
||||||
|
{/* TITLE }
|
||||||
|
<Grid.Row textAlign="center">
|
||||||
|
<h1 style={{ color: 'white', padding: '1rem', fontFamily: 'Arial' }}>
|
||||||
|
Welcome in the Simulation Panel
|
||||||
|
</h1>
|
||||||
|
</Grid.Row>
|
||||||
|
|
||||||
|
{/* TEMPERATURE SENSOR }
|
||||||
|
<Grid.Row>
|
||||||
|
<Grid.Column width={6} textAlign="center">
|
||||||
|
<Divider
|
||||||
|
style={{
|
||||||
|
marginTop: '3rem',
|
||||||
|
marginBottom: 'auto',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Image
|
||||||
|
src="./../img/thermo-simulation.png"
|
||||||
|
style={{
|
||||||
|
width: '60px',
|
||||||
|
height: 'auto',
|
||||||
|
display: 'block',
|
||||||
|
marginLeft: 'auto',
|
||||||
|
marginRight: 'auto',
|
||||||
|
marginTop: '1rem',
|
||||||
|
marginBottom: '1rem',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<p style={{ color: 'white', padding: '0.5rem' }}>
|
||||||
|
Temperature Sensor
|
||||||
|
</p>
|
||||||
|
<Divider />
|
||||||
|
</Grid.Column>
|
||||||
|
|
||||||
|
|
||||||
|
<Grid.Column width={10} textAlign="center">
|
||||||
|
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: 'block',
|
||||||
|
marginLeft: '30%',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<SimulationPanelSlider />
|
||||||
|
</div>
|
||||||
|
<Divider />
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: 'block',
|
||||||
|
marginLeft: '30%',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<SimulationPanelSlider />
|
||||||
|
</div>
|
||||||
|
</Grid.Column>
|
||||||
|
</Grid.Row>
|
||||||
|
|
||||||
|
{/* HUMIDTY SENSOR }
|
||||||
|
<Grid.Row>
|
||||||
|
<Grid.Column width={6} textAlign="center">
|
||||||
|
<Divider
|
||||||
|
style={{
|
||||||
|
marginTop: '3rem',
|
||||||
|
marginBottom: 'auto',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Image
|
||||||
|
src="./../img/humidity-simulation.png"
|
||||||
|
style={{
|
||||||
|
width: '60px',
|
||||||
|
height: 'auto',
|
||||||
|
display: 'block',
|
||||||
|
marginLeft: 'auto',
|
||||||
|
marginRight: 'auto',
|
||||||
|
marginTop: '1rem',
|
||||||
|
marginBottom: '1rem',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<p style={{ color: 'white', padding: '0.5rem' }}>
|
||||||
|
Humidity Sensor
|
||||||
|
</p>
|
||||||
|
<Divider />
|
||||||
|
</Grid.Column>
|
||||||
|
|
||||||
|
|
||||||
|
<Grid.Column width={10} textAlign="center">
|
||||||
|
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: 'block',
|
||||||
|
marginLeft: '30%',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<SimulationPanelSlider />
|
||||||
|
</div>
|
||||||
|
<Divider />
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: 'block',
|
||||||
|
marginLeft: '30%',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<SimulationPanelSlider />
|
||||||
|
</div>
|
||||||
|
</Grid.Column>
|
||||||
|
</Grid.Row>
|
||||||
|
|
||||||
|
{/* LIGHT SENSOR }
|
||||||
|
<Grid.Row>
|
||||||
|
<Grid.Column width={6} textAlign="center">
|
||||||
|
<Divider
|
||||||
|
style={{
|
||||||
|
marginTop: '3rem',
|
||||||
|
marginBottom: 'auto',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Image
|
||||||
|
src="./../img/light-simulation.png"
|
||||||
|
style={{
|
||||||
|
width: '60px',
|
||||||
|
height: 'auto',
|
||||||
|
display: 'block',
|
||||||
|
marginLeft: 'auto',
|
||||||
|
marginRight: 'auto',
|
||||||
|
marginTop: '1rem',
|
||||||
|
marginBottom: '1rem',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<p style={{ color: 'white', padding: '0.5rem' }}>
|
||||||
|
Light Sensor
|
||||||
|
</p>
|
||||||
|
<Divider />
|
||||||
|
</Grid.Column>
|
||||||
|
|
||||||
|
|
||||||
|
<Grid.Column width={10} textAlign="center">
|
||||||
|
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: 'block',
|
||||||
|
marginLeft: '30%',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<SimulationPanelSlider />
|
||||||
|
</div>
|
||||||
|
<Divider />
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: 'block',
|
||||||
|
marginLeft: '30%',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<SimulationPanelSlider />
|
||||||
|
</div>
|
||||||
|
</Grid.Column>
|
||||||
|
</Grid.Row>
|
||||||
|
|
||||||
|
{/* MOTION SENSOR }
|
||||||
|
<Grid.Row>
|
||||||
|
<Grid.Column width={6} textAlign="center">
|
||||||
|
<Divider
|
||||||
|
style={{
|
||||||
|
marginTop: '3rem',
|
||||||
|
marginBottom: 'auto',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Image
|
||||||
|
src="./../img/motion-simulation.png"
|
||||||
|
style={{
|
||||||
|
width: '60px',
|
||||||
|
height: 'auto',
|
||||||
|
display: 'block',
|
||||||
|
marginLeft: 'auto',
|
||||||
|
marginRight: 'auto',
|
||||||
|
marginTop: '1rem',
|
||||||
|
marginBottom: '1rem',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<p style={{ color: 'white', padding: '0.5rem' }}>
|
||||||
|
Motion Sensor
|
||||||
|
</p>
|
||||||
|
<Divider />
|
||||||
|
</Grid.Column>
|
||||||
|
|
||||||
|
|
||||||
|
<Grid.Column width={10} textAlign="center">
|
||||||
|
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: 'block',
|
||||||
|
marginLeft: '30%',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<SimulationPanelSlider />
|
||||||
|
</div>
|
||||||
|
<Divider />
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: 'block',
|
||||||
|
marginLeft: '30%',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<SimulationPanelSlider />
|
||||||
|
</div>
|
||||||
|
</Grid.Column>
|
||||||
|
</Grid.Row>
|
||||||
|
|
||||||
|
|
||||||
|
</Grid>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
*/
|
||||||
|
class SimulationPanel extends Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
console.log(this.props.devices);
|
||||||
|
this.state = {
|
||||||
|
value: null,
|
||||||
|
error: null,
|
||||||
|
};
|
||||||
|
this.updateSliderValues = this.updateSliderValues.bind(this);
|
||||||
|
this.saveChanges = this.saveChanges.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateSliderValues(type, data, motion) {
|
||||||
|
console.log(data, motion);
|
||||||
|
this.setState({
|
||||||
|
[type ? 'error' : 'value']: data,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
saveChanges(device) {
|
||||||
|
console.log(this.state);
|
||||||
|
const { value } = this.state;
|
||||||
|
const { error } = this.state;
|
||||||
|
if (device.kind === 'sensor') {
|
||||||
|
this.props
|
||||||
|
.updateSimulation(
|
||||||
|
{ ...device, typical: value, err: error },
|
||||||
|
)
|
||||||
|
.catch((err) => console.error('Simulation panel update error', err));
|
||||||
|
} else {
|
||||||
|
const val = device.kind === 'motionSensor' ? 'detected' : 'typical';
|
||||||
|
this.props
|
||||||
|
.saveDevice(
|
||||||
|
{ ...device, [val]: value, err: error },
|
||||||
|
null,
|
||||||
|
)
|
||||||
|
.catch((err) => console.error('Simulation panel update error', err));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
renderImage(device) {
|
||||||
|
let image = './../img/';
|
||||||
|
switch (device.kind) {
|
||||||
|
case 'thermostat':
|
||||||
|
image += 'thermo-simulation.png';
|
||||||
|
break;
|
||||||
|
case 'motionSensor':
|
||||||
|
image += 'motion-simulation.png';
|
||||||
|
break;
|
||||||
|
case 'sensor':
|
||||||
|
if (device.sensorType === 'TEMPERATURE') {
|
||||||
|
image += 'thermo-simulation.png';
|
||||||
|
} else if (device.sensorType === 'HUMIDITY') {
|
||||||
|
image += 'humidity-simulation.png';
|
||||||
|
} else {
|
||||||
|
image += 'light-simulation.png';
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Image
|
||||||
|
src={image}
|
||||||
|
style={{
|
||||||
|
width: '60px',
|
||||||
|
height: 'auto',
|
||||||
|
display: 'block',
|
||||||
|
marginLeft: 'auto',
|
||||||
|
marginRight: 'auto',
|
||||||
|
marginTop: '1rem',
|
||||||
|
marginBottom: '1rem',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
closeIcon
|
||||||
|
open={!!this.props.simulationPanel}
|
||||||
|
onClose={this.props.closeSimulationPanel}
|
||||||
|
>
|
||||||
|
<Grid celled>
|
||||||
|
<Grid.Row textAlign="center">
|
||||||
|
<h1 style={{ padding: '1rem', fontFamily: 'Arial' }}>
|
||||||
|
Welcome in the Simulation Panel
|
||||||
|
</h1>
|
||||||
|
</Grid.Row>
|
||||||
|
{
|
||||||
|
this.props.devices
|
||||||
|
? this.props.devices.map((d, i) => (
|
||||||
|
<Grid.Row key={i}>
|
||||||
|
<Grid.Column width={6} textAlign="center">
|
||||||
|
{this.renderImage(d)}
|
||||||
|
<p style={{ padding: '0.5rem' }}>
|
||||||
|
{d.name}
|
||||||
|
</p>
|
||||||
|
<Divider />
|
||||||
|
<Button
|
||||||
|
color="green"
|
||||||
|
id={d.id}
|
||||||
|
onClick={(e, { id }) => this.saveChanges(d, id)}
|
||||||
|
>
|
||||||
|
Save
|
||||||
|
</Button>
|
||||||
|
</Grid.Column>
|
||||||
|
|
||||||
|
|
||||||
|
<Grid.Column width={10} textAlign="center">
|
||||||
|
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: 'block',
|
||||||
|
marginLeft: '30%',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<SimulationPanelSlider update={this.updateSliderValues} error={false} device={d} id={d.id} />
|
||||||
|
</div>
|
||||||
|
{
|
||||||
|
d.kind === 'motionSensor'
|
||||||
|
? null
|
||||||
|
: (
|
||||||
|
<>
|
||||||
|
<Divider />
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: 'block',
|
||||||
|
marginLeft: '30%',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<SimulationPanelSlider update={this.updateSliderValues} error device={d} id={d.id} />
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</Grid.Column>
|
||||||
|
</Grid.Row>
|
||||||
|
))
|
||||||
|
: null
|
||||||
|
}
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapStateToProps = (state, _) => ({
|
||||||
|
get devices() {
|
||||||
|
const deviceInternalSensor = {
|
||||||
|
thermostat: 'Thermostat',
|
||||||
|
sensor: 'Sensor',
|
||||||
|
motionSensor: 'Sensor',
|
||||||
|
};
|
||||||
|
const deviceArray = [
|
||||||
|
...Object.values(state.devices),
|
||||||
|
].filter((e) => e.kind in deviceInternalSensor);
|
||||||
|
return deviceArray;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const SimulationPanelContainer = connect(
|
||||||
|
mapStateToProps,
|
||||||
|
RemoteService,
|
||||||
|
)(SimulationPanel);
|
||||||
|
export default SimulationPanelContainer;
|
130
smart-hut/src/components/SimulationPanelSlider.js
Normal file
|
@ -0,0 +1,130 @@
|
||||||
|
import React, { Component } from 'react';
|
||||||
|
import {
|
||||||
|
Form, Grid, Checkbox, Message, Label,
|
||||||
|
} from 'semantic-ui-react';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import { RemoteService } from '../remote';
|
||||||
|
|
||||||
|
class SimulationPanelSlider extends Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
console.log(this.props.device);
|
||||||
|
this.state = {
|
||||||
|
value: this.internalValue,
|
||||||
|
error: this.internalValue,
|
||||||
|
};
|
||||||
|
this.updateSliderValues = this.updateSliderValues.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateSliderValues(data) {
|
||||||
|
this.setState({
|
||||||
|
[this.props.error ? 'error' : 'value']: data,
|
||||||
|
});
|
||||||
|
console.log(this.state);
|
||||||
|
this.props.update(this.props.error, data, this.props.device.kind === 'motionSensor');
|
||||||
|
}
|
||||||
|
|
||||||
|
settings() {
|
||||||
|
let max;
|
||||||
|
let step;
|
||||||
|
switch (this.props.device.kind) {
|
||||||
|
case 'sensor':
|
||||||
|
if (this.props.device.sensorType === 'LIGHT') {
|
||||||
|
max = this.props.error ? 1000 : 15000;
|
||||||
|
step = 10;
|
||||||
|
} else {
|
||||||
|
max = 100;
|
||||||
|
step = 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'thermostat':
|
||||||
|
max = 100;
|
||||||
|
step = 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return { max, step };
|
||||||
|
}
|
||||||
|
|
||||||
|
get internalValue() {
|
||||||
|
if (this.props.device.kind === 'motionSensor') {
|
||||||
|
return this.props.device.detected;
|
||||||
|
}
|
||||||
|
return this.props.error ? this.props.device.err : this.props.device.typical.toFixed(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
get getValue() {
|
||||||
|
switch (this.props.device.kind) {
|
||||||
|
case 'motionSensor':
|
||||||
|
return this.props.device.detected;
|
||||||
|
case 'thermostat':
|
||||||
|
return this.props.device.internalSensorTemperature;
|
||||||
|
case 'sensor':
|
||||||
|
return this.props.device.value.toFixed(2);
|
||||||
|
default:
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<Grid columns={2}>
|
||||||
|
<Grid.Column as={Form} textAlign="center">
|
||||||
|
<Message>
|
||||||
|
<Message.Header>{this.props.error ? 'Edit error' : 'Edit value'}</Message.Header>
|
||||||
|
<p>
|
||||||
|
Actual value of
|
||||||
|
{' '}
|
||||||
|
{this.props.device.name}
|
||||||
|
:
|
||||||
|
{this.props.device.kind === 'motionSensor'
|
||||||
|
? this.getValue ? 'on' : 'off' : this.getValue}
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
{this.props.error ? 'error' : 'typical value'}
|
||||||
|
{' '}
|
||||||
|
:
|
||||||
|
{this.props.device.kind === 'motionSensor'
|
||||||
|
? this.internalValue ? 'on' : 'off' : this.internalValue}
|
||||||
|
</p>
|
||||||
|
</Message>
|
||||||
|
{
|
||||||
|
this.props.device.kind === 'motionSensor'
|
||||||
|
? (
|
||||||
|
<Checkbox
|
||||||
|
toggle
|
||||||
|
name="value"
|
||||||
|
checked={this.state.value}
|
||||||
|
onChange={(e, { checked }) => this.updateSliderValues(checked)}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
: (
|
||||||
|
<>
|
||||||
|
<Label>
|
||||||
|
Value :
|
||||||
|
<Label.Detail>{this.props.error ? this.state.error : this.state.value}</Label.Detail>
|
||||||
|
</Label>
|
||||||
|
<Form.Input
|
||||||
|
min={0}
|
||||||
|
max={this.settings().max}
|
||||||
|
name="value"
|
||||||
|
onChange={(e, { value }) => this.updateSliderValues(value)}
|
||||||
|
step={this.settings().step}
|
||||||
|
type="range"
|
||||||
|
value={this.props.error ? this.state.error : this.state.value}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</Grid.Column>
|
||||||
|
</Grid>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapStateToProps = (state, ownProps) => ({
|
||||||
|
device: state.devices[ownProps.id],
|
||||||
|
});
|
||||||
|
const SimulationPanelSliderContainer = connect(mapStateToProps, RemoteService)(SimulationPanelSlider);
|
||||||
|
export default SimulationPanelSliderContainer;
|
45
smart-hut/src/components/SliderHumidity.js
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
import React, { Component } from 'react';
|
||||||
|
import {
|
||||||
|
Form, Grid, Image, Transition, Divider,
|
||||||
|
} from 'semantic-ui-react';
|
||||||
|
|
||||||
|
|
||||||
|
export default class SliderHumidity extends Component {
|
||||||
|
state = { visible: true, duration: 78 }
|
||||||
|
|
||||||
|
handleChange = (e, { name, value }) => this.setState({ [name]: value })
|
||||||
|
|
||||||
|
handleVisibility = () => this.setState((prevState) => ({ visible: !prevState.visible }))
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { duration } = this.state;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Grid columns={2}>
|
||||||
|
<Grid.Column as={Form} textAlign="center">
|
||||||
|
<p
|
||||||
|
style={{
|
||||||
|
color: 'white',
|
||||||
|
padding: '0.5rem',
|
||||||
|
display: 'block',
|
||||||
|
marinLeft: 'auto',
|
||||||
|
marginRight: 'auto',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{`Humidity: ${duration} %`}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<Form.Input
|
||||||
|
min={0}
|
||||||
|
max={100}
|
||||||
|
name="duration"
|
||||||
|
onChange={this.handleChange}
|
||||||
|
step={1}
|
||||||
|
type="range"
|
||||||
|
value={duration}
|
||||||
|
/>
|
||||||
|
</Grid.Column>
|
||||||
|
</Grid>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
45
smart-hut/src/components/SliderLight.js
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
import React, { Component } from 'react';
|
||||||
|
import {
|
||||||
|
Form, Grid, Image, Transition, Divider,
|
||||||
|
} from 'semantic-ui-react';
|
||||||
|
|
||||||
|
|
||||||
|
export default class SliderLight extends Component {
|
||||||
|
state = { visible: true, duration: 10500 }
|
||||||
|
|
||||||
|
handleChange = (e, { name, value }) => this.setState({ [name]: value })
|
||||||
|
|
||||||
|
handleVisibility = () => this.setState((prevState) => ({ visible: !prevState.visible }))
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { duration } = this.state;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Grid columns={2}>
|
||||||
|
<Grid.Column as={Form} textAlign="center">
|
||||||
|
<p
|
||||||
|
style={{
|
||||||
|
color: 'white',
|
||||||
|
padding: '0.5rem',
|
||||||
|
display: 'block',
|
||||||
|
marinLeft: 'auto',
|
||||||
|
marginRight: 'auto',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{`Light intensity: ${duration} lm`}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<Form.Input
|
||||||
|
min={0}
|
||||||
|
max={15000}
|
||||||
|
name="duration"
|
||||||
|
onChange={this.handleChange}
|
||||||
|
step={5}
|
||||||
|
type="range"
|
||||||
|
value={duration}
|
||||||
|
/>
|
||||||
|
</Grid.Column>
|
||||||
|
</Grid>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
46
smart-hut/src/components/SliderLightRange.js
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
import React, { Component } from 'react';
|
||||||
|
import {
|
||||||
|
Form, Grid, Image, Transition, Divider,
|
||||||
|
} from 'semantic-ui-react';
|
||||||
|
|
||||||
|
|
||||||
|
export default class SliderTempRange extends Component {
|
||||||
|
state = { visible: true, duration: 500 }
|
||||||
|
|
||||||
|
handleChange = (e, { name, value }) => this.setState({ [name]: value })
|
||||||
|
|
||||||
|
handleVisibility = () => this.setState((prevState) => ({ visible: !prevState.visible }))
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { duration } = this.state;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Grid columns={2}>
|
||||||
|
<Grid.Column as={Form} textAlign="center">
|
||||||
|
<p
|
||||||
|
style={{
|
||||||
|
color: 'white',
|
||||||
|
padding: '0.5rem',
|
||||||
|
display: 'block',
|
||||||
|
marinLeft: 'auto',
|
||||||
|
marginRight: 'auto',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{`Chosen tolerance: +/- ${duration}`}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
<Form.Input
|
||||||
|
min={0}
|
||||||
|
max={1000}
|
||||||
|
name="duration"
|
||||||
|
onChange={this.handleChange}
|
||||||
|
step={1}
|
||||||
|
type="range"
|
||||||
|
value={duration}
|
||||||
|
/>
|
||||||
|
</Grid.Column>
|
||||||
|
</Grid>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
45
smart-hut/src/components/SliderMotion.js
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
import React, { Component } from 'react';
|
||||||
|
import {
|
||||||
|
Form, Grid, Image, Transition, Divider,
|
||||||
|
} from 'semantic-ui-react';
|
||||||
|
|
||||||
|
|
||||||
|
export default class SliderLight extends Component {
|
||||||
|
state = { visible: true, duration: 5 }
|
||||||
|
|
||||||
|
handleChange = (e, { name, value }) => this.setState({ [name]: value })
|
||||||
|
|
||||||
|
handleVisibility = () => this.setState((prevState) => ({ visible: !prevState.visible }))
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { duration } = this.state;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Grid columns={2}>
|
||||||
|
<Grid.Column as={Form} textAlign="center">
|
||||||
|
<p
|
||||||
|
style={{
|
||||||
|
color: 'white',
|
||||||
|
padding: '0.5rem',
|
||||||
|
display: 'block',
|
||||||
|
marinLeft: 'auto',
|
||||||
|
marginRight: 'auto',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{`Range: ${duration} meters`}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<Form.Input
|
||||||
|
min={0}
|
||||||
|
max={15}
|
||||||
|
name="duration"
|
||||||
|
onChange={this.handleChange}
|
||||||
|
step={5}
|
||||||
|
type="range"
|
||||||
|
value={duration}
|
||||||
|
/>
|
||||||
|
</Grid.Column>
|
||||||
|
</Grid>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
46
smart-hut/src/components/SliderTempRange.js
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
import React, { Component } from 'react';
|
||||||
|
import {
|
||||||
|
Form, Grid, Image, Transition, Divider,
|
||||||
|
} from 'semantic-ui-react';
|
||||||
|
|
||||||
|
|
||||||
|
export default class SliderTempRange extends Component {
|
||||||
|
state = { visible: true, duration: 5 }
|
||||||
|
|
||||||
|
handleChange = (e, { name, value }) => this.setState({ [name]: value })
|
||||||
|
|
||||||
|
handleVisibility = () => this.setState((prevState) => ({ visible: !prevState.visible }))
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { duration } = this.state;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Grid columns={2}>
|
||||||
|
<Grid.Column as={Form} textAlign="center">
|
||||||
|
<p
|
||||||
|
style={{
|
||||||
|
color: 'white',
|
||||||
|
padding: '0.5rem',
|
||||||
|
display: 'block',
|
||||||
|
marinLeft: 'auto',
|
||||||
|
marginRight: 'auto',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{`Chosen tolerance: +/- ${duration}`}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
<Form.Input
|
||||||
|
min={0}
|
||||||
|
max={10}
|
||||||
|
name="duration"
|
||||||
|
onChange={this.handleChange}
|
||||||
|
step={1}
|
||||||
|
type="range"
|
||||||
|
value={duration}
|
||||||
|
/>
|
||||||
|
</Grid.Column>
|
||||||
|
</Grid>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
45
smart-hut/src/components/SliderTemperature.js
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
import React, { Component } from 'react';
|
||||||
|
import {
|
||||||
|
Form, Grid, Image, Transition, Divider,
|
||||||
|
} from 'semantic-ui-react';
|
||||||
|
|
||||||
|
|
||||||
|
export default class SliderTemperature extends Component {
|
||||||
|
state = { visible: true, duration: 20 }
|
||||||
|
|
||||||
|
handleChange = (e, { name, value }) => this.setState({ [name]: value })
|
||||||
|
|
||||||
|
handleVisibility = () => this.setState((prevState) => ({ visible: !prevState.visible }))
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { duration } = this.state;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Grid columns={2}>
|
||||||
|
<Grid.Column as={Form} textAlign="center">
|
||||||
|
<p
|
||||||
|
style={{
|
||||||
|
color: 'white',
|
||||||
|
padding: '0.5rem',
|
||||||
|
display: 'block',
|
||||||
|
marinLeft: 'auto',
|
||||||
|
marginRight: 'auto',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{`Heat: ${duration} Celsius Degrees`}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<Form.Input
|
||||||
|
min={10}
|
||||||
|
max={35}
|
||||||
|
name="duration"
|
||||||
|
onChange={this.handleChange}
|
||||||
|
step={1}
|
||||||
|
type="range"
|
||||||
|
value={duration}
|
||||||
|
/>
|
||||||
|
</Grid.Column>
|
||||||
|
</Grid>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -653,6 +653,7 @@ class AutomationSaveModal extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
console.log(this.state.conditionsList);
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
closeIcon
|
closeIcon
|
||||||
|
|
|
@ -1,37 +1,42 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Modal from 'react-modal';
|
import Modal from 'react-modal';
|
||||||
import { Button } from 'semantic-ui-react';
|
|
||||||
|
|
||||||
const modal = {
|
|
||||||
opacity: 0,
|
|
||||||
alignItems: 'center',
|
|
||||||
display: 'flex',
|
|
||||||
justifyContent: 'center',
|
|
||||||
transition: 'opacity 200ms ease-in-out',
|
|
||||||
background: 'grey',
|
|
||||||
color: 'white',
|
|
||||||
maxWidth: '2rem',
|
|
||||||
outline: 'none',
|
|
||||||
padding: '2rem',
|
|
||||||
textAlign: 'center',
|
|
||||||
maxHeight: '50vh',
|
|
||||||
};
|
|
||||||
|
|
||||||
const VideocamModal = (props) => (
|
const VideocamModal = (props) => (
|
||||||
<Modal
|
<Modal
|
||||||
isOpen={!!props.selectedVideo}
|
isOpen={!!props.selectedVideo}
|
||||||
contentLabel="Live Cam"
|
contentLabel="Live Cam"
|
||||||
onRequestClose={props.closeModal}
|
onRequestClose={props.closeModal}
|
||||||
style={modal}
|
style={{
|
||||||
|
overlay: {
|
||||||
|
position: 'fixed',
|
||||||
|
top: 0,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
bottom: 0,
|
||||||
|
backgroundColor: 'rgba(0,0,0,0.5)',
|
||||||
|
},
|
||||||
|
content: {
|
||||||
|
position: 'absolute',
|
||||||
|
top: '40px',
|
||||||
|
left: '40px',
|
||||||
|
right: '40px',
|
||||||
|
bottom: '40px',
|
||||||
|
border: '1px solid #ccc',
|
||||||
|
background: '#fff',
|
||||||
|
overflow: 'auto',
|
||||||
|
WebkitOverflowScrolling: 'touch',
|
||||||
|
borderRadius: '4px',
|
||||||
|
outline: 'none',
|
||||||
|
padding: '20px',
|
||||||
|
backgroundColor: 'black',
|
||||||
|
},
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{props.selectedVideo && (
|
{props.selectedVideo && (
|
||||||
<video autoPlay loop muted width="100%" height="90%">
|
<video autoPlay loop muted width="100%" height="90%">
|
||||||
<source src={props.url} type="video/mp4" />
|
<source src={props.url} type="video/mp4" />
|
||||||
</video>
|
</video>
|
||||||
)}
|
)}
|
||||||
<Button fluid primary onClick={props.closeModal}>
|
|
||||||
Close
|
|
||||||
</Button>
|
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -540,6 +540,19 @@ export const RemoteService = {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
updateSimulation: (data) => (dispatch) => {
|
||||||
|
const url = `/sensor/${data.id}/simulation`;
|
||||||
|
return Endpoint.put(url, {}, data)
|
||||||
|
.then((res) => {
|
||||||
|
dispatch(actions.deviceSave(res.data));
|
||||||
|
return res.data;
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.warn('Update device: ', data, 'error: ', err);
|
||||||
|
throw new RemoteError(['Network error']);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
fastUpdateAutomation: (automation) => (dispatch) => Endpoint.put('/automation/fast', {}, automation)
|
fastUpdateAutomation: (automation) => (dispatch) => Endpoint.put('/automation/fast', {}, automation)
|
||||||
.then((res) => dispatch(actions.automationSave(res.data)))
|
.then((res) => dispatch(actions.automationSave(res.data)))
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
|
||||||
# yarn lockfile v1
|
|
||||||
|
|
||||||
|
|