WIP on redux conversion for devices

This commit is contained in:
Claudio Maggioni 2020-04-10 17:25:52 +02:00
parent eead3694e6
commit 69a6cbae6d
16 changed files with 232 additions and 395 deletions

View File

@ -4,87 +4,32 @@ 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 Device from "./devices/Device";
import NewDevice from "./devices/NewDevice";
import SettingsModal from "./devices/SettingsModal";
import { connect } from "react-redux";
import { RemoteService } from "../../remote";
class DevicePanel extends Component {
constructor(props) {
super(props);
this.state = {
editMode: false,
};
this.addDevice = this.addDevice.bind(this);
this.toggleEditMode = this.toggleEditMode.bind(this);
this.getDevices();
}
toggleEditMode(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);
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];
}
}
};*/
getDevices() {
this.props.fetchDevices().then();
this.props
.fetchDevices()
.catch((err) => console.error(`error fetching devices:`, err));
}
render() {
const edit = {
mode: this.state.editMode,
openModal: this.openModal,
};
/*var backGroundImg =
this.props.activeItem === -1 ? "" : this.props.room.image;*/
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}
device={ds.filter((d) => d.id === this.state.settingsDeviceId)[0]}
/>
) : (
""
)}
{this.props.devices.map((e, i) => {
return (
<Grid.Column key={i}>
<DeviceType type={e.kind} device={e} edit={edit} />
<Device id={e.id} />
</Grid.Column>
);
})}
@ -110,7 +55,7 @@ const mapStateToProps = (state, _) => ({
}
},
get isActiveRoomHome() {
return this.props.activeRoom === -1;
return state.active.activeRoom === -1;
},
activeRoom: state.active.activeRoom,
});

View File

@ -0,0 +1,75 @@
import React from "react";
import Light from "./Light";
import SmartPlug from "./SmartPlug";
import Sensor from "./Sensor";
import { ButtonDimmer, KnobDimmer } from "./Dimmer";
import Switcher from "./Switch";
import { Segment } from "semantic-ui-react";
import { RemoteService } from "../../../remote";
import { connect } from "react-redux";
import DeviceSettingsModal from "./DeviceSettingsModal";
class Device extends React.Component {
constructor(props) {
super(props);
this.modalRef = React.createRef();
this.edit = this.edit.bind(this);
this.resetSmartPlug = this.resetSmartPlug.bind(this);
}
edit() {
console.log("editing device with id=" + this.props.id);
this.modalRef.current.openModal();
}
resetSmartPlug() {
this.props
.resetSmartPlug(this.props.id)
.catch((err) => console.error(`Smart plug reset error`, err));
}
renderDeviceComponent() {
switch (this.props.device.kind) {
case "regularLight":
return <Light id={this.props.id} />;
case "sensor":
return <Sensor id={this.props.id} />;
case "motionSensor":
return <Sensor id={this.props.id} />;
case "buttonDimmer":
return <ButtonDimmer id={this.props.id} />;
case "knobDimmer":
return <KnobDimmer id={this.props.id} />;
case "smartPlug":
return <SmartPlug id={this.props.id} />;
case "switch":
return <Switcher id={this.props.id} />;
case "dimmableLight":
return <Light id={this.props.id} />;
default:
throw new Error("Device type unknown");
}
}
render() {
return (
<Segment>
{this.renderDeviceComponent()}
<h3>{this.props.device.name}</h3>
<button onClick={this.edit}>Edit</button>
{this.props.device.type === "smartPlug" ? (
<button onClick={this.resetSmartPlug}></button>
) : null}
<DeviceSettingsModal ref={this.modalRef} id={this.props.id} />
</Segment>
);
}
}
const mapStateToProps = (state, ownProps) => ({
device: state.devices[ownProps.id],
});
const DeviceContainer = connect(mapStateToProps, RemoteService)(Device);
export default DeviceContainer;

View File

@ -1,26 +0,0 @@
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 }));
};
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>
);
return <React.Fragment>{this.props.edit.mode ? view : ""}</React.Fragment>;
}
}

View File

@ -1,5 +1,7 @@
import React, { Component, useState } from "react";
import { Button, Checkbox, Form, Icon, Header, Modal } from "semantic-ui-react";
import { Button, Form, Icon, Header, Modal } from "semantic-ui-react";
import { connect } from "react-redux";
import { RemoteService } from "../../../remote";
const DeleteModal = (props) => (
<Modal trigger={<Button color="red">Remove</Button>} closeIcon>
@ -21,11 +23,6 @@ const SettingsForm = (props) => {
setValues({ ...values, [name]: value });
};
const handleCheckboxChange = (e, d) => {
const { name, checked } = d;
setValues({ ...values, [name]: checked });
};
const [values, setValues] = useState({ name: "" });
return (
@ -41,18 +38,6 @@ const SettingsForm = (props) => {
/>
</Form.Field>
{props.type === "smart-plug" ? (
<Form.Field>
<Checkbox
slider
name={"reset"}
onClick={handleCheckboxChange}
label="Reset Energy Consumption"
/>
</Form.Field>
) : (
""
)}
<Form.Field>
<DeleteModal removeDevice={() => props.removeDevice(values)} />
</Form.Field>
@ -67,41 +52,56 @@ const SettingsForm = (props) => {
);
};
export default class SettingsModal extends Component {
class DeviceSettingsModal extends Component {
constructor(props) {
super(props);
this.state = {
open: true,
open: false,
};
this.updateDevice = this.updateDevice.bind(this);
this.deleteDevice = this.deleteDevice.bind(this);
}
handleClose = () => {
this.setState({ open: false });
};
openModal() {
this.setState({ open: true });
}
saveSettings = (device) => {
// TODO Here there should be all the connections to save the data in the backend
console.log("SAVED: ", device);
if (device.name.length > 0) {
this.props.updateDevice(device);
}
updateDevice(values) {
if (values.name.length === 0) return;
this.props
.saveDevice({ ...this.props.device, name: values.name })
.then(() => this.setState({ open: false }))
.catch((err) =>
console.error(
`settings modal for device ${this.props.id} deletion error`,
err
)
);
}
this.props.openModal();
};
deleteDevice() {
// closing is not needed (and actually harmful due to memory leaks)
// since this component will be deleted anyways
this.props
.deleteDevice(this.props.device)
.catch((err) =>
console.error(
`settings modal for device ${this.props.id} deletion error`,
err
)
);
}
render() {
const SettingsModal = () => (
<Modal
open={true}
onOpen={this.props.openModal}
onClose={this.props.openModal}
>
<Modal open={this.state.open}>
<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}
removeDevice={this.deleteDevice}
saveFunction={this.updateDevice}
/>
</Modal.Content>
</Modal>
@ -109,3 +109,14 @@ export default class SettingsModal extends Component {
return <SettingsModal />;
}
}
const mapStateToProps = (state, ownProps) => ({
device: state.devices[ownProps.id],
});
const DeviceSettingsModalContainer = connect(
mapStateToProps,
RemoteService,
null,
{ forwardRef: true }
)(DeviceSettingsModal);
export default DeviceSettingsModalContainer;

View File

@ -1,87 +0,0 @@
import React from "react";
import Light from "./Light";
import SmartPlug from "./SmartPlug";
import Sensor from "./Sensor";
import { ButtonDimmer, KnobDimmer } from "./Dimmer";
import Switcher from "./Switch";
const DeviceType = (props) => {
switch (props.type) {
case "regularLight":
return (
<Light
updateDev={props.updateDeviceUi}
onChangeData={props.changeDeviceData}
device={props.device}
edit={props.edit}
/>
);
case "sensor":
return (
<Sensor
updateDev={props.updateDeviceUi}
onChangeData={props.changeDeviceData}
device={props.device}
edit={props.edit}
/>
);
case "motionSensor":
return (
<Sensor
updateDev={props.updateDeviceUi}
onChangeData={props.changeDeviceData}
device={props.device}
edit={props.edit}
/>
);
case "buttonDimmer":
return (
<ButtonDimmer
updateDev={props.updateDeviceUi}
onChangeData={props.changeDeviceData}
device={props.device}
edit={props.edit}
/>
);
case "knobDimmer":
return (
<KnobDimmer
updateDev={props.updateDeviceUi}
onChangeData={props.changeDeviceData}
device={props.device}
edit={props.edit}
/>
);
case "smartPlug":
return (
<SmartPlug
updateDev={props.updateDeviceUi}
onChangeData={props.changeDeviceData}
device={props.device}
edit={props.edit}
/>
);
case "switch":
return (
<Switcher
updateDev={props.updateDeviceUi}
onChangeData={props.changeDeviceData}
device={props.device}
edit={props.edit}
/>
);
case "dimmableLight":
return (
<Light
updateDev={props.updateDeviceUi}
onChangeData={props.changeDeviceData}
device={props.device}
edit={props.edit}
/>
);
default:
return "";
}
};
export default DeviceType;

View File

@ -1,63 +0,0 @@
/**
* Users can add sensors in their rooms.
* Sensors typically measure physical quantities in a room.
* You must support temperature sensors, humidity sensors, light sensors (which measure luminosity1).
* Sensors have an internal state that cannot be changed by the user.
* 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 Settings from "./DeviceSettings";
import { Image } from "semantic-ui-react";
import { imageStyle, nameStyle } from "./DigitalSensorStyle";
export default class DigitalSensor extends Component {
constructor(props) {
super(props);
this.state = {
value: false, // This value is a boolean, was this type of sensor returns presence/absence
};
this.iconOn = "/img/sensorOn.svg";
this.iconOff = "/img/sensorOff.svg";
}
setName = () => {
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) {
return this.iconOn;
}
return this.iconOff;
};
componentDidMount() {}
render() {
return (
<StyledDiv>
<Settings
deviceId={this.props.device.id}
edit={this.props.edit}
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

@ -1,17 +0,0 @@
export const imageStyle = {
width: "3.5rem",
height: "auto",
position: "absolute",
top: "20%",
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: "40%",
left: "50%",
transform: "translateX(-50%)",
};

View File

@ -19,7 +19,6 @@ import {
PlusPanel,
ThumbText,
} from "./styleComponents";
import Settings from "./DeviceSettings";
import {
CircularThumbStyle,
KnobDimmerStyle,
@ -28,10 +27,11 @@ import {
knobIcon,
knobContainer,
} from "./DimmerStyle";
import { RemoteService } from "../../../remote";
import { connect } from "react-redux";
import { call } from "../../../client_server";
export class ButtonDimmer extends Component {
export class ButtonDimmerComponent extends Component {
constructor(props) {
super(props);
this.state = {};
@ -63,13 +63,6 @@ export class ButtonDimmer extends Component {
render() {
return (
<ButtonDimmerContainer>
<Settings
deviceId={this.props.device.id}
edit={this.props.edit}
onChangeData={(id, newSettings) =>
this.props.onChangeData(id, newSettings)
}
/>
<img alt="icon" src="/img/buttonDimmer.svg" />
<span className="knob">
{this.props.device.name} ({this.props.device.id})
@ -85,7 +78,7 @@ export class ButtonDimmer extends Component {
}
}
export class KnobDimmer extends Component {
export class KnobDimmerComponent extends Component {
constructor(props) {
super(props);
this.state = {
@ -118,13 +111,6 @@ export class KnobDimmer extends Component {
render() {
return (
<div style={knobContainer}>
<Settings
deviceId={this.props.device.id}
edit={this.props.edit}
onChangeData={(id, newSettings) =>
this.props.onChangeData(id, newSettings)
}
/>
<CircularInput
style={KnobDimmerStyle}
value={+(Math.round(this.state.value / 100 + "e+2") + "e-2")}
@ -151,3 +137,11 @@ export class KnobDimmer extends Component {
);
}
}
const mapStateToProps = (state, ownProps) => ({
device: state.devices[ownProps.id],
});
const conn = connect(mapStateToProps, RemoteService);
export const KnobDimmer = conn(KnobDimmerComponent);
export const ButtonDimmer = conn(ButtonDimmerComponent);

View File

@ -15,7 +15,6 @@ import {
BottomPanel,
ThumbText,
} from "./styleComponents";
import Settings from "./DeviceSettings";
import { Image } from "semantic-ui-react";
import {
CircularInput,
@ -32,8 +31,10 @@ import {
knobIcon,
} from "./LightStyle";
import { call } from "../../../client_server";
import { RemoteService } from "../../../remote";
import { connect } from "react-redux";
export default class Light extends Component {
class Light extends Component {
constructor(props) {
super(props);
this.state = {
@ -52,7 +53,7 @@ export default class Light extends Component {
);
};
call.socketSubscribe(this.props.device.id, this.stateCallback);
// call.socketSubscribe(this.props.device.id, this.stateCallback);
}
onClickDevice = () => {
@ -91,13 +92,6 @@ export default class Light extends Component {
render() {
const intensityLightView = (
<div style={LightDimmerContainer}>
<Settings
deviceId={this.props.device.id}
edit={this.props.edit}
onChangeData={(id, newSettings) =>
this.props.onChangeData(id, newSettings)
}
/>
<CircularInput
style={LightDimmerStyle}
value={+(Math.round(this.intensity / 100 + "e+2") + "e-2")}
@ -128,14 +122,7 @@ export default class Light extends Component {
const normalLightView = (
<StyledDiv>
<Settings
deviceId={this.props.device.id}
edit={this.props.edit}
onChangeData={(id, newSettings) =>
this.props.onChangeData(id, newSettings)
}
/>
<div onClick={this.props.edit.mode ? () => {} : this.onClickDevice}>
<div onClick={this.onClickDevice}>
<Image src={this.getIcon()} style={iconStyle} />
<BottomPanel style={{ backgroundColor: "#ffa41b" }}>
<h5 style={nameStyle}>
@ -155,3 +142,9 @@ export default class Light extends Component {
);
}
}
const mapStateToProps = (state, ownProps) => ({
device: state.devices[ownProps.id],
});
const LightContainer = connect(mapStateToProps, RemoteService)(Light);
export default LightContainer;

View File

@ -35,11 +35,12 @@ import {
humiditySensorColors,
iconSensorStyle,
} from "./SensorStyle";
import Settings from "./DeviceSettings";
import { call } from "../../../client_server";
import { Image } from "semantic-ui-react";
import { RemoteService } from "../../../remote";
import { connect } from "react-redux";
export default class Sensor extends Component {
class Sensor extends Component {
constructor(props) {
super(props);
this.state = {
@ -131,13 +132,6 @@ export default class Sensor extends Component {
return (
<div style={container}>
<Settings
deviceId={this.props.device.id}
edit={this.props.edit}
onChangeData={(id, newSettings) =>
this.props.onChangeData(id, newSettings)
}
/>
{this.state.motion ? (
<MotionSensor />
) : (
@ -185,3 +179,9 @@ export default class Sensor extends Component {
);
}
}
const mapStateToProps = (state, ownProps) => ({
device: state.devices[ownProps.id],
});
const SensorContainer = connect(mapStateToProps, RemoteService)(Sensor);
export default SensorContainer;

View File

@ -11,7 +11,6 @@ import {
editModeIconStyle,
editModeStyleLeft,
} from "./styleComponents";
import Settings from "./DeviceSettings";
import { Image } from "semantic-ui-react";
import {
energyConsumedStyle,
@ -20,8 +19,10 @@ import {
nameStyle,
} from "./SmartPlugStyle";
import { call } from "../../../client_server";
import { RemoteService } from "../../../remote";
import { connect } from "react-redux";
export default class SmartPlug extends Component {
class SmartPlug extends Component {
constructor(props) {
super(props);
this.state = {
@ -81,21 +82,7 @@ export default class SmartPlug extends Component {
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)
}
/>
{this.props.edit.mode ? (
<span style={editModeStyleLeft} onClick={this.resetSmartPlug}>
<img src="/img/refresh.svg" alt="" style={editModeIconStyle} />
</span>
) : (
""
)}
<StyledDiv onClick={this.onClickDevice}>
<Image src={this.getIcon()} style={imageStyle} />
<span style={nameStyle}>
{this.props.device.name} ({this.props.device.id})
@ -115,3 +102,9 @@ export default class SmartPlug extends Component {
);
}
}
const mapStateToProps = (state, ownProps) => ({
device: state.devices[ownProps.id],
});
const SmartPlugContainer = connect(mapStateToProps, RemoteService)(SmartPlug);
export default SmartPlugContainer;

View File

@ -7,12 +7,13 @@
import React, { Component } from "react";
import { BottomPanel, StyledDiv } from "./styleComponents";
import Settings from "./DeviceSettings";
import { Image } from "semantic-ui-react";
import { imageStyle, nameStyle, turnedOnStyle } from "./SwitchStyle";
import { call } from "../../../client_server";
import { RemoteService } from "../../../remote";
import { connect } from "react-redux";
export default class Switch extends Component {
class Switch extends Component {
constructor(props) {
super(props);
this.state = {
@ -57,15 +58,7 @@ export default class Switch extends Component {
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)
}
/>
<StyledDiv onClick={this.onClickDevice}>
<Image src={this.getIcon()} style={imageStyle} />
<span style={nameStyle}>
{this.props.device.name} ({this.props.device.id})
@ -86,3 +79,9 @@ export default class Switch extends Component {
);
}
}
const mapStateToProps = (state, ownProps) => ({
device: state.devices[ownProps.id],
});
const SwitchContainer = connect(mapStateToProps, RemoteService)(Switch);
export default SwitchContainer;

View File

@ -60,7 +60,7 @@ const Endpoint = {
Authorization: `Bearer ${Endpoint.token}`,
},
}).then((res) => {
if (!res.data) {
if (!res.data && method != "delete") {
console.error("Response body is empty");
return null;
} else {
@ -294,7 +294,7 @@ export const RemoteService = {
}
return Endpoint[data.id ? "put" : "post"](url, {}, data)
.then((res) => void dispatch(actions.deviceUpdate(res.data)))
.then((res) => void dispatch(actions.deviceSave(res.data)))
.catch((err) => {
console.warn("Update device: ", data, "error: ", err);
throw new RemoteError(["Network error"]);
@ -396,7 +396,7 @@ export const RemoteService = {
*/
deleteRoom: (roomId) => {
return (dispatch) => {
Endpoint.delete(`/room/${roomId}`)
return Endpoint.delete(`/room/${roomId}`)
.then((_) => dispatch(actions.roomDelete(roomId)))
.catch((err) => {
console.warn("Room deletion error", err);
@ -407,14 +407,14 @@ export const RemoteService = {
/**
* Deletes a device
* @param {Number} deviceId the id of the device to delete
* @param {Device} device the device to delete
* @returns {Promise<Undefined, RemoteError>} promise that resolves to void and rejects
* with user-fiendly errors as a RemoteError
*/
deleteDevice: (deviceId) => {
deleteDevice: (device) => {
return (dispatch) => {
Endpoint.delete(`/device/${deviceId}`)
.then((_) => dispatch(actions.deviceDelete(deviceId)))
return Endpoint.delete(`/${device.kind}/${device.id}`)
.then((_) => dispatch(actions.deviceDelete(device.id)))
.catch((err) => {
console.warn("Device deletion error", err);
throw new RemoteError(["Network error"]);

View File

@ -1,14 +1,14 @@
import { createStore, applyMiddleware } from "redux";
import thunk from "redux-thunk";
import actions from "./storeActions";
import action from "./storeActions";
import update from "immutability-helper";
function reducer(previousState, action) {
let newState;
const createOrUpdateRoom = (room) => {
if (!(room.id in newState.rooms)) {
if (!newState.rooms[room.id]) {
newState = update(newState, {
rooms: { [room.id]: { devices: { $set: new Set() } } },
rooms: { [room.id]: { $set: { ...room, devices: new Set() } } },
});
} else {
newState = update(newState, {
@ -78,7 +78,7 @@ function reducer(previousState, action) {
rooms: {},
};
for (const room of newState.rooms) {
for (const room of Object.values(previousState.rooms)) {
change.rooms[room.id].devices = { $set: new Set() };
}
}
@ -109,9 +109,14 @@ function reducer(previousState, action) {
case "ROOM_SAVE":
createOrUpdateRoom(action.room);
break;
case "DEVICE_SAVE":
newState = update(previousState, {
devices: { [action.device.id]: { $set: action.device } },
});
break;
case "ROOM_DELETE":
if (!(actions.roomId in previousState.rooms)) {
console.warn(`Room to delete ${actions.roomId} does not exist`);
if (!(action.roomId in previousState.rooms)) {
console.warn(`Room to delete ${action.roomId} does not exist`);
break;
}
@ -124,23 +129,28 @@ function reducer(previousState, action) {
change.devices.$unset.push(id);
}
change.rooms = { $unset: actions.roomId };
change.rooms = { $unset: [action.roomId] };
newState = update(previousState, change);
break;
case "DEVICE_DELETE":
if (!(actions.deviceId in previousState.devices)) {
console.warn(`Device to delete ${actions.deviceId} does not exist`);
if (!(action.deviceId in previousState.devices)) {
console.warn(`Device to delete ${action.deviceId} does not exist`);
break;
}
newState = update(previousState, {
devices: { $unset: actions.deviceId },
rooms: {
[previousState.devices[actions.deviceId].roomId]: {
devices: { $remove: actions.deviceId },
change = {
devices: { $unset: [action.deviceId] },
};
if (previousState.rooms[previousState.devices[action.deviceId].roomId]) {
change.rooms = {
[previousState.devices[action.deviceId].roomId]: {
devices: { $remove: [action.deviceId] },
},
},
});
};
}
newState = update(previousState, change);
break;
case "LOGOUT":
newState = update(initState, {});
@ -149,7 +159,7 @@ function reducer(previousState, action) {
newState = update(previousState, {
active: {
activeRoom: {
$set: actions.activeRoom,
$set: action.activeRoom,
},
},
});

View File

@ -17,12 +17,20 @@ const actions = {
type: "ROOM_SAVE",
room,
}),
deviceSave: (device) => ({
type: "DEVICE_SAVE",
device,
}),
devicesUpdate: (roomId, devices, partial = false) => ({
type: "DEVICES_UPDATE",
roomId,
devices,
partial,
}),
roomsUpdate: (rooms) => ({
type: "ROOMS_UPDATE",
rooms,
}),
roomDelete: (roomId) => ({
type: "ROOM_DELETE",
roomId,

View File

@ -185,11 +185,13 @@ class Navbar extends Component {
}
}
const mapDispatchToProps = (dispatch) => {
return {
setActiveRoom: (activeRoom) =>
dispatch(appActions.setActiveRoom(activeRoom)),
};
const setActiveRoom = (dispatch) => {
return (activeRoom) => dispatch(appActions.setActiveRoom(activeRoom));
};
const NavbarContainer = connect(mapDispatchToProps, RemoteService)(Navbar);
const mapStateToProps = (state, _) => ({ rooms: state.rooms });
const NavbarContainer = connect(mapStateToProps, {
...RemoteService,
setActiveRoom,
})(Navbar);
export default NavbarContainer;