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}" - "docker push smarthutsm/smarthut:${CI_COMMIT_BRANCH}"
after_script: after_script:
- docker logout - 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-axios": "^2.0.3",
"react-circular-input": "^0.1.6", "react-circular-input": "^0.1.6",
"react-circular-slider-svg": "^0.1.5", "react-circular-slider-svg": "^0.1.5",
"react-device-detect": "^1.11.14",
"react-dom": "^16.12.0", "react-dom": "^16.12.0",
"react-round-slider": "^1.0.1", "react-round-slider": "^1.0.1",
"react-router": "^5.1.2", "react-router": "^5.1.2",
@ -43,5 +44,8 @@
"last 1 firefox version", "last 1 firefox version",
"last 1 safari 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> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head>
<head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" /> <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<link rel="stylesheet" href="style.css"> <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="//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="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" /> <meta name="theme-color" content="#000000" />
<meta name="description" content="Web site created using create-react-app" /> <meta
<meta name="viewport" content="minimum-scale=1, initial-scale=1, width=device-width" /> 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 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/ 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`. Learn how to configure a non-root public URL by running `npm run build`.
--> -->
<title>React App</title> <title>React App</title>
</head> </head>
<body> <body>
<noscript>You need to enable JavaScript to run this app.</noscript> <noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div> <div id="root"></div>
<!-- <!--
@ -40,6 +48,5 @@
To begin the development, run `npm start` or `yarn start`. To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`. To create a production bundle, use `npm run build` or `yarn build`.
--> -->
</body> </body>
</html> </html>

View file

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

View file

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

View file

@ -1,8 +1,8 @@
import React from 'react'; import React from "react";
import { render } from '@testing-library/react'; import { render } from "@testing-library/react";
import { Router } from "react-router"; import { Router } from "react-router";
import { createMemoryHistory } from "history"; import { createMemoryHistory } from "history";
import App from './App'; import App from "./App";
test("redirects to homepage", () => { test("redirects to homepage", () => {
const history = createMemoryHistory(); const history = createMemoryHistory();
@ -13,4 +13,3 @@ test("redirects to homepage", () => {
); );
expect(history.location.pathname).toBe("/"); 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"); var tkn = localStorage.getItem("token");
/** the ServiceSocket instance valid for the current session */
var socket;
// requests data devices // 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 = { export var call = {
setToken: function(token) { setToken: function (token) {
tkn = 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) { login: function (data, headers) {
return axios.post(config + 'register/init-reset-password', data) return axios.post(config + "auth/login", data);
}, },
resetPassword: function(data, headers) { register: function (data, headers) {
return axios.put(config + 'register/reset-password', data) return axios.post(config + "register", data);
}, },
getAllRooms: function(token) { initResetPassword: function (data, headers) {
if (!token){ 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; token = tkn;
} }
return axios.get(config + 'room', { headers: { Authorization : "Bearer " + token } }) return axios.get(config + "room", {
headers: { Authorization: "Bearer " + token },
});
}, },
getAllDevices: function(token) { getAllDevices: function (token) {
if (!token){ if (!token) {
token = tkn; token = tkn;
} }
return axios.get(config + 'device', { headers: { Authorization : "Bearer " + token } }); return axios.get(config + "device", {
headers: { Authorization: "Bearer " + token },
});
}, },
getAllDevicesByRoom: function(id, token) { getAllDevicesByRoom: function (id, token) {
if (!token){ if (!token) {
token = tkn; 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) { createRoom: function (data, headers) {
return axios.post(config + 'room', data, { headers: { Authorization : "Bearer " + tkn } }) return axios.post(config + "room", data, {
headers: { Authorization: "Bearer " + tkn },
});
}, },
updateRoom: function(data, headers) { updateRoom: function (data, headers) {
return axios.put(config + 'room?name='+ data.name, data, { headers: { Authorization : "Bearer " + tkn } }) return axios.put(config + "room/" + data.id, data, {
headers: { Authorization: "Bearer " + tkn },
});
}, },
deleteRoom: function(data, headers) { deleteRoom: function (data, headers) {
return axios.delete(config + 'room/'+data.id, { headers: { Authorization : "Bearer " + tkn } }); return axios.delete(config + "room/" + data.id, {
headers: { Authorization: "Bearer " + tkn },
});
}, },
devicePost: function(data, headers) { devicePost: function (data, headers) {
return axios.post(config + data.device, data.params, { headers: { Authorization : "Bearer " + tkn } }) 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) { deviceUpdate: function (data, typeDevice) {
let url = 'device'; let url = "device";
if (typeDevice) { if (typeDevice) {
url = 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) { deviceDelete: function (data, headers) {
return axios.delete(config + data.device + '/' + data.id, {}, { headers: { Authorization : "Bearer " + tkn } }) return axios.delete(config + data.device + "/" + data.id, {
headers: { Authorization: "Bearer " + tkn },
});
}, },
deviceGetById: function(data, headers) { deviceGetById: function (data, headers) {
return axios.get(config + data.device + '/' + data.id) return axios.get(config + data.device + "/" + data.id);
},
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 React from "react";
import PropTypes from 'prop-types'; import PropTypes from "prop-types";
import { makeStyles } from '@material-ui/core/styles'; import { makeStyles } from "@material-ui/core/styles";
import Paper from '@material-ui/core/Paper'; import Paper from "@material-ui/core/Paper";
import Typography from '@material-ui/core/Typography'; import Typography from "@material-ui/core/Typography";
import Grid from '@material-ui/core/Grid'; import Grid from "@material-ui/core/Grid";
import Link from '@material-ui/core/Link'; import Link from "@material-ui/core/Link";
const useStyles = makeStyles(theme => ({ const useStyles = makeStyles((theme) => ({
mainFeaturedPost: { mainFeaturedPost: {
position: 'relative', position: "relative",
backgroundColor: theme.palette.grey[800], backgroundColor: theme.palette.grey[800],
color: theme.palette.common.white, color: theme.palette.common.white,
marginBottom: theme.spacing(4), marginBottom: theme.spacing(4),
backgroundImage: 'img/banner.jpg', backgroundImage: "img/banner.jpg",
backgroundSize: 'cover', backgroundSize: "cover",
backgroundRepeat: 'no-repeat', backgroundRepeat: "no-repeat",
backgroundPosition: 'center', backgroundPosition: "center",
}, },
overlay: { overlay: {
position: 'absolute', position: "absolute",
top: 0, top: 0,
bottom: 0, bottom: 0,
right: 0, right: 0,
left: 0, left: 0,
backgroundColor: 'rgba(0,0,0,.3)', backgroundColor: "rgba(0,0,0,.3)",
}, },
mainFeaturedPostContent: { mainFeaturedPostContent: {
position: 'relative', position: "relative",
padding: theme.spacing(3), padding: theme.spacing(3),
[theme.breakpoints.up('md')]: { [theme.breakpoints.up("md")]: {
padding: theme.spacing(6), padding: theme.spacing(6),
paddingRight: 0, paddingRight: 0,
}, },
}, },
})); }));
export default function Banner(props) { export default function Banner(props) {
const classes = useStyles(); const classes = useStyles();
const { post } = props; const { post } = props;
return ( 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 */} {/* 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} /> <div className={classes.overlay} />
<Grid container> <Grid container>
<Grid item md={6}> <Grid item md={6}>
<div className={classes.mainFeaturedPostContent}> <div className={classes.mainFeaturedPostContent}>
<Typography component="h1" variant="h3" color="inherit" gutterBottom> <Typography
component="h1"
variant="h3"
color="inherit"
gutterBottom
>
{post.title} {post.title}
</Typography> </Typography>
<Typography variant="h5" color="inherit" paragraph> <Typography variant="h5" color="inherit" paragraph>

View file

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

View file

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

View file

@ -1,52 +1,69 @@
import React from "react"; import React from "react";
import { Dropdown, Icon, Grid, Divider} from 'semantic-ui-react' import { Dropdown, Icon, Grid, Divider } from "semantic-ui-react";
import { Segment, Image } from 'semantic-ui-react' import { Segment, Image } from "semantic-ui-react";
import {
BrowserView,
MobileView,
isBrowser,
isMobile
} from "react-device-detect";
const AvatarImage = () => ( const AvatarImage = () => (
<Image <Image
src='avatar3.png' src="avatar3.png"
style={{width: '25px', height: 'auto'}} style={{ width: "25px", height: "auto" }}
centered centered />
/> );
)
const IconHomeImage = () => ( const IconHomeImage = () => (
<Image <Image
src='smart-home.png' src="smart-home.png"
style={{width: '50px', height: 'auto'}} style={{ width: "50px", height: "auto" }}
centered centered
as='a' as="a"
href='/' href="/"
/> />
) );
const IconHomeImageMobile = () => (
<Image
src="smart-home.png"
style={{ width: "10px", height: "auto" }}
centered
as="a"
href="/"
/>
);
const TitleImage = () => ( const TitleImage = () => (
<Image src='title7.png' size='medium' centered/> <Image
) src="title7.png"
size="medium"
centered
/>
);
const BrowserStructure = (props) => (
<Grid columns="equal" divided inverted padded>
const GridExampleInverted = (props) => ( <Grid.Row color="black" textAlign="center">
<Grid columns='equal' divided inverted padded>
<Grid.Row color='black' textAlign='center' >
<Grid.Column width={3} height={0.5}> <Grid.Column width={3} height={0.5}>
<Segment color='black' inverted> <Segment color="black" inverted>
<IconHomeImage /> <IconHomeImage />
</Segment> </Segment>
</Grid.Column> </Grid.Column>
<Grid.Column> <Grid.Column>
<Segment color='black' inverted> <Segment color="black" inverted>
<TitleImage /> <TitleImage />
</Segment> </Segment>
</Grid.Column> </Grid.Column>
<Grid.Column width={2} heigth={1}> <Grid.Column width={2} heigth={1}>
<AvatarImage /> <AvatarImage />
<Divider /> <Divider />
<Dropdown item icon='setting' size='huge'> <Dropdown item icon="setting" size="huge">
<Dropdown.Menu> <Dropdown.Menu>
<Dropdown.Item> <Dropdown.Item>
<Icon name='dropdown' /> <Icon name="dropdown" />
<span className='text'>Settings</span> <span className="text">Settings</span>
<Dropdown.Menu> <Dropdown.Menu>
<Dropdown.Item>Document</Dropdown.Item> <Dropdown.Item>Document</Dropdown.Item>
<Dropdown.Item>Image</Dropdown.Item> <Dropdown.Item>Image</Dropdown.Item>
@ -54,135 +71,66 @@ const GridExampleInverted = (props) => (
</Dropdown.Item> </Dropdown.Item>
<Dropdown.Item>See profile...</Dropdown.Item> <Dropdown.Item>See profile...</Dropdown.Item>
<Dropdown.Divider /> <Dropdown.Divider />
<Dropdown.Item onClick={props.logout }>Logout</Dropdown.Item> <Dropdown.Item onClick={props.logout}>Logout</Dropdown.Item>
</Dropdown.Menu> </Dropdown.Menu>
</Dropdown> </Dropdown>
</Grid.Column> </Grid.Column>
</Grid.Row> </Grid.Row>
</Grid> </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 { export default class MyHeader extends React.Component {
render() { render() {
return ( return (
<div> <div>
<GridExampleInverted logout={this.props.logout} /> <BrowserView>
<BrowserStructure logout={this.props.logout} />
</BrowserView>
<MobileView>
<MobileStructure />
</MobileView>
</div> </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, Image,
Menu, Menu,
Sidebar, Sidebar,
Responsive Responsive,
} from "semantic-ui-react"; } from "semantic-ui-react";
const NavBarMobile = ({ const NavBarMobile = ({
children, children,
leftItems, leftItems,
onPusherClick, onPusherClick,
onToggle, onToggle,
rightItems, rightItems,
visible visible,
}) => ( }) => (
<Sidebar.Pushable> <Sidebar.Pushable>
<Sidebar <Sidebar
as={Menu} as={Menu}
@ -41,42 +40,47 @@ const NavBarMobile = ({
<Icon name="sidebar" /> <Icon name="sidebar" />
</Menu.Item> </Menu.Item>
<Menu.Menu position="right"> <Menu.Menu position="right">
{_.map(rightItems, item => <Menu.Item {...item} />)} {_.map(rightItems, (item) => (
<Menu.Item {...item} />
))}
</Menu.Menu> </Menu.Menu>
</Menu> </Menu>
{children} {children}
</Sidebar.Pusher> </Sidebar.Pusher>
</Sidebar.Pushable> </Sidebar.Pushable>
); );
const NavBarDesktop = ({ leftItems, rightItems }) => ( const NavBarDesktop = ({ leftItems, rightItems }) => (
<Menu fixed="top" inverted> <Menu fixed="top" inverted>
<Menu.Item> <Menu.Item>
<Image size="mini" src="smart-home_index.png" /> <Image size="mini" src="smart-home_index.png" />
</Menu.Item> </Menu.Item>
{_.map(leftItems, item => <Menu.Item {...item} />)} {_.map(leftItems, (item) => (
<Menu.Item {...item} />
))}
<Menu.Menu position="right"> <Menu.Menu position="right">
{_.map(rightItems, item => <Menu.Item {...item} />)} {_.map(rightItems, (item) => (
<Menu.Item {...item} />
))}
</Menu.Menu> </Menu.Menu>
</Menu> </Menu>
); );
const NavBarChildren = ({ children }) => ( const NavBarChildren = ({ children }) => (
<Container style={{ marginTop: "5em" }}>{children}</Container> <Container style={{ marginTop: "5em" }}>{children}</Container>
); );
class HomeNavabarApp extends Component { class HomeNavabarApp extends Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
logged : true, logged: true,
email: "", email: "",
password : "" password: "",
}; };
} }
state = { state = {
visible: false visible: false,
}; };
handlePusher = () => { handlePusher = () => {
@ -113,17 +117,17 @@ class HomeNavabarApp extends Component {
} }
} }
const leftItems = [ const leftItems = [{ as: "a", content: "Home", key: "home", href: "/" }];
{ as: "a", content: "Home", key: "home", href:"/" }, const rightItems = [
]; { as: "a", content: "Login", key: "login", href: "/login" },
const rightItems = [ { as: "a", content: "Sign up", key: "register", href: "/signup" },
{ as: "a", content: "Login", key: "login", href:"/login" }, ];
{ as: "a", content: "Sign up", key: "register", href:"/signup" }
];
const HomeNavbarApp = () => ( const HomeNavbarApp = () => (
<HomeNavabarApp leftItems={leftItems} rightItems={rightItems}> <HomeNavabarApp
</HomeNavabarApp> leftItems={leftItems}
); rightItems={rightItems}
></HomeNavabarApp>
);
export default HomeNavbarApp; export default HomeNavbarApp;

View file

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

View file

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

View file

@ -1,34 +1,26 @@
import React, {Component} from "react"; import React, { Component } from "react";
import {editModeIconStyle, editModeStyle} from "./styleComponents"; import { editModeIconStyle, editModeStyle } from "./styleComponents";
export default class Settings extends Component { export default class Settings extends Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
displayForm: true, displayForm: true,
}
}; };
}
displayForm = () => { displayForm = () => {
this.setState((prevState) => ({displayForm: !prevState.displayForm})); this.setState((prevState) => ({ displayForm: !prevState.displayForm }));
}; };
render() { render() {
const view = ( const view = (
<div onClick={() => this.props.edit.openModal(this.props.deviceId)}> <div onClick={() => this.props.edit.openModal(this.props.deviceId)}>
<span style={editModeStyle}> <span style={editModeStyle}>
<img <img src="/img/settings.svg" alt="" style={editModeIconStyle} />
src="/img/settings.svg"
alt=""
style={editModeIconStyle}/>
</span> </span>
</div> </div>
); );
return ( return <React.Fragment>{this.props.edit.mode ? view : ""}</React.Fragment>;
<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 Light from "./Light";
import SmartPlug from "./SmartPlug"; import SmartPlug from "./SmartPlug";
import Sensor from "./Sensor"; import Sensor from "./Sensor";
import DefaultDimmer from "./Dimmer"; import DefaultDimmer from "./Dimmer";
import Switcher from "./Switch"; import Switcher from "./Switch";
const DeviceType = (props) => { const DeviceType = (props) => {
switch(props.type) { switch (props.type) {
case "regular-light": case "regularLight":
return (<Light onChangeData={props.changeDeviceData} device={props.device} edit={props.edit} />) return (
<Light
onChangeData={props.changeDeviceData}
device={props.device}
edit={props.edit}
/>
);
case "sensor": case "sensor":
return <Sensor onChangeData={props.changeDeviceData} device={props.device} edit={props.edit} /> return (
case "dimmer": <Sensor
return <DefaultDimmer onChangeData={props.changeDeviceData} device={props.device} edit={props.edit} /> onChangeData={props.changeDeviceData}
case "smartplug": device={props.device}
return <SmartPlug onChangeData={props.changeDeviceData} device={props.device} edit={props.edit} /> 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": case "switch":
return <Switcher onChangeData={props.changeDeviceData} device={props.device} edit={props.edit} /> return (
case "light": <Switcher
return (<Light onChangeData={props.changeDeviceData} device={props.device} edit={props.edit} />) onChangeData={props.changeDeviceData}
device={props.device}
edit={props.edit}
/>
);
case "dimmableLight":
return (
<Light
onChangeData={props.changeDeviceData}
device={props.device}
edit={props.edit}
/>
);
default: default:
return "" return "";
} }
} };
export default DeviceType; export default DeviceType;

View file

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

View file

@ -5,13 +5,13 @@ export const imageStyle = {
top: "20%", top: "20%",
left: "50%", left: "50%",
transform: "translateX(-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 = { export const nameStyle = {
color : "black", color: "black",
position: "absolute", position: "absolute",
top: "40%", top: "40%",
left: "50%", 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 . 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{ export class StatefulDimmer extends Component {
constructor(props){ constructor(props) {
super(props); super(props);
this.state = { this.state = {
intensityLevel : 0, intensityLevel: 0,
pointingLDevices:[] pointingLDevices: [],
} };
} }
componentDidMount() { componentDidMount() {}
}
render() { render() {
return( return <div>This is a Dimmer</div>;
<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 // As far as I am concern, even though this dimmer doesn't have state, internally it's needed
constructor(props){ constructor(props) {
super(props); super(props);
this.state = { this.state = {
pointingDevices :[] pointingDevices: [],
} };
} }
componentDidMount() { componentDidMount() {}
}
render() { render() {
return( return <div>This is a Dimmer</div>;
<div>
This is a Dimmer
</div>
)
} }
} }

View file

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

View file

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

View file

@ -6,33 +6,72 @@
* For this story, make the sensors return a constant value with some small random error. * 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 Settings from "./DeviceSettings";
import {StyledDiv} from "./styleComponents"; import { StyledDiv } from "./styleComponents";
import { call } from "../../../client_server";
export default class Sensor extends Component { export default class Sensor extends Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
turnedOn: false, turnedOn: false,
value: 20, value: 0,
error: 2.4
}; };
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 = () => { setName = () => {
if (this.props.device.name.length > 15) { 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; return this.props.device.name;
}; };
componentDidMount() { 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() { render() {
return ( return (
@ -40,25 +79,37 @@ export default class Sensor extends Component {
<Settings <Settings
deviceId={this.props.device.id} deviceId={this.props.device.id}
edit={this.props.edit} edit={this.props.edit}
onChangeData={(id, newSettings) => this.props.onChangeData(id, newSettings)}/> onChangeData={(id, newSettings) =>
this.props.onChangeData(id, newSettings)
}
/>
<CircularInput <CircularInput value={this.state.value / 100} style={style}>
value={this.state.value / 100} <CircularTrack />
style={style} <CircularProgress />
<text
style={valueStyle}
x={100}
y={80}
textAnchor="middle"
dy="0.3em"
fontWeight="bold"
> >
<CircularTrack/> {Math.round(this.state.value)}
<CircularProgress/> {this.units}
<text style={valueStyle} x={100} y={80} textAnchor="middle" dy="0.3em" fontWeight="bold">
{Math.round(this.state.value)}{this.units}
</text> </text>
<text style={errorStyle} x={100} y={100} textAnchor="middle" dy="0.6em" fontWeight="bold"> <text
&#177;{this.state.error} style={sensorText}
</text> x={100}
<text style={sensorText} x={100} y={150} textAnchor="middle" dy="0.3em" fontWeight="bold"> y={150}
textAnchor="middle"
dy="0.3em"
fontWeight="bold"
>
{this.setName()} {this.setName()}
</text> </text>
</CircularInput> </CircularInput>
</StyledDiv> </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 = { export const sensorText = {
fill: "#3e99ff", fill: "#3e99ff",
fontSize: "1.2rem", fontSize: "1.2rem",
fontFamily: "Lato", fontFamily: "Lato",
textShadow: "1px 1px 0.5px rgba(0, 0, 0, .2)", textShadow: "1px 1px 0.5px rgba(0, 0, 0, .2)",
} };
export const valueStyle = { export const valueStyle = {
fill: "#3e99ff", fill: "#3e99ff",
@ -14,10 +20,9 @@ export const valueStyle = {
textShadow: "1px 1px 0.5px rgba(0, 0, 0, .2)", textShadow: "1px 1px 0.5px rgba(0, 0, 0, .2)",
}; };
export const errorStyle = { export const errorStyle = {
fill: "#ff4050", fill: "#ff4050",
fontSize: "1.5rem", fontSize: "1.5rem",
fontFamily: "Lato", fontFamily: "Lato",
textShadow: "1px 1px 0.5px rgba(0, 0, 0, .2)", textShadow: "1px 1px 0.5px rgba(0, 0, 0, .2)",
} };

View file

@ -1,56 +1,73 @@
import React, {Component, useState} from 'react'; import React, { Component, useState } from "react";
import {Button, Checkbox, Form, Icon, Header, Modal} from "semantic-ui-react"; import { Button, Checkbox, Form, Icon, Header, Modal } from "semantic-ui-react";
const DeleteModal = (props) => ( const DeleteModal = (props) => (
<Modal trigger={<Button color='red'>Remove</Button>} closeIcon> <Modal trigger={<Button color="red">Remove</Button>} closeIcon>
<Header icon='archive' content='Are you sure ?' /> <Header icon="archive" content="Are you sure ?" />
<Modal.Actions> <Modal.Actions>
<Button color='red'> <Button color="red">
<Icon name='remove' /> No <Icon name="remove" /> No
</Button> </Button>
<Button onClick={() => props.removeDevice()} color='green'> <Button onClick={() => props.removeDevice()} color="green">
<Icon name='checkmark' /> Yes <Icon name="checkmark" /> Yes
</Button> </Button>
</Modal.Actions> </Modal.Actions>
</Modal> </Modal>
) );
const SettingsForm = (props) => { const SettingsForm = (props) => {
const handleInputChange = (e) => {
const handleInputChange = e => { const { name, value } = e.target;
const {name, value} = e.target; setValues({ ...values, [name]: value });
setValues({...values, [name]: value})
}; };
const handleCheckboxChange = (e,d) => { const handleCheckboxChange = (e, d) => {
const {name, checked} = d; const { name, checked } = d;
setValues({...values, [name]: checked}) setValues({ ...values, [name]: checked });
}; };
const [values, setValues] = useState({name: ''}); const [values, setValues] = useState({ name: "" });
return ( return (
<Form> <Form>
<Form.Field> <Form.Field>
<label>New Name: </label> <label>New Name: </label>
<input autoComplete="off" name="name" onChange={handleInputChange} value={values.name} placeholder='Device name'/> <input
autoComplete="off"
name="name"
onChange={handleInputChange}
value={values.name}
placeholder="Device name"
/>
</Form.Field> </Form.Field>
{props.type === "smart-plug" ? ( {props.type === "smart-plug" ? (
<Form.Field> <Form.Field>
<Checkbox slider name={"reset"} onClick={handleCheckboxChange} label='Reset Energy Consumption'/> <Checkbox
slider
name={"reset"}
onClick={handleCheckboxChange}
label="Reset Energy Consumption"
/>
</Form.Field> </Form.Field>
) : ""} ) : (
""
)}
<Form.Field> <Form.Field>
<DeleteModal removeDevice={() => props.removeDevice(values)} /> <DeleteModal removeDevice={() => props.removeDevice(values)} />
</Form.Field> </Form.Field>
<Button onClick={() => props.saveFunction(values)} color="blue" type='submit'>Save</Button> <Button
onClick={() => props.saveFunction(values)}
color="blue"
type="submit"
>
Save
</Button>
</Form> </Form>
) );
} };
export default class SettingsModal extends Component { export default class SettingsModal extends Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
@ -59,7 +76,7 @@ export default class SettingsModal extends Component {
} }
handleClose = () => { handleClose = () => {
this.setState({open: false}); this.setState({ open: false });
}; };
saveSettings = (device) => { saveSettings = (device) => {
@ -72,19 +89,23 @@ export default class SettingsModal extends Component {
this.props.openModal(); this.props.openModal();
}; };
render() { render() {
const SettingsModal = () => ( const SettingsModal = () => (
<Modal open={true} onOpen={this.props.openModal} onClose={this.props.openModal}> <Modal
open={true}
onOpen={this.props.openModal}
onClose={this.props.openModal}
>
<Modal.Header>Settings of {this.props.device.name}</Modal.Header> <Modal.Header>Settings of {this.props.device.name}</Modal.Header>
<Modal.Content> <Modal.Content>
<SettingsForm type={this.props.device.type} removeDevice={this.props.removeDevice} saveFunction={this.saveSettings}/> <SettingsForm
type={this.props.device.type}
removeDevice={this.props.removeDevice}
saveFunction={this.saveSettings}
/>
</Modal.Content> </Modal.Content>
</Modal> </Modal>
); );
return ( return <SettingsModal />;
<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 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. The user can reset this value.
**/ **/
import React, {Component} from 'react'; import React, { Component } from "react";
import {StyledDiv} from "./styleComponents"; import { StyledDiv } from "./styleComponents";
import Settings from "./DeviceSettings"; import Settings from "./DeviceSettings";
import {Image} from "semantic-ui-react"; import { Image } from "semantic-ui-react";
import {energyConsumedStyle, imageStyle, nameStyle} from "./SmartPlugStyle"; import { energyConsumedStyle, imageStyle, nameStyle } from "./SmartPlugStyle";
import { call } from "../../../client_server";
export default class SmartPlug extends Component { export default class SmartPlug extends Component {
constructor(props){ constructor(props) {
super(props); super(props);
this.state = { this.state = {
turnedOn: false, turnedOn: false,
energyConsumed : 0 // kWh energyConsumed: 0, // kWh
}; };
this.iconOn = "/img/smart-plug.svg"; this.iconOn = "/img/smart-plug.svg";
this.iconOff = "/img/smart-plug-off.svg" this.iconOff = "/img/smart-plug-off.svg";
} }
onClickDevice = () => { 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 = () => { getIcon = () => {
if(this.state.turnedOn){ if (this.state.turnedOn) {
return this.iconOn; return this.iconOn;
} }
return this.iconOff; return this.iconOff;
}; };
componentDidMount() { componentDidMount() {
this.setState({
turnedOn: this.props.device.on,
energyConsumed: this.props.device.totalConsumption,
});
} }
render(){ render() {
return ( return (
<StyledDiv onClick={this.props.edit.mode ? () => {} : this.onClickDevice}> <StyledDiv onClick={this.props.edit.mode ? () => {} : this.onClickDevice}>
<Settings <Settings
deviceId={this.props.device.id} deviceId={this.props.device.id}
edit={this.props.edit} edit={this.props.edit}
onChangeData={(id, newSettings) => this.props.onChangeData(id, newSettings)}/> onChangeData={(id, newSettings) =>
<Image src={this.getIcon()} style={imageStyle}/> this.props.onChangeData(id, newSettings)
}
/>
<Image src={this.getIcon()} style={imageStyle} />
<h4 style={energyConsumedStyle}>{this.state.energyConsumed} KWh</h4> <h4 style={energyConsumedStyle}>{this.state.energyConsumed} KWh</h4>
<h5 style={nameStyle}>{this.props.device.name}</h5> <h5 style={nameStyle}>{this.props.device.name}</h5>
</StyledDiv> </StyledDiv>
) );
} }
} }

View file

@ -1,11 +1,10 @@
export const energyConsumedStyle = { export const energyConsumedStyle = {
color : "black", color: "black",
fontSize : "1.3rem", fontSize: "1.3rem",
position: "absolute", position: "absolute",
top: "30%", top: "30%",
left: "50%", left: "50%",
transform: "translateX(-50%)" transform: "translateX(-50%)",
}; };
export const imageStyle = { export const imageStyle = {
@ -15,13 +14,13 @@ export const imageStyle = {
top: "10%", top: "10%",
left: "50%", left: "50%",
transform: "translateX(-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 = { export const nameStyle = {
color : "black", color: "black",
position: "absolute", position: "absolute",
top: "50%", top: "50%",
left: "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. * The user can change the state of a switch through the SmartHut interface.
*/ */
import React, {Component} from 'react'; import React, { Component } from "react";
import {StyledDiv} from "./styleComponents"; import { StyledDiv } from "./styleComponents";
import Settings from "./DeviceSettings"; import Settings from "./DeviceSettings";
import {Image} from "semantic-ui-react"; import { Image } from "semantic-ui-react";
import {imageStyle, nameStyle} from "./SwitchStyle"; import { imageStyle, nameStyle } from "./SwitchStyle";
import { call } from "../../../client_server";
export default class Switch extends Component { export default class Switch extends Component {
constructor(props){ constructor(props) {
super(props); super(props);
this.state = { this.state = {
turnedOn: false, turnedOn: false,
pointingLights : [] pointingLights: [],
}; };
this.iconOn = "/img/switchOn.svg"; this.iconOn = "/img/switchOn.svg";
this.iconOff = "/img/switchOff.svg"; this.iconOff = "/img/switchOff.svg";
} }
onClickDevice = () => { 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 = () => { getIcon = () => {
if(this.state.turnedOn){ if (this.state.turnedOn) {
return this.iconOn; return this.iconOn;
} }
return this.iconOff; return this.iconOff;
}; };
componentDidMount() { componentDidMount() {
this.setState({
turnedOn: this.props.device.on,
});
} }
render(){ render() {
return ( return (
<StyledDiv onClick={this.props.edit.mode ? () => {} : this.onClickDevice}> <StyledDiv onClick={this.props.edit.mode ? () => {} : this.onClickDevice}>
<Settings <Settings
deviceId={this.props.device.id} deviceId={this.props.device.id}
edit={this.props.edit} edit={this.props.edit}
onChangeData={(id, newSettings) => this.props.onChangeData(id, newSettings)}/> onChangeData={(id, newSettings) =>
<Image src={this.getIcon()} style={imageStyle}/> this.props.onChangeData(id, newSettings)
}
/>
<Image src={this.getIcon()} style={imageStyle} />
<h5 style={nameStyle}>{this.props.device.name}</h5> <h5 style={nameStyle}>{this.props.device.name}</h5>
</StyledDiv> </StyledDiv>
) );
} }
} }

View file

@ -5,13 +5,13 @@ export const imageStyle = {
top: "15%", top: "15%",
left: "50%", left: "50%",
transform: "translateX(-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 = { export const nameStyle = {
color : "black", color: "black",
position: "absolute", position: "absolute",
top: "45%", top: "45%",
left: "50%", left: "50%",
transform: "translateX(-50%)" transform: "translateX(-50%)",
}; };

View file

@ -1,18 +1,24 @@
export const LightDevice = { export const LightDevice = {
img : "/img/lightOff.svg", img: "/img/lightOff.svg",
imgClick : "/img/lightOn.svg" imgClick: "/img/lightOn.svg",
}; };
export const SmartPlugDevice = { export const SmartPlugDevice = {
img : "/img/smart-plug.svg", img: "/img/smart-plug.svg",
imgClick : "/img/smart-plug-off.svg" imgClick: "/img/smart-plug-off.svg",
}; };
export const TemperatureSensor = { export const TemperatureSensor = {
type : "temperature_sensor", type: "temperature_sensor",
img : "", img: "",
imgClick : "", imgClick: "",
units: "ºC", 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 const DEVICE_NAME_MAX_LENGTH = 15;
export function checkMaxLength(name){ export function checkMaxLength(name) {
return !(name.length > DEVICE_NAME_MAX_LENGTH); return !(name.length > DEVICE_NAME_MAX_LENGTH);
} }

View file

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

View file

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

View file

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

View file

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

View file

@ -2,4 +2,4 @@
// allows you to do things like: // allows you to do things like:
// expect(element).toHaveTextContent(/react/i) // expect(element).toHaveTextContent(/react/i)
// learn more: https://github.com/testing-library/jest-dom // 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 React, { Component } from "react";
import HomeNavbar from "./../components/HomeNavbar"; import HomeNavbar from "./../components/HomeNavbar";
import { import { Image, Divider, Message, Grid } from "semantic-ui-react";
Image,
Divider,
Message,
Grid
} from "semantic-ui-react";
class Paragraph extends Component { class Paragraph extends Component {
state = { visible: true } state = { visible: true };
handleDismiss = () => { handleDismiss = () => {
this.setState({ visible: false }) this.setState({ visible: false });
setTimeout(() => { setTimeout(() => {
this.setState({ visible: true }) this.setState({ visible: true });
}, 2000) }, 2000);
} };
render() { render() {
if (this.state.visible) { if (this.state.visible) {
return ( return (
<Message <Message
onDismiss={this.handleDismiss} onDismiss={this.handleDismiss}
header='Link has been sent!' header="Link has been sent!"
content='An e-mail has been sent your address, please follow the content="An e-mail has been sent your address, please follow the
instruction to create a new password' instruction to create a new password"
/> />
) );
} }
return ( return (
@ -37,64 +32,48 @@ class Paragraph extends Component {
<br /> <br />
<br /> <br />
</p> </p>
) );
}
} }
}
const MessageReg = () => (
const MessageReg = () => (
<Grid> <Grid>
<HomeNavbar /> <HomeNavbar />
<Divider /> <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 height={3}>
</Grid.Row> <Grid.Column width={6}></Grid.Column>
<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={10}> <Grid.Column width={10}>
<Image src='title5.png' /> <Image src="title5.png" />
</Grid.Column>
<Grid.Column width={3}>
</Grid.Column> </Grid.Column>
<Grid.Column width={3}></Grid.Column>
</Grid.Row> </Grid.Row>
<Grid.Row height={3}> <Grid.Row height={3}></Grid.Row>
</Grid.Row> <Grid.Row height={3}></Grid.Row>
<Grid.Row height={3}> <Grid.Column width={3}></Grid.Column>
</Grid.Row>
<Grid.Column width={3}>
</Grid.Column>
<Grid.Column width={4}> <Grid.Column width={4}>
<Image src='./img/logo.png' /> <Image src="./img/logo.png" />
</Grid.Column> </Grid.Column>
<Grid.Column width={6}> <Grid.Column width={6}>
<Paragraph /> <Paragraph />
</Grid.Column> </Grid.Column>
<Grid.Column width={4}> <Grid.Column width={4}></Grid.Column>
</Grid.Column> <Grid.Row height={3}></Grid.Row>
<Grid.Row height={3}></Grid.Row>
<Grid.Row height={3}> <Grid.Row height={3}>
</Grid.Row> <Grid.Column width={3}></Grid.Column>
<Grid.Row height={3}>
</Grid.Row>
<Grid.Row height={3}>
<Grid.Column width={3}>
</Grid.Column>
<Grid.Column width={10}> <Grid.Column width={10}>
<Divider /> <Divider />
</Grid.Column> </Grid.Column>
<Grid.Column width={3}> <Grid.Column width={3}></Grid.Column>
</Grid.Column>
</Grid.Row> </Grid.Row>
</Grid> </Grid>
) );
export default class ConfirmForgotPasswrod extends React.Component { export default class ConfirmForgotPasswrod extends React.Component {
render () { render() {
return ( return <MessageReg />;
<MessageReg />
)
} }
} }

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -3,9 +3,7 @@ import React from "react";
import HeaderController from "./../components/HeaderController"; import HeaderController from "./../components/HeaderController";
export default class TestHeaderController extends React.Component { export default class TestHeaderController extends React.Component {
render () { render() {
return ( return <HeaderController />;
<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" resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc"
integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw= 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: pretty-bytes@^5.1.0:
version "5.3.0" version "5.3.0"
resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.3.0.tgz#f2849e27db79fb4d6cfe24764fc4134f165989f2" 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" strip-ansi "6.0.0"
text-table "0.2.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: react-dom@^16.12.0:
version "16.12.0" version "16.12.0"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.12.0.tgz#0da4b714b8d13c2038c9396b54a92baea633fe11" 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" resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= 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" version "0.7.21"
resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.21.tgz#853cf9ce93f642f67174273cc34565ae6f308777" resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.21.tgz#853cf9ce93f642f67174273cc34565ae6f308777"
integrity sha512-+O8/qh/Qj8CgC6eYBVBykMrNtp5Gebn4dlGD/kKXVkJNDwyrAwSIqwz8CDf+tsAIWVycKcku6gIXJ0qwx/ZXaQ== integrity sha512-+O8/qh/Qj8CgC6eYBVBykMrNtp5Gebn4dlGD/kKXVkJNDwyrAwSIqwz8CDf+tsAIWVycKcku6gIXJ0qwx/ZXaQ==