Refactor redux almost complete

This commit is contained in:
britea 2020-04-11 18:29:32 +02:00
parent ed68bebe8e
commit b60a050a70
9 changed files with 232 additions and 133 deletions

View file

@ -20,9 +20,6 @@ const TitleImage = () => <Image src="sm_logo.png" size="medium" centered />;
export class MyHeader extends React.Component { export class MyHeader extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = {
username: "",
};
this.getInfo(); this.getInfo();
this.logout = this.logout.bind(this); this.logout = this.logout.bind(this);
@ -57,7 +54,7 @@ export class MyHeader extends React.Component {
<Grid.Column width={2} heigth={1}> <Grid.Column width={2} heigth={1}>
<Label as="a" image color="black"> <Label as="a" image color="black">
<img alt="SmartHut logo" src="smart-home.png" /> <img alt="SmartHut logo" src="smart-home.png" />
{this.state.username} {this.props.username}
</Label> </Label>
<Divider /> <Divider />
<Button onClick={this.logout}>Logout</Button> <Button onClick={this.logout}>Logout</Button>
@ -79,10 +76,10 @@ export class MyHeader extends React.Component {
<Grid.Column> <Grid.Column>
<Label as="a" image color="black"> <Label as="a" image color="black">
<img alt="SmartHut logo" src="smart-home.png" /> <img alt="SmartHut logo" src="smart-home.png" />
{this.state.username} {this.props.username}
</Label> </Label>
<Divider /> <Divider />
<Button onClick={this.props.logout}>Logout</Button> <Button onClick={this.logout}>Logout</Button>
</Grid.Column> </Grid.Column>
</Grid.Row> </Grid.Row>
</Grid> </Grid>

View file

@ -32,7 +32,7 @@ class RoomModal extends Component {
get initialState() { get initialState() {
return { return {
selectedIcon: "home", selectedIcon: this.type === "new" ? "home" : this.props.room.icon,
name: this.type === "new" ? "New Room" : this.props.room.name, name: this.type === "new" ? "New Room" : this.props.room.name,
img: this.type === "new" ? null : this.props.room.image, img: this.type === "new" ? null : this.props.room.image,
openModal: false, openModal: false,
@ -41,9 +41,11 @@ class RoomModal extends Component {
removeImage(e) { removeImage(e) {
e.preventDefault(); e.preventDefault();
this.setState(update(this.state, { this.setState(
image: {$set: NO_IMAGE} update(this.state, {
})); image: { $set: null },
})
);
} }
setInitialState() { setInitialState() {
@ -61,36 +63,38 @@ class RoomModal extends Component {
image: this.state.img, image: this.state.img,
}; };
this.props.saveRoom(data, null) this.props
.saveRoom(data, null)
.then(() => { .then(() => {
this.setInitialState(); this.setInitialState();
this.closeModal(); this.closeModal();
}) })
.catch((err) => console.error('error in creating room', err)); .catch((err) => console.error("error in creating room", err));
}; };
modifyRoomModal = (e) => { modifyRoomModal = (e) => {
let data = { let data = {
icon: icon: this.state.selectedIcon,
this.state.selectedIcon === "" name: this.state.name,
? this.props.room.icon
: this.state.selectedIcon,
name: this.state.name === "" ? this.props.room.name : this.state.name,
image: this.state.img, image: this.state.img,
}; };
this.props.saveRoom(data, this.props.id) console.log("data", data);
this.props
.saveRoom(data, this.props.id)
.then(() => { .then(() => {
this.setInitialState(); this.setInitialState();
this.closeModal(); this.closeModal();
}) })
.catch((err) => console.error('error in updating room', err)); .catch((err) => console.error("error in updating room", err));
}; };
deleteRoom = (e) => { deleteRoom = (e) => {
// no need to close modal since this room modal instance will be deleted this.props
this.props.deleteRoom(this.props.id) .deleteRoom(this.props.id)
.catch((err) => console.error('error in deleting room', err)); .then(() => this.closeModal())
.catch((err) => console.error("error in deleting room", err));
}; };
changeSomething = (event) => { changeSomething = (event) => {
@ -101,7 +105,6 @@ class RoomModal extends Component {
closeModal = (e) => { closeModal = (e) => {
this.setState({ openModal: false }); this.setState({ openModal: false });
this.updateIcon("home");
}; };
openModal = (e) => { openModal = (e) => {
@ -172,7 +175,7 @@ class RoomModal extends Component {
</div> </div>
) : null} ) : null}
<Modal onClose={this.closeModal} open={this.state.openModal}> <Modal closeIcon onClose={this.closeModal} open={this.state.openModal}>
<Header> <Header>
{this.type === "new" ? "Add new room" : "Modify room"} {this.type === "new" ? "Add new room" : "Modify room"}
</Header> </Header>
@ -192,7 +195,7 @@ class RoomModal extends Component {
<p>Insert an image of the room:</p> <p>Insert an image of the room:</p>
<Form.Field> <Form.Field>
<Image <Image
src={this.state.img === null ? NO_IMAGE : this.state.img} src={!this.state.img ? NO_IMAGE : this.state.img}
size="small" size="small"
onClick={() => this.fileInputRef.current.click()} onClick={() => this.fileInputRef.current.click()}
/> />
@ -207,9 +210,9 @@ class RoomModal extends Component {
onChange={this.getBase64.bind(this)} onChange={this.getBase64.bind(this)}
/> />
</Form.Field> </Form.Field>
{this.state.img ? {this.state.img ? (
<Button onClick={this.unsetImage}>Remove image</Button> <Button onClick={this.unsetImage}>Remove image</Button>
: null } ) : null}
</Form> </Form>
<div style={spaceDiv}> <div style={spaceDiv}>
@ -244,9 +247,7 @@ class RoomModal extends Component {
<Button <Button
color="green" color="green"
onClick={ onClick={
this.type === "new" this.type === "new" ? this.addRoomModal : this.modifyRoomModal
? this.addRoomModal
: this.modifyRoomModal
} }
> >
<Icon name="checkmark" />{" "} <Icon name="checkmark" />{" "}
@ -264,7 +265,7 @@ const setActiveRoom = (activeRoom) => {
}; };
const mapStateToProps = (state, ownProps) => ({ const mapStateToProps = (state, ownProps) => ({
room: ownProps.id ? state.rooms[ownProps.id] : null room: ownProps.id ? state.rooms[ownProps.id] : null,
}); });
const RoomModalContainer = connect( const RoomModalContainer = connect(
mapStateToProps, mapStateToProps,

View file

@ -81,10 +81,9 @@ class DeviceSettingsModal extends Component {
} }
deleteDevice() { deleteDevice() {
// closing is not needed (and actually harmful due to memory leaks)
// since this component will be deleted anyways
this.props this.props
.deleteDevice(this.props.device) .deleteDevice(this.props.device)
.then(() => this.setState({ open: false }))
.catch((err) => .catch((err) =>
console.error( console.error(
`settings modal for device ${this.props.id} deletion error`, `settings modal for device ${this.props.id} deletion error`,

View file

@ -31,24 +31,23 @@ import { RemoteService } from "../../../remote";
import { connect } from "react-redux"; import { connect } from "react-redux";
export class ButtonDimmerComponent extends Component { export class ButtonDimmerComponent extends Component {
increaseIntensity = () => { increaseIntensity = () => {
this.props.device.buttonDimmerDim(this.props.id, "UP") this.props
.catch((err) => console.error('button dimmer increase error', err)); .buttonDimmerDim(this.props.id, "UP")
.catch((err) => console.error("button dimmer increase error", err));
}; };
decreaseIntensity = () => { decreaseIntensity = () => {
this.props.device.buttonDimmerDim(this.props.id, "DOWN") this.props
.catch((err) => console.error('button dimmer decrease error', err)); .buttonDimmerDim(this.props.id, "DOWN")
.catch((err) => console.error("button dimmer decrease error", err));
}; };
render() { render() {
return ( return (
<ButtonDimmerContainer> <ButtonDimmerContainer>
<img alt="icon" src="/img/buttonDimmer.svg" /> <img alt="icon" src="/img/buttonDimmer.svg" />
<span className="knob"> <span className="knob">Button Dimmer</span>
Button Dimmer
</span>
<PlusPanel name="UP" onClick={this.increaseIntensity}> <PlusPanel name="UP" onClick={this.increaseIntensity}>
<span>&#43;</span> <span>&#43;</span>
</PlusPanel> </PlusPanel>
@ -61,19 +60,23 @@ export class ButtonDimmerComponent extends Component {
} }
export class KnobDimmerComponent extends Component { export class KnobDimmerComponent extends Component {
setIntensity = (newValue) => { setIntensity = (newValue) => {
const val = Math.round(newValue * 100); const val = Math.round(newValue * 100);
this.props.device.knobDimmerDimTok(this.props.id, val) this.props
.catch((err) => console.error('knob dimmer set intensity error', err)); .knobDimmerDimTo(this.props.id, val)
.catch((err) => console.error("knob dimmer set intensity error", err));
}; };
get intensity() {
return this.props.device.intensity || 0;
}
render() { render() {
return ( return (
<div style={knobContainer}> <div style={knobContainer}>
<CircularInput <CircularInput
style={KnobDimmerStyle} style={KnobDimmerStyle}
value={+(Math.round(this.props.device.intensity / 100 + "e+2") + "e-2")} value={+(Math.round(this.intensity / 100 + "e+2") + "e-2")}
onChange={this.setIntensity} onChange={this.setIntensity}
> >
<text <text
@ -87,7 +90,7 @@ export class KnobDimmerComponent extends Component {
Knob Dimmer Knob Dimmer
</text> </text>
<CircularProgress <CircularProgress
style={{ ...KnobProgress, opacity: this.props.device.intensity + 0.1 }} style={{ ...KnobProgress, opacity: this.intensity + 0.1 }}
/> />
<CircularThumb style={CircularThumbStyle} /> <CircularThumb style={CircularThumbStyle} />
<ThumbText color={"#1a2849"} /> <ThumbText color={"#1a2849"} />

View file

@ -45,13 +45,14 @@ class Light extends Component {
} }
get intensity() { get intensity() {
return this.props.device.intensity; return this.props.device.intensity || 0;
} }
onClickDevice = () => { onClickDevice = () => {
this.props.device.on = !this.turnedOn; const on = !this.turnedOn;
this.props.saveDevice({ ...this.props.device, on: !this.turnedOn }) this.props
.catch((err) => console.error('regular light update error', err)) .saveDevice({ ...this.props.device, on })
.catch((err) => console.error("regular light update error", err));
}; };
getIcon = () => { getIcon = () => {
@ -60,8 +61,9 @@ class Light extends Component {
setIntensity = (newValue) => { setIntensity = (newValue) => {
const intensity = Math.round(newValue * 100); const intensity = Math.round(newValue * 100);
this.props.saveDevice({ ...this.props.device, intensity }) this.props
.catch((err) => console.error('intensity light update error', err)) .saveDevice({ ...this.props.device, intensity })
.catch((err) => console.error("intensity light update error", err));
}; };
render() { render() {
@ -100,9 +102,7 @@ class Light extends Component {
<div onClick={this.onClickDevice}> <div onClick={this.onClickDevice}>
<Image src={this.getIcon()} style={iconStyle} /> <Image src={this.getIcon()} style={iconStyle} />
<BottomPanel style={{ backgroundColor: "#ffa41b" }}> <BottomPanel style={{ backgroundColor: "#ffa41b" }}>
<h5 style={nameStyle}> <h5 style={nameStyle}>Light</h5>
Light
</h5>
</BottomPanel> </BottomPanel>
</div> </div>
</StyledDiv> </StyledDiv>

View file

@ -88,65 +88,58 @@ class NewDevice extends Component {
this.setState({ lightsAttached: d.value }); this.setState({ lightsAttached: d.value });
}; };
createDevice() { async createDevice() {
// Connect to the backend and create device here. // Connect to the backend and create device here.
const data = { const data = {
params: { id: null,
roomId: this.props.activeRoom,
name: this.state.deviceName, name: this.state.deviceName,
}, kind: this.state.motion ? "motionSensor" : this.state.typeOfDevice,
device: this.state.motion ? "motionSensor" : this.state.typeOfDevice, };
let outputs = null;
const defaultNames = {
regularLight: "New regular light",
dimmableLight: "New intensity light",
smartPlug: "New smart Plug",
sensor: "New sensor",
switch: "New switch",
buttonDimmer: "New button dimmer",
knobDimmer: "New knob dimmer",
}; };
if (this.state.deviceName === "") {
data.name = defaultNames[this.state.typeOfDevice];
}
switch (this.state.typeOfDevice) { switch (this.state.typeOfDevice) {
case "regularLight":
if (this.state.deviceName === "") {
data.params["name"] = "Regular Light";
}
break;
case "smartPlug":
if (this.state.deviceName === "") {
data.params["name"] = "Smart Plug";
}
break;
case "dimmableLight": case "dimmableLight":
if (this.state.deviceName === "") { data.intensity = 0;
data.params["name"] = "Dimmable Light";
}
data.params["intensity"] = 0;
break; break;
case "sensor": case "sensor":
if (this.state.deviceName === "") {
data.params["name"] = "Sensor";
}
if (!this.state.motion) { if (!this.state.motion) {
data.params["sensor"] = this.state.typeOfSensor; data.sensor = this.state.typeOfSensor;
data.params["value"] = 0; data.value = 0;
} }
break; break;
case "switch": case "switch":
if (this.state.deviceName === "") {
data.params["name"] = "Switch";
}
data.params["lights"] = this.state.lightsAttached;
break;
case "buttonDimmer": case "buttonDimmer":
if (this.state.deviceName === "") {
data.params["name"] = "Button Dimmer";
}
data.params["lights"] = this.state.lightsAttached;
break;
case "knobDimmer": case "knobDimmer":
if (this.state.deviceName === "") { outputs = this.state.lightsAttached;
data.params["name"] = "Knob Dimmer";
}
data.params["lights"] = this.state.lightsAttached;
break; break;
default: default:
break; break;
} }
this.props.addDevice(data); try {
let newDevice = await this.props.saveDevice(data);
if (outputs) {
await this.props.connectOutputs(newDevice, outputs);
}
this.resetState(); this.resetState();
} catch (e) {
console.error("device creation error: ", e);
}
} }
render() { render() {
@ -380,10 +373,8 @@ class NewDevice extends Component {
} }
const mapStateToProps = (state, _) => ({ const mapStateToProps = (state, _) => ({
devices: Object.values(state.devices) devices: Object.values(state.devices),
activeRoom: state.active.activeRoom,
}); });
const NewDeviceContainer = connect( const NewDeviceContainer = connect(mapStateToProps, RemoteService)(NewDevice);
mapStateToProps,
RemoteService
)(NewDevice);
export default NewDeviceContainer; export default NewDeviceContainer;

View file

@ -11,7 +11,7 @@ class RemoteError extends Error {
messages; messages;
constructor(messages) { constructor(messages) {
super("remote error"); super(messages.join(" - "));
this.messages = messages; this.messages = messages;
} }
} }
@ -283,7 +283,7 @@ export const RemoteService = {
* is used for updates and the POST "/<device.kind>" * is used for updates and the POST "/<device.kind>"
* endpoints are used for creation. * endpoints are used for creation.
* @param {Device} data the device to update. * @param {Device} data the device to update.
* @returns {Promise<Undefined, RemoteError>} promise that resolves to void and rejects * @returns {Promise<Device, RemoteError>} promise that resolves to the saved device and rejects
* with user-fiendly errors as a RemoteError * with user-fiendly errors as a RemoteError
*/ */
saveDevice: (data) => { saveDevice: (data) => {
@ -294,7 +294,10 @@ export const RemoteService = {
} }
return Endpoint[data.id ? "put" : "post"](url, {}, data) return Endpoint[data.id ? "put" : "post"](url, {}, data)
.then((res) => void dispatch(actions.deviceSave(res.data))) .then((res) => {
dispatch(actions.deviceSave(res.data));
return res.data;
})
.catch((err) => { .catch((err) => {
console.warn("Update device: ", data, "error: ", err); console.warn("Update device: ", data, "error: ", err);
throw new RemoteError(["Network error"]); throw new RemoteError(["Network error"]);
@ -302,13 +305,51 @@ export const RemoteService = {
}; };
}, },
/**
* Connetcs a series of output devices to an input device.
* Output devices for Switch input can be: Normal Light, Dimmable Light, Smart Plug.
* Output devices for Dimmers input can be: Dimmable Light.
*
* @typedef {"switch" | "buttonDimmer" | "knobDimmer"} ConnectableInput
*
* @param {ConnectableInput} newDevice.kind kind of the input device
* @param {Integer} newDevice.id id of the input device
* @param {Integer[]} outputs ids of the output device
* @returns {Promise<Undefined, RemoteError>} promise that resolves to void and rejects
* with user-fiendly errors as a RemoteError
*/
connectOutputs: (newDevice, outputs) => {
return (dispatch) => {
let url = `/${newDevice.kind}/${newDevice.id}/lights`;
return Endpoint.post(url, {}, outputs)
.then((res) => {
dispatch(actions.deviceOperationUpdate(res.data));
return res.data;
})
.catch((err) => {
console.warn(
"ConnectOutputs of ",
newDevice.id,
" with outputs: ",
outputs,
"error: ",
err
);
throw new RemoteError(["Network error"]);
});
};
},
_operateInput: (url, getUrl, action) => { _operateInput: (url, getUrl, action) => {
return (dispatch) => { return (dispatch) => {
return Endpoint.put(url, {}, action) return Endpoint.put(url, {}, action)
.then(async (res) => { .then(async (res) => {
const inputDevice = await Endpoint.get(getUrl); const inputDevice = await Endpoint.get(getUrl);
delete inputDevice.outputs; delete inputDevice.outputs;
dispatch(actions.deviceOperationUpdate([...res.data, inputDevice.data])); dispatch(
actions.deviceOperationUpdate([...res.data, inputDevice.data])
);
}) })
.catch((err) => { .catch((err) => {
console.warn(`${url} error`, err); console.warn(`${url} error`, err);
@ -328,10 +369,14 @@ export const RemoteService = {
* with user-fiendly errors as a RemoteError * with user-fiendly errors as a RemoteError
*/ */
switchOperate: (switchId, type) => { switchOperate: (switchId, type) => {
return RemoteService._operateInput("/switch/operate", `/switch/${switchId}`, { return RemoteService._operateInput(
"/switch/operate",
`/switch/${switchId}`,
{
type: type.toUpperCase(), type: type.toUpperCase(),
id: switchId, id: switchId,
}); }
);
}, },
/** /**
@ -343,10 +388,14 @@ export const RemoteService = {
* with user-fiendly errors as a RemoteError * with user-fiendly errors as a RemoteError
*/ */
knobDimmerDimTo: (dimmerId, intensity) => { knobDimmerDimTo: (dimmerId, intensity) => {
return RemoteService._operateInput("/knobDimmer/dimTo", `/knobDimmer/${dimmerId}`, { return RemoteService._operateInput(
"/knobDimmer/dimTo",
`/knobDimmer/${dimmerId}`,
{
intensity, intensity,
id: dimmerId, id: dimmerId,
}); }
);
}, },
/** /**

View file

@ -3,7 +3,8 @@ import thunk from "redux-thunk";
import update from "immutability-helper"; import update from "immutability-helper";
function reducer(previousState, action) { function reducer(previousState, action) {
let newState; let newState, change;
const createOrUpdateRoom = (room) => { const createOrUpdateRoom = (room) => {
if (!newState.rooms[room.id]) { if (!newState.rooms[room.id]) {
newState = update(newState, { newState = update(newState, {
@ -35,13 +36,24 @@ function reducer(previousState, action) {
} }
}; };
let change; const updateDeviceProps = (device) => {
// In some updates the information regarding a device is incomplete
// due to a fault in the type system and JPA repository management
// in the backend. Therefore to solve this avoid to delete existing
// attributes of this device in the previous state, but just update
// the new ones.
change.devices[device.id] = {};
for (const key in device) {
change.devices[device.id][key] = { $set: device[key] };
}
};
switch (action.type) { switch (action.type) {
case "LOGIN_UPDATE": case "LOGIN_UPDATE":
newState = update(previousState, { login: { $set: action.login } }); newState = update(previousState, { login: { $set: action.login } });
break; break;
case "USER_INFO_UPDATE": case "USER_INFO_UPDATE":
newState = update(previousState, { userInfo: { $set: action.user } }); newState = update(previousState, { userInfo: { $set: action.userInfo } });
break; break;
case "ROOMS_UPDATE": case "ROOMS_UPDATE":
newState = previousState; newState = previousState;
@ -105,7 +117,11 @@ function reducer(previousState, action) {
pendingJoins: { rooms: {} }, pendingJoins: { rooms: {} },
}; };
for (const device of action.devices) { for (const device of action.devices) {
if (!newState.devices[device.id]) {
change.devices[device.id] = { $set: device }; change.devices[device.id] = { $set: device };
} else {
updateDeviceProps(device);
}
if (device.roomId in newState.rooms) { if (device.roomId in newState.rooms) {
change.rooms[device.roomId] = change.rooms[device.roomId] || {}; change.rooms[device.roomId] = change.rooms[device.roomId] || {};
@ -135,9 +151,28 @@ function reducer(previousState, action) {
createOrUpdateRoom(action.room); createOrUpdateRoom(action.room);
break; break;
case "DEVICE_SAVE": case "DEVICE_SAVE":
newState = update(previousState, { change = {
devices: { [action.device.id]: { $set: action.device } }, devices: { [action.device.id]: { $set: action.device } },
}); };
if (previousState.rooms[action.device.roomId]) {
change.rooms = {
[action.device.roomId]: {
devices: {
$add: [action.device.id],
},
},
};
} else {
change.pendingJoins = {
rooms: {
[action.device.roomId]: {
$add: [action.device.id],
},
},
};
}
newState = update(previousState, change);
break; break;
case "ROOM_DELETE": case "ROOM_DELETE":
if (!(action.roomId in previousState.rooms)) { if (!(action.roomId in previousState.rooms)) {
@ -157,7 +192,7 @@ function reducer(previousState, action) {
change.rooms = { $unset: [action.roomId] }; change.rooms = { $unset: [action.roomId] };
if (previousState.active.activeRoom === action.roomId) { if (previousState.active.activeRoom === action.roomId) {
change.active = { activeRoom: {$set: -1}}; change.active = { activeRoom: { $set: -1 } };
} }
newState = update(previousState, change); newState = update(previousState, change);
@ -200,6 +235,7 @@ function reducer(previousState, action) {
} }
console.log("new state: ", newState); console.log("new state: ", newState);
console.log("active room: ", newState.active.activeRoom);
return newState; return newState;
} }

View file

@ -22,6 +22,7 @@ class Navbar extends Component {
this.toggleEditMode = this.toggleEditMode.bind(this); this.toggleEditMode = this.toggleEditMode.bind(this);
this.selectRoom = this.selectRoom.bind(this); this.selectRoom = this.selectRoom.bind(this);
this.openCurrentModalMobile = this.openCurrentModalMobile.bind(this);
this.getRooms(); this.getRooms();
} }
@ -40,7 +41,13 @@ class Navbar extends Component {
get activeItemName() { get activeItemName() {
if (this.props.activeRoom === -1) return "Home"; if (this.props.activeRoom === -1) return "Home";
return this.props.rooms[this.props.activeRoom]; return this.props.rooms[this.props.activeRoom].name;
}
openCurrentModalMobile() {
console.log(this.activeItem, this.props.roomModalRefs);
const currentModal = this.props.roomModalRefs[this.activeItem].current;
currentModal.openModal();
} }
toggleEditMode(e) { toggleEditMode(e) {
@ -48,7 +55,7 @@ class Navbar extends Component {
} }
selectRoom(e, { id }) { selectRoom(e, { id }) {
this.activeItem = id; this.activeItem = id || -1;
} }
render() { render() {
@ -65,9 +72,9 @@ class Navbar extends Component {
<Menu inverted fluid vertical> <Menu inverted fluid vertical>
<Menu.Item <Menu.Item
key={-1} key={-1}
id={-1} id={null}
name="Home" name="Home"
active={this.activeRoom === -1} active={this.activeItem === -1}
onClick={this.selectRoom} onClick={this.selectRoom}
> >
<Grid> <Grid>
@ -86,7 +93,7 @@ class Navbar extends Component {
id={e.id} id={e.id}
key={i} key={i}
name={e.name} name={e.name}
active={this.activeRoom === e.id} active={this.activeItem === e.id}
onClick={this.selectRoom} onClick={this.selectRoom}
> >
<Grid> <Grid>
@ -124,9 +131,9 @@ class Navbar extends Component {
<Dropdown.Menu> <Dropdown.Menu>
<Dropdown.Item <Dropdown.Item
key={-1} key={-1}
id={-1} id={null}
name="Home" name="Home"
active={this.activeRoom === -1} active={this.activeItem === -1}
onClick={this.selectRoom} onClick={this.selectRoom}
> >
<Grid> <Grid>
@ -145,7 +152,7 @@ class Navbar extends Component {
id={e.id} id={e.id}
key={i} key={i}
name={e.name} name={e.name}
active={this.activeRoom === e.id} active={this.activeItem === e.id}
onClick={this.selectRoom} onClick={this.selectRoom}
> >
<Grid> <Grid>
@ -156,7 +163,11 @@ class Navbar extends Component {
<Grid.Column>{e.name}</Grid.Column> <Grid.Column>{e.name}</Grid.Column>
</Grid.Row> </Grid.Row>
</Grid> </Grid>
<RoomModal nicolaStop={true} id={e} /> <RoomModal
ref={this.props.roomModalRefs[e.id]}
nicolaStop={true}
id={e.id}
/>
</Dropdown.Item> </Dropdown.Item>
); );
})} })}
@ -168,9 +179,14 @@ class Navbar extends Component {
<Grid.Column width={8}> <Grid.Column width={8}>
<RoomModal id={null} /> <RoomModal id={null} />
</Grid.Column> </Grid.Column>
{this.activeRoom !== -1 ? ( {this.activeItem !== -1 ? (
<Grid.Column width={8}> <Grid.Column width={8}>
<Button icon fluid labelPosition="left"> <Button
icon
fluid
labelPosition="left"
onClick={this.openCurrentModalMobile}
>
<Icon name="pencil" size="small" /> <Icon name="pencil" size="small" />
EDIT ROOM EDIT ROOM
</Button> </Button>
@ -188,7 +204,14 @@ const setActiveRoom = (activeRoom) => {
return (dispatch) => dispatch(appActions.setActiveRoom(activeRoom)); return (dispatch) => dispatch(appActions.setActiveRoom(activeRoom));
}; };
const mapStateToProps = (state, _) => ({ rooms: state.rooms }); const mapStateToProps = (state, _) => ({
rooms: state.rooms,
activeRoom: state.active.activeRoom,
roomModalRefs: Object.keys(state.rooms).reduce(
(acc, key) => ({ ...acc, [key]: React.createRef() }),
{}
),
});
const NavbarContainer = connect(mapStateToProps, { const NavbarContainer = connect(mapStateToProps, {
...RemoteService, ...RemoteService,
setActiveRoom, setActiveRoom,