Converting project to Redux store

This commit is contained in:
britea 2020-04-09 17:24:30 +02:00
parent bad5d04238
commit eead3694e6
5 changed files with 191 additions and 459 deletions

View File

@ -7,9 +7,10 @@ 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 { connect } from "react-redux";
import { RemoteService } from "../../remote";
export default class DevicePanel extends Component {
class DevicePanel extends Component {
constructor(props) {
super(props);
this.state = {
@ -17,10 +18,13 @@ export default class DevicePanel extends Component {
};
this.addDevice = this.addDevice.bind(this);
this.toggleEditMode = this.toggleEditMode.bind(this);
this.getDevices();
}
editModeController = (e) =>
toggleEditMode(e) {
this.setState((prevState) => ({ editMode: !prevState.editMode }));
}
openModal = (settingsDeviceId) => {
this.setState((prevState) => ({
@ -29,107 +33,30 @@ export default class DevicePanel extends Component {
}));
};
changeDeviceData = (deviceId, newSettings) => {
/*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];
}
}
for (let prop in this.props.devices[deviceId]) {
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();
};
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();
getDevices() {
this.props.fetchDevices().then();
}
updateDevice = (data) => {
const roomId = this.props.devices.filter(
(d) => d.id === this.state.settingsDeviceId
)[0].roomId;
data["id"] = this.state.settingsDeviceId;
data["roomId"] = roomId;
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,
@ -149,31 +76,21 @@ export default class DevicePanel extends Component {
{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
updateDev={this.props.updateDeviceUi}
type={e.kind}
onChangeData={this.changeDeviceData}
device={e}
edit={edit}
/>
</Grid.Column>
);
})
: null}
{this.props.activeItem !== -1 ? (
{this.props.devices.map((e, i) => {
return (
<Grid.Column key={i}>
<DeviceType type={e.kind} device={e} edit={edit} />
</Grid.Column>
);
})}
{!this.props.isActiveRoomHome ? (
<Grid.Column>
<NewDevice addDevice={this.addDevice} devices={ds} />
<NewDevice />
</Grid.Column>
) : null}
</Grid>
@ -181,3 +98,24 @@ export default class DevicePanel extends Component {
);
}
}
const mapStateToProps = (state, _) => ({
get devices() {
if (state.active.activeRoom === -1) {
return Object.values(state.devices);
} else {
return state.rooms[state.active.activeRoom].devices.map(
(id) => state.devices[id]
);
}
},
get isActiveRoomHome() {
return this.props.activeRoom === -1;
},
activeRoom: state.active.activeRoom,
});
const DevicePanelContainer = connect(
mapStateToProps,
RemoteService
)(DevicePanel);
export default DevicePanelContainer;

View File

@ -143,12 +143,16 @@ function reducer(previousState, action) {
});
break;
case "LOGOUT":
newState = {
login: { loggedIn: false, token: null },
rooms: [],
devices: [],
userInfo: null,
};
newState = update(initState, {});
break;
case "SET_ACTIVE_ROOM":
newState = update(previousState, {
active: {
activeRoom: {
$set: actions.activeRoom,
},
},
});
break;
default:
console.warn(`Action type ${action.type} unknown`, action);
@ -159,23 +163,33 @@ function reducer(previousState, action) {
return newState;
}
const initState = {
errors: {},
active: {
activeRoom: -1,
},
login: {
loggedIn: false,
token: null,
},
userInfo: null,
/** @type {[integer]Room} */
rooms: {},
/** @type {[integer]Device} */
devices: {},
};
function createSmartHutStore() {
const token = localStorage.getItem("token");
const exp = localStorage.getItem("exp");
const initialState = {
errors: {},
const initialState = update(initState, {
login: {
token: token,
token: { $set: token },
loggedIn: { $set: !!(token && exp > new Date().getTime()) },
},
userInfo: null,
/** @type {[integer]Room} */
rooms: {},
/** @type {[integer]Device} */
devices: {},
};
});
initialState.login.loggedIn = !!(token && exp > new Date().getTime());
if (!initialState.login.loggedIn) {
localStorage.removeItem("token");
localStorage.removeItem("exp");

View File

@ -33,4 +33,12 @@ const actions = {
}),
};
export const appActions = {
// -1 for home view
setActiveRoom: (activeRoom = -1) => ({
type: "SET_ACTIVE_ROOM",
activeRoom,
}),
};
export default actions;

View File

@ -2,191 +2,9 @@ import React, { Component } from "react";
import DevicePanel from "../components/dashboard/DevicePanel";
import Navbar from "./Navbar";
import MyHeader from "../components/HeaderController";
import { call } from "../client_server";
import { Grid, Responsive } from "semantic-ui-react";
/*
rooms -> actual rooms
activeItem -> the current room in view
devices -> current device in current room view
id of Home is -1
*/
export default class Dashboard extends Component {
constructor(props) {
super(props);
this.state = {
rooms: [],
activeItem: -1,
devices: [],
image: "",
tkn: this.props.tkn,
};
this.addRoom = this.addRoom.bind(this);
this.deleteRoom = this.deleteRoom.bind(this);
this.updateRoom = this.updateRoom.bind(this);
this.addDevice = this.addDevice.bind(this);
this.handleItemClick = this.handleItemClick.bind(this);
}
getDevices() {
if (this.state.activeItem === -1) {
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) {
//console.log(res.data);
this.setState({
devices: res.data,
});
}
})
.catch((err) => {});
}
}
getRooms() {
call
.getAllRooms(this.props.tkn)
.then((res) => {
this.setState({
rooms: res.data,
});
})
.catch((err) => {});
}
componentDidMount() {
this.getRooms();
this.getDevices();
}
addRoom(data) {
call
.createRoom(data)
.then((res) => {
if (res.status === 200 && res.data) {
this.getRooms();
this.handleItemClick(-1);
}
})
.catch((err) => {
//console.log(err);
});
}
deleteRoom() {
let data = {
id: this.state.activeItem,
};
call
.deleteRoom(data)
.then((res) => {
//remove room in state.rooms
this.getRooms();
this.setState({
activeItem: -1,
});
this.handleItemClick(-1);
})
.catch((err) => {
//console.log(err);
});
}
updateRoom(data) {
data.id = this.state.activeItem;
call
.updateRoom(data)
.then((res) => {
if (res.status === 200 && res.data) {
this.getRooms();
this.forceUpdate();
}
})
.catch((err) => {});
}
handleItemClick(id) {
this.setState({
activeItem: id,
});
if (id === -1) {
call
.getAllDevices(this.props.tkn)
.then((res) => {
if (res.status === 200) {
this.setState({
devices: res.data,
});
}
})
.catch((err) => {
//console.log(err);
});
} else {
call
.getAllDevicesByRoom(id, this.props.tkn)
.then((res) => {
if (res.status === 200) {
this.setState({
devices: res.data,
});
this.forceUpdate();
}
})
.catch((err) => {
//console.log(err);
});
}
this.state.rooms.forEach((item) => {
if (item.id === id) {
this.setState({ room: item });
}
});
}
addDevice(data) {
data.params["roomId"] = this.state.activeItem;
call
.devicePost(data, this.props.tkn)
.then((res) => {
this.getDevices();
})
.catch((err) => {});
}
updateDeviceUi = (data) => {
let ds = this.state.devices;
ds.forEach((e) => {
if (e.id === data.id) {
e = data;
}
});
this.setState({
devices: ds,
});
return;
};
render() {
return (
<div style={{ height: "110vh", background: "#1b1c1d" }}>
@ -194,29 +12,16 @@ export default class Dashboard extends Component {
<Grid>
<Grid.Row color="black">
<Grid.Column>
<MyHeader logout={this.props.logout} />
<MyHeader />
</Grid.Column>
</Grid.Row>
<Grid.Row color="black">
<Grid.Column width={3}>
<Navbar
activeItem={this.state.activeItem}
addRoom={this.addRoom}
updateRoom={this.updateRoom}
deleteRoom={this.deleteRoom}
rooms={this.state.rooms}
handleItemClick={this.handleItemClick}
/>
<Navbar />
</Grid.Column>
<Grid.Column width={13}>
<DevicePanel
tkn={this.props.tkn}
activeItem={this.state.activeItem}
addDevice={this.addDevice}
devices={this.state.devices}
room={this.state.room}
/>
<DevicePanel />
</Grid.Column>
</Grid.Row>
</Grid>
@ -225,32 +30,17 @@ export default class Dashboard extends Component {
<Grid inverted>
<Grid.Row color="black">
<Grid.Column>
<MyHeader logout={this.props.logout} />
<MyHeader />
</Grid.Column>
</Grid.Row>
<Grid.Row color="black">
<Grid.Column color="black">
<Navbar
activeItem={this.state.activeItem}
addRoom={this.addRoom}
updateRoom={this.updateRoom}
deleteRoom={this.deleteRoom}
rooms={this.state.rooms}
handleItemClick={this.handleItemClick}
/>
<Navbar />
</Grid.Column>
</Grid.Row>
<Grid.Row>
<Grid.Column>
<DevicePanel
img={this.state.image}
tkn={this.props.tkn}
activeItem={this.state.activeItem}
addDevice={this.addDevice}
devices={this.state.devices}
updateDev={this.updateDeviceUi}
room={this.state.room}
/>
<DevicePanel />
</Grid.Column>
</Grid.Row>
</Grid>

View File

@ -9,45 +9,48 @@ import {
} from "semantic-ui-react";
import { editButtonStyle } from "../components/dashboard/devices/styleComponents";
import ModalWindow from "../components/modalform";
import { RemoteService } from "../remote";
import { connect } from "react-redux";
import { appActions } from "../storeActions";
class Navbar extends Component {
constructor(props) {
super(props);
this.state = {
activeItemName: "Home",
activeItem: -1,
edited: "",
editMode: false,
room: "",
};
this.roomRefs = {};
this.props.rooms.forEach((e) => {
this.roomRefs[e.id] = React.createRef();
});
this.toggleEditMode = this.toggleEditMode.bind(this);
this.selectRoom = this.selectRoom.bind(this);
this.getRooms();
}
componentDidMount() {
this.setState({
activeItem: this.props.activeItem,
});
getRooms() {
this.props.fetchAllRooms().catch(console.error);
}
editModeController = (e) =>
get activeItem() {
return this.props.activeRoom;
}
set activeItem(item) {
this.props.setActiveRoom(item);
}
get activeItemName() {
console.log(this.constructor);
if (this.props.activeRoom === -1) return "Home";
return this.props.rooms[this.props.activeRoom];
}
toggleEditMode(e) {
this.setState((prevState) => ({ editMode: !prevState.editMode }));
}
handleClick = (e, { id, name }) => {
const room = this.props.rooms.filter((d) => d.id === id)[0];
//console.log(room);
this.setState({
activeItem: id,
activeItemName: name,
});
this.activeRoom = room;
//console.log(this.activeRoom);
this.forceUpdate();
this.props.handleItemClick(id);
};
selectRoom(e, { id }) {
this.activeItem = id;
}
render() {
return (
@ -55,7 +58,7 @@ class Navbar extends Component {
<Responsive minWidth={768}>
<Grid>
<Grid.Row color="black">
<button style={editButtonStyle} onClick={this.editModeController}>
<button style={editButtonStyle} onClick={this.toggleEditMode}>
Edit
</button>
</Grid.Row>
@ -65,8 +68,8 @@ class Navbar extends Component {
key={-1}
id={-1}
name="Home"
active={this.state.activeItem === -1}
onClick={this.handleClick}
active={this.activeRoom === -1}
onClick={this.selectRoom}
>
<Grid>
<Grid.Row>
@ -78,46 +81,36 @@ class Navbar extends Component {
</Grid>
</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}
{Object.values(this.props.rooms).map((e, i) => {
return (
<Menu.Item
id={e.id}
key={i}
name={e.name}
active={this.activeRoom === e.id}
onClick={this.selectRoom}
>
<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.id} />
) : null}
</Grid.Column>
</Grid.Row>
</Grid>
</Menu.Item>
);
})}
<Menu.Item
name="newM"
active={this.state.activeItem === "newM"}
>
<Menu.Item name="newM">
<Grid>
<Grid.Row centered name="new">
<ModalWindow type="new" addRoom={this.props.addRoom} />
<ModalWindow type="new" />
</Grid.Row>
</Grid>
</Menu.Item>
@ -128,14 +121,14 @@ class Navbar extends Component {
<Responsive maxWidth={768}>
<Menu>
<Dropdown item fluid text={this.state.activeItemName}>
<Dropdown item fluid text={this.activeItemName}>
<Dropdown.Menu>
<Dropdown.Item
key={-1}
id={-1}
name="Home"
active={this.state.activeItem === "Home"}
onClick={this.handleClick}
active={this.activeRoom === -1}
onClick={this.selectRoom}
>
<Grid>
<Grid.Row>
@ -147,56 +140,38 @@ class Navbar extends Component {
</Grid>
</Dropdown.Item>
{this.props.rooms
? this.props.rooms.map((e, i) => {
if (!this.roomRefs[e.id])
this.roomRefs[e.id] = React.createRef();
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>
<ModalWindow
ref={this.roomRefs[e.id]}
type="modify"
nicolaStop={true}
idRoom={e}
updateRoom={this.props.updateRoom}
deleteRoom={this.props.deleteRoom}
/>
</Dropdown.Item>
);
})
: null}
{Object.values(this.props.rooms).map((e, i) => {
return (
<Dropdown.Item
id={e.id}
key={i}
name={e.name}
active={this.activeRoom === e.id}
onClick={this.selectRoom}
>
<Grid>
<Grid.Row>
<Grid.Column width={1}>
<Icon name={e.icon} size="small" />
</Grid.Column>
<Grid.Column>{e.name}</Grid.Column>
</Grid.Row>
</Grid>
<ModalWindow type="modify" nicolaStop={true} idRoom={e} />
</Dropdown.Item>
);
})}
</Dropdown.Menu>
</Dropdown>
</Menu>
<Grid inverted>
<Grid.Row>
<Grid.Column width={8}>
<ModalWindow type="new" addRoom={this.props.addRoom} />
<ModalWindow type="new" />
</Grid.Column>
{this.state.activeItem !== -1 ? (
{this.activeRoom !== -1 ? (
<Grid.Column width={8}>
<Button
icon
fluid
labelPosition="left"
onClick={() =>
this.roomRefs[this.state.activeItem].current.openModal()
}
>
<Button icon fluid labelPosition="left">
<Icon name="pencil" size="small" />
EDIT ROOM
</Button>
@ -210,4 +185,11 @@ class Navbar extends Component {
}
}
export default Navbar;
const mapDispatchToProps = (dispatch) => {
return {
setActiveRoom: (activeRoom) =>
dispatch(appActions.setActiveRoom(activeRoom)),
};
};
const NavbarContainer = connect(mapDispatchToProps, RemoteService)(Navbar);
export default NavbarContainer;