Merge branch 'dev' of lab.si.usi.ch:sa4-2020/the-sanmarinoes/frontend into base64

This commit is contained in:
Nicola Brunner 2020-03-24 15:55:51 +01:00
commit 10aeb75730
57 changed files with 2973 additions and 2463 deletions

View file

@ -42,3 +42,6 @@ smartHut_deploy:
- "docker push smarthutsm/smarthut:${CI_COMMIT_BRANCH}"
after_script:
- docker logout
only:
- dev
- master

12
hooks/pre-commit.sh Executable file
View file

@ -0,0 +1,12 @@
#!/bin/sh
FILES=$(git diff --cached --name-only --diff-filter=ACMR "*.js" "*.jsx" | sed 's| |\\ |g')
[ -z "$FILES" ] && exit 0
# Prettify all selected files
echo "$FILES" | xargs ./smart-hut/node_modules/.bin/prettier --write
# Add back the modified/prettified files to staging
echo "$FILES" | xargs git add
exit 0

14
hooks/setup.sh Executable file
View file

@ -0,0 +1,14 @@
#!/bin/sh
git config --unset core.hooksPath
if [[ -z $(which realpath) ]]; then
this_dir="$(pwd)/hooks"
else
this_dir="$(dirname $(realpath "$0"))"
fi
hook_script="$this_dir/pre-commit.sh"
ln -svf "$hook_script" "$this_dir/../.git/hooks/pre-commit"
echo "Commit hook installed"

View file

@ -15,6 +15,7 @@
"react-axios": "^2.0.3",
"react-circular-input": "^0.1.6",
"react-circular-slider-svg": "^0.1.5",
"react-device-detect": "^1.11.14",
"react-dom": "^16.12.0",
"react-round-slider": "^1.0.1",
"react-router": "^5.1.2",
@ -43,5 +44,8 @@
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"prettier": "2.0.1"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

View file

@ -1,15 +1,23 @@
<!DOCTYPE html>
<html lang="en">
<head>
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<link rel="stylesheet" href="style.css">
<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/semantic-ui@2.4.2/dist/semantic.min.css" />
<link rel="stylesheet" href="style.css" />
<link
rel="stylesheet"
href="//cdn.jsdelivr.net/npm/semantic-ui@2.4.2/dist/semantic.min.css"
/>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta name="description" content="Web site created using create-react-app" />
<meta name="viewport" content="minimum-scale=1, initial-scale=1, width=device-width" />
<meta
name="description"
content="Web site created using create-react-app"
/>
<meta
name="viewport"
content="minimum-scale=1, initial-scale=1, width=device-width"
/>
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
@ -25,9 +33,9 @@
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React App</title>
</head>
</head>
<body>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!--
@ -40,6 +48,5 @@
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</body>
</html>

View file

@ -1,8 +1,7 @@
{
"short_name": "React App",
"name": "Create React App Sample",
"icons": [
],
"icons": [],
"start_url": ".",
"display": "standalone",
"theme_color": "#000000",

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

View file

@ -1,7 +1,6 @@
*{
* {
margin: 0;
padding: 0;
font-family: "Lato", Helvetica, SansSerif, serif;
}
/*background: linear-gradient(to bottom, rgba(0, 46, 200, 0.51), rgba(0, 0, 0, 0.51));*/

View file

@ -1,5 +1,5 @@
import React, {Component} from "react";
import {BrowserRouter, Switch, Route, Redirect } from "react-router-dom";
import React, { Component } from "react";
import { BrowserRouter, Switch, Route, Redirect } from "react-router-dom";
import Home from "./views/Home";
import Dashboard from "./views/Dashboard";
import Signup from "./views/Signup";
@ -10,9 +10,9 @@ import ChangePass from "./views/Forgot-pass-reset";
import ConfirmForgotPasswrod from "./views/ConfirmForgotPassword";
import ConfirmRegistration from "./views/ConfirmRegistration";
import Instruction from "./views/Instruction";
import queryString from 'query-string';
import queryString from "query-string";
import { call } from './client_server';
import { call } from "./client_server";
/*let userJsonString = JSON.parse(localStorage.getItem("token"));
let date = new Date().getTime().toString();
@ -33,10 +33,11 @@ class App extends Component {
let date = new Date().getTime();
if (userJsonString && exp && date < exp) {
loggedIn = true;
} else {
localStorage.removeItem("token");
localStorage.removeItem("exp");
}
}catch(exception) {
}
} catch (exception) {}
this.state = {
loggedIn: loggedIn,
@ -49,80 +50,89 @@ class App extends Component {
componentDidMount() {
if (window.location) {
const values = queryString.parse(window.location.search);
console.log(values);
this.setState({
query : values
query: values,
});
} else {
this.setState({
query : "ciao"
query: "ciao",
});
}
}
auth(data) {
return call.login(data.params)
.then(res => {
return call
.login(data.params)
.then((res) => {
if (res.data && res.status === 200) {
let expire = new Date().getTime() + 60 * 60 * 5 * 1000;
localStorage.setItem("token", res.data.jwttoken);
localStorage.setItem("exp", new Date().getTime() + (60*60*5))
localStorage.setItem("exp", expire);
call.setToken(res.data.jwttoken);
this.setState(
{
this.setState({
user: data.params.user,
token: res.data.jwttoken,
loggedIn: true,
}
);
});
return res;
//this.props.history.push("/dashboard");
} else {
this.setState({
error: res.data.message
error: res.data.message,
});
return this.state.error;
}
}).catch(err => {
})
.catch((err) => {
console.log(err);
return {status : "Errore"};
return { status: "Errore" };
});
};
}
logout() {
this.setState({
loggedIn : false,
loggedIn: false,
});
localStorage.removeItem("token");
};
localStorage.removeItem("exp");
}
render() {
return (
<BrowserRouter>
<Switch>
<Route path="/" exact component={Home} />
<Route path="/login" >
{ this.state.loggedIn && this.state.token ? <Redirect tkn={this.state.token} to="/dashboard" /> : <Login auth={this.auth} /> }
<Route path="/login">
{this.state.loggedIn && this.state.token ? (
<Redirect tkn={this.state.token} to="/dashboard" />
) : (
<Login auth={this.auth} />
)}
</Route>
<Route path="/signup" exact component={Signup} />
<Route path="/dashboard" >
{this.state.loggedIn ? <Dashboard tkn={this.state.token} logout={this.logout} /> : <Redirect to="/login" />}
<Route path="/dashboard">
{this.state.loggedIn ? (
<Dashboard tkn={this.state.token} logout={this.logout} />
) : (
<Redirect to="/login" />
)}
</Route>
<Route path="/forgot-password" >
<Route path="/forgot-password">
<ForgotPass />
</Route>
<Route path="/sent-email" >
<Route path="/sent-email">
<ConfirmForgotPasswrod />
</Route>
<Route path="/sent-email-reg" >
<Route path="/sent-email-reg">
<ConfirmRegistration />
</Route>
<Route path="/instruction" >
<Route path="/instruction">
<Instruction />
</Route>
<Route path="/forgot-pass-reset" > </Route>
<Route path="/password-reset" >
<ChangePass query={this.state.query}/>
<Route path="/forgot-pass-reset"> </Route>
<Route path="/password-reset">
<ChangePass query={this.state.query} />
</Route>
<Route component={FourOhFour} />
</Switch>
@ -132,4 +142,3 @@ class App extends Component {
}
export default App;

View file

@ -1,8 +1,8 @@
import React from 'react';
import { render } from '@testing-library/react';
import React from "react";
import { render } from "@testing-library/react";
import { Router } from "react-router";
import { createMemoryHistory } from "history";
import App from './App';
import App from "./App";
test("redirects to homepage", () => {
const history = createMemoryHistory();
@ -13,4 +13,3 @@ test("redirects to homepage", () => {
);
expect(history.location.pathname).toBe("/");
});

View file

@ -1,8 +1,13 @@
import axios from 'axios';
// vim: set ts=2 sw=2 et tw=80:
let config = 'http://localhost:8080/';
import axios from "axios";
let config = "http://localhost:8080/";
var tkn = localStorage.getItem("token");
/** the ServiceSocket instance valid for the current session */
var socket;
// requests data devices
/*
@ -25,66 +30,215 @@ var tkn = localStorage.getItem("token");
*/
/** The number of times a connection to the socket was tried */
var retries = 0;
/** Class to handle connection with the sensor socket */
class ServiceSocket {
/**
* Create a new sensor socket connection
* @param {string} token - The JWT token (needed for authentication)
* @param {Object.<number, function>|null} callbacks - A callback map from
* device id to callback function
*/
constructor(token, callbacks) {
this.token = token;
this.authenticated = false;
this.callbacks = callbacks || {};
this.connection = new WebSocket("ws://localhost:8080/sensor-socket");
this.connection.onopen = (evt) => {
this.connection.send(JSON.stringify({ token }));
};
this.connection.onmessage = (evt) => {
let data = JSON.parse(evt.data);
if (!this.authenticated) {
if (data.authenticated) {
this.authenticated = true;
retries = 0;
} else {
console.error("socket authentication failed");
}
} else {
if (data.id && this.callbacks[data.id]) {
this.callbacks[data.id].forEach((f) => f(data));
}
}
};
this.connection.onerror = (evt) => {
if (retries >= 5) {
console.error("too many socket connection retries");
return;
}
retries++;
socket = new ServiceSocket(this.token, this.callbacks);
};
}
/**
* Registers a new callback function to be called when updates on the device
* with the id given are recieved
* @param {number} id - the id of the device to check updates for
* @param {function} stateCallback - a function that recieves a device as the
* first parameter, that will be called whenever a update is recieved
*/
subscribe(id, stateCallback) {
if (this.callbacks[id] === undefined) {
this.callbacks[id] = [];
}
this.callbacks[id].push(stateCallback);
}
/**
* Unregisters a function previously registered with `subscribe(...)`.
* @param {number} id - the id of the device to stop checking updates for
* @param {function} stateCallback - the callback to unregister
*/
unsubscribe(id, stateCallback) {
this.callbacks[id].splice(this.callbacks[id].indexOf(stateCallback), 1);
}
/**
* Closes the underlying websocket connection
*/
close() {
this.connection.close();
}
}
if (tkn) {
socket = new ServiceSocket(tkn);
}
export var call = {
setToken: function(token) {
setToken: function (token) {
tkn = token;
if (tkn) {
if (socket) {
socket.close();
}
socket = new ServiceSocket(tkn);
}
},
login: function(data, headers) {
return axios.post(config +'auth/login', data)
/**
* Registers a new callback function to be called when updates on the device
* with the id given are recieved
* @param {number} id - the id of the device to check updates for
* @param {function} stateCallback - a function that recieves a device as the
* first parameter, that will be called whenever a update is recieved
*/
socketSubscribe: function (id, callback) {
socket.subscribe(id, callback);
},
register: function(data, headers) {
return axios.post(config + 'register', data)
/**
* Unregisters a function previously registered with `subscribe(...)`.
* @param {number} id - the id of the device to stop checking updates for
* @param {function} stateCallback - the callback to unregister
*/
socketUnsubscribe: function (id, callback) {
socket.unsubscribe(id, callback);
},
initResetPassword: function(data, headers) {
return axios.post(config + 'register/init-reset-password', data)
login: function (data, headers) {
return axios.post(config + "auth/login", data);
},
resetPassword: function(data, headers) {
return axios.put(config + 'register/reset-password', data)
register: function (data, headers) {
return axios.post(config + "register", data);
},
getAllRooms: function(token) {
if (!token){
initResetPassword: function (data, headers) {
return axios.post(config + "register/init-reset-password", data);
},
resetPassword: function (data, headers) {
return axios.put(config + "register/reset-password", data);
},
getAllRooms: function (token) {
if (!token) {
token = tkn;
}
return axios.get(config + 'room', { headers: { Authorization : "Bearer " + token } })
return axios.get(config + "room", {
headers: { Authorization: "Bearer " + token },
});
},
getAllDevices: function(token) {
if (!token){
getAllDevices: function (token) {
if (!token) {
token = tkn;
}
return axios.get(config + 'device', { headers: { Authorization : "Bearer " + token } });
return axios.get(config + "device", {
headers: { Authorization: "Bearer " + token },
});
},
getAllDevicesByRoom: function(id, token) {
if (!token){
getAllDevicesByRoom: function (id, token) {
if (!token) {
token = tkn;
}
return axios.get(config + 'room/' + id + '/devices' , { headers: { Authorization : "Bearer " + token } });
return axios.get(config + "room/" + id + "/devices", {
headers: { Authorization: "Bearer " + token },
});
},
createRoom: function(data, headers) {
return axios.post(config + 'room', data, { headers: { Authorization : "Bearer " + tkn } })
createRoom: function (data, headers) {
return axios.post(config + "room", data, {
headers: { Authorization: "Bearer " + tkn },
});
},
updateRoom: function(data, headers) {
return axios.put(config + 'room?name='+ data.name, data, { headers: { Authorization : "Bearer " + tkn } })
updateRoom: function (data, headers) {
return axios.put(config + "room/" + data.id, data, {
headers: { Authorization: "Bearer " + tkn },
});
},
deleteRoom: function(data, headers) {
return axios.delete(config + 'room/'+data.id, { headers: { Authorization : "Bearer " + tkn } });
deleteRoom: function (data, headers) {
return axios.delete(config + "room/" + data.id, {
headers: { Authorization: "Bearer " + tkn },
});
},
devicePost: function(data, headers) {
return axios.post(config + data.device, data.params, { headers: { Authorization : "Bearer " + tkn } })
devicePost: function (data, headers) {
return axios
.post(config + data.device, data.params, {
headers: { Authorization: "Bearer " + tkn },
})
.then((res) => {
if (res.status === 200 && data.device === "switch") {
data.params.lights.forEach((e) => {
let urlUp =
config +
data.device +
"/" +
res.data.id +
"/lights?switchableId=" +
e;
axios.post(
urlUp,
{},
{ headers: { Authorization: "Bearer " + tkn } }
);
});
}
return res;
});
},
deviceUpdate: function(data, typeDevice) {
let url = 'device';
deviceUpdate: function (data, typeDevice) {
let url = "device";
if (typeDevice) {
url = typeDevice;
}
return axios.put(config + url, data, { headers: { Authorization : "Bearer " + tkn } })
return axios.put(config + url, data, {
headers: { Authorization: "Bearer " + tkn },
});
},
deviceDelete: function(data, headers) {
return axios.delete(config + data.device + '/' + data.id, {}, { headers: { Authorization : "Bearer " + tkn } })
deviceDelete: function (data, headers) {
return axios.delete(config + data.device + "/" + data.id, {
headers: { Authorization: "Bearer " + tkn },
});
},
deviceGetById: function(data, headers) {
return axios.get(config + data.device + '/' + data.id)
deviceGetById: function (data, headers) {
return axios.get(config + data.device + "/" + data.id);
},
deviceGetAll: function (data, headers) {
return axios.get(config + data.device);
},
deviceGetAll: function(data, headers) {
return axios.get(config + data.device)
}
};

View file

@ -1,54 +1,67 @@
import React from 'react';
import PropTypes from 'prop-types';
import { makeStyles } from '@material-ui/core/styles';
import Paper from '@material-ui/core/Paper';
import Typography from '@material-ui/core/Typography';
import Grid from '@material-ui/core/Grid';
import Link from '@material-ui/core/Link';
import React from "react";
import PropTypes from "prop-types";
import { makeStyles } from "@material-ui/core/styles";
import Paper from "@material-ui/core/Paper";
import Typography from "@material-ui/core/Typography";
import Grid from "@material-ui/core/Grid";
import Link from "@material-ui/core/Link";
const useStyles = makeStyles(theme => ({
const useStyles = makeStyles((theme) => ({
mainFeaturedPost: {
position: 'relative',
position: "relative",
backgroundColor: theme.palette.grey[800],
color: theme.palette.common.white,
marginBottom: theme.spacing(4),
backgroundImage: 'img/banner.jpg',
backgroundSize: 'cover',
backgroundRepeat: 'no-repeat',
backgroundPosition: 'center',
backgroundImage: "img/banner.jpg",
backgroundSize: "cover",
backgroundRepeat: "no-repeat",
backgroundPosition: "center",
},
overlay: {
position: 'absolute',
position: "absolute",
top: 0,
bottom: 0,
right: 0,
left: 0,
backgroundColor: 'rgba(0,0,0,.3)',
backgroundColor: "rgba(0,0,0,.3)",
},
mainFeaturedPostContent: {
position: 'relative',
position: "relative",
padding: theme.spacing(3),
[theme.breakpoints.up('md')]: {
[theme.breakpoints.up("md")]: {
padding: theme.spacing(6),
paddingRight: 0,
},
},
}));
export default function Banner(props) {
const classes = useStyles();
const { post } = props;
return (
<Paper className={classes.mainFeaturedPost} style={{ backgroundImage: `url(${post.image})` }}>
<Paper
className={classes.mainFeaturedPost}
style={{ backgroundImage: `url(${post.image})` }}
>
{/* Increase the priority of the hero background image */}
{<img style={{ display: 'none' }} src={post.image} alt={post.imageText} />}
{
<img
style={{ display: "none" }}
src={post.image}
alt={post.imageText}
/>
}
<div className={classes.overlay} />
<Grid container>
<Grid item md={6}>
<div className={classes.mainFeaturedPostContent}>
<Typography component="h1" variant="h3" color="inherit" gutterBottom>
<Typography
component="h1"
variant="h3"
color="inherit"
gutterBottom
>
{post.title}
</Typography>
<Typography variant="h5" color="inherit" paragraph>

View file

@ -1,9 +1,9 @@
import React from 'react';
import React from "react";
export default function Footer() {
return(
return (
<div>
<p>This is the footer</p>
</div>
)
);
}

View file

@ -1,14 +1,14 @@
import React from 'react';
import PropTypes from 'prop-types';
import { makeStyles } from '@material-ui/core/styles';
import Toolbar from '@material-ui/core/Toolbar';
import Button from '@material-ui/core/Button';
import IconButton from '@material-ui/core/IconButton';
import SearchIcon from '@material-ui/icons/Search';
import Typography from '@material-ui/core/Typography';
import Link from '@material-ui/core/Link';
import React from "react";
import PropTypes from "prop-types";
import { makeStyles } from "@material-ui/core/styles";
import Toolbar from "@material-ui/core/Toolbar";
import Button from "@material-ui/core/Button";
import IconButton from "@material-ui/core/IconButton";
import SearchIcon from "@material-ui/icons/Search";
import Typography from "@material-ui/core/Typography";
import Link from "@material-ui/core/Link";
const useStyles = makeStyles(theme => ({
const useStyles = makeStyles((theme) => ({
toolbar: {
borderBottom: `1px solid ${theme.palette.divider}`,
},
@ -16,8 +16,8 @@ const useStyles = makeStyles(theme => ({
flex: 1,
},
toolbarSecondary: {
justifyContent: 'space-between',
overflowX: 'auto',
justifyContent: "space-between",
overflowX: "auto",
},
toolbarLink: {
padding: theme.spacing(1),
@ -42,8 +42,12 @@ export default function Header(props) {
>
{title}
</Typography>
<Toolbar component="nav" variant="dense" className={classes.toolbarSecondary}>
{sections.map(section => (
<Toolbar
component="nav"
variant="dense"
className={classes.toolbarSecondary}
>
{sections.map((section) => (
<Link
color="inherit"
noWrap
@ -56,8 +60,9 @@ export default function Header(props) {
</Link>
))}
</Toolbar>
<Button size="small" variant="outlined" style={{margin: "0 1rem"}}>Login</Button>
<Button size="small" variant="outlined" style={{ margin: "0 1rem" }}>
Login
</Button>
<Button variant="outlined" size="small">
Sign up

View file

@ -1,52 +1,69 @@
import React from "react";
import { Dropdown, Icon, Grid, Divider} from 'semantic-ui-react'
import { Segment, Image } from 'semantic-ui-react'
import { Dropdown, Icon, Grid, Divider } from "semantic-ui-react";
import { Segment, Image } from "semantic-ui-react";
import {
BrowserView,
MobileView,
isBrowser,
isMobile
} from "react-device-detect";
const AvatarImage = () => (
<Image
src='avatar3.png'
style={{width: '25px', height: 'auto'}}
centered
/>
)
src="avatar3.png"
style={{ width: "25px", height: "auto" }}
centered />
);
const IconHomeImage = () => (
const IconHomeImage = () => (
<Image
src='smart-home.png'
style={{width: '50px', height: 'auto'}}
src="smart-home.png"
style={{ width: "50px", height: "auto" }}
centered
as='a'
href='/'
as="a"
href="/"
/>
)
);
const IconHomeImageMobile = () => (
<Image
src="smart-home.png"
style={{ width: "10px", height: "auto" }}
centered
as="a"
href="/"
/>
);
const TitleImage = () => (
<Image src='title7.png' size='medium' centered/>
)
<Image
src="title7.png"
size="medium"
centered
/>
);
const GridExampleInverted = (props) => (
<Grid columns='equal' divided inverted padded>
<Grid.Row color='black' textAlign='center' >
const BrowserStructure = (props) => (
<Grid columns="equal" divided inverted padded>
<Grid.Row color="black" textAlign="center">
<Grid.Column width={3} height={0.5}>
<Segment color='black' inverted>
<Segment color="black" inverted>
<IconHomeImage />
</Segment>
</Grid.Column>
<Grid.Column>
<Segment color='black' inverted>
<Segment color="black" inverted>
<TitleImage />
</Segment>
</Grid.Column>
<Grid.Column width={2} heigth={1}>
<AvatarImage />
<Divider />
<Dropdown item icon='setting' size='huge'>
<Dropdown item icon="setting" size="huge">
<Dropdown.Menu>
<Dropdown.Item>
<Icon name='dropdown' />
<span className='text'>Settings</span>
<Icon name="dropdown" />
<span className="text">Settings</span>
<Dropdown.Menu>
<Dropdown.Item>Document</Dropdown.Item>
<Dropdown.Item>Image</Dropdown.Item>
@ -54,135 +71,66 @@ const GridExampleInverted = (props) => (
</Dropdown.Item>
<Dropdown.Item>See profile...</Dropdown.Item>
<Dropdown.Divider />
<Dropdown.Item onClick={props.logout }>Logout</Dropdown.Item>
<Dropdown.Item onClick={props.logout}>Logout</Dropdown.Item>
</Dropdown.Menu>
</Dropdown>
</Grid.Column>
</Grid.Row>
</Grid>
)
);
const MobileStructure = (props) => (
<Grid columns="equal" divided inverted padded>
<Grid.Row color="black" textAlign="center">
<Segment color="black" inverted>
<TitleImage />
</Segment>
</Grid.Row>
<Grid.Row color="black" textAlign="center">
<Grid.Column>
<IconHomeImage />
</Grid.Column>
<Grid.Column >
<AvatarImage />
<Divider />
<Dropdown item icon="setting" size="huge">
<Dropdown.Menu>
<Dropdown.Item>
<Icon name="dropdown" />
<span className="text">Settings</span>
<Dropdown.Menu>
<Dropdown.Item>Document</Dropdown.Item>
<Dropdown.Item>Image</Dropdown.Item>
</Dropdown.Menu>
</Dropdown.Item>
<Dropdown.Item>See profile...</Dropdown.Item>
<Dropdown.Divider />
<Dropdown.Item onClick={props.logout}>Logout</Dropdown.Item>
</Dropdown.Menu>
</Dropdown>
</Grid.Column>
</Grid.Row>
</Grid>
);
export default class MyHeader extends React.Component {
render() {
return (
<div>
<GridExampleInverted logout={this.props.logout} />
<BrowserView>
<BrowserStructure logout={this.props.logout} />
</BrowserView>
<MobileView>
<MobileStructure />
</MobileView>
</div>
);
}
}
// const navbar = {
// backgroundColor: "#20222b",
// color: "white",
// marginBottom: "4.6rem",
// padding: "3.2rem 0"
// };
// const navbar__buttons = {
// borderBottom: "1px solid lighten($light-blue, 10%)",
// display: "flex",
// justifyContent: "space-between",
// padding: "3.2rem 1.6rem"
// }
// const button = {
// background: "#8357c5",
// border: "none",
// borderBottom: "1px solid purple",
// color: "white",
// fontWeight: "500",
// padding: "1.2rem"
// }
// const MenuExampleButtons = () => (
// <Menu>
// <Menu.Item>
// <Button primary>Sign up</Button>
// </Menu.Item>
// <Menu.Item>
// <Button>Log-in</Button>
// </Menu.Item>
// <Menu.Item>
// <Button>Log-in</Button>
// </Menu.Item>
// <Menu.Item>
// <Button>Log-in</Button>
// </Menu.Item>
// </Menu>
// )
// class MenuExampleInvertedSegment extends Component {
// state = { activeItem: 'home' }
// handleItemClick = (e, { name }) => this.setState({ activeItem: name })
// render() {
// const { activeItem } = this.state
// return (
// <Segment inverted>
// <Menu inverted secondary>
// <Menu.Item
// name='home'
// active={activeItem === 'home'}
// onClick={this.handleItemClick}
// />
// <Menu.Item
// name='messages'
// active={activeItem === 'messages'}
// onClick={this.handleItemClick}
// />
// <Menu.Item />
// <Menu.Item />
// <Menu.Item />
// <Menu.Item />
// <Menu.Item />
// <Menu.Item />
// <HeaderExampleIconProp />
// <Menu.Item />
// <Menu.Item />
// <Menu.Item />
// <Menu.Item />
// <Menu.Item />
// <Menu.Item
// name='messages'
// active={activeItem === 'messages'}
// onClick={this.handleItemClick}
// />
// <Dropdown item icon='wrench' simple>
// <Dropdown.Menu>
// <Dropdown.Item>
// <Icon name='dropdown' />
// <span className='text'>New</span>
// <Dropdown.Menu>
// <Dropdown.Item>Document</Dropdown.Item>
// <Dropdown.Item>Image</Dropdown.Item>
// </Dropdown.Menu>
// </Dropdown.Item>
// <Dropdown.Item>Open</Dropdown.Item>
// <Dropdown.Item>Save...</Dropdown.Item>
// <Dropdown.Item>Edit Permissions</Dropdown.Item>
// <Dropdown.Divider />
// <Dropdown.Header>Export</Dropdown.Header>
// <Dropdown.Item>Share</Dropdown.Item>
// </Dropdown.Menu>
// </Dropdown>
// <ImageExampleWrapped />
// <Menu.Item />
// </Menu>
// </Segment>
// )
// }
// }
}

View file

@ -6,18 +6,17 @@ import {
Image,
Menu,
Sidebar,
Responsive
Responsive,
} from "semantic-ui-react";
const NavBarMobile = ({
children,
leftItems,
onPusherClick,
onToggle,
rightItems,
visible
}) => (
visible,
}) => (
<Sidebar.Pushable>
<Sidebar
as={Menu}
@ -41,42 +40,47 @@ const NavBarMobile = ({
<Icon name="sidebar" />
</Menu.Item>
<Menu.Menu position="right">
{_.map(rightItems, item => <Menu.Item {...item} />)}
{_.map(rightItems, (item) => (
<Menu.Item {...item} />
))}
</Menu.Menu>
</Menu>
{children}
</Sidebar.Pusher>
</Sidebar.Pushable>
);
);
const NavBarDesktop = ({ leftItems, rightItems }) => (
const NavBarDesktop = ({ leftItems, rightItems }) => (
<Menu fixed="top" inverted>
<Menu.Item>
<Image size="mini" src="smart-home_index.png" />
</Menu.Item>
{_.map(leftItems, item => <Menu.Item {...item} />)}
{_.map(leftItems, (item) => (
<Menu.Item {...item} />
))}
<Menu.Menu position="right">
{_.map(rightItems, item => <Menu.Item {...item} />)}
{_.map(rightItems, (item) => (
<Menu.Item {...item} />
))}
</Menu.Menu>
</Menu>
);
);
const NavBarChildren = ({ children }) => (
const NavBarChildren = ({ children }) => (
<Container style={{ marginTop: "5em" }}>{children}</Container>
);
);
class HomeNavabarApp extends Component {
constructor(props) {
super(props);
this.state = {
logged : true,
logged: true,
email: "",
password : ""
password: "",
};
}
state = {
visible: false
visible: false,
};
handlePusher = () => {
@ -113,17 +117,17 @@ class HomeNavabarApp extends Component {
}
}
const leftItems = [
{ as: "a", content: "Home", key: "home", href:"/" },
];
const rightItems = [
{ as: "a", content: "Login", key: "login", href:"/login" },
{ as: "a", content: "Sign up", key: "register", href:"/signup" }
];
const leftItems = [{ as: "a", content: "Home", key: "home", href: "/" }];
const rightItems = [
{ as: "a", content: "Login", key: "login", href: "/login" },
{ as: "a", content: "Sign up", key: "register", href: "/signup" },
];
const HomeNavbarApp = () => (
<HomeNavabarApp leftItems={leftItems} rightItems={rightItems}>
</HomeNavabarApp>
);
<HomeNavabarApp
leftItems={leftItems}
rightItems={rightItems}
></HomeNavabarApp>
);
export default HomeNavbarApp;

View file

@ -2,32 +2,32 @@ import React, { Component } from 'react';
import { Button, Grid, Responsive } from 'semantic-ui-react'
export default class SelectIcons extends Component {
constructor(props) {
super(props);
this.state = {
currentIcon: this.props.currentIcon
}
currentIcon: this.props.currentIcon,
};
}
selectIcon = (e) => {
let el = e.target.name;
if (e.target.tagName === "I"){
console.log(e.target.parentNode);
if (e.target.tagName === "I") {
el = e.target.parentNode.name;
}
this.props.updateIcon(el);
this.setState({currentIcon : el})
}
this.setState({ currentIcon: el });
};
render(){
const myicons = [['home', 'coffee', 'beer', 'glass martini', 'film', 'video'],
['music', 'headphones', 'fax', 'phone', 'laptop','bath'],
['shower', 'bed', 'child', 'warehouse', 'car', 'bicycle'],
['motorcycle', 'archive', 'boxes', 'cubes', 'chess', 'gamepad'],
['futbol', 'table tennis', 'server', 'tv', 'heart', 'camera'],
['trophy', 'wrench', 'image', 'book', 'university', 'medkit'],
['paw', 'tree', 'utensils', 'male', 'female', 'life ring outline']];
render() {
const myicons = [
["home", "coffee", "beer", "glass martini", "film", "video"],
["music", "headphones", "fax", "phone", "laptop", "bath"],
["shower", "bed", "child", "warehouse", "car", "bicycle"],
["motorcycle", "archive", "boxes", "cubes", "chess", "gamepad"],
["futbol", "table tennis", "server", "tv", "heart", "camera"],
["trophy", "wrench", "image", "book", "university", "medkit"],
["paw", "tree", "utensils", "male", "female", "life ring outline"],
];
return (
<Grid centered relaxed>
@ -36,15 +36,22 @@ export default class SelectIcons extends Component {
return (
<Grid.Row key={i}>
{e.map((e, i) => {
return(<Grid.Column key={i}>
<Button name={e} color={e === this.state.currentIcon ? "black" : null } icon={e} size="small" onClick={this.selectIcon}/>
</Grid.Column>)
return (
<Grid.Column key={i}>
<Button
name={e}
color={e === this.state.currentIcon ? "black" : null}
icon={e}
size="small"
onClick={this.selectIcon}
/>
</Grid.Column>
);
})}
</Grid.Row>
)
})
}
</ Grid>
)
);
})}
</Grid>
);
}
}

View file

@ -1,52 +1,53 @@
import React, {Component} from 'react';
import {
Grid,
} from "semantic-ui-react";
import {editButtonStyle, panelStyle} from "./devices/styleComponents";
import {checkMaxLength, DEVICE_NAME_MAX_LENGTH} from "./devices/constants";
import DeviceType from './devices/DeviceTypeController';
// vim: set ts=2 sw=2 et tw=80:
import React, { Component } from "react";
import { Grid } from "semantic-ui-react";
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';
import { call } from "../../client_server";
export default class DevicePanel extends Component {
constructor(props) {
super(props);
this.state = {
editMode : false,
editMode: false,
};
this.addDevice = this.addDevice.bind(this);
}
editModeController = (e) => this.setState((prevState) => ({ editMode: !prevState.editMode }));
editModeController = (e) =>
this.setState((prevState) => ({ editMode: !prevState.editMode }));
openModal = (settingsDeviceId) => {
this.setState(prevState => ({
this.setState((prevState) => ({
openSettingsModal: !prevState.openSettingsModal,
settingsDeviceId: settingsDeviceId
}))
}
settingsDeviceId: settingsDeviceId,
}));
};
changeDeviceData = (deviceId, newSettings) => {
console.log(newSettings.name, " <-- new name --> ", deviceId );
this.props.devices.map(device => {
if(device.id === deviceId){
for(let prop in newSettings){
if(device.hasOwnProperty(prop)){
if(prop==="name"){
if(checkMaxLength(newSettings[prop])){
console.log(newSettings.name, " <-- new name --> ", deviceId);
this.props.devices.map((device) => {
if (device.id === deviceId) {
for (let prop in newSettings) {
if (device.hasOwnProperty(prop)) {
if (prop === "name") {
if (checkMaxLength(newSettings[prop])) {
device[prop] = newSettings[prop];
} else {
alert(
"Name must be less than " +
DEVICE_NAME_MAX_LENGTH +
" characters."
);
}
} else {
device[prop] = newSettings[prop];
}
else{
alert("Name must be less than " + DEVICE_NAME_MAX_LENGTH + " characters.");
}
}else{
device[prop] = newSettings[prop];
}
}
}
}
@ -57,77 +58,79 @@ export default class DevicePanel extends Component {
getDevices() {
if (this.props.activeItem === -1) {
call.getAllDevices()
.then(res => {
if ( res.status === 200) {
call
.getAllDevices()
.then((res) => {
if (res.status === 200) {
this.setState({
devices: res.data
devices: res.data,
});
}
}).catch(err => {
})
.catch((err) => {
console.log(err);
});
} else {
call.getAllDevicesByRoom(this.props.activeItem)
.then(res => {
call
.getAllDevicesByRoom(this.props.activeItem)
.then((res) => {
if (res.status === 200) {
this.setState({
devices: res.data
devices: res.data,
});
}
}).catch(err => {
});
})
.catch((err) => {});
}
}
async addDevice(data) {
const ds = await this.props.addDevice(data);
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)
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 => {
console.log(data);
call
.deviceUpdate(data)
.then((res) => {
if (res.status === 200) {
this.getDevices();
this.forceUpdate();
}
}).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
.catch((err) => {});
};
call.deviceDelete(data)
.then(res => {
console.log(res)
removeDevice = () => {
const item = this.props.devices.filter(
(d) => d.id === this.state.settingsDeviceId
)[0];
const data = {
device: item.kind,
id: this.state.settingsDeviceId,
};
call
.deviceDelete(data)
.then((res) => {
if (res.status === 200) {
this.openModal();
this.getDevices();
this.forceUpdate();
}
}).catch(err => {
});
}
})
.catch((err) => {});
};
render() {
const edit = {
@ -137,39 +140,41 @@ export default class DevicePanel extends Component {
const ds = this.state.devices ? this.state.devices : this.props.devices;
return (
<div style={panelStyle}>
<button style={editButtonStyle} onClick={this.editModeController}>Edit</button>
<button style={editButtonStyle} onClick={this.editModeController}>
Edit
</button>
<Grid doubling columns={4} divided="vertically">
{this.state.openSettingsModal ?
<SettingsModal openModal={this.openModal}
{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) => {
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={edit}/>
<DeviceType
type={e.kind}
onChangeData={this.changeDeviceData}
device={e}
edit={edit}
/>
</Grid.Column>
)
);
})
:
null
}
{
this.props.activeItem !== -1 ?
: null}
{this.props.activeItem !== -1 ? (
<Grid.Column>
<NewDevice addDevice={this.addDevice} devices={ds}/>
<NewDevice addDevice={this.addDevice} devices={ds} />
</Grid.Column>
:
null
}
) : null}
</Grid>
</div>
)
);
}
}

View file

@ -1,34 +1,26 @@
import React, {Component} from "react";
import {editModeIconStyle, editModeStyle} from "./styleComponents";
import React, { Component } from "react";
import { editModeIconStyle, editModeStyle } from "./styleComponents";
export default class Settings extends Component {
constructor(props) {
super(props);
this.state = {
displayForm: true,
}
};
}
displayForm = () => {
this.setState((prevState) => ({displayForm: !prevState.displayForm}));
this.setState((prevState) => ({ displayForm: !prevState.displayForm }));
};
render() {
const view = (
<div onClick={() => this.props.edit.openModal(this.props.deviceId)}>
<span style={editModeStyle}>
<img
src="/img/settings.svg"
alt=""
style={editModeIconStyle}/>
<img src="/img/settings.svg" alt="" style={editModeIconStyle} />
</span>
</div>
);
return (
<React.Fragment>
{this.props.edit.mode ? view : ("")}
</React.Fragment>
)
};
return <React.Fragment>{this.props.edit.mode ? view : ""}</React.Fragment>;
}
}

View file

@ -1,28 +1,63 @@
import React from 'react';
import React from "react";
import Light from "./Light";
import SmartPlug from "./SmartPlug";
import Sensor from "./Sensor";
import DefaultDimmer from "./Dimmer";
import Switcher from "./Switch";
const DeviceType = (props) => {
switch(props.type) {
case "regular-light":
return (<Light onChangeData={props.changeDeviceData} device={props.device} edit={props.edit} />)
switch (props.type) {
case "regularLight":
return (
<Light
onChangeData={props.changeDeviceData}
device={props.device}
edit={props.edit}
/>
);
case "sensor":
return <Sensor onChangeData={props.changeDeviceData} device={props.device} edit={props.edit} />
case "dimmer":
return <DefaultDimmer onChangeData={props.changeDeviceData} device={props.device} edit={props.edit} />
case "smartplug":
return <SmartPlug onChangeData={props.changeDeviceData} device={props.device} edit={props.edit} />
return (
<Sensor
onChangeData={props.changeDeviceData}
device={props.device}
edit={props.edit}
/>
);
case "buttonDimmer":
return (
<DefaultDimmer
onChangeData={props.changeDeviceData}
device={props.device}
edit={props.edit}
/>
);
case "smartPlug":
return (
<SmartPlug
onChangeData={props.changeDeviceData}
device={props.device}
edit={props.edit}
/>
);
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 (
<Switcher
onChangeData={props.changeDeviceData}
device={props.device}
edit={props.edit}
/>
);
case "dimmableLight":
return (
<Light
onChangeData={props.changeDeviceData}
device={props.device}
edit={props.edit}
/>
);
default:
return ""
return "";
}
}
};
export default DeviceType;

View file

@ -6,13 +6,17 @@
* For this story, make the sensors return a constant value with some small random error.
*/
import React, {Component} from "react";
import {CircularInput, CircularProgress, CircularTrack} from "react-circular-input";
import {errorStyle, sensorText, style, valueStyle} from "./SensorStyle";
import {StyledDiv} from "./styleComponents";
import React, { Component } from "react";
import {
CircularInput,
CircularProgress,
CircularTrack,
} from "react-circular-input";
import { errorStyle, sensorText, style, valueStyle } from "./SensorStyle";
import { StyledDiv } from "./styleComponents";
import Settings from "./DeviceSettings";
import {Image} from "semantic-ui-react";
import {imageStyle, nameStyle} from "./DigitalSensorStyle";
import { Image } from "semantic-ui-react";
import { imageStyle, nameStyle } from "./DigitalSensorStyle";
export default class DigitalSensor extends Component {
constructor(props) {
@ -22,26 +26,24 @@ export default class DigitalSensor extends Component {
};
this.iconOn = "/img/sensorOn.svg";
this.iconOff = "/img/sensorOff.svg"
this.iconOff = "/img/sensorOff.svg";
}
setName = () => {
if(this.props.device.name.length > 15){
return this.props.device.name.slice(0,12) + "..."
if (this.props.device.name.length > 15) {
return this.props.device.name.slice(0, 12) + "...";
}
return this.props.device.name;
};
getIcon = () => {
if(this.state.value){
if (this.state.value) {
return this.iconOn;
}
return this.iconOff;
};
componentDidMount() {
}
componentDidMount() {}
render() {
return (
@ -49,10 +51,13 @@ export default class DigitalSensor extends Component {
<Settings
deviceId={this.props.device.id}
edit={this.props.edit}
onChangeData={(id, newSettings) => this.props.onChangeData(id, newSettings)}/>
<Image src={this.getIcon()} style={imageStyle}/>
onChangeData={(id, newSettings) =>
this.props.onChangeData(id, newSettings)
}
/>
<Image src={this.getIcon()} style={imageStyle} />
<h5 style={nameStyle}>{this.props.device.name}</h5>
</StyledDiv>
)
);
}
}

View file

@ -5,13 +5,13 @@ export const imageStyle = {
top: "20%",
left: "50%",
transform: "translateX(-50%)",
filter: "drop-shadow( 1px 1px 0.5px rgba(0, 0, 0, .25))"
filter: "drop-shadow( 1px 1px 0.5px rgba(0, 0, 0, .25))",
};
export const nameStyle = {
color : "black",
color: "black",
position: "absolute",
top: "40%",
left: "50%",
transform: "translateX(-50%)"
transform: "translateX(-50%)",
};

View file

@ -7,46 +7,36 @@
The user can change the state of a dimmer through an intuitive UI in SmartHut .
**/
import React, {Component} from 'react';
import React, { Component } from "react";
export class StatefulDimmer extends Component{
constructor(props){
export class StatefulDimmer extends Component {
constructor(props) {
super(props);
this.state = {
intensityLevel : 0,
pointingLDevices:[]
}
intensityLevel: 0,
pointingLDevices: [],
};
}
componentDidMount() {
}
componentDidMount() {}
render() {
return(
<div>
This is a Dimmer
</div>
)
return <div>This is a Dimmer</div>;
}
}
export default class DefaultDimmer extends Component{
export default class DefaultDimmer extends Component {
// As far as I am concern, even though this dimmer doesn't have state, internally it's needed
constructor(props){
constructor(props) {
super(props);
this.state = {
pointingDevices :[]
}
pointingDevices: [],
};
}
componentDidMount() {
}
componentDidMount() {}
render() {
return(
<div>
This is a Dimmer
</div>
)
return <div>This is a Dimmer</div>;
}
}

View file

@ -6,13 +6,23 @@
* be shown accordingly in the SmartHut views (house view and room views).
*/
import React, {Component} from "react";
import {iconStyle, StyledDiv} from "./styleComponents";
import React, { Component } from "react";
import { iconStyle, StyledDiv } from "./styleComponents";
import Settings from "./DeviceSettings";
import {Image} from "semantic-ui-react";
import {CircularInput, CircularProgress, CircularThumb, CircularTrack} from "react-circular-input";
import {valueStyle, intensityLightStyle, style, nameStyle} from "./LightStyle";
import { call } from '../../../client_server';
import { Image } from "semantic-ui-react";
import {
CircularInput,
CircularProgress,
CircularThumb,
CircularTrack,
} from "react-circular-input";
import {
valueStyle,
intensityLightStyle,
style,
nameStyle,
} from "./LightStyle";
import { call } from "../../../client_server";
export default class Light extends Component {
constructor(props) {
@ -21,22 +31,26 @@ export default class Light extends Component {
turnedOn: false,
};
this.iconOn = "/img/lightOn.svg";
this.iconOff = "/img/lightOff.svg"
this.iconOff = "/img/lightOff.svg";
}
onClickDevice = () => {
this.setState((prevState) => ({turnedOn: !prevState.turnedOn}));
this.props.device.on = !this.state.turnedOn;
call.deviceUpdate(this.props.device, "regularLight").then((res) => {
if (res.status === 200) {
this.setState((prevState) => ({ turnedOn: !prevState.turnedOn }));
}
});
};
setIntensity = (newValue) => {
this.props.device.intensity = Math.round(newValue) <= 1 ? 1 : Math.round(newValue );
console.log(this.props.device.intensity)
call.deviceUpdate(this.props.device, 'dimmableLight')
.then(res => {
if (res.status === 200 ) {
this.setState({intensity: newValue});
this.props.device.intensity =
Math.round(newValue * 100) <= 1 ? 1 : Math.round(newValue * 100);
call.deviceUpdate(this.props.device, "dimmableLight").then((res) => {
if (res.status === 200) {
this.setState({ intensity: newValue });
}
})
});
};
getIcon = () => {
@ -49,38 +63,52 @@ export default class Light extends Component {
componentDidMount() {
if (this.props.device.hasOwnProperty("intensity")) {
this.setState({
intensity: this.props.device.intensity
intensity: this.props.device.intensity,
});
}
this.setState({
turnedOn: this.props.device.on,
});
// Get the state and update it
}
render() {
const intensityLightView = (
<CircularInput
value={this.props.device.intensity}
value={+(Math.round(this.props.device.intensity / 100 + "e+2") + "e-2")}
onChange={this.setIntensity}
style={style}
>
<CircularTrack/>
<CircularProgress/>
<CircularThumb/>
<CircularTrack />
<CircularProgress />
<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.props.device.intensity)}%
</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}
</text>
</CircularInput>
);
const normalLightView = (
<div onClick={this.props.edit.mode ? () => {
} : this.onClickDevice}>
<Image src={this.getIcon()} style={iconStyle}/>
<div onClick={this.props.edit.mode ? () => {} : this.onClickDevice}>
<Image src={this.getIcon()} style={iconStyle} />
<h5 style={nameStyle}>{this.props.device.name}</h5>
</div>
);
@ -90,9 +118,14 @@ export default class Light extends Component {
<Settings
deviceId={this.props.device.id}
edit={this.props.edit}
onChangeData={(id, newSettings) => this.props.onChangeData(id, newSettings)}/>
{this.props.device.intensity ? (intensityLightView) : (normalLightView)}
onChangeData={(id, newSettings) =>
this.props.onChangeData(id, newSettings)
}
/>
{this.props.device.intensity >= 0
? intensityLightView
: normalLightView}
</StyledDiv>
)
);
}
}

View file

@ -1,4 +1,10 @@
export const style = {width: "10rem", height: "10rem", position: "absolute", top: "0", left: "0"};
export const style = {
width: "10rem",
height: "10rem",
position: "absolute",
top: "0",
left: "0",
};
export const valueStyle = {
fill: "#3e99ff",
fontSize: "2.5rem",
@ -14,10 +20,10 @@ export const intensityLightStyle = {
};
export const nameStyle = {
fontSize : "1rem",
fontSize: "1rem",
position: "absolute",
top: "50%",
left: "50%",
transform: "translateX(-50%)",
color : "black"
color: "black",
};

View file

@ -1,19 +1,27 @@
import React, {Component} from 'react';
import styled from 'styled-components';
import {Button, Dropdown, Form, Icon, Image, Input, Modal} from "semantic-ui-react";
import React, { Component } from "react";
import styled from "styled-components";
import {
Button,
Dropdown,
Form,
Icon,
Image,
Input,
Modal,
} from "semantic-ui-react";
const StyledDiv = styled.div`
background-color : #ff4050;
padding : 3rem;
background-color: #ff4050;
padding: 3rem;
width: 10rem;
height: 10rem;
border-radius : 100%;
border : none;
position : relative;
border-radius: 100%;
border: none;
position: relative;
box-shadow: 3px 2px 10px 5px #ccc;
transition : all .3s ease-out;
:hover{
background-color : #ff2436;
transition: all 0.3s ease-out;
:hover {
background-color: #ff2436;
}
`;
@ -22,15 +30,18 @@ export default class NewDevice extends Component {
super(props);
this.state = {
step: 1,
openModal : false
openModal: false,
};
this.baseState = this.state
this.baseState = this.state;
this.createDevice = this.createDevice.bind(this);
}
handleOpen = () => {this.setState({openModal : true})};
handleClose = () => {this.setState({openModal : false})};
handleOpen = () => {
this.setState({ openModal: true });
};
handleClose = () => {
this.setState({ openModal: false });
};
resetState = () => {
this.setState(this.baseState);
@ -38,92 +49,97 @@ export default class NewDevice extends Component {
};
nextStep = () => {
this.setState((prevState) => ({step: prevState.step + 1}));
this.setState((prevState) => ({ step: prevState.step + 1 }));
};
previousStep = () => {
this.setState((prevState) => ({step: prevState.step - 1}));
this.setState((prevState) => ({ step: prevState.step - 1 }));
};
setTypeOfDevice = (e, d) => {
if (d.value === "dimmableLight"){
this.setState({typeOfDevice: d.value,
intensity: 0,});
if (d.value === "dimmableLight") {
this.setState({ typeOfDevice: d.value, intensity: 0 });
} else {
this.setState({typeOfDevice: d.value,});
this.setState({ typeOfDevice: d.value });
}
};
setDeviceName = (e, d) => {
this.setState({deviceName: d.value});
this.setState({ deviceName: d.value });
};
setTypeOfSensor = (e, d) => {
this.setState({typeOfSensor: d.value});
this.setState({ typeOfSensor: d.value });
};
setLightsDimmerSwitch = (e, d) => {
this.setState({lightsAttached : d.value});
this.setState({ lightsAttached: d.value });
};
createDevice() {
// Connect to the backend and create device here.
const data = {
params: {
"name": this.state.deviceName,
name: this.state.deviceName,
},
device: this.state.typeOfDevice
device: this.state.typeOfDevice,
};
}
switch(this.state.typeOfDevice) {
switch (this.state.typeOfDevice) {
case "dimmableLight":
data.params["intensity"] = 1;
break;
case "sensor":
data.params["sensor"] = this.state.typeOfSensor;
data.params["value"] = 0;
break;
case "switch":
data.params["lights"] = this.state.lightsAttached;
break;
default:
break;
}
console.log(data);
this.props.addDevice(data);
this.resetState();
};
}
render() {
const deviceOptions = [
{
key: 'light',
text: 'Normal Light',
value: 'regularLight',
image: {avatar: true, src: '/img/lightOn.svg'},
key: "light",
text: "Normal Light",
value: "regularLight",
image: { avatar: true, src: "/img/lightOn.svg" },
},
{
key: 'intensity-light',
text: 'Intensity Light',
value: 'dimmableLight',
image: {avatar: true, src: '/img/intensity-light.svg'},
key: "intensity-light",
text: "Intensity Light",
value: "dimmableLight",
image: { avatar: true, src: "/img/intensity-light.svg" },
},
{
key: 'smart-plug',
text: 'Smart Plug',
value: 'smartPlug',
image: {avatar: true, src: '/img/smart-plug.svg'},
key: "smart-plug",
text: "Smart Plug",
value: "smartPlug",
image: { avatar: true, src: "/img/smart-plug.svg" },
},
{
key: 'sensor',
text: 'Sensor',
value: 'sensor',
image: {avatar: true, src: '/img/sensorOn.svg'},
key: "sensor",
text: "Sensor",
value: "sensor",
image: { avatar: true, src: "/img/sensorOn.svg" },
},
{
key: 'switch',
text: 'Switch',
value: 'switch',
image: {avatar: true, src: '/img/switchOn.svg'},
key: "switch",
text: "Switch",
value: "switch",
image: { avatar: true, src: "/img/switchOn.svg" },
},
{
key: 'dimmer',
text: 'Dimmer',
value: 'dimmer',
image: {avatar: true, src: '/img/dimmer.svg'},
key: "dimmer",
text: "Dimmer",
value: "buttonDimmer",
image: { avatar: true, src: "/img/dimmer.svg" },
},
];
const sensorOptions = [
@ -131,41 +147,39 @@ export default class NewDevice extends Component {
key: "temperature",
text: "Temperature Sensor",
value: "TEMPERATURE",
image: {avatar: true, src: '/img/temperature-sensor.svg'},
image: { avatar: true, src: "/img/temperature-sensor.svg" },
},
{
key: "humidity",
text: "Humidity Sensor",
value: "HUMIDITY",
image: {avatar: true, src: '/img/humidity-sensor.svg'},
image: { avatar: true, src: "/img/humidity-sensor.svg" },
},
{
key: "light",
text: "Light Sensor",
value: "LIGHT",
image: {avatar: true, src: '/img/light-sensor.svg'},
image: { avatar: true, src: "/img/light-sensor.svg" },
},
{
key: "motion",
text: "Motion Sensor",
value: "motionSensor",
image: {avatar: true, src: '/img/sensorOn.svg'},
}
image: { avatar: true, src: "/img/sensorOn.svg" },
},
];
const availableLights = [];
this.props.devices.forEach(d => {
availableLights.push(
{
this.props.devices.forEach((d) => {
availableLights.push({
key: d.id,
text: d.name,
value: d.id,
}
)
});
});
const step1 = (
<Dropdown
name="typeOfDevice"
placeholder='Select a Type of Device'
placeholder="Select a Type of Device"
fluid
selection
onChange={this.setTypeOfDevice}
@ -173,74 +187,114 @@ export default class NewDevice extends Component {
/>
);
const step2 = (typeOfDevice) => {
const deviceName = (<div>
const deviceName = (
<div>
<Form.Field>
<label>Device Name: </label>
<Input fluid size={"large"} onChange={this.setDeviceName} focus placeholder='Device Name'/>
<Input
fluid
size={"large"}
onChange={this.setDeviceName}
focus
placeholder="Device Name"
/>
</Form.Field>
</div>);
const sensorForm = (<Form.Field style={{marginTop : "1rem"}}>
</div>
);
const sensorForm = (
<Form.Field style={{ marginTop: "1rem" }}>
<label>Type of Sensor: </label>
<Dropdown
name="typeOfDevice"
placeholder='Select a Type of Sensor'
placeholder="Select a Type of Sensor"
fluid
selection
onChange={this.setTypeOfSensor}
options={sensorOptions}
/>
</Form.Field>);
const switchDimmerOptions = (<Form.Field style={{marginTop : "1rem"}}>
</Form.Field>
);
const switchDimmerOptions = (
<Form.Field style={{ marginTop: "1rem" }}>
<label>Select the Lights You Want to Attach: </label>
<Dropdown
name="typeOfDevice"
placeholder='Select Lights'
placeholder="Select Lights"
fluid
multiple
onChange={this.setLightsDimmerSwitch}
options={availableLights}
/>
</Form.Field>);
</Form.Field>
);
return (
<Form>
{deviceName}
{this.state.typeOfDevice === "sensor" ? (sensorForm) : ""}
{this.state.typeOfDevice === "switch" || this.state.typeOfDevice === "dimmer" ?
(switchDimmerOptions) : ""
}
{this.state.typeOfDevice === "sensor" ? sensorForm : ""}
{this.state.typeOfDevice === "switch" ||
this.state.typeOfDevice === "dimmer"
? switchDimmerOptions
: ""}
</Form>
)
);
};
const steps = [step1, step2()];
return (
<Modal closeIcon open={this.state.openModal} onClose={this.resetState} trigger={<StyledDiv onClick={this.handleOpen}>
<Image src="/img/add.svg" style={{filter: "invert()"}}/>
</StyledDiv>} centered={true}>
<Modal
closeIcon
open={this.state.openModal}
onClose={this.resetState}
trigger={
<StyledDiv onClick={this.handleOpen}>
<Image src="/img/add.svg" style={{ filter: "invert()" }} />
</StyledDiv>
}
centered={true}
>
<Modal.Header>Add a New Device</Modal.Header>
<Modal.Content>
{steps[this.state.step -1]}
</Modal.Content>
<Modal.Content>{steps[this.state.step - 1]}</Modal.Content>
<Modal.Actions>
{this.state.step > 1 ? (
<Button onClick={this.previousStep} color="blue" icon labelPosition='left'>
<Icon name='left arrow'/>
<Button
onClick={this.previousStep}
color="blue"
icon
labelPosition="left"
>
<Icon name="left arrow" />
Back
</Button>
) : ""}
) : (
""
)}
{this.state.step < steps.length ? (
<Button color="blue" onClick={this.nextStep} icon labelPosition='right'>
<Button
color="blue"
onClick={this.nextStep}
icon
labelPosition="right"
>
Next
<Icon name='right arrow'/>
<Icon name="right arrow" />
</Button>
) : ""}
) : (
""
)}
{this.state.step === steps.length ? (
<Button onClick={this.createDevice} color="blue" icon labelPosition='right'>
<Icon name='up arrow'/>
<Button
onClick={this.createDevice}
color="blue"
icon
labelPosition="right"
>
<Icon name="up arrow" />
Finish
</Button>
) : ""}
) : (
""
)}
</Modal.Actions>
</Modal>
)
);
}
}

View file

@ -6,33 +6,72 @@
* For this story, make the sensors return a constant value with some small random error.
*/
import React, {Component} from "react";
import {CircularInput, CircularProgress, CircularTrack} from "react-circular-input";
import {errorStyle, sensorText, style, valueStyle} from "./SensorStyle";
/*
OPTIONAL STATE
error: 2.4
<text style={errorStyle} x={100} y={100} textAnchor="middle" dy="0.6em" fontWeight="bold">
&#177;{this.state.error}
</text>
errorStyle,
*/
import React, { Component } from "react";
import {
CircularInput,
CircularProgress,
CircularTrack,
} from "react-circular-input";
import { sensorText, style, valueStyle } from "./SensorStyle";
import Settings from "./DeviceSettings";
import {StyledDiv} from "./styleComponents";
import { StyledDiv } from "./styleComponents";
import { call } from "../../../client_server";
export default class Sensor extends Component {
constructor(props) {
super(props);
this.state = {
turnedOn: false,
value: 20,
error: 2.4
value: 0,
};
this.units = "ºC"
this.units = "";
this.stateCallback = (e) => this.setState(Object.assign(this.state, e));
call.socketSubscribe(this.props.device.id, this.stateCallback);
}
componentWillUnmount() {
call.socketUnsubscribe(this.props.device.id, this.stateCallback);
}
setName = () => {
if (this.props.device.name.length > 15) {
return this.props.device.name.slice(0, 12) + "..."
return this.props.device.name.slice(0, 12) + "...";
}
return this.props.device.name;
};
componentDidMount() {
switch (this.props.device.sensor) {
case "TEMPERATURE":
this.units = "ºC";
break;
case "HUMIDITY":
this.units = "%";
break;
case "LIGHT":
this.units = "lm";
break;
default:
this.units = "";
}
this.setState({
value: this.props.device.value,
});
}
render() {
return (
@ -40,25 +79,37 @@ export default class Sensor extends Component {
<Settings
deviceId={this.props.device.id}
edit={this.props.edit}
onChangeData={(id, newSettings) => this.props.onChangeData(id, newSettings)}/>
onChangeData={(id, newSettings) =>
this.props.onChangeData(id, newSettings)
}
/>
<CircularInput
value={this.state.value / 100}
style={style}
<CircularInput value={this.state.value / 100} style={style}>
<CircularTrack />
<CircularProgress />
<text
style={valueStyle}
x={100}
y={80}
textAnchor="middle"
dy="0.3em"
fontWeight="bold"
>
<CircularTrack/>
<CircularProgress/>
<text style={valueStyle} x={100} y={80} textAnchor="middle" dy="0.3em" fontWeight="bold">
{Math.round(this.state.value)}{this.units}
{Math.round(this.state.value)}
{this.units}
</text>
<text style={errorStyle} x={100} y={100} textAnchor="middle" dy="0.6em" fontWeight="bold">
&#177;{this.state.error}
</text>
<text style={sensorText} x={100} y={150} textAnchor="middle" dy="0.3em" fontWeight="bold">
<text
style={sensorText}
x={100}
y={150}
textAnchor="middle"
dy="0.3em"
fontWeight="bold"
>
{this.setName()}
</text>
</CircularInput>
</StyledDiv>
)
);
}
}

View file

@ -1,11 +1,17 @@
export const style = {width: "10rem", height: "10rem", position: "absolute", top: "0", left: "0"};
export const style = {
width: "10rem",
height: "10rem",
position: "absolute",
top: "0",
left: "0",
};
export const sensorText = {
fill: "#3e99ff",
fontSize: "1.2rem",
fontFamily: "Lato",
textShadow: "1px 1px 0.5px rgba(0, 0, 0, .2)",
}
};
export const valueStyle = {
fill: "#3e99ff",
@ -14,10 +20,9 @@ export const valueStyle = {
textShadow: "1px 1px 0.5px rgba(0, 0, 0, .2)",
};
export const errorStyle = {
fill: "#ff4050",
fontSize: "1.5rem",
fontFamily: "Lato",
textShadow: "1px 1px 0.5px rgba(0, 0, 0, .2)",
}
};

View file

@ -1,56 +1,73 @@
import React, {Component, useState} from 'react';
import {Button, Checkbox, Form, Icon, Header, Modal} from "semantic-ui-react";
import React, { Component, useState } from "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 trigger={<Button color="red">Remove</Button>} closeIcon>
<Header icon="archive" content="Are you sure ?" />
<Modal.Actions>
<Button color='red'>
<Icon name='remove' /> No
<Button color="red">
<Icon name="remove" /> No
</Button>
<Button onClick={() => props.removeDevice()} color='green'>
<Icon name='checkmark' /> Yes
<Button onClick={() => props.removeDevice()} color="green">
<Icon name="checkmark" /> Yes
</Button>
</Modal.Actions>
</Modal>
)
);
const SettingsForm = (props) => {
const handleInputChange = e => {
const {name, value} = e.target;
setValues({...values, [name]: value})
const handleInputChange = (e) => {
const { name, value } = e.target;
setValues({ ...values, [name]: value });
};
const handleCheckboxChange = (e,d) => {
const {name, checked} = d;
setValues({...values, [name]: checked})
const handleCheckboxChange = (e, d) => {
const { name, checked } = d;
setValues({ ...values, [name]: checked });
};
const [values, setValues] = useState({name: ''});
const [values, setValues] = useState({ name: "" });
return (
<Form>
<Form.Field>
<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>
{props.type === "smart-plug" ? (
<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>
<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>
)
}
);
};
export default class SettingsModal extends Component {
constructor(props) {
super(props);
this.state = {
@ -59,7 +76,7 @@ export default class SettingsModal extends Component {
}
handleClose = () => {
this.setState({open: false});
this.setState({ open: false });
};
saveSettings = (device) => {
@ -72,19 +89,23 @@ export default class SettingsModal extends Component {
this.props.openModal();
};
render() {
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.Content>
<SettingsForm type={this.props.device.type} removeDevice={this.props.removeDevice} saveFunction={this.saveSettings}/>
<SettingsForm
type={this.props.device.type}
removeDevice={this.props.removeDevice}
saveFunction={this.saveSettings}
/>
</Modal.Content>
</Modal>
);
return (
<SettingsModal/>
)
return <SettingsModal />;
}
}

View file

@ -4,48 +4,61 @@
The smart plug also stores the total energy consumed while the plug is active, in terms of kilowatt-hours 2(kWh) .
The user can reset this value.
**/
import React, {Component} from 'react';
import {StyledDiv} from "./styleComponents";
import React, { Component } from "react";
import { StyledDiv } from "./styleComponents";
import Settings from "./DeviceSettings";
import {Image} from "semantic-ui-react";
import {energyConsumedStyle, imageStyle, nameStyle} from "./SmartPlugStyle";
import { Image } from "semantic-ui-react";
import { energyConsumedStyle, imageStyle, nameStyle } from "./SmartPlugStyle";
import { call } from "../../../client_server";
export default class SmartPlug extends Component {
constructor(props){
constructor(props) {
super(props);
this.state = {
turnedOn: false,
energyConsumed : 0 // kWh
energyConsumed: 0, // kWh
};
this.iconOn = "/img/smart-plug.svg";
this.iconOff = "/img/smart-plug-off.svg"
this.iconOff = "/img/smart-plug-off.svg";
}
onClickDevice = () => {
this.setState((prevState) => ({turnedOn: !prevState.turnedOn}));
this.props.device.on = !this.state.turnedOn;
call.deviceUpdate(this.props.device, "smartPlug").then((res) => {
if (res.status === 200) {
this.setState((prevState) => ({ turnedOn: !prevState.turnedOn }));
}
});
};
getIcon = () => {
if(this.state.turnedOn){
if (this.state.turnedOn) {
return this.iconOn;
}
return this.iconOff;
};
componentDidMount() {
this.setState({
turnedOn: this.props.device.on,
energyConsumed: this.props.device.totalConsumption,
});
}
render(){
render() {
return (
<StyledDiv onClick={this.props.edit.mode ? () => {} : this.onClickDevice}>
<Settings
deviceId={this.props.device.id}
edit={this.props.edit}
onChangeData={(id, newSettings) => this.props.onChangeData(id, newSettings)}/>
<Image src={this.getIcon()} style={imageStyle}/>
onChangeData={(id, newSettings) =>
this.props.onChangeData(id, newSettings)
}
/>
<Image src={this.getIcon()} style={imageStyle} />
<h4 style={energyConsumedStyle}>{this.state.energyConsumed} KWh</h4>
<h5 style={nameStyle}>{this.props.device.name}</h5>
</StyledDiv>
)
);
}
}

View file

@ -1,11 +1,10 @@
export const energyConsumedStyle = {
color : "black",
fontSize : "1.3rem",
color: "black",
fontSize: "1.3rem",
position: "absolute",
top: "30%",
left: "50%",
transform: "translateX(-50%)"
transform: "translateX(-50%)",
};
export const imageStyle = {
@ -15,13 +14,13 @@ export const imageStyle = {
top: "10%",
left: "50%",
transform: "translateX(-50%)",
filter: "drop-shadow( 1px 1px 0.5px rgba(0, 0, 0, .25))"
filter: "drop-shadow( 1px 1px 0.5px rgba(0, 0, 0, .25))",
};
export const nameStyle = {
color : "black",
color: "black",
position: "absolute",
top: "50%",
left: "50%",
transform: "translateX(-50%)"
transform: "translateX(-50%)",
};

View file

@ -5,48 +5,69 @@
* The user can change the state of a switch through the SmartHut interface.
*/
import React, {Component} from 'react';
import {StyledDiv} from "./styleComponents";
import React, { Component } from "react";
import { StyledDiv } from "./styleComponents";
import Settings from "./DeviceSettings";
import {Image} from "semantic-ui-react";
import {imageStyle, nameStyle} from "./SwitchStyle";
import { Image } from "semantic-ui-react";
import { imageStyle, nameStyle } from "./SwitchStyle";
import { call } from "../../../client_server";
export default class Switch extends Component {
constructor(props){
constructor(props) {
super(props);
this.state = {
turnedOn: false,
pointingLights : []
pointingLights: [],
};
this.iconOn = "/img/switchOn.svg";
this.iconOff = "/img/switchOff.svg";
}
onClickDevice = () => {
this.setState((prevState) => ({turnedOn: !prevState.turnedOn}));
this.props.device.on = !this.state.turnedOn;
let state = "";
if (this.props.device.on) {
state = "ON";
} else {
state = "OFF";
}
let data = {
type: state,
id: this.props.device.id,
};
call.deviceUpdate(data, "switch/operate").then((res) => {
if (res.status === 200) {
this.setState((prevState) => ({ turnedOn: !prevState.turnedOn }));
}
});
};
getIcon = () => {
if(this.state.turnedOn){
if (this.state.turnedOn) {
return this.iconOn;
}
return this.iconOff;
};
componentDidMount() {
this.setState({
turnedOn: this.props.device.on,
});
}
render(){
render() {
return (
<StyledDiv onClick={this.props.edit.mode ? () => {} : this.onClickDevice}>
<Settings
deviceId={this.props.device.id}
edit={this.props.edit}
onChangeData={(id, newSettings) => this.props.onChangeData(id, newSettings)}/>
<Image src={this.getIcon()} style={imageStyle}/>
onChangeData={(id, newSettings) =>
this.props.onChangeData(id, newSettings)
}
/>
<Image src={this.getIcon()} style={imageStyle} />
<h5 style={nameStyle}>{this.props.device.name}</h5>
</StyledDiv>
)
);
}
}

View file

@ -5,13 +5,13 @@ export const imageStyle = {
top: "15%",
left: "50%",
transform: "translateX(-50%)",
filter: "drop-shadow( 1px 1px 0.5px rgba(0, 0, 0, .25))"
filter: "drop-shadow( 1px 1px 0.5px rgba(0, 0, 0, .25))",
};
export const nameStyle = {
color : "black",
color: "black",
position: "absolute",
top: "45%",
left: "50%",
transform: "translateX(-50%)"
transform: "translateX(-50%)",
};

View file

@ -1,18 +1,24 @@
export const LightDevice = {
img : "/img/lightOff.svg",
imgClick : "/img/lightOn.svg"
img: "/img/lightOff.svg",
imgClick: "/img/lightOn.svg",
};
export const SmartPlugDevice = {
img : "/img/smart-plug.svg",
imgClick : "/img/smart-plug-off.svg"
img: "/img/smart-plug.svg",
imgClick: "/img/smart-plug-off.svg",
};
export const TemperatureSensor = {
type : "temperature_sensor",
img : "",
imgClick : "",
type: "temperature_sensor",
img: "",
imgClick: "",
units: "ºC",
};
export const deviceList = ["Light", "Dimmer", "Switcher", "Smart Plug", "Sensor"];
export const deviceList = [
"Light",
"Dimmer",
"Switcher",
"Smart Plug",
"Sensor",
];

View file

@ -1,5 +1,5 @@
export const DEVICE_NAME_MAX_LENGTH = 15;
export function checkMaxLength(name){
export function checkMaxLength(name) {
return !(name.length > DEVICE_NAME_MAX_LENGTH);
}

View file

@ -1,20 +1,20 @@
import styled from "styled-components";
export const editButtonStyle = {
position : "absolute",
position: "absolute",
top: "0",
right : "0",
backgroundColor : "#3e99ff",
borderRadius : "0 0 0 20px",
padding : ".4rem 1.2rem",
outline : "none",
color : "white",
fontFamily : "Lato",
textTransform : "uppercase"
right: "0",
backgroundColor: "#3e99ff",
borderRadius: "0 0 0 20px",
padding: ".4rem 1.2rem",
outline: "none",
color: "white",
fontFamily: "Lato",
textTransform: "uppercase",
};
export const panelStyle = {
position : "relative",
position: "relative",
backgroundColor: "#fafafa",
height: "100vh",
width: "auto",
@ -22,26 +22,26 @@ export const panelStyle = {
};
export const editModeStyle = {
position : "absolute",
position: "absolute",
top: "15%",
right: "0",
width : "1.5rem",
height : "1.5rem",
backgroundColor : "black",
width: "1.5rem",
height: "1.5rem",
backgroundColor: "black",
borderRadius: "100%",
zIndex : "1000",
cursor : "pointer",
zIndex: "1000",
cursor: "pointer",
};
export const editModeIconStyle = {
position : "absolute",
position: "absolute",
top: "50%",
left: "50%",
transform : "translate(-50%, -50%)",
transform: "translate(-50%, -50%)",
width: "0.75rem",
height : "0.75rem",
borderRadius : "20%",
zIndex : "101"
height: "0.75rem",
borderRadius: "20%",
zIndex: "101",
};
export const iconStyle = {
@ -51,50 +51,49 @@ export const iconStyle = {
top: "20%",
left: "50%",
transform: "translateX(-50%)",
filter: "drop-shadow( 1px 1px 0.5px rgba(0, 0, 0, .25))"
filter: "drop-shadow( 1px 1px 0.5px rgba(0, 0, 0, .25))",
};
export const nameStyle = {
position: "absolute",
top: "50%",
left: "50%",
transform: "translateX(-50%)"
transform: "translateX(-50%)",
};
export const formStyle = {
position : "absolute",
position: "absolute",
zIndex: "1000",
width : "80rem",
height : "10rem",
padding : "1rem",
margin : "1rem",
borderRadius : "10%",
boxShadow : "1px 1px 5px 2px #5d5d5d",
width: "80rem",
height: "10rem",
padding: "1rem",
margin: "1rem",
borderRadius: "10%",
boxShadow: "1px 1px 5px 2px #5d5d5d",
backgroundColor: "#3e99ff",
};
export const addDeviceFormStyle = {
maxWidth : "400px",
background : "#3e99ff",
paddingRight : "5rem",
maxWidth: "400px",
background: "#3e99ff",
paddingRight: "5rem",
};
export const StyledDiv = styled.div`
background-color : white;
padding : 3rem;
background-color: white;
padding: 3rem;
width: 10rem;
height: 10rem;
border-radius : 100%;
border : none;
position : relative;
border-radius: 100%;
border: none;
position: relative;
box-shadow: 3px 2px 10px 5px #ccc;
transition : all .3s ease-out;
text-align : center;
:hover{
background-color : #f2f2f2;
transition: all 0.3s ease-out;
text-align: center;
:hover {
background-color: #f2f2f2;
}
:active{
transform : translate(0.3px, 0.8px);
:active {
transform: translate(0.3px, 0.8px);
box-shadow: 0.5px 0.5px 7px 3.5px #ccc;
}
`;

View file

@ -1,22 +1,30 @@
import React, { Component } from 'react';
import { Button, Header, Modal, Form, Input, Icon, Responsive, Image } from 'semantic-ui-react';
import React, { Component } from "react";
import {
Button,
Header,
Modal,
Form,
Input,
Icon,
Responsive,
Image
} from "semantic-ui-react";
import SelectIcons from "./SelectIcons";
const NO_IMAGE="https://react.semantic-ui.com/images/wireframe/image.png";
export default class ModalWindow extends Component {
constructor(props) {
super(props);
console.table(this.props);
this.state = {
id : "",
id: "",
selectedIcon: "",
name: "",
name: this.props.type === "new" ? "" : this.props.idRoom.name,
img: this.props.type === "new" ? null : this.props.idRoom.image,
openModal: false
openModal: false,
};
this.fileInputRef = React.createRef();
@ -27,47 +35,49 @@ console.table(this.props);
addRoomModal = (e) => {
let data = {
"icon" : this.state.selectedIcon,
"name" : this.state.name,
"image" : this.state.img
}
icon: this.state.selectedIcon,
name: this.state.name,
image: this.state.img,
};
this.props.addRoom(data);
this.closeModal();
}
};
modifyRoomModal = (e) => {
let data = {
"icon" : this.state.selectedIcon === "" ? this.props.idRoom.icon : this.state.selectedIcon ,
"name" : this.state.name === ""? this.props.idRoom.name : this.state.name,
"image" : this.state.img
}
icon:
this.state.selectedIcon === ""
? this.props.idRoom.icon
: this.state.selectedIcon,
name: this.state.name === "" ? this.props.idRoom.name : this.state.name,
image: this.state.img,
};
this.props.updateRoom(data);
this.closeModal();
}
};
deleteRoom = (e) => {
this.props.deleteRoom();
this.closeModal();
}
};
changeSomething = (event) => {
let nam = event.target.name;
let val = event.target.value;
this.setState({[nam]: val});
}
this.setState({ [nam]: val });
};
closeModal = (e) => {
this.setState({openModal:false});
this.updateIcon('home');
}
this.setState({ openModal: false });
this.updateIcon("home");
};
openModal = (e) => {
this.setState({openModal:true})
}
this.setState({ openModal: true });
};
updateIcon(e) {
this.setState({selectedIcon : e})
this.setState({ selectedIcon: e });
}
getBase64(file, callback) {
@ -83,20 +93,29 @@ console.table(this.props);
render(){
const spaceDiv = {
background: '#f4f4f4',
padding: '10px 10px',
margin: '10px 0px'
}
background: "#f4f4f4",
padding: "10px 10px",
margin: "10px 0px",
};
return (
<div>
<Responsive minWidth={768} >
{this.props.type === "new" ?
<Button icon labelPosition='left' inverted onClick={this.openModal}>
<Icon name='plus' size='small'/>
<Responsive minWidth={768}>
{this.props.type === "new" ? (
<Button icon labelPosition="left" inverted onClick={this.openModal}>
<Icon name="plus" size="small" />
ADD ROOM
</Button>
) : (
<Icon name="pencil" size="small" onClick={this.openModal} />
)}
</Responsive>
<Responsive maxWidth={768}>
{this.props.type === "new" ? (
<Button icon fluid labelPosition="left" onClick={this.openModal}>
<Icon name="plus" size="small" />
ADD ROOM
</Button>)
:
<Icon name='pencil' size='small' onClick={this.openModal} />
}
@ -124,19 +143,24 @@ console.table(this.props);
<Form>
<p>Insert the name of the room:</p>
<Form.Field>
<Input label='Room name' placeholder='Room Name' name="name" type='text' onChange={this.changeSomething}
value={this.props.type === "new" && this.props.idRoom !== -1 ? null : this.props.idRoom.name }/>
<Input
label='Room name'
placeholder='Room Name'
name="name"
type='text'
onChange={this.changeSomething}
value={this.state.name}/>
</Form.Field>
<p>Insert an image of the room:</p>
<Form.Field>
<Image src={this.state.img == null ? NO_IMAGE : this.state.img}
<Image
src={this.state.img == null ? NO_IMAGE : this.state.img}
size='small'
onClick={() => this.fileInputRef.current.click()}/>
<input ref={this.fileInputRef} hidden label='Room image' type='file' name="img" accept="image/png, image/jpeg"
onChange={this.getBase64.bind(this)}
value={this.props.type === "new" && this.props.idRoom !== -1 ? null : this.props.idRoom.images }/>
onChange={this.getBase64.bind(this)}/>
</Form.Field>
</Form>

View file

@ -1,15 +1,11 @@
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import * as serviceWorker from './serviceWorker';
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import * as serviceWorker from "./serviceWorker";
//React Router
//import { BrowserRouter, Route, Switch } from "react-router-dom";
const index = (
<App />
);
const index = <App />;
ReactDOM.render(
index
, document.getElementById('root'));
ReactDOM.render(index, document.getElementById("root"));
serviceWorker.unregister();

View file

@ -11,9 +11,9 @@
// opt-in, read https://bit.ly/CRA-PWA
const isLocalhost = Boolean(
window.location.hostname === 'localhost' ||
window.location.hostname === "localhost" ||
// [::1] is the IPv6 localhost address.
window.location.hostname === '[::1]' ||
window.location.hostname === "[::1]" ||
// 127.0.0.0/8 are considered localhost for IPv4.
window.location.hostname.match(
/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
@ -21,7 +21,7 @@ const isLocalhost = Boolean(
);
export function register(config) {
if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
if (process.env.NODE_ENV === "production" && "serviceWorker" in navigator) {
// The URL constructor is available in all browsers that support SW.
const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);
if (publicUrl.origin !== window.location.origin) {
@ -31,7 +31,7 @@ export function register(config) {
return;
}
window.addEventListener('load', () => {
window.addEventListener("load", () => {
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
if (isLocalhost) {
@ -42,8 +42,8 @@ export function register(config) {
// service worker/PWA documentation.
navigator.serviceWorker.ready.then(() => {
console.log(
'This web app is being served cache-first by a service ' +
'worker. To learn more, visit https://bit.ly/CRA-PWA'
"This web app is being served cache-first by a service " +
"worker. To learn more, visit https://bit.ly/CRA-PWA"
);
});
} else {
@ -57,21 +57,21 @@ export function register(config) {
function registerValidSW(swUrl, config) {
navigator.serviceWorker
.register(swUrl)
.then(registration => {
.then((registration) => {
registration.onupdatefound = () => {
const installingWorker = registration.installing;
if (installingWorker == null) {
return;
}
installingWorker.onstatechange = () => {
if (installingWorker.state === 'installed') {
if (installingWorker.state === "installed") {
if (navigator.serviceWorker.controller) {
// At this point, the updated precached content has been fetched,
// but the previous service worker will still serve the older
// content until all client tabs are closed.
console.log(
'New content is available and will be used when all ' +
'tabs for this page are closed. See https://bit.ly/CRA-PWA.'
"New content is available and will be used when all " +
"tabs for this page are closed. See https://bit.ly/CRA-PWA."
);
// Execute callback
@ -82,7 +82,7 @@ function registerValidSW(swUrl, config) {
// At this point, everything has been precached.
// It's the perfect time to display a
// "Content is cached for offline use." message.
console.log('Content is cached for offline use.');
console.log("Content is cached for offline use.");
// Execute callback
if (config && config.onSuccess) {
@ -93,25 +93,25 @@ function registerValidSW(swUrl, config) {
};
};
})
.catch(error => {
console.error('Error during service worker registration:', error);
.catch((error) => {
console.error("Error during service worker registration:", error);
});
}
function checkValidServiceWorker(swUrl, config) {
// Check if the service worker can be found. If it can't reload the page.
fetch(swUrl, {
headers: { 'Service-Worker': 'script' }
headers: { "Service-Worker": "script" },
})
.then(response => {
.then((response) => {
// Ensure service worker exists, and that we really are getting a JS file.
const contentType = response.headers.get('content-type');
const contentType = response.headers.get("content-type");
if (
response.status === 404 ||
(contentType != null && contentType.indexOf('javascript') === -1)
(contentType != null && contentType.indexOf("javascript") === -1)
) {
// No service worker found. Probably a different app. Reload the page.
navigator.serviceWorker.ready.then(registration => {
navigator.serviceWorker.ready.then((registration) => {
registration.unregister().then(() => {
window.location.reload();
});
@ -123,18 +123,18 @@ function checkValidServiceWorker(swUrl, config) {
})
.catch(() => {
console.log(
'No internet connection found. App is running in offline mode.'
"No internet connection found. App is running in offline mode."
);
});
}
export function unregister() {
if ('serviceWorker' in navigator) {
if ("serviceWorker" in navigator) {
navigator.serviceWorker.ready
.then(registration => {
.then((registration) => {
registration.unregister();
})
.catch(error => {
.catch((error) => {
console.error(error.message);
});
}

View file

@ -2,4 +2,4 @@
// allows you to do things like:
// expect(element).toHaveTextContent(/react/i)
// learn more: https://github.com/testing-library/jest-dom
import '@testing-library/jest-dom/extend-expect';
import "@testing-library/jest-dom/extend-expect";

View file

@ -1,33 +1,28 @@
import React, { Component } from "react";
import HomeNavbar from "./../components/HomeNavbar";
import {
Image,
Divider,
Message,
Grid
} from "semantic-ui-react";
import { Image, Divider, Message, Grid } from "semantic-ui-react";
class Paragraph extends Component {
state = { visible: true }
state = { visible: true };
handleDismiss = () => {
this.setState({ visible: false })
this.setState({ visible: false });
setTimeout(() => {
this.setState({ visible: true })
}, 2000)
}
this.setState({ visible: true });
}, 2000);
};
render() {
if (this.state.visible) {
return (
<Message
onDismiss={this.handleDismiss}
header='Link has been sent!'
content='An e-mail has been sent your address, please follow the
instruction to create a new password'
header="Link has been sent!"
content="An e-mail has been sent your address, please follow the
instruction to create a new password"
/>
)
);
}
return (
@ -37,64 +32,48 @@ class Paragraph extends Component {
<br />
<br />
</p>
)
}
);
}
}
const MessageReg = () => (
const MessageReg = () => (
<Grid>
<HomeNavbar />
<Divider />
<Grid.Row height={3}></Grid.Row>
<Grid.Row height={3}></Grid.Row>
<Grid.Row height={3}></Grid.Row>
<Grid.Row height={3}>
</Grid.Row>
<Grid.Row height={3}>
</Grid.Row>
<Grid.Row height={3}>
</Grid.Row>
<Grid.Row height={3}>
<Grid.Column width={6}>
</Grid.Column>
<Grid.Column width={6}></Grid.Column>
<Grid.Column width={10}>
<Image src='title5.png' />
</Grid.Column>
<Grid.Column width={3}>
<Image src="title5.png" />
</Grid.Column>
<Grid.Column width={3}></Grid.Column>
</Grid.Row>
<Grid.Row height={3}>
</Grid.Row>
<Grid.Row height={3}>
</Grid.Row>
<Grid.Column width={3}>
</Grid.Column>
<Grid.Row height={3}></Grid.Row>
<Grid.Row height={3}></Grid.Row>
<Grid.Column width={3}></Grid.Column>
<Grid.Column width={4}>
<Image src='./img/logo.png' />
<Image src="./img/logo.png" />
</Grid.Column>
<Grid.Column width={6}>
<Paragraph />
</Grid.Column>
<Grid.Column width={4}>
</Grid.Column>
<Grid.Column width={4}></Grid.Column>
<Grid.Row height={3}></Grid.Row>
<Grid.Row height={3}></Grid.Row>
<Grid.Row height={3}>
</Grid.Row>
<Grid.Row height={3}>
</Grid.Row>
<Grid.Row height={3}>
<Grid.Column width={3}>
</Grid.Column>
<Grid.Column width={3}></Grid.Column>
<Grid.Column width={10}>
<Divider />
</Grid.Column>
<Grid.Column width={3}>
</Grid.Column>
<Grid.Column width={3}></Grid.Column>
</Grid.Row>
</Grid>
)
);
export default class ConfirmForgotPasswrod extends React.Component {
render () {
return (
<MessageReg />
)
render() {
return <MessageReg />;
}
}

View file

@ -1,33 +1,28 @@
import React, { Component } from "react";
import HomeNavbar from "./../components/HomeNavbar";
import {
Image,
Divider,
Message,
Grid
} from "semantic-ui-react";
import { Image, Divider, Message, Grid } from "semantic-ui-react";
class Paragraph extends Component {
state = { visible: true }
state = { visible: true };
handleDismiss = () => {
this.setState({ visible: false })
this.setState({ visible: false });
setTimeout(() => {
this.setState({ visible: true })
}, 2000)
}
this.setState({ visible: true });
}, 2000);
};
render() {
if (this.state.visible) {
return (
<Message
onDismiss={this.handleDismiss}
header='Congratulation!'
content='An e-mail has been sent your address, please confirm
your registration by following the enclosed link'
header="Congratulation!"
content="An e-mail has been sent your address, please confirm
your registration by following the enclosed link"
/>
)
);
}
return (
@ -37,64 +32,48 @@ class Paragraph extends Component {
<br />
<br />
</p>
)
}
);
}
}
const MessageReg = () => (
const MessageReg = () => (
<Grid>
<HomeNavbar />
<Divider />
<Grid.Row height={3}></Grid.Row>
<Grid.Row height={3}></Grid.Row>
<Grid.Row height={3}></Grid.Row>
<Grid.Row height={3}>
</Grid.Row>
<Grid.Row height={3}>
</Grid.Row>
<Grid.Row height={3}>
</Grid.Row>
<Grid.Row height={3}>
<Grid.Column width={6}>
</Grid.Column>
<Grid.Column width={6}></Grid.Column>
<Grid.Column width={10}>
<Image src='title5.png' />
</Grid.Column>
<Grid.Column width={3}>
<Image src="title5.png" />
</Grid.Column>
<Grid.Column width={3}></Grid.Column>
</Grid.Row>
<Grid.Row height={3}>
</Grid.Row>
<Grid.Row height={3}>
</Grid.Row>
<Grid.Column width={3}>
</Grid.Column>
<Grid.Row height={3}></Grid.Row>
<Grid.Row height={3}></Grid.Row>
<Grid.Column width={3}></Grid.Column>
<Grid.Column width={4}>
<Image src='./img/logo.png' />
<Image src="./img/logo.png" />
</Grid.Column>
<Grid.Column width={6}>
<Paragraph />
</Grid.Column>
<Grid.Column width={4}>
</Grid.Column>
<Grid.Column width={4}></Grid.Column>
<Grid.Row height={3}></Grid.Row>
<Grid.Row height={3}></Grid.Row>
<Grid.Row height={3}>
</Grid.Row>
<Grid.Row height={3}>
</Grid.Row>
<Grid.Row height={3}>
<Grid.Column width={3}>
</Grid.Column>
<Grid.Column width={3}></Grid.Column>
<Grid.Column width={10}>
<Divider />
</Grid.Column>
<Grid.Column width={3}>
</Grid.Column>
<Grid.Column width={3}></Grid.Column>
</Grid.Row>
</Grid>
)
);
export default class ConfirmRegistration extends React.Component {
render () {
return (
<MessageReg />
)
render() {
return <MessageReg />;
}
}

View file

@ -1,10 +1,10 @@
import React, {Component} from 'react';
import React, { Component } from "react";
import DevicePanel from "../components/dashboard/DevicePanel";
import Navbar from './Navbar'
import MyHeader from '../components/HeaderController'
import Navbar from "./Navbar";
import MyHeader from "../components/HeaderController";
import { call } from '../client_server';
import { Grid, Responsive } from 'semantic-ui-react'
import { call } from "../client_server";
import { Grid, Responsive } from "semantic-ui-react";
/*
rooms -> actual rooms
activeItem -> the current room in view
@ -14,7 +14,7 @@ import { Grid, Responsive } from 'semantic-ui-react'
id of Home is -1
*/
export default class Dashboard extends Component{
export default class Dashboard extends Component {
constructor(props) {
super(props);
this.state = {
@ -33,40 +33,43 @@ export default class Dashboard extends Component{
getDevices() {
if (this.state.activeItem === -1) {
call.getAllDevices()
.then(res => {
if ( res.status === 200) {
call
.getAllDevices()
.then((res) => {
if (res.status === 200) {
console.log(res.data);
this.setState({
devices: res.data
devices: res.data,
});
}
}).catch(err => {
})
.catch((err) => {
console.log(err);
});
} else {
call.getAllDevicesByRoom(this.state.activeItem)
.then(res => {
call
.getAllDevicesByRoom(this.state.activeItem)
.then((res) => {
if (res.status === 200) {
this.setState({
devices: res.data
devices: res.data,
});
}
}).catch(err => {
});
}
}
getRooms() {
call.getAllRooms(this.props.tkn)
.then(res => {
this.setState({
rooms: res.data
})
}).catch(err => {
.catch((err) => {});
}
}
getRooms() {
call
.getAllRooms(this.props.tkn)
.then((res) => {
this.setState({
rooms: res.data,
});
}
})
.catch((err) => {});
}
componentDidMount() {
this.getRooms();
@ -74,69 +77,77 @@ getRooms() {
}
addRoom(data) {
call.createRoom(data)
.then(res => {
call
.createRoom(data)
.then((res) => {
if (res.status === 200 && res.data) {
this.getRooms();
}
}).catch(err => {
})
.catch((err) => {
console.log(err);
});
};
}
deleteRoom() {
let data = {
id : this.state.activeItem
}
call.deleteRoom(data)
.then(res => {
id: this.state.activeItem,
};
call
.deleteRoom(data)
.then((res) => {
//remove room in state.rooms
this.getRooms();
}).catch(err => {
})
.catch((err) => {
console.log(err);
});
}
updateRoom(data) {
console.log(data)
call.updateRoom(data)
.then(res => {
data.id = this.state.activeItem;
call
.updateRoom(data)
.then((res) => {
if (res.status === 200 && res.data) {
this.getRooms();
this.forceUpdate();
}
}).catch(err => {
})
.catch((err) => {});
}
handleItemClick(id) {
// el -> obj of name and id
//da fare richiesta get della room e settare activeItem
this.setState({
activeItem: id
activeItem: id,
});
if ( id === -1) {
call.getAllDevices(this.props.tkn)
.then(res => {
if ( res.status === 200) {
if (id === -1) {
call
.getAllDevices(this.props.tkn)
.then((res) => {
if (res.status === 200) {
this.setState({
devices: res.data
devices: res.data,
});
}
}).catch(err => {
})
.catch((err) => {
console.log(err);
});
} else {
call.getAllDevicesByRoom(id, this.props.tkn)
.then(res => {
call
.getAllDevicesByRoom(id, this.props.tkn)
.then((res) => {
if (res.status === 200) {
this.setState({
devices: res.data
devices: res.data,
});
this.forceUpdate();
}
}).catch(err => {
})
.catch((err) => {
console.log(err);
});
}
@ -144,59 +155,79 @@ getRooms() {
addDevice(data) {
data.params["roomId"] = this.state.activeItem;
call.devicePost(data, this.props.tkn)
.then(res => {
this.setState(state => ({
devices: state.devices.concat([res.data])
call
.devicePost(data, this.props.tkn)
.then((res) => {
this.setState((state) => ({
devices: state.devices.concat([res.data]),
}));
return this.state.devices;
}).catch(err => {
});
})
.catch((err) => {});
}
render () {
return(
<div style={{height : "110vh", background: '#1b1c1d'}}>
<Responsive minWidth={768} >
<Grid >
<Grid.Row color='black'>
render() {
return (
<div style={{ height: "110vh", background: "#1b1c1d" }}>
<Responsive minWidth={768}>
<Grid>
<Grid.Row color="black">
<Grid.Column>
<MyHeader logout={this.props.logout} />
</Grid.Column>
</Grid.Row>
<Grid.Row color='black'>
<Grid.Row color="black">
<Grid.Column width={3}>
<Navbar addRoom={this.addRoom} updateRoom={this.updateRoom} deleteRoom={this.deleteRoom} rooms={this.state.rooms} handleItemClick={this.handleItemClick}/>
<Navbar
addRoom={this.addRoom}
updateRoom={this.updateRoom}
deleteRoom={this.deleteRoom}
rooms={this.state.rooms}
handleItemClick={this.handleItemClick}
/>
</Grid.Column>
<Grid.Column width={13}>
<DevicePanel tkn={this.props.tkn} activeItem={this.state.activeItem} 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>
</Responsive>
<Responsive maxWidth={768} >
<Responsive maxWidth={768}>
<Grid inverted>
<Grid.Row color='black'>
<Grid.Row color="black">
<Grid.Column>
<MyHeader logout={this.props.logout} />
</Grid.Column>
</Grid.Row>
<Grid.Row color='black'>
<Grid.Column color='black'>
<Navbar addRoom={this.addRoom} deleteRoom={this.deleteRoom} rooms={this.state.rooms} handleItemClick={this.handleItemClick}/>
<Grid.Row color="black">
<Grid.Column color="black">
<Navbar
addRoom={this.addRoom}
deleteRoom={this.deleteRoom}
rooms={this.state.rooms}
handleItemClick={this.handleItemClick}
/>
</Grid.Column>
</Grid.Row>
<Grid.Row >
<Grid.Column >
<DevicePanel tkn={this.props.tkn} activeItem={this.state.activeItem} addDevice={this.addDevice} devices={this.state.devices} />
<Grid.Row>
<Grid.Column>
<DevicePanel
tkn={this.props.tkn}
activeItem={this.state.activeItem}
addDevice={this.addDevice}
devices={this.state.devices}
/>
</Grid.Column>
</Grid.Row>
</Grid>
</Responsive>
</div>
)
);
}
}

View file

@ -1,9 +1,7 @@
import React, {Component} from 'react';
import {Button } from 'semantic-ui-react';
import React, { Component } from "react";
import { Button } from "semantic-ui-react";
export default class Dashboard extends Component {
handleLogOut = (e) => {
console.log(this.props);
this.props.logout();
@ -11,12 +9,9 @@ export default class Dashboard extends Component {
render() {
return (
<Button
circular
style={{margin: "2em"}}
onClick={this.handleLogOut}
>
Go Home </Button>
)
<Button circular style={{ margin: "2em" }} onClick={this.handleLogOut}>
Go Home{" "}
</Button>
);
}
}

View file

@ -1,9 +1,16 @@
import React, {Component} from 'react';
import {Button, Form, Grid, Header, Image, Icon, Message} from 'semantic-ui-react';
import { call } from '../client_server';
import React, { Component } from "react";
import {
Button,
Form,
Grid,
Header,
Image,
Icon,
Message,
} from "semantic-ui-react";
import { call } from "../client_server";
import { Redirect } from "react-router-dom";
export default class ChangePass extends Component {
constructor(props) {
super(props);
@ -12,41 +19,44 @@ export default class ChangePass extends Component {
error: {
state: false,
message: "",
}
}
},
};
this.handleChangePassword = this.handleChangePassword.bind(this);
}
onChangeHandler = (event) => {
let nam = event.target.name;
let val = event.target.value;
this.setState({[nam]: val});
this.setState({ [nam]: val });
};
checkpassword = (e) => {
if (e.target.value !== this.state.password) {
this.setState({error: {
state : true,
message : "Passwords do not match.",
}});
this.setState({
error: {
state: true,
message: "Passwords do not match.",
},
});
}
};
handleChangePassword = (e) => {
const params = {
"confirmationToken" : this.props.query.token ,
"password" : this.state.password
}
call.resetPassword(params)
.then(res => {
if (res.status !== 200){
this.setState({ error: { state: true,
message: "Errore"}});
confirmationToken: this.props.query.token,
password: this.state.password,
};
call
.resetPassword(params)
.then((res) => {
if (res.status !== 200) {
this.setState({ error: { state: true, message: "Errore" } });
} else {
return <Redirect to="/" />
return <Redirect to="/" />;
}
// else set a message that an email has been sent
}).catch(err => {
})
.catch((err) => {
console.log(err);
});
};
@ -54,49 +64,59 @@ export default class ChangePass extends Component {
render() {
return (
<React.Fragment>
<Button
circular
style={{margin: "2em"}}
href="/"
<Button circular style={{ margin: "2em" }} href="/">
<Icon name="arrow alternate circle left" />
Go Home{" "}
</Button>
<Grid
textAlign="center"
style={{ height: "70vh" }}
verticalAlign="middle"
>
<Icon name='arrow alternate circle left'/>
Go Home </Button>
<Grid textAlign='center' style={{height: '70vh'}} verticalAlign='middle'>
<Grid.Column style={{maxWidth: 450}}>
<Header as='h2' color='blue' textAlign='center'>
<Image src='img/logo.png'/> Reset Password
<Grid.Column style={{ maxWidth: 450 }}>
<Header as="h2" color="blue" textAlign="center">
<Image src="img/logo.png" /> Reset Password
</Header>
<Form size='large' style={{marginTop : "2em"}} error={this.state.error.state}>
<Form
size="large"
style={{ marginTop: "2em" }}
error={this.state.error.state}
>
<Message
error
header='Change Password Error'
content= {this.state.error.message}
header="Change Password Error"
content={this.state.error.message}
/>
<Form.Input
icon='address card outline'
iconPosition='left'
placeholder='Reset your password'
icon="address card outline"
iconPosition="left"
placeholder="Reset your password"
name="password"
type='password'
type="password"
onChange={this.onChangeHandler}
required
/>
<Form.Input
icon='address card outline'
iconPosition='left'
placeholder='Confirm Password'
icon="address card outline"
iconPosition="left"
placeholder="Confirm Password"
name="confirm-password"
type='password'
type="password"
onChange={this.checkpassword}
required
/>
<Button color='blue' fluid size='large' onClick={this.handleChangePassword}>
<Button
color="blue"
fluid
size="large"
onClick={this.handleChangePassword}
>
Confirm password
</Button>
</Form>
</Grid.Column>
</Grid>
</React.Fragment>
)
);
}
}

View file

@ -1,8 +1,15 @@
import React, {Component} from 'react';
import {Button, Form, Grid, Header, Image, Icon, Message} from 'semantic-ui-react';
import {Redirect } from "react-router-dom";
import { call } from '../client_server';
import React, { Component } from "react";
import {
Button,
Form,
Grid,
Header,
Image,
Icon,
Message,
} from "semantic-ui-react";
import { Redirect } from "react-router-dom";
import { call } from "../client_server";
export default class ForgotPass extends Component {
constructor(props) {
@ -14,77 +21,88 @@ export default class ForgotPass extends Component {
message: "",
},
success: false,
}
};
}
onChangeHandler = (event) => {
let nam = event.target.name;
let val = event.target.value;
this.setState({[nam]: val});
this.setState({ [nam]: val });
};
handleSendEmail = (e) => {
e.preventDefault();
const params = {
"email" : this.state.user,
}
email: this.state.user,
};
call.initResetPassword(params)
.then(res => {
call
.initResetPassword(params)
.then((res) => {
console.log(res);
if (res.status === 200) {
this.setState({success : true});
this.setState({ success: true });
}
if (res.status === "Errore") {
this.setState({ error: { state: true,
message: "Errore"}});
this.setState({ error: { state: true, message: "Errore" } });
}
//set a message that an email has been sent
}).catch(err => {
})
.catch((err) => {
console.log(err);
});
};
render() {
if (this.state.success) {
return <Redirect to="sent-email" />
return <Redirect to="sent-email" />;
}
return (
<React.Fragment>
<Button
circular
style={{margin: "2em"}}
href="/"
<Button circular style={{ margin: "2em" }} href="/">
<Icon name="arrow alternate circle left" />
Go Home{" "}
</Button>
<Grid
textAlign="center"
style={{ height: "70vh" }}
verticalAlign="middle"
>
<Icon name='arrow alternate circle left'/>
Go Home </Button>
<Grid textAlign='center' style={{height: '70vh'}} verticalAlign='middle'>
<Grid.Column style={{maxWidth: 450}}>
<Header as='h2' color='blue' textAlign='center'>
<Image src='img/logo.png'/> Reset Password
<Grid.Column style={{ maxWidth: 450 }}>
<Header as="h2" color="blue" textAlign="center">
<Image src="img/logo.png" /> Reset Password
</Header>
<Form size='large' style={{marginTop : "2em"}} error={this.state.error.state}>
<Form
size="large"
style={{ marginTop: "2em" }}
error={this.state.error.state}
>
<Message
error
header='Send E-mail Error'
content= {this.state.error.message}
header="Send E-mail Error"
content={this.state.error.message}
/>
<Form.Input
icon='address card outline'
iconPosition='left'
placeholder='Username or E-mail'
icon="address card outline"
iconPosition="left"
placeholder="Username or E-mail"
name="user"
type='text'
type="text"
onChange={this.onChangeHandler}
required
/>
<Button color='blue' fluid size='large' onClick={this.handleSendEmail}>
<Button
color="blue"
fluid
size="large"
onClick={this.handleSendEmail}
>
Send E-mail
</Button>
</Form>
</Grid.Column>
</Grid>
</React.Fragment>
)
);
}
}

View file

@ -11,30 +11,30 @@ import {
Header,
Divider,
Message,
Grid
Grid,
} from "semantic-ui-react";
class Paragraph extends Component {
state = { visible: true }
state = { visible: true };
handleDismiss = () => {
this.setState({ visible: false })
this.setState({ visible: false });
setTimeout(() => {
this.setState({ visible: true })
}, 2000)
}
this.setState({ visible: true });
}, 2000);
};
render() {
if (this.state.visible) {
return (
<Message
onDismiss={this.handleDismiss}
header='Link has been sent!'
content='An e-mail has been sent your address, please follow the
instruction to create a new password'
header="Link has been sent!"
content="An e-mail has been sent your address, please follow the
instruction to create a new password"
/>
)
);
}
return (
@ -44,64 +44,48 @@ class Paragraph extends Component {
<br />
<br />
</p>
)
}
);
}
}
const MessageReg = () => (
const MessageReg = () => (
<Grid>
<HomeNavbar />
<Divider />
<Grid.Row height={3}></Grid.Row>
<Grid.Row height={3}></Grid.Row>
<Grid.Row height={3}></Grid.Row>
<Grid.Row height={3}>
</Grid.Row>
<Grid.Row height={3}>
</Grid.Row>
<Grid.Row height={3}>
</Grid.Row>
<Grid.Row height={3}>
<Grid.Column width={6}>
</Grid.Column>
<Grid.Column width={6}></Grid.Column>
<Grid.Column width={10}>
<Image src='title5.png' />
</Grid.Column>
<Grid.Column width={3}>
<Image src="title5.png" />
</Grid.Column>
<Grid.Column width={3}></Grid.Column>
</Grid.Row>
<Grid.Row height={3}>
</Grid.Row>
<Grid.Row height={3}>
</Grid.Row>
<Grid.Column width={3}>
</Grid.Column>
<Grid.Row height={3}></Grid.Row>
<Grid.Row height={3}></Grid.Row>
<Grid.Column width={3}></Grid.Column>
<Grid.Column width={4}>
<Image src='./img/logo.png' />
<Image src="./img/logo.png" />
</Grid.Column>
<Grid.Column width={6}>
<Paragraph />
</Grid.Column>
<Grid.Column width={4}>
</Grid.Column>
<Grid.Column width={4}></Grid.Column>
<Grid.Row height={3}></Grid.Row>
<Grid.Row height={3}></Grid.Row>
<Grid.Row height={3}>
</Grid.Row>
<Grid.Row height={3}>
</Grid.Row>
<Grid.Row height={3}>
<Grid.Column width={3}>
</Grid.Column>
<Grid.Column width={3}></Grid.Column>
<Grid.Column width={10}>
<Divider />
</Grid.Column>
<Grid.Column width={3}>
</Grid.Column>
<Grid.Column width={3}></Grid.Column>
</Grid.Row>
</Grid>
)
);
export default class ForgotPasswrod extends React.Component {
render () {
return (
<MessageReg />
)
render() {
return <MessageReg />;
}
}

View file

@ -1,55 +1,69 @@
import React, {Component} from 'react';
import { Grid, Button, Segment, Responsive, Image} from 'semantic-ui-react';
import {Link } from "react-router-dom";
import MyHeader from '../components/HeaderController'
import React, { Component } from "react";
import { Grid, Button, Segment, Responsive, Image } from "semantic-ui-react";
import { Link } from "react-router-dom";
import MyHeader from "../components/HeaderController";
export default class FourOhFour extends Component {
constructor(props) {
super(props);
const meme = ['1.jpeg', '2.jpeg', '3.png', '4.jpeg', '5.jpeg', '6.jpg', '7.jpg',
'8.jpg', '9.jpeg', '10.jpg', '11.jpeg', '12.gif', '13.gif', '14.gif'];
const meme = [
"1.jpeg",
"2.jpeg",
"3.png",
"4.jpeg",
"5.jpeg",
"6.jpg",
"7.jpg",
"8.jpg",
"9.jpeg",
"10.jpg",
"11.jpeg",
"12.gif",
"13.gif",
"14.gif",
];
var arrayNum = Math.floor(Math.random() * 13) + 1;
var path = 'img/room_404_meme/' + meme[arrayNum];
this.state = {meme : path};
var path = "img/room_404_meme/" + meme[arrayNum];
this.state = { meme: path };
}
render() {
return (
<Segment.Group>
<Responsive as={Segment} minWidth={768}>
<div style={{height : "110vh", background: '#1b1c1d'}}>
<Grid >
<Grid.Row color='black'>
<div style={{ height: "110vh", background: "#1b1c1d" }}>
<Grid>
<Grid.Row color="black">
<Grid.Column>
<MyHeader logout={this.props.logout} />
</Grid.Column>
</Grid.Row>
<Grid.Row color='black'>
<Grid.Row color="black">
<Grid.Column width={16}>
<Segment inverted color='red'>
<Segment inverted color="red">
<Grid>
<Grid.Row>
<Grid.Column textAlign='center'>
<Grid.Column textAlign="center">
<h1>404 Page Not Found</h1>
</Grid.Column>
</Grid.Row>
<Grid.Row>
<Grid.Column width={8}>
<Image centered src={this.state.meme} size='medium' />
<Image centered src={this.state.meme} size="medium" />
</Grid.Column>
<Grid.Column width={8}>
<p>
Hey what are you doing here?
Looks like you are lost, this room does not exist. Maybe you were looking for
the kitchen, or the garage, or the bedroom, or your love room... so don't
wait here and let's go back to our main room! ...or refresh this page
some times...
Hey what are you doing here? Looks like you are
lost, this room does not exist. Maybe you were
looking for the kitchen, or the garage, or the
bedroom, or your love room... so don't wait here and
let's go back to our main room! ...or refresh this
page some times...
</p>
<Button fluid inverted color='white'>
<Link style={{color: 'black'}} to="/">Let's go back to our main room!</Link>
<Button fluid inverted color="white">
<Link style={{ color: "black" }} to="/">
Let's go back to our main room!
</Link>
</Button>
</Grid.Column>
</Grid.Row>
@ -62,38 +76,41 @@ export default class FourOhFour extends Component {
</Responsive>
<Responsive as={Segment} maxWidth={768}>
<div style={{background: '#1b1c1d'}}>
<Grid >
<Grid.Row color='black'>
<div style={{ background: "#1b1c1d" }}>
<Grid>
<Grid.Row color="black">
<Grid.Column>
<MyHeader logout={this.props.logout} />
</Grid.Column>
</Grid.Row>
<Grid.Row color='black'>
<Grid.Row color="black">
<Grid.Column width={16}>
<Segment inverted color='red'>
<Segment inverted color="red">
<Grid>
<Grid.Row>
<Grid.Column textAlign='center'>
<Grid.Column textAlign="center">
<h1>404 Page Not Found</h1>
</Grid.Column>
</Grid.Row>
<Grid.Row>
<Grid.Column width={16}>
<Image centered src={this.state.meme} size='medium' />
<Image centered src={this.state.meme} size="medium" />
</Grid.Column>
</Grid.Row>
<Grid.Row>
<Grid.Column width={16}>
<p>
Hey what are you doing here?
Looks like you are lost, this room does not exist. Maybe you were looking for
the kitchen, or the garage, or the bedroom, or your love room... so don't
wait here and let's go back to our main room! ...or refresh this page
some times...
Hey what are you doing here? Looks like you are
lost, this room does not exist. Maybe you were
looking for the kitchen, or the garage, or the
bedroom, or your love room... so don't wait here and
let's go back to our main room! ...or refresh this
page some times...
</p>
<Button fluid inverted color='white'>
<Link style={{color: 'black'}} to="/">Let's go back to our main room!</Link>
<Button fluid inverted color="white">
<Link style={{ color: "black" }} to="/">
Let's go back to our main room!
</Link>
</Button>
</Grid.Column>
</Grid.Row>
@ -105,6 +122,6 @@ export default class FourOhFour extends Component {
</div>
</Responsive>
</Segment.Group>
)
);
}
}

View file

@ -1,6 +1,6 @@
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import HomeNavbar from './../components/HomeNavbar';
import PropTypes from "prop-types";
import React, { Component } from "react";
import HomeNavbar from "./../components/HomeNavbar";
import {
Button,
Container,
@ -14,15 +14,15 @@ import {
Segment,
Sidebar,
Visibility,
} from 'semantic-ui-react';
} from "semantic-ui-react";
// Heads up!
// We using React Static to prerender our docs with server side rendering, this is a quite simple solution.
// For more advanced usage please check Responsive docs under the "Usage" section.
const getWidth = () => {
const isSSR = typeof window === 'undefined';
const isSSR = typeof window === "undefined";
return isSSR ? Responsive.onlyTablet.minWidth : window.innerWidth;
}
};
/* eslint-disable react/no-multi-comp */
/* Heads up! HomepageHeading uses inline styling, however it's not the best practice. Use CSS or styled components for
@ -31,44 +31,44 @@ const getWidth = () => {
const HomepageHeading = ({ mobile }) => (
<Container text>
<Header
as='h1'
content='SmartHut'
as="h1"
content="SmartHut"
inverted
style={{
fontSize: mobile ? '2em' : '4em',
fontWeight: 'normal',
fontSize: mobile ? "2em" : "4em",
fontWeight: "normal",
marginBottom: 0,
marginTop: mobile ? '1.5em' : '3em',
marginTop: mobile ? "1.5em" : "3em",
}}
/>
<Header
as='h2'
content='Keep your Home fully Connected'
as="h2"
content="Keep your Home fully Connected"
inverted
style={{
fontSize: mobile ? '1.5em' : '1.7em',
fontWeight: 'normal',
marginTop: mobile ? '0.5em' : '1.5em',
fontSize: mobile ? "1.5em" : "1.7em",
fontWeight: "normal",
marginTop: mobile ? "0.5em" : "1.5em",
}}
/>
<Button size='huge' color="orange" href="/signup">
<Button size="huge" color="orange" href="/signup">
Get Started
<Icon name='right arrow' />
<Icon name="right arrow" />
</Button>
</Container>
)
);
HomepageHeading.propTypes = {
mobile: PropTypes.bool,
}
};
class DesktopContainer extends Component {
state = {};
hideFixedMenu = () => this.setState({ fixed: false })
showFixedMenu = () => this.setState({ fixed: true })
hideFixedMenu = () => this.setState({ fixed: false });
showFixedMenu = () => this.setState({ fixed: true });
render() {
const { children } = this.props
const { children } = this.props;
return (
<Responsive getWidth={getWidth} minWidth={Responsive.onlyTablet.minWidth}>
@ -79,10 +79,10 @@ class DesktopContainer extends Component {
>
<Segment
basic
textAlign='center'
textAlign="center"
style={{
minHeight: 700,
padding: '1em 0em',
padding: "1em 0em",
background: ` linear-gradient(to bottom, rgba(0, 46, 200, 0.51), rgba(0, 0, 0, 0.51)), url("img/header.jpg")`,
backgroundSize: "cover",
}}
@ -95,20 +95,20 @@ class DesktopContainer extends Component {
{children}
</Responsive>
)
);
}
}
DesktopContainer.propTypes = {
children: PropTypes.node,
}
};
class MobileContainer extends Component {
state = {}
state = {};
handleSidebarHide = () => this.setState({ sidebarOpened: false })
handleSidebarHide = () => this.setState({ sidebarOpened: false });
handleToggle = () => this.setState({ sidebarOpened: true })
handleToggle = () => this.setState({ sidebarOpened: true });
render() {
const { children } = this.props;
@ -122,36 +122,36 @@ class MobileContainer extends Component {
>
<Sidebar
as={Menu}
animation='push'
animation="push"
inverted
onHide={this.handleSidebarHide}
vertical
visible={sidebarOpened}
>
<Menu.Item as='a' active>
<Menu.Item as="a" active>
Home
</Menu.Item>
<Menu.Item as='a'>Log in</Menu.Item>
<Menu.Item as='a'>Sign Up</Menu.Item>
<Menu.Item as="a">Log in</Menu.Item>
<Menu.Item as="a">Sign Up</Menu.Item>
</Sidebar>
<Sidebar.Pusher dimmed={sidebarOpened}>
<Segment
inverted
textAlign='center'
style={{ minHeight: 350, padding: '1em 0em' }}
textAlign="center"
style={{ minHeight: 350, padding: "1em 0em" }}
vertical
>
<Container>
<Menu inverted pointing secondary size='large'>
<Menu inverted pointing secondary size="large">
<Menu.Item onClick={this.handleToggle}>
<Icon name='sidebar' />
<Icon name="sidebar" />
</Menu.Item>
<Menu.Item position='right'>
<Button as='a' inverted>
<Menu.Item position="right">
<Button as="a" inverted>
Log in
</Button>
<Button as='a' inverted style={{ marginLeft: '0.5em' }}>
<Button as="a" inverted style={{ marginLeft: "0.5em" }}>
Sign Up
</Button>
</Menu.Item>
@ -163,109 +163,108 @@ class MobileContainer extends Component {
{children}
</Sidebar.Pusher>
</Responsive>
)
);
}
}
MobileContainer.propTypes = {
children: PropTypes.node,
}
};
const ResponsiveContainer = ({ children }) => (
<div>
<DesktopContainer>{children}</DesktopContainer>
<MobileContainer>{children}</MobileContainer>
</div>
)
);
ResponsiveContainer.propTypes = {
children: PropTypes.node,
}
};
const Home = () => (
<ResponsiveContainer>
<Segment style={{ padding: '8em 0em' }} vertical>
<Grid container stackable verticalAlign='middle'>
<Segment style={{ padding: "8em 0em" }} vertical>
<Grid container stackable verticalAlign="middle">
<Grid.Row>
<Grid.Column width={8}>
<Header as='h3' style={{ fontSize: '2em' }}>
<Header as="h3" style={{ fontSize: "2em" }}>
We help you keep your home connected
</Header>
<p style={{ fontSize: '1.33em' }}>
<p style={{ fontSize: "1.33em" }}>
In a few steps your home will be fully connected with SmartHut.
</p>
<Header as='h3' style={{ fontSize: '2em' }}>
<Header as="h3" style={{ fontSize: "2em" }}>
Choose between a wide range of devices
</Header>
<p style={{ fontSize: '1.33em' }}>
<p style={{ fontSize: "1.33em" }}>
SmartHut is a leading worldwide company in technology innovation.
Explore our website to find the best devices for each room of your home!
Explore our website to find the best devices for each room of your
home!
</p>
</Grid.Column>
<Grid.Column floated='right' width={6}>
<Image bordered rounded size='large' src='/img/banner.jpg' />
<Grid.Column floated="right" width={6}>
<Image bordered rounded size="large" src="/img/banner.jpg" />
</Grid.Column>
</Grid.Row>
<Grid.Row>
<Grid.Column textAlign='center'>
<Button size='huge'>Check It Out</Button>
<Grid.Column textAlign="center">
<Button size="huge">Check It Out</Button>
</Grid.Column>
</Grid.Row>
</Grid>
</Segment>
<Segment style={{ padding: '8em 0em' }} vertical>
<Segment style={{ padding: "8em 0em" }} vertical>
<Container text>
<Header as='h3' style={{ fontSize: '2em' }}>
<Header as="h3" style={{ fontSize: "2em" }}>
Have you ever dreamt about a smart home?
</Header>
<p style={{ fontSize: '1.33em' }}>
Let us carrying you into the future. With SmartHut, being at home
will be a refreshing experience. With just a few clicks, you will be
able the set the illumination of your entire place.
Follow the intelligent light, follow SmartHut.
<p style={{ fontSize: "1.33em" }}>
Let us carrying you into the future. With SmartHut, being at home will
be a refreshing experience. With just a few clicks, you will be able
the set the illumination of your entire place. Follow the intelligent
light, follow SmartHut.
</p>
<Button as='a' size='large'>
<Button as="a" size="large">
Read More
</Button>
</Container>
</Segment>
<Segment inverted vertical style={{ padding: '5em 0em' }}>
<Segment inverted vertical style={{ padding: "5em 0em" }}>
<Container>
<Grid divided inverted stackable>
<Grid.Row>
<Grid.Column width={3}>
<Header inverted as='h4' content='About' />
<Header inverted as="h4" content="About" />
<List link inverted>
<List.Item as='a'>Sitemap</List.Item>
<List.Item as='a'>Contact Us</List.Item>
<List.Item as='a'>Religious Ceremonies</List.Item>
<List.Item as='a'>Gazebo Plans</List.Item>
<List.Item as="a">Sitemap</List.Item>
<List.Item as="a">Contact Us</List.Item>
<List.Item as="a">Religious Ceremonies</List.Item>
<List.Item as="a">Gazebo Plans</List.Item>
</List>
</Grid.Column>
<Grid.Column width={3}>
<Header inverted as='h4' content='Services' />
<Header inverted as="h4" content="Services" />
<List link inverted>
<List.Item as='a'>Banana Pre-Order</List.Item>
<List.Item as='a'>DNA FAQ</List.Item>
<List.Item as='a'>How To Access</List.Item>
<List.Item as='a'>Favorite X-Men</List.Item>
<List.Item as="a">Banana Pre-Order</List.Item>
<List.Item as="a">DNA FAQ</List.Item>
<List.Item as="a">How To Access</List.Item>
<List.Item as="a">Favorite X-Men</List.Item>
</List>
</Grid.Column>
<Grid.Column width={7}>
<Header as='h4' inverted>
<Header as="h4" inverted>
SmartHut
</Header>
<p>
Keep your Home connected.
</p>
<p>Keep your Home connected.</p>
</Grid.Column>
</Grid.Row>
</Grid>
</Container>
</Segment>
</ResponsiveContainer>
)
);
export default Home;

View file

@ -1,22 +1,17 @@
import React, { Component } from "react";
import HomeNavbar from "./../components/HomeNavbar";
import {
Container,
Header,
Divider,
Grid
} from "semantic-ui-react";
import { Container, Header, Divider, Grid } from "semantic-ui-react";
const ContainerExampleAlignment = () => (
<div>
<HomeNavbar />
<Container textAlign='justified'>
<Container textAlign="justified">
<Header as="h1"> Instructions Page </Header>
<Grid>
<Grid.Row height={15}></Grid.Row>
</Grid>
</Container>
<Container textAlign='justified'>
<Container textAlign="justified">
<b>First Step</b>
<Divider />
<p>
@ -36,7 +31,7 @@ const ContainerExampleAlignment = () => (
</p>
<Divider />
</Container>
<Container textAlign='justified'>
<Container textAlign="justified">
<b>Second Step</b>
<Divider />
<p>
@ -56,7 +51,7 @@ const ContainerExampleAlignment = () => (
</p>
<Divider />
</Container>
<Container textAlign='justified'>
<Container textAlign="justified">
<b>Third Step</b>
<Divider />
<p>
@ -75,11 +70,11 @@ const ContainerExampleAlignment = () => (
ultricies nisi.
</p>
<Divider />
</Container>
<Container textAlign='justified'>
<b>Last Step</b>
<Divider />
<p>
</Container>
<Container textAlign="justified">
<b>Last Step</b>
<Divider />
<p>
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo
ligula eget dolor. Aenean massa strong. Cum sociis natoque penatibus et
magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis,
@ -93,17 +88,14 @@ const ContainerExampleAlignment = () => (
Phasellus viverra nulla ut metus varius laoreet. Quisque rutrum. Aenean
imperdiet. Etiam ultricies nisi vel augue. Curabitur ullamcorper
ultricies nisi.
</p>
<Divider />
</Container>
</p>
<Divider />
</Container>
</div>
)
);
export default class Insturction extends Component{
export default class Insturction extends Component {
render() {
return(
<ContainerExampleAlignment />
)
return <ContainerExampleAlignment />;
}
}

View file

@ -1,37 +1,46 @@
import React, {Component} from 'react';
import {Button, Form, Grid, Header, Image, Message, Icon, Checkbox, Input} from 'semantic-ui-react';
import React, { Component } from "react";
import {
Button,
Form,
Grid,
Header,
Image,
Message,
Icon,
Checkbox,
Input,
} from "semantic-ui-react";
export default class Login extends Component {
constructor(props) {
super(props);
this.state = {
user: "",
password : "",
password: "",
fireRedirect: false,
error : { state : false,
message: ""},
error: { state: false, message: "" },
};
}
handleLogin = (e) => {
e.preventDefault();
const params = {
"usernameOrEmail": this.state.user,
"password": this.state.password,
usernameOrEmail: this.state.user,
password: this.state.password,
};
this.props.auth({
this.props
.auth({
user: this.state.user,
params : params,
}).then(res => {
params: params,
})
.then((res) => {
if (res.status === 200) {
} else {
this.setState({error: { state: true,
message: "Errore"}});
this.setState({ error: { state: true, message: "Errore" } });
}
}).catch(err => {
})
.catch((err) => {
console.log(err);
});
};
@ -39,63 +48,83 @@ export default class Login extends Component {
onChangeHandler = (event) => {
let nam = event.target.name;
let val = event.target.value;
this.setState({[nam]: val});
this.setState({ [nam]: val });
};
toggle = () => this.setState((prevState) => ({ rememberme: !prevState.rememberme }));
toggle = () =>
this.setState((prevState) => ({ rememberme: !prevState.rememberme }));
render() {
return (
<React.Fragment>
<Button
circular
style={{margin: "2em"}}
href="/"
>
<Icon name='arrow alternate circle left'/>
<Button circular style={{ margin: "2em" }} href="/">
<Icon name="arrow alternate circle left" />
Go Home
</Button>
<Grid textAlign='center' style={{height: '70vh'}} verticalAlign='middle'>
<Grid.Column style={{maxWidth: 450}}>
<Header as='h2' color='blue' textAlign='center'>
<Image src='img/logo.png'/> Log-in to SmartHut
<Grid
textAlign="center"
style={{ height: "70vh" }}
verticalAlign="middle"
>
<Grid.Column style={{ maxWidth: 450 }}>
<Header as="h2" color="blue" textAlign="center">
<Image src="img/logo.png" /> Log-in to SmartHut
</Header>
<Form size='large' style={{marginTop : "2em"}} error={this.state.error.state}>
<Form
size="large"
style={{ marginTop: "2em" }}
error={this.state.error.state}
>
<Message
error
header='Login Error'
content= {this.state.error.message}
header="Login Error"
content={this.state.error.message}
/>
<Form.Input
control={Input}
type="text"
icon='user'
icon="user"
name="user"
iconPosition='left'
placeholder='Username or E-mail'
iconPosition="left"
placeholder="Username or E-mail"
onChange={this.onChangeHandler}
/>
<Form.Input
icon='lock'
iconPosition='left'
placeholder='Password'
icon="lock"
iconPosition="left"
placeholder="Password"
name="password"
type='password'
type="password"
onChange={this.onChangeHandler}
/>
<Checkbox type="checkbox" name="rememberme" onClick={this.toggle} label='Remember me' style={{margin: "1.5em 0", float : "left"}}/>
<Checkbox
type="checkbox"
name="rememberme"
onClick={this.toggle}
label="Remember me"
style={{ margin: "1.5em 0", float: "left" }}
/>
<Button color='blue' fluid size='large' onClick={this.handleLogin}>
<Button
color="blue"
fluid
size="large"
onClick={this.handleLogin}
>
Login
</Button>
</Form>
<Message>
<p><a href="/forgot-password">Forgot Password?</a></p>
<p>New to us? <a href='/signup'> Sign Up</a></p>
<p>
<a href="/forgot-password">Forgot Password?</a>
</p>
<p>
New to us? <a href="/signup"> Sign Up</a>
</p>
</Message>
</Grid.Column>
</Grid>
</React.Fragment>
)
);
}
}

View file

@ -1,23 +1,30 @@
import React, { Component } from 'react';
import { Menu, Grid, Icon, Responsive, Segment, Dropdown } from "semantic-ui-react";
import {editButtonStyle} from "../components/dashboard/devices/styleComponents";
import React, { Component } from "react";
import {
Menu,
Grid,
Icon,
Responsive,
Segment,
Dropdown,
} from "semantic-ui-react";
import { editButtonStyle } from "../components/dashboard/devices/styleComponents";
import ModalWindow from "../components/modalform";
class Navbar extends Component {
constructor(props) {
super(props);
this.state = {
activeItemName: 'Home',
activeItemName: "Home",
activeItem: -1,
edited: "",
editMode : false
}
editMode: false,
};
}
editModeController = (e) => this.setState((prevState) => ({ editMode: !prevState.editMode }));
editModeController = (e) =>
this.setState((prevState) => ({ editMode: !prevState.editMode }));
handleClick = (e, {id, name}) => {
console.log(id);
handleClick = (e, { id, name }) => {
let obj = undefined;
this.props.rooms.forEach((e) => {
if (e.id === id) {
@ -28,45 +35,47 @@ class Navbar extends Component {
this.setState({
activeItem: id,
activeRoom: obj,
activeItemName: name
activeItemName: name,
});
this.props.handleItemClick(id)
}
this.props.handleItemClick(id);
};
render(){
render() {
//const { activeItem } = this.state
return (
<div style={{background: '#1b1c1d'}}>
<div style={{ background: "#1b1c1d!important" }}>
<Segment.Group>
<Responsive as={Segment} minWidth={768}>
<Grid>
<Grid.Row color='black'>
<button style={editButtonStyle} onClick={this.editModeController}>Edit</button>
<Grid.Row color="black">
<button
style={editButtonStyle}
onClick={this.editModeController}
>
Edit
</button>
</Grid.Row>
<Grid.Row color='black'>
<Grid.Row color="black">
<Menu inverted fluid vertical>
<Menu.Item
key={-1}
id={-1}
name='Home'
name="Home"
active={this.state.activeItem === -1}
onClick={this.handleClick}
>
<Grid>
<Grid.Row>
<Grid.Column>
<Icon name="home" size="small"/>
</Grid.Column>
<Grid.Column>
HOME
<Icon name="home" size="small" />
</Grid.Column>
<Grid.Column>HOME</Grid.Column>
</Grid.Row>
</Grid>
</Menu.Item>
</ Menu.Item>
{this.props.rooms ?
this.props.rooms.map((e, i) => {
{this.props.rooms
? this.props.rooms.map((e, i) => {
return (
<Menu.Item
id={e.id}
@ -78,36 +87,36 @@ class Navbar extends Component {
<Grid>
<Grid.Row>
<Grid.Column>
<Icon name={e.icon} size="small"/>
</Grid.Column>
<Grid.Column width={8}>
{e.name}
<Icon name={e.icon} size="small" />
</Grid.Column>
<Grid.Column width={8}>{e.name}</Grid.Column>
<Grid.Column floated="right">
{this.state.editMode ?
<ModalWindow type="modify" idRoom={e} updateRoom={this.props.updateRoom} deleteRoom={this.props.deleteRoom}/>
: null
}
{this.state.editMode ? (
<ModalWindow
type="modify"
idRoom={e}
updateRoom={this.props.updateRoom}
deleteRoom={this.props.deleteRoom}
/>
) : null}
</Grid.Column>
</Grid.Row>
</Grid>
</ Menu.Item>
)
}) : null
}
</Menu.Item>
);
})
: null}
<Menu.Item
name='newM'
active={this.state.activeItem === 'newM'}
name="newM"
active={this.state.activeItem === "newM"}
>
<Grid>
<Grid.Row centered name='new'>
<ModalWindow type="new" addRoom={this.props.addRoom}/>
<Grid.Row centered name="new">
<ModalWindow type="new" addRoom={this.props.addRoom} />
</Grid.Row>
</Grid>
</ Menu.Item>
</Menu.Item>
</Menu>
</Grid.Row>
</Grid>
@ -117,26 +126,25 @@ class Navbar extends Component {
<Menu inverted>
<Dropdown item fluid text={this.state.activeItemName}>
<Dropdown.Menu>
<Dropdown.Item
key={-1}
name='Home'
active={this.state.activeItem === 'Home'}
onClick={this.handleClick}>
id={-1}
name="Home"
active={this.state.activeItem === "Home"}
onClick={this.handleClick}
>
<Grid>
<Grid.Row>
<Grid.Column>
<Icon name="home" size="small"/>
</Grid.Column>
<Grid.Column>
Home
<Icon name="home" size="small" />
</Grid.Column>
<Grid.Column>Home</Grid.Column>
</Grid.Row>
</Grid>
</Dropdown.Item>
{this.props.rooms ?
this.props.rooms.map((e, i) => {
{this.props.rooms
? this.props.rooms.map((e, i) => {
return (
<Dropdown.Item
id={e.id}
@ -148,38 +156,36 @@ class Navbar extends Component {
<Grid>
<Grid.Row>
<Grid.Column width={1}>
<Icon name={e.icon} size="small"/>
</Grid.Column>
<Grid.Column>
{e.name}
<Icon name={e.icon} size="small" />
</Grid.Column>
<Grid.Column>{e.name}</Grid.Column>
</Grid.Row>
</Grid>
</ Dropdown.Item>
)
}) : null
}
</Dropdown.Item>
);
})
: null}
</Dropdown.Menu>
</Dropdown>
</Menu>
{
this.state.activeItem !== -1 ?
<Grid>
<Grid inverted>
<Grid.Row>
<Grid.Column width={8}>
<ModalWindow type="new" idRoom={this.state.activeItem === -1? -1 : this.state.activeRoom} updateRoom={this.props.updateRoom} deleteRoom={this.props.deleteRoom}/>
<ModalWindow type="new" addRoom={this.props.addRoom} />
</Grid.Column>
{this.state.activeItem !== -1 ? (
<Grid.Column width={8}>
<ModalWindow type="modify" idRoom={this.state.activeItem === -1? -1 : this.state.activeRoom} updateRoom={this.props.updateRoom} deleteRoom={this.props.deleteRoom}/>
<ModalWindow
type="modify"
idRoom={this.state.activeRoom}
updateRoom={this.props.updateRoom}
deleteRoom={this.props.deleteRoom}
/>
</Grid.Column>
) : null}
</Grid.Row>
</Grid>
:
null
}
</Responsive>
</Segment.Group>
</div>
);

View file

@ -1,40 +1,49 @@
import React, {Component} from 'react';
import {Button, Form, Grid, Header, Image, Icon, Input, Message} from 'semantic-ui-react';
import {Redirect } from "react-router-dom";
import { call } from '../client_server';
import React, { Component } from "react";
import {
Button,
Form,
Grid,
Header,
Image,
Icon,
Input,
Message,
} from "semantic-ui-react";
import { Redirect } from "react-router-dom";
import { call } from "../client_server";
export default class Signup extends Component{
export default class Signup extends Component {
constructor(props) {
super(props);
this.state = {
completeName: "",
username: "",
email: "",
password : "",
error : { state : false,
message: ""},
success : false,
password: "",
error: { state: false, message: "" },
success: false,
};
}
handleRegistration = (e) => {
e.preventDefault();
const params = {
"email": this.state.email,
"name": this.state.completeName,
"password": this.state.password,
"username": this.state.username,
email: this.state.email,
name: this.state.completeName,
password: this.state.password,
username: this.state.username,
};
call.register(params)
.then(res => {
if (res.status === 200 && res.data){
this.setState({success: true});
call
.register(params)
.then((res) => {
if (res.status === 200 && res.data) {
this.setState({ success: true });
} else {
this.setState({error: { state: true,
message: "Errore"}});
this.setState({ error: { state: true, message: "Errore" } });
}
}).catch(err => {
})
.catch((err) => {
//console.log(err);
});
};
@ -42,58 +51,63 @@ export default class Signup extends Component{
onChangeHandler = (event) => {
let nam = event.target.name;
let val = event.target.value;
this.setState({[nam]: val});
this.setState({ [nam]: val });
};
render() {
if (this.state.success) {
return <Redirect to="sent-email-reg" />
return <Redirect to="sent-email-reg" />;
}
return (
<React.Fragment>
<Button
circular
style={{margin: "2em"}}
href="/"
<Button circular style={{ margin: "2em" }} href="/">
<Icon name="arrow alternate circle left" />
Go Home{" "}
</Button>
<Grid
textAlign="center"
style={{ height: "70vh" }}
verticalAlign="middle"
>
<Icon name='arrow alternate circle left'/>
Go Home </Button>
<Grid textAlign='center' style={{height: '70vh'}} verticalAlign='middle'>
<Grid.Column style={{maxWidth: 450}}>
<Header as='h2' color='blue' textAlign='center'>
<Image src='img/logo.png'/> Sign-up to SmartHut
<Grid.Column style={{ maxWidth: 450 }}>
<Header as="h2" color="blue" textAlign="center">
<Image src="img/logo.png" /> Sign-up to SmartHut
</Header>
<Form size='large' style={{marginTop : "2em"}} error={this.state.error.state}>
<Form
size="large"
style={{ marginTop: "2em" }}
error={this.state.error.state}
>
<Message
error
header='Singup Error'
content= {this.state.error.message}
header="Singup Error"
content={this.state.error.message}
/>
<Form.Input
icon='address card outline'
iconPosition='left'
placeholder='First Name and Last Name'
icon="address card outline"
iconPosition="left"
placeholder="First Name and Last Name"
name="completeName"
type='text'
type="text"
onChange={this.onChangeHandler}
required
/>
<Form.Input
icon='user'
iconPosition='left'
placeholder='Username'
icon="user"
iconPosition="left"
placeholder="Username"
name="username"
type='text'
type="text"
onChange={this.onChangeHandler}
required
/>
<Form.Input
control={Input}
type="name"
icon='envelope outline'
icon="envelope outline"
name="email"
iconPosition='left'
placeholder='E-mail'
iconPosition="left"
placeholder="E-mail"
onChange={this.onChangeHandler}
/*error={{
content: 'Please enter a valid email address',
@ -102,22 +116,27 @@ export default class Signup extends Component{
required
/>
<Form.Input
icon='lock'
iconPosition='left'
placeholder='Password (at least 8 characters)'
icon="lock"
iconPosition="left"
placeholder="Password (at least 8 characters)"
name="password"
type='password'
type="password"
onChange={this.onChangeHandler}
minLength={6}
required
/>
<Button color='blue' fluid size='large' onClick={this.handleRegistration}>
<Button
color="blue"
fluid
size="large"
onClick={this.handleRegistration}
>
Register
</Button>
</Form>
</Grid.Column>
</Grid>
</React.Fragment>
)
);
}
}

View file

@ -3,9 +3,7 @@ import React from "react";
import HeaderController from "./../components/HeaderController";
export default class TestHeaderController extends React.Component {
render () {
return (
<HeaderController/>
)
render() {
return <HeaderController />;
}
}

View file

@ -8421,6 +8421,11 @@ prepend-http@^1.0.0:
resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc"
integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=
prettier@2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.0.1.tgz#3f00ac71263be34684b2b2c8d7e7f63737592dac"
integrity sha512-piXGBcY1zoFOG0MvHpNE5reAGseLmaCRifQ/fmfF49BcYkInEs/naD/unxGNAeOKFA5+JxVrPyMvMlpzcd20UA==
pretty-bytes@^5.1.0:
version "5.3.0"
resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.3.0.tgz#f2849e27db79fb4d6cfe24764fc4134f165989f2"
@ -8710,6 +8715,13 @@ react-dev-utils@^10.2.0:
strip-ansi "6.0.0"
text-table "0.2.0"
react-device-detect@^1.11.14:
version "1.11.14"
resolved "https://registry.yarnpkg.com/react-device-detect/-/react-device-detect-1.11.14.tgz#02ba2398e2ce81fb0eaed3e62a9ad713ab3870a7"
integrity sha512-WSjch241xI+rXHVtJaSYxNUT2WAykzfJgMI2Hg9xjNNTlIZdJu/fmWf4iedNH7qzFq+JaJ6fDJu3mrKFLerKBw==
dependencies:
ua-parser-js "^0.7.20"
react-dom@^16.12.0:
version "16.12.0"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.12.0.tgz#0da4b714b8d13c2038c9396b54a92baea633fe11"
@ -10363,7 +10375,7 @@ typedarray@^0.0.6:
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
ua-parser-js@^0.7.18:
ua-parser-js@^0.7.18, ua-parser-js@^0.7.20:
version "0.7.21"
resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.21.tgz#853cf9ce93f642f67174273cc34565ae6f308777"
integrity sha512-+O8/qh/Qj8CgC6eYBVBykMrNtp5Gebn4dlGD/kKXVkJNDwyrAwSIqwz8CDf+tsAIWVycKcku6gIXJ0qwx/ZXaQ==