From 43615ba3b12426a19741951cae497edee128ab75 Mon Sep 17 00:00:00 2001 From: tommi27 Date: Fri, 24 Apr 2020 16:54:50 +0200 Subject: [PATCH 01/13] Host should work, cannot solve an error --- smart-hut/src/components/HostModal.js | 190 ++++++++++++++++ .../src/components/dashboard/HostsPanel.js | 45 ++++ smart-hut/src/remote.js | 20 ++ smart-hut/src/store.js | 23 ++ smart-hut/src/storeActions.js | 9 + smart-hut/src/views/Dashboard.js | 23 ++ smart-hut/src/views/HostsNavbar.js | 204 ++++++++++++++++++ 7 files changed, 514 insertions(+) create mode 100644 smart-hut/src/components/HostModal.js create mode 100644 smart-hut/src/components/dashboard/HostsPanel.js create mode 100644 smart-hut/src/views/HostsNavbar.js diff --git a/smart-hut/src/components/HostModal.js b/smart-hut/src/components/HostModal.js new file mode 100644 index 0000000..55f4e4b --- /dev/null +++ b/smart-hut/src/components/HostModal.js @@ -0,0 +1,190 @@ +import React, { Component } from "react"; +import { Button, Header, Modal, Icon, Responsive } from "semantic-ui-react"; +import { connect } from "react-redux"; +import { RemoteService } from "../remote"; +import { appActions } from "../storeActions"; +//import { update } from "immutability-helper"; + +class HostModal extends Component { + constructor(props) { + super(props); + this.state = this.initialState; + this.setInitialState(); + + this.addHostModal = this.addHostModal.bind(this); + this.modifyHostModal = this.modifyHostModal.bind(this); + this.deleteHost = this.deleteHost.bind(this); + } + + get initialState() { + return { + //INITIAL STATE HERE + }; + } + + setInitialState() { + this.setState(this.initialState); + } + + get type() { + return !this.props.id ? "new" : "modify"; + } + + addHostModal = (e) => { + /*let data = { + // DATA HERE + };*/ + // TODO CALL TO REMOTE SERVER TO ADD SCENE + /*this.props + .saveRoom(data, null) + .then(() => { + this.setInitialState(); + this.closeModal(); + }) + .catch((err) => console.error("error in creating room", err));*/ + }; + + modifyHostModal = (e) => { + /* let data = { + // DATA HERE + };*/ + // TODO CALL TO REMOTE SERVER TO MODIFY SCENE + /*this.props + .saveRoom(data, this.props.id) + .then(() => { + this.setInitialState(); + this.closeModal(); + }) + .catch((err) => console.error("error in updating room", err));*/ + }; + + deleteHost = (e) => { + // TODO CALL TO REMOTE SERVER TO DELETE SCENE + /* + this.props + .deleteRoom(this.props.id) + .then(() => this.closeModal()) + .catch((err) => console.error("error in deleting room", err));*/ + }; + + changeSomething = (event) => { + let nam = event.target.name; + let val = event.target.value; + this.setState({ [nam]: val }); + }; + + closeModal = (e) => { + this.setState({ openModal: false }); + }; + + openModal = (e) => { + this.setState({ openModal: true }); + }; + + render() { + return ( +
+ {!this.props.nicolaStop ? ( +
+ + {this.type === "new" ? ( + + ) : ( + + )} + + + {this.type === "new" ? ( + + ) : ( + + )} + +
+ ) : null} + + +
+ {this.type === "new" ? "Add new hosts" : "Modify hosts"} +
+ + { + //TODO FORM TO ADD OR MODIFY SCENE + } + + {this.type === "modify" ? ( + + ) : null} + + + + + + +
+
+ ); + } +} + +const setActiveHost = (activeHost) => { + return (dispatch) => + dispatch(appActions.setActiveHost(activeHost)); +}; + +const mapStateToProps = (state, ownProps) => ({ + hostss: ownProps.id ? state.hostss[ownProps.id] : null, +}); +const HostModalContainer = connect( + mapStateToProps, + { ...RemoteService, setActiveHost }, + null, + { forwardRef: true } +)(HostModal); +export default HostModalContainer; diff --git a/smart-hut/src/components/dashboard/HostsPanel.js b/smart-hut/src/components/dashboard/HostsPanel.js new file mode 100644 index 0000000..c019c10 --- /dev/null +++ b/smart-hut/src/components/dashboard/HostsPanel.js @@ -0,0 +1,45 @@ +import React, { Component } from "react"; +import { connect } from "react-redux"; +import { RemoteService } from "../../remote"; + +class HostsPanel extends Component { + constructor(props) { + super(props); + } + + render() { + return ( + + {!this.props.isActiveDefaultHost + ? this.props.hostDevices.map((e, i) => { + return ( + + + + ); + }) + : null} + {!this.props.isActiveDefaultHost ? ( + + + + ) : ( + + Welcome to the Host View, select a host to view their devices. + + )} + + ); + } +} + +const mapStateToProps = (state, _) => ({ + activeTab: state.active.activeTab, + activeHost: state.active.activeHost, + hostDevices: state.hostDevices, +}); +const HostsPanelContainer = connect( + mapStateToProps, + RemoteService +)(HostsPanel); +export default HostsPanelContainer; diff --git a/smart-hut/src/remote.js b/smart-hut/src/remote.js index 66d47bd..8b508bc 100644 --- a/smart-hut/src/remote.js +++ b/smart-hut/src/remote.js @@ -346,6 +346,26 @@ export const RemoteService = { }; }, + /** + * Fetches all devices in a particular room, or fetches all devices. + * This also updates the devices attribute on values in the map rooms. + * @param {Number|null} roomId the room to which fetch devices + * from, null to fetch from all rooms + * @returns {Promise} promise that resolves to void and rejects + * with user-fiendly errors as a RemoteError + */ + fetchAllHosts: () => { + return (dispatch) => { + return Endpoint.get(`/user`) + .then((res) => void dispatch(actions.getHosts(res.data))) + .catch((err) => { + // TODO CHANGE ERROR MESSAGE + console.error(`Fetch hosts error`, err); + throw new RemoteError(["Network error"]); + }); + }; + }, + /** * Creates/Updates a room with the given data * @param {String} data.name the room's name, diff --git a/smart-hut/src/store.js b/smart-hut/src/store.js index 350cc7b..d78bac8 100644 --- a/smart-hut/src/store.js +++ b/smart-hut/src/store.js @@ -469,6 +469,15 @@ function reducer(previousState, action) { }, }); break; + case "SET_ACTIVE_HOST": + newState = update(previousState, { + active: { + activeHost: { + $set: action.activeHost, + }, + }, + }); + break; case "REDUX_WEBSOCKET::MESSAGE": const devices = JSON.parse(action.payload.message); //console.log("socket", JSON.stringify(devices, null, 2)); @@ -479,6 +488,13 @@ function reducer(previousState, action) { devices, }); break; + case "GET_HOSTS": + change = {}; + for (const host of action.hosts) { + change.$add = host; + } + newState = update(previousState, change); + break; default: console.warn(`Action type ${action.type} unknown`, action); return previousState; @@ -497,6 +513,7 @@ const initState = { activeTab: "Devices", activeScene: -1, activeAutomation: -1, + activeHost: -1, }, login: { loggedIn: false, @@ -513,6 +530,12 @@ const initState = { devices: {}, /** @type {[integer]SceneState} */ sceneStates: {}, + /** @type {[integer]Guest} */ + guests: {}, + /** @type {[integer]Host} */ + hosts: {}, + /** @type {[integer]HostDevice} */ + hostDevices: {}, }; function createSmartHutStore() { diff --git a/smart-hut/src/storeActions.js b/smart-hut/src/storeActions.js index e8ee30a..769ce8b 100644 --- a/smart-hut/src/storeActions.js +++ b/smart-hut/src/storeActions.js @@ -91,6 +91,11 @@ const actions = { type: "DEVICE_DELETE", deviceId, }), + + getHosts: (hosts) => ({ + type: "GET_HOSTS", + hosts, + }) }; export const appActions = { @@ -111,6 +116,10 @@ export const appActions = { type: "SET_ACTIVE_AUTOMATION", activeAutomation, }), + setActiveHosts: (activeHost = -1) => ({ + type: "SET_ACTIVE_HOST", + activeHost, + }), }; export default actions; diff --git a/smart-hut/src/views/Dashboard.js b/smart-hut/src/views/Dashboard.js index bb92ea8..17772e6 100644 --- a/smart-hut/src/views/Dashboard.js +++ b/smart-hut/src/views/Dashboard.js @@ -2,8 +2,11 @@ import React, { Component } from "react"; import DevicePanel from "../components/dashboard/DevicePanel"; import ScenesPanel from "../components/dashboard/ScenesPanel"; import AutomationsPanel from "../components/dashboard/AutomationsPanel"; +import HostsPanel from "../components/dashboard/HostsPanel"; import Navbar from "./Navbar"; import ScenesNavbar from "./ScenesNavbar"; +import AutomationsNavbar from "./AutomationsNavbar"; +import HostsNavbar from "./HostsNavbar"; import MyHeader from "../components/HeaderController"; import { Grid, Responsive, Button, Menu } from "semantic-ui-react"; import { @@ -55,6 +58,8 @@ class Dashboard extends Component { return ; case "Automations": return ; + case "Hosts": + return ; default: return

ERROR

; } @@ -66,6 +71,10 @@ class Dashboard extends Component { return ; case "Scenes": return ; + case "Automations": + return ; + case "Hosts": + return ; default: return

ERROR

; } @@ -106,6 +115,12 @@ class Dashboard extends Component { active={this.activeTab === "Automations"} onClick={this.selectTab} /> + @@ -153,6 +168,14 @@ class Dashboard extends Component { color={this.activeTab === "Automations" ? "yellow" : "grey"} onClick={this.selectTab} /> + + + + + + + + + + + AUTOMATIONS + + + + {Object.values(this.props.hosts).map((e, i) => { + return ( + + + + {e.name} + + {this.state.editMode ? ( + + ) : null} + + + + + ); + })} + + + + + + + + + + + + + + + + + + + + + + + Hosts + + + + + {Object.values(this.props.hosts).map((e, i) => { + return ( + + + + {e.name} + + {this.state.editMode ? ( + + ) : null} + + + + + ); + })} + + + + + + + + + + {this.activeItemHost !== -1 ? ( + + + + ) : null} + + + + + ); + } +} + +const setActiveHost = (activeHost) => { + return (dispatch) => + dispatch(appActions.setActiveHost(activeHost)); +}; + +const mapStateToProps = (state, _) => ({ + hosts: state.hosts, + activeHost: state.active.activeHost, + hostModalRefs: Object.keys(state.hosts).reduce( + (acc, key) => ({ ...acc, [key]: React.createRef() }), + {} + ), +}); +const HostsNavbarContainer = connect(mapStateToProps, { + ...RemoteService, + setActiveHost, +})(HostsNavbar); +export default HostsNavbarContainer; From c5e1e1bd8d5a5498a684bcd075058f044c652a96 Mon Sep 17 00:00:00 2001 From: tommi27 Date: Sat, 25 Apr 2020 17:46:52 +0200 Subject: [PATCH 02/13] added actions without working code --- .../src/components/dashboard/HostsPanel.js | 5 +++- smart-hut/src/remote.js | 25 +++++++++++++++---- smart-hut/src/store.js | 19 ++++++++++++++ smart-hut/src/storeActions.js | 23 ++++++++++++++++- 4 files changed, 65 insertions(+), 7 deletions(-) diff --git a/smart-hut/src/components/dashboard/HostsPanel.js b/smart-hut/src/components/dashboard/HostsPanel.js index c019c10..5421fc9 100644 --- a/smart-hut/src/components/dashboard/HostsPanel.js +++ b/smart-hut/src/components/dashboard/HostsPanel.js @@ -1,6 +1,9 @@ import React, { Component } from "react"; import { connect } from "react-redux"; import { RemoteService } from "../../remote"; +import { Grid } from "semantic-ui-react"; +import Device from "./devices/Device"; +import NewSceneDevice from "./NewSceneDevice"; class HostsPanel extends Component { constructor(props) { @@ -11,7 +14,7 @@ class HostsPanel extends Component { return ( {!this.props.isActiveDefaultHost - ? this.props.hostDevices.map((e, i) => { + ? Object.values(this.props.hostDevices).map((e, i) => { return ( diff --git a/smart-hut/src/remote.js b/smart-hut/src/remote.js index 8b508bc..42081d8 100644 --- a/smart-hut/src/remote.js +++ b/smart-hut/src/remote.js @@ -347,10 +347,7 @@ export const RemoteService = { }, /** - * Fetches all devices in a particular room, or fetches all devices. - * This also updates the devices attribute on values in the map rooms. - * @param {Number|null} roomId the room to which fetch devices - * from, null to fetch from all rooms + * Fetches all hosts of a particular user. * @returns {Promise} promise that resolves to void and rejects * with user-fiendly errors as a RemoteError */ @@ -359,13 +356,31 @@ export const RemoteService = { return Endpoint.get(`/user`) .then((res) => void dispatch(actions.getHosts(res.data))) .catch((err) => { - // TODO CHANGE ERROR MESSAGE console.error(`Fetch hosts error`, err); throw new RemoteError(["Network error"]); }); }; }, +/** + * Adds the current user as a guest to another user + * identified through a host id. + * @param {Number} hostId the host to add. + * @param {String} username the username of the guest to add. + * @returns {Promise} promise that resolves to void and rejects + * with user-fiendly errors as a RemoteError + */ + addUserAsGuest: (hostId, username) => { + return (dispatch) => { + return Endpoint.post(`/user/guest`) + .then((res) => void dispatch(actions.guestSave(res.data))) + .catch((err) => { + console.error(`Guest save error`, err); + throw new RemoteError(["Network Error"]); + }); + }; + }, + /** * Creates/Updates a room with the given data * @param {String} data.name the room's name, diff --git a/smart-hut/src/store.js b/smart-hut/src/store.js index d78bac8..62b34be 100644 --- a/smart-hut/src/store.js +++ b/smart-hut/src/store.js @@ -495,6 +495,25 @@ function reducer(previousState, action) { } newState = update(previousState, change); break; + case "GET_HOST_DEVICES": + change = {}; + // TODO ACTUAL WORKING CODE + break; + case "GUEST_SAVE": + change = {}; + // TODO ACTUAL WORKING CODE + newState = update(previousState, change); + break; + case "GUEST_UPDATE": + change = {}; + // TODO ACTUAL WORKING CODE + newState = update(previousState, change); + break; + case "GUEST_DELETE": + change = {}; + // TODO ACTUAL WORKING CODE + newState = update(previousState, change); + break; default: console.warn(`Action type ${action.type} unknown`, action); return previousState; diff --git a/smart-hut/src/storeActions.js b/smart-hut/src/storeActions.js index 769ce8b..cf18ebb 100644 --- a/smart-hut/src/storeActions.js +++ b/smart-hut/src/storeActions.js @@ -95,7 +95,28 @@ const actions = { getHosts: (hosts) => ({ type: "GET_HOSTS", hosts, - }) + }), + + getHostDevices: (host) => ({ + type: "GET_HOST_DEVICES", + host, + }), + + guestSave: (guest) => ({ + type: "GUEST_SAVE", + guest, + }), + + guestUpdate: (guest) => ({ + type: "GUEST_UPDATE", + guest, + }), + + guestDelete: (guest) => ({ + type: "GUEST_DELETE", + guest, + }), + }; export const appActions = { From 091ab50c0eda9c18fa41ee77b463928784c786c5 Mon Sep 17 00:00:00 2001 From: "Claudio Maggioni (maggicl)" Date: Sat, 2 May 2020 16:40:29 +0200 Subject: [PATCH 03/13] WIP --- smart-hut/src/components/HostModal.js | 154 ++++-------------- .../src/components/dashboard/HostsPanel.js | 5 +- .../src/components/dashboard/ScenesPanel.js | 9 +- .../dashboard/devices/Thermostat.css | 2 +- smart-hut/src/remote.js | 24 +-- smart-hut/src/store.js | 51 ++---- smart-hut/src/storeActions.js | 23 ++- smart-hut/src/views/Dashboard.js | 5 +- smart-hut/src/views/HostsNavbar.js | 121 +++----------- smart-hut/src/views/Navbar.js | 4 +- smart-hut/src/views/ScenesNavbar.js | 4 +- 11 files changed, 109 insertions(+), 293 deletions(-) diff --git a/smart-hut/src/components/HostModal.js b/smart-hut/src/components/HostModal.js index 55f4e4b..8867b47 100644 --- a/smart-hut/src/components/HostModal.js +++ b/smart-hut/src/components/HostModal.js @@ -9,11 +9,8 @@ class HostModal extends Component { constructor(props) { super(props); this.state = this.initialState; - this.setInitialState(); - this.addHostModal = this.addHostModal.bind(this); - this.modifyHostModal = this.modifyHostModal.bind(this); - this.deleteHost = this.deleteHost.bind(this); + this.saveGuestSettings = this.saveGuestSettings.bind(this); } get initialState() { @@ -26,47 +23,6 @@ class HostModal extends Component { this.setState(this.initialState); } - get type() { - return !this.props.id ? "new" : "modify"; - } - - addHostModal = (e) => { - /*let data = { - // DATA HERE - };*/ - // TODO CALL TO REMOTE SERVER TO ADD SCENE - /*this.props - .saveRoom(data, null) - .then(() => { - this.setInitialState(); - this.closeModal(); - }) - .catch((err) => console.error("error in creating room", err));*/ - }; - - modifyHostModal = (e) => { - /* let data = { - // DATA HERE - };*/ - // TODO CALL TO REMOTE SERVER TO MODIFY SCENE - /*this.props - .saveRoom(data, this.props.id) - .then(() => { - this.setInitialState(); - this.closeModal(); - }) - .catch((err) => console.error("error in updating room", err));*/ - }; - - deleteHost = (e) => { - // TODO CALL TO REMOTE SERVER TO DELETE SCENE - /* - this.props - .deleteRoom(this.props.id) - .then(() => this.closeModal()) - .catch((err) => console.error("error in deleting room", err));*/ - }; - changeSomething = (event) => { let nam = event.target.name; let val = event.target.value; @@ -81,101 +37,55 @@ class HostModal extends Component { this.setState({ openModal: true }); }; + saveGuestSettings() {} + render() { return ( -
- {!this.props.nicolaStop ? ( -
- - {this.type === "new" ? ( - - ) : ( - - )} - - - {this.type === "new" ? ( - - ) : ( - - )} - -
- ) : null} + + + + + + {this.type === "new" ? ( + + ) : ( + + )} + -
- {this.type === "new" ? "Add new hosts" : "Modify hosts"} -
+
Select guests
- { - //TODO FORM TO ADD OR MODIFY SCENE - } - - {this.type === "modify" ? ( - - ) : null} + +

Spaghetti!

+
-
-
+ ); } } const setActiveHost = (activeHost) => { - return (dispatch) => - dispatch(appActions.setActiveHost(activeHost)); + return (dispatch) => dispatch(appActions.setActiveHost(activeHost)); }; const mapStateToProps = (state, ownProps) => ({ diff --git a/smart-hut/src/components/dashboard/HostsPanel.js b/smart-hut/src/components/dashboard/HostsPanel.js index 5421fc9..9f75294 100644 --- a/smart-hut/src/components/dashboard/HostsPanel.js +++ b/smart-hut/src/components/dashboard/HostsPanel.js @@ -41,8 +41,5 @@ const mapStateToProps = (state, _) => ({ activeHost: state.active.activeHost, hostDevices: state.hostDevices, }); -const HostsPanelContainer = connect( - mapStateToProps, - RemoteService -)(HostsPanel); +const HostsPanelContainer = connect(mapStateToProps, RemoteService)(HostsPanel); export default HostsPanelContainer; diff --git a/smart-hut/src/components/dashboard/ScenesPanel.js b/smart-hut/src/components/dashboard/ScenesPanel.js index 1950f6b..7a69fc5 100644 --- a/smart-hut/src/components/dashboard/ScenesPanel.js +++ b/smart-hut/src/components/dashboard/ScenesPanel.js @@ -3,7 +3,7 @@ import { connect } from "react-redux"; import { RemoteService } from "../../remote"; import Device from "./devices/Device"; import NewSceneDevice from "./NewSceneDevice"; -import { Grid, Button, Card, Segment, Header } from "semantic-ui-react"; +import { Button, Card, Segment, Header, Icon } from "semantic-ui-react"; class ScenesPanel extends Component { constructor(props) { @@ -42,7 +42,12 @@ class ScenesPanel extends Component { ) : ( - Welcome to the Scene View, you add a Scene + +
+ + Please select a scene on the left or add a new one. +
+
)} {!this.props.isActiveDefaultScene ? this.props.sceneStates.map((e, i) => { diff --git a/smart-hut/src/components/dashboard/devices/Thermostat.css b/smart-hut/src/components/dashboard/devices/Thermostat.css index 15c4314..cf6fa0b 100644 --- a/smart-hut/src/components/dashboard/devices/Thermostat.css +++ b/smart-hut/src/components/dashboard/devices/Thermostat.css @@ -28,4 +28,4 @@ background: white; border-radius: 5px; } -*/ \ No newline at end of file +*/ diff --git a/smart-hut/src/remote.js b/smart-hut/src/remote.js index 42081d8..8b41831 100644 --- a/smart-hut/src/remote.js +++ b/smart-hut/src/remote.js @@ -353,7 +353,7 @@ export const RemoteService = { */ fetchAllHosts: () => { return (dispatch) => { - return Endpoint.get(`/user`) + return Endpoint.get(`/user/hosts`) .then((res) => void dispatch(actions.getHosts(res.data))) .catch((err) => { console.error(`Fetch hosts error`, err); @@ -362,21 +362,21 @@ export const RemoteService = { }; }, -/** - * Adds the current user as a guest to another user - * identified through a host id. - * @param {Number} hostId the host to add. - * @param {String} username the username of the guest to add. - * @returns {Promise} promise that resolves to void and rejects - * with user-fiendly errors as a RemoteError - */ + /** + * Adds the current user as a guest to another user + * identified through a host id. + * @param {Number} hostId the host to add. + * @param {String} username the username of the guest to add. + * @returns {Promise} promise that resolves to void and rejects + * with user-fiendly errors as a RemoteError + */ addUserAsGuest: (hostId, username) => { return (dispatch) => { - return Endpoint.post(`/user/guest`) + return Endpoint.post(`/user/guest`) .then((res) => void dispatch(actions.guestSave(res.data))) .catch((err) => { - console.error(`Guest save error`, err); - throw new RemoteError(["Network Error"]); + console.error(`Guest save error`, err); + throw new RemoteError(["Network Error"]); }); }; }, diff --git a/smart-hut/src/store.js b/smart-hut/src/store.js index 62b34be..ef6c1cd 100644 --- a/smart-hut/src/store.js +++ b/smart-hut/src/store.js @@ -469,15 +469,15 @@ function reducer(previousState, action) { }, }); break; - case "SET_ACTIVE_HOST": - newState = update(previousState, { - active: { - activeHost: { - $set: action.activeHost, - }, + case "SET_ACTIVE_HOST": + newState = update(previousState, { + active: { + activeHost: { + $set: action.activeHost, }, - }); - break; + }, + }); + break; case "REDUX_WEBSOCKET::MESSAGE": const devices = JSON.parse(action.payload.message); //console.log("socket", JSON.stringify(devices, null, 2)); @@ -488,32 +488,15 @@ function reducer(previousState, action) { devices, }); break; - case "GET_HOSTS": - change = {}; - for (const host of action.hosts) { - change.$add = host; - } - newState = update(previousState, change); - break; - case "GET_HOST_DEVICES": - change = {}; - // TODO ACTUAL WORKING CODE - break; - case "GUEST_SAVE": - change = {}; - // TODO ACTUAL WORKING CODE - newState = update(previousState, change); - break; - case "GUEST_UPDATE": - change = {}; - // TODO ACTUAL WORKING CODE - newState = update(previousState, change); - break; - case "GUEST_DELETE": - change = {}; - // TODO ACTUAL WORKING CODE - newState = update(previousState, change); - break; + case "HOSTS_UPDATE": + change = { + hosts: {}, + }; + for (const host of action.hosts) { + change.hosts[host.id] = { $set: host }; + } + newState = update(previousState, change); + break; default: console.warn(`Action type ${action.type} unknown`, action); return previousState; diff --git a/smart-hut/src/storeActions.js b/smart-hut/src/storeActions.js index cf18ebb..ec56c13 100644 --- a/smart-hut/src/storeActions.js +++ b/smart-hut/src/storeActions.js @@ -92,31 +92,30 @@ const actions = { deviceId, }), - getHosts: (hosts) => ({ - type: "GET_HOSTS", - hosts, + hostsUpdate: (hosts) => ({ + type: "HOSTS_UPDATE", + hosts, }), getHostDevices: (host) => ({ - type: "GET_HOST_DEVICES", - host, + type: "GET_HOST_DEVICES", + host, }), guestSave: (guest) => ({ - type: "GUEST_SAVE", - guest, + type: "GUEST_SAVE", + guest, }), guestUpdate: (guest) => ({ - type: "GUEST_UPDATE", - guest, + type: "GUEST_UPDATE", + guest, }), guestDelete: (guest) => ({ - type: "GUEST_DELETE", - guest, + type: "GUEST_DELETE", + guest, }), - }; export const appActions = { diff --git a/smart-hut/src/views/Dashboard.js b/smart-hut/src/views/Dashboard.js index 17772e6..6912248 100644 --- a/smart-hut/src/views/Dashboard.js +++ b/smart-hut/src/views/Dashboard.js @@ -5,7 +5,6 @@ import AutomationsPanel from "../components/dashboard/AutomationsPanel"; import HostsPanel from "../components/dashboard/HostsPanel"; import Navbar from "./Navbar"; import ScenesNavbar from "./ScenesNavbar"; -import AutomationsNavbar from "./AutomationsNavbar"; import HostsNavbar from "./HostsNavbar"; import MyHeader from "../components/HeaderController"; import { Grid, Responsive, Button, Menu } from "semantic-ui-react"; @@ -71,8 +70,6 @@ class Dashboard extends Component { return ; case "Scenes": return ; - case "Automations": - return ; case "Hosts": return ; default: @@ -96,7 +93,7 @@ class Dashboard extends Component { - + ({ editMode: !prevState.editMode })); - } - render() { return (
- - - - + - - - - - - AUTOMATIONS - - + Hosts {Object.values(this.props.hosts).map((e, i) => { - return ( - - - - {e.name} - - {this.state.editMode ? ( - - ) : null} - - - - - ); + return ( + + {e.name} + + ); })} - - - - - + @@ -122,14 +87,7 @@ class HostsNavbar extends Component { active={this.activeItemHost === -1} onClick={this.selectHosts} > - - - - - - Hosts - - + Hosts {Object.values(this.props.hosts).map((e, i) => { @@ -141,43 +99,13 @@ class HostsNavbar extends Component { active={this.activeItemHost === e.id} onClick={this.selectHosts} > - - - {e.name} - - {this.state.editMode ? ( - - ) : null} - - - + {e.name} ); })} -
- - - - - - {this.activeItemHost !== -1 ? ( - - - - ) : null} - - ); @@ -185,17 +113,12 @@ class HostsNavbar extends Component { } const setActiveHost = (activeHost) => { - return (dispatch) => - dispatch(appActions.setActiveHost(activeHost)); + return (dispatch) => dispatch(appActions.setActiveHost(activeHost)); }; const mapStateToProps = (state, _) => ({ hosts: state.hosts, activeHost: state.active.activeHost, - hostModalRefs: Object.keys(state.hosts).reduce( - (acc, key) => ({ ...acc, [key]: React.createRef() }), - {} - ), }); const HostsNavbarContainer = connect(mapStateToProps, { ...RemoteService, diff --git a/smart-hut/src/views/Navbar.js b/smart-hut/src/views/Navbar.js index ede6748..a716173 100644 --- a/smart-hut/src/views/Navbar.js +++ b/smart-hut/src/views/Navbar.js @@ -82,7 +82,9 @@ class Navbar extends Component { - House View + + Home view + diff --git a/smart-hut/src/views/ScenesNavbar.js b/smart-hut/src/views/ScenesNavbar.js index 76661bb..e4b3b89 100644 --- a/smart-hut/src/views/ScenesNavbar.js +++ b/smart-hut/src/views/ScenesNavbar.js @@ -86,7 +86,7 @@ class ScenesNavbar extends Component { active={this.activeItemScene === -1} onClick={this.selectScene} > - SCENES + Scenes {Object.values(this.props.scenes).map((e, i) => { @@ -137,7 +137,7 @@ class ScenesNavbar extends Component { > - Scene + Scenes From a6fbd1a5d26fb8766feffe7125dfbcbe14e96b03 Mon Sep 17 00:00:00 2001 From: Claudio Maggioni Date: Sat, 2 May 2020 20:50:34 +0200 Subject: [PATCH 04/13] WIP --- smart-hut/src/views/Dashboard.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/smart-hut/src/views/Dashboard.js b/smart-hut/src/views/Dashboard.js index 6912248..e8c58c3 100644 --- a/smart-hut/src/views/Dashboard.js +++ b/smart-hut/src/views/Dashboard.js @@ -114,7 +114,7 @@ class Dashboard extends Component { /> @@ -170,7 +170,9 @@ class Dashboard extends Component { name="Hosts" content="Hosts" active={this.activeTab === "Hosts"} - color={this.activeTab === "Hosts" ? "yellow" : "grey"} + color={ + this.activeTab === "Hosts and Guests" ? "yellow" : "grey" + } onClick={this.selectTab} /> From 9b2253b1612203d297e177144db092a68f4254e2 Mon Sep 17 00:00:00 2001 From: "Claudio Maggioni (maggicl)" Date: Sat, 2 May 2020 22:37:20 +0200 Subject: [PATCH 05/13] Guest selection panel working --- smart-hut/src/components/HostModal.js | 107 ++++++++++++------ .../src/components/dashboard/HostsPanel.js | 34 ++---- .../components/dashboard/NewSceneDevice.js | 1 + smart-hut/src/remote.js | 42 +++++-- smart-hut/src/store.js | 62 ++-------- smart-hut/src/storeActions.js | 56 ++++----- smart-hut/src/views/HostsNavbar.js | 25 ++-- 7 files changed, 166 insertions(+), 161 deletions(-) diff --git a/smart-hut/src/components/HostModal.js b/smart-hut/src/components/HostModal.js index 8867b47..789c484 100644 --- a/smart-hut/src/components/HostModal.js +++ b/smart-hut/src/components/HostModal.js @@ -1,43 +1,71 @@ import React, { Component } from "react"; -import { Button, Header, Modal, Icon, Responsive } from "semantic-ui-react"; +import { + Button, + Header, + Modal, + Icon, + Form, + Responsive, + Dropdown, +} from "semantic-ui-react"; import { connect } from "react-redux"; -import { RemoteService } from "../remote"; +import { RemoteService, Forms } from "../remote"; import { appActions } from "../storeActions"; //import { update } from "immutability-helper"; class HostModal extends Component { constructor(props) { super(props); - this.state = this.initialState; + this.state = { guests: [], users: [] }; + this.props + .fetchGuests() + .then(() => { + this.setState({ + ...this.state, + guests: this.props.guests.map((u) => u.id), + }); + }) + .catch(console.error); + + Forms.fetchAllUsers() + .then((users) => + this.setState({ + ...this.state, + users: users.map((u) => ({ + key: u.id, + text: `@${u.username} (${u.name})`, + value: u.id, + })), + }) + ) + .catch(console.error); + + this.saveGuestSettings = this.saveGuestSettings.bind(this); + this.closeModal = this.closeModal.bind(this); + this.openModal = this.openModal.bind(this); + this.setGuests = this.setGuests.bind(this); this.saveGuestSettings = this.saveGuestSettings.bind(this); } - get initialState() { - return { - //INITIAL STATE HERE - }; + setGuests(_, guests) { + this.setState({ guests: guests.value }); } - setInitialState() { - this.setState(this.initialState); - } - - changeSomething = (event) => { - let nam = event.target.name; - let val = event.target.value; - this.setState({ [nam]: val }); - }; - - closeModal = (e) => { + closeModal() { this.setState({ openModal: false }); - }; + } - openModal = (e) => { + openModal() { this.setState({ openModal: true }); - }; + } - saveGuestSettings() {} + saveGuestSettings() { + this.props + .updateGuests(this.state.guests) + .then(this.closeModal) + .catch(console.error); + } render() { return ( @@ -49,17 +77,10 @@ class HostModal extends Component { - {this.type === "new" ? ( - - ) : ( - - )} + @@ -68,6 +89,22 @@ class HostModal extends Component {

Spaghetti!

+ +
+ + + + +
+
- ) : ( - - )} - - - {this.type === "new" ? ( - - ) : ( - - )} - - - ) : null} - - -
- {this.type === "new" ? "Add new automation" : "Modify automation"} -
- - { - //TODO FORM TO ADD OR MODIFY SCENE - } - - {this.type === "modify" ? ( - - ) : null} - - - - - - -
*/} - - ); - } -} - -const setActiveAutomation = (activeAutomation) => { - return (dispatch) => - dispatch(appActions.setActiveAutomation(activeAutomation)); -}; - -const mapStateToProps = (state, ownProps) => ({ - automations: ownProps.id ? state.automations[ownProps.id] : null, -}); -const AutomationModalContainer = connect( - mapStateToProps, - { ...RemoteService, setActiveAutomation }, - null, - { forwardRef: true } -)(AutomationModal); -export default AutomationModalContainer; diff --git a/smart-hut/src/components/RoomModal.js b/smart-hut/src/components/RoomModal.js index eabdb89..2054b8a 100644 --- a/smart-hut/src/components/RoomModal.js +++ b/smart-hut/src/components/RoomModal.js @@ -21,7 +21,6 @@ class RoomModal extends Component { constructor(props) { super(props); this.state = this.initialState; - this.setInitialState(); this.fileInputRef = React.createRef(); diff --git a/smart-hut/src/components/dashboard/HostsPanel.js b/smart-hut/src/components/dashboard/HostsPanel.js index 538cb89..a9199c8 100644 --- a/smart-hut/src/components/dashboard/HostsPanel.js +++ b/smart-hut/src/components/dashboard/HostsPanel.js @@ -7,13 +7,19 @@ import Device from "../../components/dashboard/devices/Device"; class HostsPanel extends Component { constructor(props) { super(props); - if (this.props.activeHost !== -1) { + } + + componentDidUpdate(oldProps) { + if ( + oldProps.activeHost !== this.props.activeHost && + this.props.activeHost !== -1 + ) { this.props.fetchDevices(null, this.props.activeHost).catch(console.error); } } render() { - console.log(this.props); + console.log(this.props.hostDevices); return ( {this.props.isActiveDefaultHost && ( @@ -42,7 +48,8 @@ class HostsPanel extends Component { const mapStateToProps = (state, _) => ({ isActiveDefaultHost: state.active.activeHost === -1, activeHost: state.active.activeHost, - hostDeviceIds: Object.keys(state.hostDevices[state.activeHost] || {}), + hostDevices: state.hostDevices, + hostDeviceIds: Object.keys(state.hostDevices[state.active.activeHost] || {}), }); const HostsPanelContainer = connect(mapStateToProps, RemoteService)(HostsPanel); export default HostsPanelContainer; diff --git a/smart-hut/src/components/dashboard/devices/Curtain.js b/smart-hut/src/components/dashboard/devices/Curtain.js index d475455..e055b34 100644 --- a/smart-hut/src/components/dashboard/devices/Curtain.js +++ b/smart-hut/src/components/dashboard/devices/Curtain.js @@ -2,6 +2,7 @@ import React, { Component } from "react"; import "./Curtains.css"; import { RemoteService } from "../../../remote"; import { connect } from "react-redux"; +import mapStateToProps from "../../../deviceProps"; class Curtain extends Component { constructor(props) { @@ -112,15 +113,5 @@ class Curtain extends Component { } } -const mapStateToProps = (state, ownProps) => ({ - get stateOrDevice() { - if (state.active.activeTab === "Devices") { - return state.devices[ownProps.id]; - } else { - return state.sceneStates[ownProps.id]; - } - }, - //device: state.devices[ownProps.id], -}); const CurtainContainer = connect(mapStateToProps, RemoteService)(Curtain); export default CurtainContainer; diff --git a/smart-hut/src/components/dashboard/devices/Device.js b/smart-hut/src/components/dashboard/devices/Device.js index 61ee18b..d153cdf 100644 --- a/smart-hut/src/components/dashboard/devices/Device.js +++ b/smart-hut/src/components/dashboard/devices/Device.js @@ -11,6 +11,7 @@ import { Header, Button, Icon, Card } from "semantic-ui-react"; import { RemoteService } from "../../../remote"; import { connect } from "react-redux"; import DeviceSettingsModal from "./DeviceSettingsModal"; +import mapStateToProps from "../../../deviceProps"; const centerComponent = { marginLeft: "50%", @@ -45,66 +46,33 @@ class Device extends React.Component { } renderDeviceComponent() { - switch (this.props.type) { - case "curtains": - return ( - - ); - case "thermostat": - return ( - - ); - case "regularLight": - return ( - - ); - case "sensor": - return ( - - ); - case "motionSensor": - return ; - case "buttonDimmer": - return ( - - ); - case "knobDimmer": - return ( - - ); - case "smartPlug": - return ( - - ); - case "switch": - return ( - - ); - case "dimmableLight": - return ; - case "securityCamera": - return ( - - ); - default: - throw new Error("Device type unknown"); + const mapKindToComponent = { + curtains: Curtains, + thermostat: Thermostat, + regularLight: Light, + sensor: Sensor, + motionSensor: Sensor, + buttonDimmer: ButtonDimmer, + knobDimmer: KnobDimmer, + smartPlug: SmartPlug, + switch: Switcher, + dimmableLight: Light, + securityCamera: Videocam, + }; + + if (!(this.props.type in mapKindToComponent)) { + throw new Error(`device kind ${this.props.type} not known`); } + + return React.createElement( + mapKindToComponent[this.props.type], + { + tab: this.props.tab, + id: this.props.id, + hostId: this.props.hostId, + }, + "" + ); } deviceDescription() { @@ -165,7 +133,7 @@ class Device extends React.Component { {this.props.tab === "Devices" ? this.deviceDescription() - : this.stateDescription()} + : this.props.tab === "Scenes" && this.stateDescription()} {this.props.tab === "Devices" ? ( ({ - get stateOrDevice() { - return getStateOrDevice(state, ownProps); - }, - get device() { - return getDevice(state, ownProps); - }, - get roomName() { - return (state.rooms[getDevice(state, ownProps).roomId] || {}).name; - }, - get type() { - return getDevice(state, ownProps).kind; - }, -}); const DeviceContainer = connect(mapStateToProps, RemoteService)(Device); export default DeviceContainer; diff --git a/smart-hut/src/components/dashboard/devices/Dimmer.js b/smart-hut/src/components/dashboard/devices/Dimmer.js index d4762fd..ccec658 100644 --- a/smart-hut/src/components/dashboard/devices/Dimmer.js +++ b/smart-hut/src/components/dashboard/devices/Dimmer.js @@ -29,6 +29,7 @@ import { } from "./DimmerStyle"; import { RemoteService } from "../../../remote"; import { connect } from "react-redux"; +import mapStateToProps from "../../../deviceProps"; export class ButtonDimmerComponent extends Component { increaseIntensity = () => { @@ -128,15 +129,6 @@ export class KnobDimmerComponent extends Component { } } -const mapStateToProps = (state, ownProps) => ({ - get stateOrDevice() { - if (state.active.activeTab === "Devices") { - return state.devices[ownProps.id]; - } else { - return state.sceneStates[ownProps.id]; - } - }, -}); const conn = connect(mapStateToProps, RemoteService); export const KnobDimmer = conn(KnobDimmerComponent); diff --git a/smart-hut/src/components/dashboard/devices/Light.js b/smart-hut/src/components/dashboard/devices/Light.js index ebf0565..def795e 100644 --- a/smart-hut/src/components/dashboard/devices/Light.js +++ b/smart-hut/src/components/dashboard/devices/Light.js @@ -31,6 +31,7 @@ import { } from "./LightStyle"; import { RemoteService } from "../../../remote"; import { connect } from "react-redux"; +import mapStateToProps from "../../../deviceProps"; class Light extends Component { constructor(props) { @@ -62,7 +63,7 @@ class Light extends Component { } get intensity() { - return this.props.stateOrDevice.intensity || 0; + return this.state.intensity || 0; } onClickDevice = () => { @@ -119,7 +120,6 @@ class Light extends Component { .saveDevice({ ...this.props.stateOrDevice, intensity }) .catch((err) => console.error("regular light update error", err)); } else { - console.log("CIAOOOOOOOOO", this.props.stateOrDevice); this.props .updateState( { id: this.props.stateOrDevice.id, intensity: intensity }, @@ -153,7 +153,7 @@ class Light extends Component { @@ -184,22 +184,5 @@ class Light extends Component { } } -const mapStateToProps = (state, ownProps) => ({ - get stateOrDevice() { - if (state.active.activeTab === "Devices") { - return state.devices[ownProps.id]; - } else { - return state.sceneStates[ownProps.id]; - } - }, - get device() { - if (state.active.activeTab === "Devices") { - return state.devices[ownProps.id]; - } else { - return state.devices[state.sceneStates[ownProps.id].deviceId]; - } - }, -}); - const LightContainer = connect(mapStateToProps, RemoteService)(Light); export default LightContainer; diff --git a/smart-hut/src/components/dashboard/devices/Sensor.js b/smart-hut/src/components/dashboard/devices/Sensor.js index ad80a4c..f171b6a 100644 --- a/smart-hut/src/components/dashboard/devices/Sensor.js +++ b/smart-hut/src/components/dashboard/devices/Sensor.js @@ -38,6 +38,7 @@ import { import { Image } from "semantic-ui-react"; import { RemoteService } from "../../../remote"; import { connect } from "react-redux"; +import mapStateToProps from "../../../deviceProps"; class Sensor extends Component { constructor(props) { @@ -194,14 +195,5 @@ class Sensor extends Component { } } -const mapStateToProps = (state, ownProps) => ({ - get stateOrDevice() { - if (state.active.activeTab === "Devices") { - return state.devices[ownProps.id]; - } else { - return state.sceneStates[ownProps.id]; - } - }, -}); const SensorContainer = connect(mapStateToProps, RemoteService)(Sensor); export default SensorContainer; diff --git a/smart-hut/src/components/dashboard/devices/SmartPlug.js b/smart-hut/src/components/dashboard/devices/SmartPlug.js index 5074429..3e93749 100644 --- a/smart-hut/src/components/dashboard/devices/SmartPlug.js +++ b/smart-hut/src/components/dashboard/devices/SmartPlug.js @@ -15,6 +15,7 @@ import { } from "./SmartPlugStyle"; import { RemoteService } from "../../../remote"; import { connect } from "react-redux"; +import mapStateToProps from "../../../deviceProps"; class SmartPlug extends Component { constructor(props) { @@ -70,21 +71,5 @@ class SmartPlug extends Component { } } -const mapStateToProps = (state, ownProps) => ({ - get stateOrDevice() { - if (state.active.activeTab === "Devices") { - return state.devices[ownProps.id]; - } else { - return state.sceneStates[ownProps.id]; - } - }, - get device() { - if (state.active.activeTab === "Devices") { - return state.devices[ownProps.id]; - } else { - return state.devices[state.sceneStates[ownProps.id].deviceId]; - } - }, -}); const SmartPlugContainer = connect(mapStateToProps, RemoteService)(SmartPlug); export default SmartPlugContainer; diff --git a/smart-hut/src/components/dashboard/devices/Switch.js b/smart-hut/src/components/dashboard/devices/Switch.js index 113c1f1..62e9c84 100644 --- a/smart-hut/src/components/dashboard/devices/Switch.js +++ b/smart-hut/src/components/dashboard/devices/Switch.js @@ -11,6 +11,7 @@ import { Image } from "semantic-ui-react"; import { imageStyle, nameStyle, turnedOnStyle } from "./SwitchStyle"; import { RemoteService } from "../../../remote"; import { connect } from "react-redux"; +import mapStateToProps from "../../../deviceProps"; class Switch extends Component { constructor(props) { @@ -55,8 +56,5 @@ class Switch extends Component { } } -const mapStateToProps = (state, ownProps) => ({ - device: state.devices[ownProps.id], -}); const SwitchContainer = connect(mapStateToProps, RemoteService)(Switch); export default SwitchContainer; diff --git a/smart-hut/src/components/dashboard/devices/Thermostats.js b/smart-hut/src/components/dashboard/devices/Thermostats.js index c2012bd..17f33f2 100644 --- a/smart-hut/src/components/dashboard/devices/Thermostats.js +++ b/smart-hut/src/components/dashboard/devices/Thermostats.js @@ -5,6 +5,7 @@ import { connect } from "react-redux"; import "./Thermostat.css"; import Slider from "react-rangeslider"; import "react-rangeslider/lib/index.css"; +import mapStateToProps from "../../../deviceProps"; import { stateTag, @@ -144,24 +145,6 @@ class Thermostats extends Component { } } -const mapStateToProps = (state, ownProps) => ({ - get stateOrDevice() { - if (state.active.activeTab === "Devices") { - return state.devices[ownProps.id]; - } else { - return state.sceneStates[ownProps.id]; - } - }, - get device() { - if (state.active.activeTab === "Devices") { - return state.devices[ownProps.id]; - } else { - return state.devices[state.sceneStates[ownProps.id].deviceId]; - } - }, - activeTab: state.activeTab, -}); - const ThermostatContainer = connect( mapStateToProps, RemoteService diff --git a/smart-hut/src/components/dashboard/devices/Videocam.js b/smart-hut/src/components/dashboard/devices/Videocam.js index c434be0..ee52409 100644 --- a/smart-hut/src/components/dashboard/devices/Videocam.js +++ b/smart-hut/src/components/dashboard/devices/Videocam.js @@ -7,6 +7,7 @@ import { RemoteService } from "../../../remote"; import { endpointURL } from "../../../endpoint"; import { connect } from "react-redux"; import VideocamModal from "./VideocamModal"; +import mapStateToProps from "../../../deviceProps"; class Videocam extends Component { constructor(props) { @@ -58,12 +59,5 @@ class Videocam extends Component { } } -const mapStateToProps = (state, ownProps) => ({ - device: - ownProps.tab === "Devices" - ? state.devices[ownProps.id] - : state.devices[state.sceneStates[ownProps.id].deviceId], - state: state.sceneStates[ownProps.id], -}); const VideocamContainer = connect(mapStateToProps, RemoteService)(Videocam); export default VideocamContainer; diff --git a/smart-hut/src/deviceProps.js b/smart-hut/src/deviceProps.js new file mode 100644 index 0000000..9f5f4ae --- /dev/null +++ b/smart-hut/src/deviceProps.js @@ -0,0 +1,51 @@ +function getStateOrDevice(state, ownProps) { + switch (state.active.activeTab) { + case "Devices": + return state.devices[ownProps.id]; + case "Scenes": + return state.sceneStates[ownProps.id]; + case "Hosts": + return state.hostDevices[ownProps.hostId][ownProps.id]; + default: + throw new Error( + `stateOrDevice has no value in tab "${state.active.activeTab}"` + ); + } +} + +function getDevice(state, ownProps) { + switch (state.active.activeTab) { + case "Scenes": + return state.devices[getStateOrDevice(state, ownProps).deviceId]; + case "Devices": + case "Hosts": + return getStateOrDevice(state, ownProps); + default: + throw new Error(`device has no value in tab "${state.active.activeTab}"`); + } +} + +function getRoomName(state, ownProps) { + switch (state.active.activeTab) { + case "Scenes": + case "Devices": + return (state.rooms[getDevice(state, ownProps).roomId] || {}).name; + case "Hosts": + return "Room Name not implemented yet"; + } +} + +export default function mapStateToProps(state, ownProps) { + return { + get stateOrDevice() { + return getStateOrDevice(state, ownProps); + }, + get device() { + return getDevice(state, ownProps); + }, + get roomName() {}, + get type() { + return getDevice(state, ownProps).kind; + }, + }; +} diff --git a/smart-hut/src/store.js b/smart-hut/src/store.js index 33b0bef..6d1ae28 100644 --- a/smart-hut/src/store.js +++ b/smart-hut/src/store.js @@ -3,7 +3,6 @@ import thunk from "redux-thunk"; import update from "immutability-helper"; import reduxWebSocket, { connect } from "@giantmachines/redux-websocket"; import { socketURL } from "./endpoint"; -import actions from "./storeActions"; function reducer(previousState, action) { let newState, change; diff --git a/smart-hut/src/views/Dashboard.js b/smart-hut/src/views/Dashboard.js index e8c58c3..ab2c952 100644 --- a/smart-hut/src/views/Dashboard.js +++ b/smart-hut/src/views/Dashboard.js @@ -21,7 +21,6 @@ class Dashboard extends Component { constructor(props) { super(props); this.state = this.initialState; - this.setInitialState(); this.activeTab = "Devices"; this.selectTab = this.selectTab.bind(this); } From 0252870c705fb35d7b32f92abfd8126691df925d Mon Sep 17 00:00:00 2001 From: "Claudio Maggioni (maggicl)" Date: Sun, 3 May 2020 18:11:04 +0200 Subject: [PATCH 09/13] fixed bug in deviceProps.js --- smart-hut/src/deviceProps.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/smart-hut/src/deviceProps.js b/smart-hut/src/deviceProps.js index 9f5f4ae..efdb6ae 100644 --- a/smart-hut/src/deviceProps.js +++ b/smart-hut/src/deviceProps.js @@ -43,7 +43,9 @@ export default function mapStateToProps(state, ownProps) { get device() { return getDevice(state, ownProps); }, - get roomName() {}, + get roomName() { + return getRoomName(state, ownProps); + }, get type() { return getDevice(state, ownProps).kind; }, From c7dc34eedc1033192739cd6ad8a0c5e7ce1e60da Mon Sep 17 00:00:00 2001 From: "Claudio Maggioni (maggicl)" Date: Sun, 3 May 2020 18:13:50 +0200 Subject: [PATCH 10/13] other minor fixes --- smart-hut/src/components/dashboard/devices/Light.js | 2 +- smart-hut/src/components/dashboard/devices/Thermostats.js | 3 --- smart-hut/src/deviceProps.js | 4 ++++ smart-hut/src/views/Login.js | 1 - 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/smart-hut/src/components/dashboard/devices/Light.js b/smart-hut/src/components/dashboard/devices/Light.js index def795e..10e8a8f 100644 --- a/smart-hut/src/components/dashboard/devices/Light.js +++ b/smart-hut/src/components/dashboard/devices/Light.js @@ -136,7 +136,7 @@ class Light extends Component {
diff --git a/smart-hut/src/components/dashboard/devices/Thermostats.js b/smart-hut/src/components/dashboard/devices/Thermostats.js index 17f33f2..71216bf 100644 --- a/smart-hut/src/components/dashboard/devices/Thermostats.js +++ b/smart-hut/src/components/dashboard/devices/Thermostats.js @@ -25,7 +25,6 @@ class Thermostats extends Component { measuredTemperature: this.props.device.measuredTemperature, useExternalSensors: this.props.device.useExternalSensors, }; - console.log(this.state); this.setMode = this.setMode.bind(this); this.setTargetTemperature = this.setTargetTemperature.bind(this); } @@ -34,13 +33,11 @@ class Thermostats extends Component { if (this.state.timeout) { clearTimeout(this.state.timeout); } - console.log(mode); //i came to the conclusion that is not possible to set mode. // Good job Jacob (Claudio) //this.mode = "HEATING"; const turnOn = mode; - console.log(turnOn); if (this.props.tab === "Devices") { this.props .saveDevice({ ...this.props.stateOrDevice, turnOn }) diff --git a/smart-hut/src/deviceProps.js b/smart-hut/src/deviceProps.js index efdb6ae..22a6d3b 100644 --- a/smart-hut/src/deviceProps.js +++ b/smart-hut/src/deviceProps.js @@ -32,6 +32,10 @@ function getRoomName(state, ownProps) { return (state.rooms[getDevice(state, ownProps).roomId] || {}).name; case "Hosts": return "Room Name not implemented yet"; + default: + throw new Error( + `room name has no value in tab "${state.active.activeTab}"` + ); } } diff --git a/smart-hut/src/views/Login.js b/smart-hut/src/views/Login.js index 3544e7a..3a0bf71 100644 --- a/smart-hut/src/views/Login.js +++ b/smart-hut/src/views/Login.js @@ -31,7 +31,6 @@ class Login extends Component { .login(this.state.user, this.state.password) .then(() => this.props.history.push("/dashboard")) .catch((err) => { - console.log("CIAO", err); this.setState({ error: { state: true, message: err.messages.join(" - ") }, }); From 770469ade3c82399e0a2192aaf69eb94b8056a33 Mon Sep 17 00:00:00 2001 From: "Claudio Maggioni (maggicl)" Date: Sun, 3 May 2020 19:51:00 +0200 Subject: [PATCH 11/13] Socket update handling done except deletion messages, currently not implemented in the server side --- .../src/components/dashboard/HostsPanel.js | 6 +- .../dashboard/devices/Thermostats.js | 2 +- smart-hut/src/deviceProps.js | 6 +- smart-hut/src/remote.js | 15 ++++- smart-hut/src/store.js | 57 ++++++++++++++++--- smart-hut/src/storeActions.js | 5 ++ 6 files changed, 74 insertions(+), 17 deletions(-) diff --git a/smart-hut/src/components/dashboard/HostsPanel.js b/smart-hut/src/components/dashboard/HostsPanel.js index a9199c8..ca63068 100644 --- a/smart-hut/src/components/dashboard/HostsPanel.js +++ b/smart-hut/src/components/dashboard/HostsPanel.js @@ -5,21 +5,17 @@ import { Card, Segment, Header, Icon } from "semantic-ui-react"; import Device from "../../components/dashboard/devices/Device"; class HostsPanel extends Component { - constructor(props) { - super(props); - } - componentDidUpdate(oldProps) { if ( oldProps.activeHost !== this.props.activeHost && this.props.activeHost !== -1 ) { this.props.fetchDevices(null, this.props.activeHost).catch(console.error); + this.props.fetchAllRooms(this.props.activeHost).catch(console.error); } } render() { - console.log(this.props.hostDevices); return ( {this.props.isActiveDefaultHost && ( diff --git a/smart-hut/src/components/dashboard/devices/Thermostats.js b/smart-hut/src/components/dashboard/devices/Thermostats.js index 71216bf..4eeb868 100644 --- a/smart-hut/src/components/dashboard/devices/Thermostats.js +++ b/smart-hut/src/components/dashboard/devices/Thermostats.js @@ -130,7 +130,7 @@ class Thermostats extends Component { ) : null}
- {this.props.tab === "Devices" + {this.props.tab !== "Scenes" ? this.props.device.mode : this.props.stateOrDevice.on ? "WILL TURN ON" diff --git a/smart-hut/src/deviceProps.js b/smart-hut/src/deviceProps.js index 22a6d3b..a1602d7 100644 --- a/smart-hut/src/deviceProps.js +++ b/smart-hut/src/deviceProps.js @@ -31,7 +31,11 @@ function getRoomName(state, ownProps) { case "Devices": return (state.rooms[getDevice(state, ownProps).roomId] || {}).name; case "Hosts": - return "Room Name not implemented yet"; + const hostRooms = state.hostRooms[ownProps.hostId]; + if (!hostRooms) return ""; + const room = hostRooms[getDevice(state, ownProps).roomId]; + if (!room) return ""; + return room.name; default: throw new Error( `room name has no value in tab "${state.active.activeTab}"` diff --git a/smart-hut/src/remote.js b/smart-hut/src/remote.js index 3bbb42c..dcb4b26 100644 --- a/smart-hut/src/remote.js +++ b/smart-hut/src/remote.js @@ -261,13 +261,22 @@ export const RemoteService = { /** * Fetches all rooms that belong to this user. This call does not * populate the devices attribute in rooms. + * @param {Number|null} hostId the user id of the host we need to fetch the rooms from. + * Null if we need to fetch our own rooms. * @returns {Promise} promise that resolves to void and rejects * with user-fiendly errors as a RemoteError */ - fetchAllRooms: () => { + fetchAllRooms: (hostId = null) => { return (dispatch) => { - return Endpoint.get("/room") - .then((res) => void dispatch(actions.roomsUpdate(res.data))) + return Endpoint.get("/room", hostId ? { hostId } : null) + .then( + (res) => + void dispatch( + hostId + ? actions.hostRoomsUpdate(hostId, res.data) + : actions.roomsUpdate(res.data) + ) + ) .catch((err) => { console.error("Fetch all rooms error", err); throw new RemoteError(["Network error"]); diff --git a/smart-hut/src/store.js b/smart-hut/src/store.js index 6d1ae28..2050fd5 100644 --- a/smart-hut/src/store.js +++ b/smart-hut/src/store.js @@ -99,6 +99,20 @@ function reducer(previousState, action) { createOrUpdateRoom(room); } break; + case "HOST_ROOMS_UPDATE": + change = { + hostRooms: { + [action.hostId]: { $set: {} }, + }, + }; + const rooms = change.hostRooms[action.hostId].$set; + + for (const room of action.rooms) { + rooms[room.id] = room; + } + + newState = update(previousState, change); + break; case "SCENES_UPDATE": newState = previousState; for (const scene of action.scenes) { @@ -256,18 +270,25 @@ function reducer(previousState, action) { newState = update(newState, change); break; case "HOST_DEVICES_UPDATE": + newState = action.partial + ? previousState + : update(previousState, { + hostDevices: { [action.hostId]: { $set: {} } }, + }); + newState.hostDevices[action.hostId] = + newState.hostDevices[action.hostId] || {}; change = { hostDevices: { - [action.hostId]: { $set: {} }, + [action.hostId]: {}, }, }; - const deviceMap = change.hostDevices[action.hostId].$set; + const deviceMap = change.hostDevices[action.hostId]; for (const device of action.devices) { - deviceMap[device.id] = device; + deviceMap[device.id] = { $set: device }; } - newState = update(previousState, change); + newState = update(newState, change); break; case "AUTOMATION_UPDATE": const automations = {}; @@ -456,14 +477,34 @@ function reducer(previousState, action) { }); break; case "REDUX_WEBSOCKET::MESSAGE": - const devices = JSON.parse(action.payload.message); - //console.log("socket", JSON.stringify(devices, null, 2)); + const allDevices = JSON.parse(action.payload.message); + const devices = allDevices.filter( + (d) => + (d.fromHostId === null || d.fromHostId === undefined) && !d.deleted + ); + const hostDevicesMapByHostId = allDevices + .filter((d) => d.fromHostId && !d.deleted) + .reduce((a, e) => { + const hostId = e.fromHostId; + //delete e.fromHostId; + a[hostId] = a[hostId] || []; + a[hostId].push(e); + return a; + }, {}); newState = reducer(previousState, { type: "DEVICES_UPDATE", partial: true, devices, }); + for (const hostId in hostDevicesMapByHostId) { + newState = reducer(newState, { + type: "HOST_DEVICES_UPDATE", + devices: hostDevicesMapByHostId[hostId], + partial: true, + hostId, + }); + } break; case "HG_UPDATE": newState = update(previousState, { @@ -509,8 +550,10 @@ const initState = { guests: [], /** @type {User[]} */ hosts: [], - /** @type {[integer]HostDevice} */ + /** @type {[integer]Device} */ hostDevices: {}, + /** @type {[integer]Eoom} */ + hostRooms: {}, }; function createSmartHutStore() { diff --git a/smart-hut/src/storeActions.js b/smart-hut/src/storeActions.js index fbd02c7..bfce32b 100644 --- a/smart-hut/src/storeActions.js +++ b/smart-hut/src/storeActions.js @@ -76,6 +76,11 @@ const actions = { type: "ROOMS_UPDATE", rooms, }), + hostRoomsUpdate: (hostId, rooms) => ({ + type: "HOST_ROOMS_UPDATE", + hostId, + rooms, + }), roomDelete: (roomId) => ({ type: "ROOM_DELETE", roomId, From c145be02b4b3911ea2b56907e55e7e1cd76ccab7 Mon Sep 17 00:00:00 2001 From: "Claudio Maggioni (maggicl)" Date: Mon, 4 May 2020 11:13:19 +0200 Subject: [PATCH 12/13] Lights can be modified by a guest --- .../components/dashboard/devices/Curtain.js | 1 + .../components/dashboard/devices/Dimmer.js | 2 +- .../src/components/dashboard/devices/Light.js | 20 ++++++++++++------- .../components/dashboard/devices/SmartPlug.js | 2 +- .../components/dashboard/devices/Switch.js | 2 +- .../dashboard/devices/Thermostats.js | 2 ++ smart-hut/src/deviceProps.js | 8 ++++++++ smart-hut/src/remote.js | 14 ++++++++++--- smart-hut/src/store.js | 14 ++++++++++++- smart-hut/src/storeActions.js | 5 +++++ 10 files changed, 56 insertions(+), 14 deletions(-) diff --git a/smart-hut/src/components/dashboard/devices/Curtain.js b/smart-hut/src/components/dashboard/devices/Curtain.js index e055b34..45850f6 100644 --- a/smart-hut/src/components/dashboard/devices/Curtain.js +++ b/smart-hut/src/components/dashboard/devices/Curtain.js @@ -101,6 +101,7 @@ class Curtain extends Component { {Math.round(this.props.stateOrDevice.intensity)}% { const on = !this.turnedOn; - if (this.props.tab === "Devices") { + if (this.props.tab !== "Scenes") { this.props - .saveDevice({ ...this.props.stateOrDevice, on }) + .saveDevice( + { ...this.props.stateOrDevice, on }, + this.props.tab === "Hosts" ? this.props.activeHost : null + ) .catch((err) => console.error("regular light update error", err)); } else { if (this.props.device.kind === "regularLight") { @@ -115,10 +118,13 @@ class Light extends Component { saveIntensity = () => { const intensity = Math.round(this.state.intensity); - if (this.props.tab === "Devices") { + if (this.props.tab !== "Scenes") { this.props - .saveDevice({ ...this.props.stateOrDevice, intensity }) - .catch((err) => console.error("regular light update error", err)); + .saveDevice( + { ...this.props.stateOrDevice, intensity }, + this.props.tab === "Hosts" ? this.props.activeHost : null + ) + .catch((err) => console.error("dimmable light update error", err)); } else { this.props .updateState( @@ -137,8 +143,8 @@ class Light extends Component { + {} : this.onClickDevice}> Smart Plug diff --git a/smart-hut/src/components/dashboard/devices/Switch.js b/smart-hut/src/components/dashboard/devices/Switch.js index 62e9c84..8c4e4d9 100644 --- a/smart-hut/src/components/dashboard/devices/Switch.js +++ b/smart-hut/src/components/dashboard/devices/Switch.js @@ -38,7 +38,7 @@ class Switch extends Component { render() { return ( - + {} : this.onClickDevice}> Switch diff --git a/smart-hut/src/components/dashboard/devices/Thermostats.js b/smart-hut/src/components/dashboard/devices/Thermostats.js index 4eeb868..8fa9df7 100644 --- a/smart-hut/src/components/dashboard/devices/Thermostats.js +++ b/smart-hut/src/components/dashboard/devices/Thermostats.js @@ -99,6 +99,7 @@ class Thermostats extends Component {

Thermostat {this.props.tab === "Devices" ? ( } promise that resolves to the saved device and rejects * with user-fiendly errors as a RemoteError */ - saveDevice: (data) => { + saveDevice: (data, hostId = null) => { return (dispatch) => { let url = "/device"; if ((data.id && data.flowType === "OUTPUT") || !data.id) { url = "/" + data.kind; } - return Endpoint[data.id ? "put" : "post"](url, {}, data) + return Endpoint[data.id ? "put" : "post"]( + url, + hostId ? { hostId } : {}, + data + ) .then((res) => { - dispatch(actions.deviceSave(res.data)); + dispatch( + hostId + ? actions.hostDeviceSave(hostId, res.data) + : actions.deviceSave(res.data) + ); return res.data; }) .catch((err) => { diff --git a/smart-hut/src/store.js b/smart-hut/src/store.js index 2050fd5..e68060f 100644 --- a/smart-hut/src/store.js +++ b/smart-hut/src/store.js @@ -3,6 +3,7 @@ import thunk from "redux-thunk"; import update from "immutability-helper"; import reduxWebSocket, { connect } from "@giantmachines/redux-websocket"; import { socketURL } from "./endpoint"; +import actions from "./storeActions"; function reducer(previousState, action) { let newState, change; @@ -333,6 +334,18 @@ function reducer(previousState, action) { } newState = update(previousState, change); break; + case "HOST_DEVICE_SAVE": + change = { + hostDevices: { + [action.hostId]: { + [action.device.id]: { + $set: action.device, + }, + }, + }, + }; + newState = update(previousState, change); + break; case "AUTOMATION_SAVE": change = { @@ -491,7 +504,6 @@ function reducer(previousState, action) { a[hostId].push(e); return a; }, {}); - newState = reducer(previousState, { type: "DEVICES_UPDATE", partial: true, diff --git a/smart-hut/src/storeActions.js b/smart-hut/src/storeActions.js index bfce32b..64c2a52 100644 --- a/smart-hut/src/storeActions.js +++ b/smart-hut/src/storeActions.js @@ -25,6 +25,11 @@ const actions = { type: "DEVICE_SAVE", device, }), + hostDeviceSave: (hostId, device) => ({ + type: "HOST_DEVICE_SAVE", + hostId, + device, + }), triggerSave: (automation) => ({ type: "TRIGGER_SAVE", automation, From cfe1f35226d48b3c9d1d1e62ecdb3dc7db664cf8 Mon Sep 17 00:00:00 2001 From: "Claudio Maggioni (maggicl)" Date: Mon, 4 May 2020 11:57:42 +0200 Subject: [PATCH 13/13] Deletion propagation implemented --- smart-hut/src/store.js | 42 +++++++++++++++++++++++++++++++++--------- 1 file changed, 33 insertions(+), 9 deletions(-) diff --git a/smart-hut/src/store.js b/smart-hut/src/store.js index e68060f..a8b4e66 100644 --- a/smart-hut/src/store.js +++ b/smart-hut/src/store.js @@ -346,6 +346,16 @@ function reducer(previousState, action) { }; newState = update(previousState, change); break; + case "HOST_DEVICES_DELETE": + change = { + hostDevices: { + [action.hostId]: { + $unset: [action.deviceIds], + }, + }, + }; + newState = update(previousState, change); + break; case "AUTOMATION_SAVE": change = { @@ -496,26 +506,40 @@ function reducer(previousState, action) { (d.fromHostId === null || d.fromHostId === undefined) && !d.deleted ); const hostDevicesMapByHostId = allDevices - .filter((d) => d.fromHostId && !d.deleted) + .filter((d) => d.fromHostId) .reduce((a, e) => { const hostId = e.fromHostId; //delete e.fromHostId; - a[hostId] = a[hostId] || []; - a[hostId].push(e); + a[hostId] = a[hostId] || { updated: [], deletedIds: [] }; + if (e.deleted) { + a[hostId].deletedIds.push(e.id); + } else { + a[hostId].updated.push(e); + } return a; }, {}); + newState = reducer(previousState, { type: "DEVICES_UPDATE", partial: true, devices, }); for (const hostId in hostDevicesMapByHostId) { - newState = reducer(newState, { - type: "HOST_DEVICES_UPDATE", - devices: hostDevicesMapByHostId[hostId], - partial: true, - hostId, - }); + if (hostDevicesMapByHostId[hostId].updated.length > 0) + newState = reducer(newState, { + type: "HOST_DEVICES_UPDATE", + devices: hostDevicesMapByHostId[hostId].updated, + partial: true, + hostId, + }); + if (hostDevicesMapByHostId[hostId].deletedIds.length > 0) { + newState = reducer(newState, { + type: "HOST_DEVICES_DELETE", + deviceIds: hostDevicesMapByHostId[hostId].deletedIds, + partial: true, + hostId, + }); + } } break; case "HG_UPDATE":