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

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

View File

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

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

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

14
hooks/setup.sh Executable file
View File

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

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

View File

@ -1,21 +1,29 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<link rel="stylesheet" href="style.css">
<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/semantic-ui@2.4.2/dist/semantic.min.css" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta name="description" content="Web site created using create-react-app" />
<meta name="viewport" content="minimum-scale=1, initial-scale=1, width=device-width" />
<!--
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<link rel="stylesheet" href="style.css" />
<link
rel="stylesheet"
href="//cdn.jsdelivr.net/npm/semantic-ui@2.4.2/dist/semantic.min.css"
/>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using create-react-app"
/>
<meta
name="viewport"
content="minimum-scale=1, initial-scale=1, width=device-width"
/>
<!--
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/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<!--
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
@ -24,13 +32,13 @@
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React App</title>
</head>
<title>React App</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!--
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
@ -40,6 +48,5 @@
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</body>
</html>

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

View File

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

View File

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

View File

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

View File

@ -1,90 +1,244 @@
import axios from 'axios';
// vim: set ts=2 sw=2 et tw=80:
let config = 'http://localhost:8080/';
import axios from "axios";
let config = "http://localhost:8080/";
var tkn = localStorage.getItem("token");
/** the ServiceSocket instance valid for the current session */
var socket;
// requests data devices
/*
{
params : data,
device: 'tipoDiDevice',
id: se serve
params : data,
device: 'tipoDiDevice',
id: se serve
}
device routes:
- buttonDimmer
- dimmableLight
- knobDimmer
- motionSensor
- regularLight
- sensor
- smartPlug
- switch
device routes:
- buttonDimmer
- dimmableLight
- knobDimmer
- motionSensor
- regularLight
- sensor
- smartPlug
- switch
*/
export var call = {
setToken: function(token) {
tkn = token;
},
login: function(data, headers) {
return axios.post(config +'auth/login', data)
},
register: function(data, headers) {
return axios.post(config + 'register', data)
},
initResetPassword: function(data, headers) {
return axios.post(config + 'register/init-reset-password', data)
},
resetPassword: function(data, headers) {
return axios.put(config + 'register/reset-password', data)
},
getAllRooms: function(token) {
if (!token){
token = tkn;
/** 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");
}
return axios.get(config + 'room', { headers: { Authorization : "Bearer " + token } })
},
getAllDevices: function(token) {
if (!token){
token = tkn;
} else {
if (data.id && this.callbacks[data.id]) {
this.callbacks[data.id].forEach((f) => f(data));
}
return axios.get(config + 'device', { headers: { Authorization : "Bearer " + token } });
},
getAllDevicesByRoom: function(id, token) {
if (!token){
token = tkn;
}
return axios.get(config + 'room/' + id + '/devices' , { headers: { Authorization : "Bearer " + token } });
},
createRoom: function(data, headers) {
return axios.post(config + 'room', data, { headers: { Authorization : "Bearer " + tkn } })
},
updateRoom: function(data, headers) {
return axios.put(config + 'room?name='+ data.name, data, { headers: { Authorization : "Bearer " + tkn } })
},
deleteRoom: function(data, headers) {
return axios.delete(config + 'room/'+data.id, { headers: { Authorization : "Bearer " + tkn } });
},
devicePost: function(data, headers) {
return axios.post(config + data.device, data.params, { headers: { Authorization : "Bearer " + tkn } })
},
deviceUpdate: function(data, typeDevice) {
let url = 'device';
if (typeDevice) {
url = typeDevice;
}
return axios.put(config + url, data, { headers: { Authorization : "Bearer " + tkn } })
},
deviceDelete: function(data, headers) {
return axios.delete(config + data.device + '/' + data.id, {}, { headers: { Authorization : "Bearer " + tkn } })
},
deviceGetById: function(data, headers) {
return axios.get(config + data.device + '/' + data.id)
},
deviceGetAll: function(data, headers) {
return axios.get(config + data.device)
}
};
this.connection.onerror = (evt) => {
if (retries >= 5) {
console.error("too many socket connection retries");
return;
}
retries++;
socket = new ServiceSocket(this.token, this.callbacks);
};
}
/**
* Registers a new callback function to be called when updates on the device
* with the id given are recieved
* @param {number} id - the id of the device to check updates for
* @param {function} stateCallback - a function that recieves a device as the
* first parameter, that will be called whenever a update is recieved
*/
subscribe(id, stateCallback) {
if (this.callbacks[id] === undefined) {
this.callbacks[id] = [];
}
this.callbacks[id].push(stateCallback);
}
/**
* Unregisters a function previously registered with `subscribe(...)`.
* @param {number} id - the id of the device to stop checking updates for
* @param {function} stateCallback - the callback to unregister
*/
unsubscribe(id, stateCallback) {
this.callbacks[id].splice(this.callbacks[id].indexOf(stateCallback), 1);
}
/**
* Closes the underlying websocket connection
*/
close() {
this.connection.close();
}
}
if (tkn) {
socket = new ServiceSocket(tkn);
}
export var call = {
setToken: function (token) {
tkn = token;
if (tkn) {
if (socket) {
socket.close();
}
socket = new ServiceSocket(tkn);
}
},
/**
* 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);
},
/**
* 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);
},
login: function (data, headers) {
return axios.post(config + "auth/login", data);
},
register: function (data, headers) {
return axios.post(config + "register", data);
},
initResetPassword: function (data, headers) {
return axios.post(config + "register/init-reset-password", data);
},
resetPassword: function (data, headers) {
return axios.put(config + "register/reset-password", data);
},
getAllRooms: function (token) {
if (!token) {
token = tkn;
}
return axios.get(config + "room", {
headers: { Authorization: "Bearer " + token },
});
},
getAllDevices: function (token) {
if (!token) {
token = tkn;
}
return axios.get(config + "device", {
headers: { Authorization: "Bearer " + token },
});
},
getAllDevicesByRoom: function (id, token) {
if (!token) {
token = tkn;
}
return axios.get(config + "room/" + id + "/devices", {
headers: { Authorization: "Bearer " + token },
});
},
createRoom: function (data, headers) {
return axios.post(config + "room", data, {
headers: { Authorization: "Bearer " + tkn },
});
},
updateRoom: function (data, headers) {
return axios.put(config + "room/" + data.id, data, {
headers: { Authorization: "Bearer " + tkn },
});
},
deleteRoom: function (data, headers) {
return axios.delete(config + "room/" + data.id, {
headers: { Authorization: "Bearer " + tkn },
});
},
devicePost: function (data, headers) {
return axios
.post(config + data.device, data.params, {
headers: { Authorization: "Bearer " + tkn },
})
.then((res) => {
if (res.status === 200 && data.device === "switch") {
data.params.lights.forEach((e) => {
let urlUp =
config +
data.device +
"/" +
res.data.id +
"/lights?switchableId=" +
e;
axios.post(
urlUp,
{},
{ headers: { Authorization: "Bearer " + tkn } }
);
});
}
return res;
});
},
deviceUpdate: function (data, typeDevice) {
let url = "device";
if (typeDevice) {
url = typeDevice;
}
return axios.put(config + url, data, {
headers: { Authorization: "Bearer " + tkn },
});
},
deviceDelete: function (data, headers) {
return axios.delete(config + data.device + "/" + data.id, {
headers: { Authorization: "Bearer " + tkn },
});
},
deviceGetById: function (data, headers) {
return axios.get(config + data.device + "/" + data.id);
},
deviceGetAll: function (data, headers) {
return axios.get(config + data.device);
},
};

View File

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

View File

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

View File

@ -1,73 +1,78 @@
import React from 'react';
import PropTypes from 'prop-types';
import { makeStyles } from '@material-ui/core/styles';
import Toolbar from '@material-ui/core/Toolbar';
import Button from '@material-ui/core/Button';
import IconButton from '@material-ui/core/IconButton';
import SearchIcon from '@material-ui/icons/Search';
import Typography from '@material-ui/core/Typography';
import Link from '@material-ui/core/Link';
import React from "react";
import PropTypes from "prop-types";
import { makeStyles } from "@material-ui/core/styles";
import Toolbar from "@material-ui/core/Toolbar";
import Button from "@material-ui/core/Button";
import IconButton from "@material-ui/core/IconButton";
import SearchIcon from "@material-ui/icons/Search";
import Typography from "@material-ui/core/Typography";
import Link from "@material-ui/core/Link";
const useStyles = makeStyles(theme => ({
toolbar: {
borderBottom: `1px solid ${theme.palette.divider}`,
},
toolbarTitle: {
flex: 1,
},
toolbarSecondary: {
justifyContent: 'space-between',
overflowX: 'auto',
},
toolbarLink: {
padding: theme.spacing(1),
flexShrink: 0,
},
const useStyles = makeStyles((theme) => ({
toolbar: {
borderBottom: `1px solid ${theme.palette.divider}`,
},
toolbarTitle: {
flex: 1,
},
toolbarSecondary: {
justifyContent: "space-between",
overflowX: "auto",
},
toolbarLink: {
padding: theme.spacing(1),
flexShrink: 0,
},
}));
export default function Header(props) {
const classes = useStyles();
const { sections, title } = props;
const classes = useStyles();
const { sections, title } = props;
return (
<React.Fragment>
<Toolbar className={classes.toolbar}>
<Typography
component="h2"
variant="h5"
color="inherit"
align="center"
noWrap
className={classes.toolbarTitle}
>
{title}
</Typography>
<Toolbar component="nav" variant="dense" className={classes.toolbarSecondary}>
{sections.map(section => (
<Link
color="inherit"
noWrap
key={section.title}
variant="body2"
href={section.url}
className={classes.toolbarLink}
>
{section.title}
</Link>
))}
</Toolbar>
<Button size="small" variant="outlined" style={{margin: "0 1rem"}}>Login</Button>
return (
<React.Fragment>
<Toolbar className={classes.toolbar}>
<Typography
component="h2"
variant="h5"
color="inherit"
align="center"
noWrap
className={classes.toolbarTitle}
>
{title}
</Typography>
<Toolbar
component="nav"
variant="dense"
className={classes.toolbarSecondary}
>
{sections.map((section) => (
<Link
color="inherit"
noWrap
key={section.title}
variant="body2"
href={section.url}
className={classes.toolbarLink}
>
{section.title}
</Link>
))}
</Toolbar>
<Button size="small" variant="outlined" style={{ margin: "0 1rem" }}>
Login
</Button>
<Button variant="outlined" size="small">
Sign up
</Button>
</Toolbar>
</React.Fragment>
);
<Button variant="outlined" size="small">
Sign up
</Button>
</Toolbar>
</React.Fragment>
);
}
Header.propTypes = {
sections: PropTypes.array,
title: PropTypes.string,
};
sections: PropTypes.array,
title: PropTypes.string,
};

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,23 +1,29 @@
export const style = {width: "10rem", height: "10rem", position: "absolute", top: "0", left: "0"};
export const style = {
width: "10rem",
height: "10rem",
position: "absolute",
top: "0",
left: "0",
};
export const valueStyle = {
fill: "#3e99ff",
fontSize: "2.5rem",
fontFamily: "Lato",
textShadow: "1px 1px 0.5px rgba(0, 0, 0, .2)",
fill: "#3e99ff",
fontSize: "2.5rem",
fontFamily: "Lato",
textShadow: "1px 1px 0.5px rgba(0, 0, 0, .2)",
};
export const intensityLightStyle = {
fill: "#3e99ff",
fontSize: "1.2rem",
fontFamily: "Lato",
textShadow: "1px 1px 0.5px rgba(0, 0, 0, .2)",
fill: "#3e99ff",
fontSize: "1.2rem",
fontFamily: "Lato",
textShadow: "1px 1px 0.5px rgba(0, 0, 0, .2)",
};
export const nameStyle = {
fontSize : "1rem",
position: "absolute",
top: "50%",
left: "50%",
transform: "translateX(-50%)",
color : "black"
fontSize: "1rem",
position: "absolute",
top: "50%",
left: "50%",
transform: "translateX(-50%)",
color: "black",
};

View File

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

View File

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

View File

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

View File

@ -1,56 +1,73 @@
import React, {Component, useState} from 'react';
import {Button, Checkbox, Form, Icon, Header, Modal} from "semantic-ui-react";
import React, { Component, useState } from "react";
import { Button, Checkbox, Form, Icon, Header, Modal } from "semantic-ui-react";
const DeleteModal = (props) => (
<Modal trigger={<Button color='red'>Remove</Button>} closeIcon>
<Header icon='archive' content='Are you sure ?' />
<Modal trigger={<Button color="red">Remove</Button>} closeIcon>
<Header icon="archive" content="Are you sure ?" />
<Modal.Actions>
<Button color='red'>
<Icon name='remove' /> No
<Button color="red">
<Icon name="remove" /> No
</Button>
<Button onClick={() => props.removeDevice()} color='green'>
<Icon name='checkmark' /> Yes
<Button onClick={() => props.removeDevice()} color="green">
<Icon name="checkmark" /> Yes
</Button>
</Modal.Actions>
</Modal>
)
);
const SettingsForm = (props) => {
const handleInputChange = e => {
const {name, value} = e.target;
setValues({...values, [name]: value})
const handleInputChange = (e) => {
const { name, value } = e.target;
setValues({ ...values, [name]: value });
};
const handleCheckboxChange = (e,d) => {
const {name, checked} = d;
setValues({...values, [name]: checked})
const handleCheckboxChange = (e, d) => {
const { name, checked } = d;
setValues({ ...values, [name]: checked });
};
const [values, setValues] = useState({name: ''});
const [values, setValues] = useState({ name: "" });
return (
<Form>
<Form.Field>
<label>New Name: </label>
<input autoComplete="off" name="name" onChange={handleInputChange} value={values.name} placeholder='Device name'/>
<input
autoComplete="off"
name="name"
onChange={handleInputChange}
value={values.name}
placeholder="Device name"
/>
</Form.Field>
{props.type === "smart-plug" ? (
<Form.Field>
<Checkbox slider name={"reset"} onClick={handleCheckboxChange} label='Reset Energy Consumption'/>
<Checkbox
slider
name={"reset"}
onClick={handleCheckboxChange}
label="Reset Energy Consumption"
/>
</Form.Field>
) : ""}
) : (
""
)}
<Form.Field>
<DeleteModal removeDevice={() => props.removeDevice(values)} />
</Form.Field>
<Button onClick={() => props.saveFunction(values)} color="blue" type='submit'>Save</Button>
<Button
onClick={() => props.saveFunction(values)}
color="blue"
type="submit"
>
Save
</Button>
</Form>
)
}
);
};
export default class SettingsModal extends Component {
constructor(props) {
super(props);
this.state = {
@ -59,7 +76,7 @@ export default class SettingsModal extends Component {
}
handleClose = () => {
this.setState({open: false});
this.setState({ open: false });
};
saveSettings = (device) => {
@ -72,19 +89,23 @@ export default class SettingsModal extends Component {
this.props.openModal();
};
render() {
const SettingsModal = () => (
<Modal open={true} onOpen={this.props.openModal} onClose={this.props.openModal}>
<Modal
open={true}
onOpen={this.props.openModal}
onClose={this.props.openModal}
>
<Modal.Header>Settings of {this.props.device.name}</Modal.Header>
<Modal.Content>
<SettingsForm type={this.props.device.type} removeDevice={this.props.removeDevice} saveFunction={this.saveSettings}/>
<SettingsForm
type={this.props.device.type}
removeDevice={this.props.removeDevice}
saveFunction={this.saveSettings}
/>
</Modal.Content>
</Modal>
);
return (
<SettingsModal/>
)
return <SettingsModal />;
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,22 +1,17 @@
import React, { Component } from "react";
import HomeNavbar from "./../components/HomeNavbar";
import {
Container,
Header,
Divider,
Grid
} from "semantic-ui-react";
import { Container, Header, Divider, Grid } from "semantic-ui-react";
const ContainerExampleAlignment = () => (
<div>
<HomeNavbar />
<Container textAlign='justified'>
<Header as="h1"> Instructions Page </Header>
<Grid>
<Grid.Row height={15}></Grid.Row>
</Grid>
<Container textAlign="justified">
<Header as="h1"> Instructions Page </Header>
<Grid>
<Grid.Row height={15}></Grid.Row>
</Grid>
</Container>
<Container textAlign='justified'>
<Container textAlign="justified">
<b>First Step</b>
<Divider />
<p>
@ -36,74 +31,71 @@ const ContainerExampleAlignment = () => (
</p>
<Divider />
</Container>
<Container textAlign='justified'>
<b>Second Step</b>
<Divider />
<p>
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo
ligula eget dolor. Aenean massa strong. Cum sociis natoque penatibus et
magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis,
ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa
quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget,
arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo.
Nullam dictum felis eu pede link mollis pretium. Integer tincidunt. Cras
dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend
tellus. Aenean leo ligula, porttitor eu, consequat vitae, eleifend ac,
enim. Aliquam lorem ante, dapibus in, viverra quis, feugiat a, tellus.
Phasellus viverra nulla ut metus varius laoreet. Quisque rutrum. Aenean
imperdiet. Etiam ultricies nisi vel augue. Curabitur ullamcorper
ultricies nisi.
</p>
<Divider />
</Container>
<Container textAlign='justified'>
<b>Third Step</b>
<Divider />
<p>
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo
ligula eget dolor. Aenean massa strong. Cum sociis natoque penatibus et
magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis,
ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa
quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget,
arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo.
Nullam dictum felis eu pede link mollis pretium. Integer tincidunt. Cras
dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend
tellus. Aenean leo ligula, porttitor eu, consequat vitae, eleifend ac,
enim. Aliquam lorem ante, dapibus in, viverra quis, feugiat a, tellus.
Phasellus viverra nulla ut metus varius laoreet. Quisque rutrum. Aenean
imperdiet. Etiam ultricies nisi vel augue. Curabitur ullamcorper
ultricies nisi.
</p>
<Divider />
</Container>
<Container textAlign='justified'>
<b>Last Step</b>
<Divider />
<p>
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo
ligula eget dolor. Aenean massa strong. Cum sociis natoque penatibus et
magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis,
ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa
quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget,
arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo.
Nullam dictum felis eu pede link mollis pretium. Integer tincidunt. Cras
dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend
tellus. Aenean leo ligula, porttitor eu, consequat vitae, eleifend ac,
enim. Aliquam lorem ante, dapibus in, viverra quis, feugiat a, tellus.
Phasellus viverra nulla ut metus varius laoreet. Quisque rutrum. Aenean
imperdiet. Etiam ultricies nisi vel augue. Curabitur ullamcorper
ultricies nisi.
</p>
<Divider />
</Container>
<Container textAlign="justified">
<b>Second Step</b>
<Divider />
<p>
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo
ligula eget dolor. Aenean massa strong. Cum sociis natoque penatibus et
magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis,
ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa
quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget,
arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo.
Nullam dictum felis eu pede link mollis pretium. Integer tincidunt. Cras
dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend
tellus. Aenean leo ligula, porttitor eu, consequat vitae, eleifend ac,
enim. Aliquam lorem ante, dapibus in, viverra quis, feugiat a, tellus.
Phasellus viverra nulla ut metus varius laoreet. Quisque rutrum. Aenean
imperdiet. Etiam ultricies nisi vel augue. Curabitur ullamcorper
ultricies nisi.
</p>
<Divider />
</Container>
<Container textAlign="justified">
<b>Third Step</b>
<Divider />
<p>
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo
ligula eget dolor. Aenean massa strong. Cum sociis natoque penatibus et
magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis,
ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa
quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget,
arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo.
Nullam dictum felis eu pede link mollis pretium. Integer tincidunt. Cras
dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend
tellus. Aenean leo ligula, porttitor eu, consequat vitae, eleifend ac,
enim. Aliquam lorem ante, dapibus in, viverra quis, feugiat a, tellus.
Phasellus viverra nulla ut metus varius laoreet. Quisque rutrum. Aenean
imperdiet. Etiam ultricies nisi vel augue. Curabitur ullamcorper
ultricies nisi.
</p>
<Divider />
</Container>
<Container textAlign="justified">
<b>Last Step</b>
<Divider />
<p>
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo
ligula eget dolor. Aenean massa strong. Cum sociis natoque penatibus et
magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis,
ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa
quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget,
arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo.
Nullam dictum felis eu pede link mollis pretium. Integer tincidunt. Cras
dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend
tellus. Aenean leo ligula, porttitor eu, consequat vitae, eleifend ac,
enim. Aliquam lorem ante, dapibus in, viverra quis, feugiat a, tellus.
Phasellus viverra nulla ut metus varius laoreet. Quisque rutrum. Aenean
imperdiet. Etiam ultricies nisi vel augue. Curabitur ullamcorper
ultricies nisi.
</p>
<Divider />
</Container>
</div>
)
);
export default class Insturction extends Component{
render() {
return(
<ContainerExampleAlignment />
)
}
}
export default class Insturction extends Component {
render() {
return <ContainerExampleAlignment />;
}
}

View File

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

View File

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

View File

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

View File

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

View File

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