Fixes to Device in preparation to use in Hosts tab

This commit is contained in:
Claudio Maggioni (maggicl) 2020-05-03 17:18:34 +02:00
parent f6f46918c6
commit c95f7a95f7
7 changed files with 90 additions and 49 deletions

View file

@ -29,7 +29,7 @@ class DevicePanel extends Component {
return <Device key={i} tab={this.props.tab} id={e.id} />; return <Device key={i} tab={this.props.tab} id={e.id} />;
})} })}
{!this.props.isActiveRoomHome ? ( {!this.props.isActiveRoomHome ? (
<Card style={{ height: "23em" }}> <Card style={{ height: "27em" }}>
<Segment basic style={{ width: "100%", height: "100%" }}> <Segment basic style={{ width: "100%", height: "100%" }}>
<NewDevice /> <NewDevice />
</Segment> </Segment>

View file

@ -2,9 +2,18 @@ import React, { Component } from "react";
import { connect } from "react-redux"; import { connect } from "react-redux";
import { RemoteService } from "../../remote"; import { RemoteService } from "../../remote";
import { Card, Segment, Header, Icon } from "semantic-ui-react"; import { Card, Segment, Header, Icon } from "semantic-ui-react";
import Device from "../../components/dashboard/devices/Device";
class HostsPanel extends Component { class HostsPanel extends Component {
constructor(props) {
super(props);
if (this.props.activeHost !== -1) {
this.props.fetchDevices(null, this.props.activeHost).catch(console.error);
}
}
render() { render() {
console.log(this.props);
return ( return (
<Card.Group centered style={{ paddingTop: "3rem" }}> <Card.Group centered style={{ paddingTop: "3rem" }}>
{this.props.isActiveDefaultHost && ( {this.props.isActiveDefaultHost && (
@ -15,6 +24,16 @@ class HostsPanel extends Component {
</Header> </Header>
</Segment> </Segment>
)} )}
{this.props.hostDeviceIds.map((id) => {
return (
<Device
key={id}
hostId={this.props.activeHost}
tab="Hosts"
id={id}
/>
);
})}
</Card.Group> </Card.Group>
); );
} }
@ -23,7 +42,7 @@ class HostsPanel extends Component {
const mapStateToProps = (state, _) => ({ const mapStateToProps = (state, _) => ({
isActiveDefaultHost: state.active.activeHost === -1, isActiveDefaultHost: state.active.activeHost === -1,
activeHost: state.active.activeHost, activeHost: state.active.activeHost,
hostDevices: state.hostDevices, hostDeviceIds: Object.keys(state.hostDevices[state.activeHost] || {}),
}); });
const HostsPanelContainer = connect(mapStateToProps, RemoteService)(HostsPanel); const HostsPanelContainer = connect(mapStateToProps, RemoteService)(HostsPanel);
export default HostsPanelContainer; export default HostsPanelContainer;

View file

@ -65,7 +65,6 @@ const mapStateToProps = (state, _) => ({
const stateArray = [ const stateArray = [
...state.scenes[state.active.activeScene].sceneStates, ...state.scenes[state.active.activeScene].sceneStates,
].sort(); ].sort();
console.log("STATESCENE", stateArray);
return stateArray.map((id) => state.sceneStates[id]); return stateArray.map((id) => state.sceneStates[id]);
} else { } else {
return []; return [];

View file

@ -41,16 +41,11 @@ class Device extends React.Component {
} }
deleteState() { deleteState() {
console.log("alpaca ", this.props);
this.props.deleteState(this.props.id, this.props.stateOrDevice.kind); this.props.deleteState(this.props.id, this.props.stateOrDevice.kind);
} }
renderDeviceComponent() { renderDeviceComponent() {
switch ( switch (this.props.type) {
this.props.tab === "Devices"
? this.props.stateOrDevice.kind
: this.props.type
) {
case "curtains": case "curtains":
return ( return (
<Curtains <Curtains
@ -151,22 +146,16 @@ class Device extends React.Component {
} }
get deviceName() { get deviceName() {
return this.props.tab === "Devices" return this.props.device.name;
? this.props.stateOrDevice.name
: this.props.device.name;
} }
render() { render() {
return ( return (
<Card style={{ height: this.props.tab === "Devices" ? "23em" : "27em" }}> <Card style={{ height: "27em" }}>
<Card.Content> <Card.Content>
<Card.Header textAlign="center"> <Card.Header textAlign="center">
<Header as="h3">{this.deviceName}</Header> <Header as="h3">{this.deviceName}</Header>
{this.props.tab === "Scenes" ? (
<Header as="h4">{this.props.roomName}</Header> <Header as="h4">{this.props.roomName}</Header>
) : (
""
)}
</Card.Header> </Card.Header>
<Card.Description style={centerComponent}> <Card.Description style={centerComponent}>
@ -189,42 +178,45 @@ class Device extends React.Component {
} }
} }
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}"`);
}
}
const mapStateToProps = (state, ownProps) => ({ const mapStateToProps = (state, ownProps) => ({
get stateOrDevice() { get stateOrDevice() {
if (state.active.activeTab === "Devices") { return getStateOrDevice(state, ownProps);
return state.devices[ownProps.id];
} else {
return state.sceneStates[ownProps.id];
}
}, },
get device() { get device() {
if (state.active.activeTab === "Devices") { return getDevice(state, ownProps);
return state.devices[ownProps.id];
} else {
return state.devices[state.sceneStates[ownProps.id].deviceId];
}
}, },
get roomName() { get roomName() {
if (state.active.activeTab === "Scenes") { return (state.rooms[getDevice(state, ownProps).roomId] || {}).name;
const device = state.devices[state.sceneStates[ownProps.id].deviceId];
return state.rooms[device.roomId].name;
} else {
return "";
}
}, },
get type() { get type() {
if (state.active.activeTab === "Scenes") { return getDevice(state, ownProps).kind;
if (state.sceneStates[ownProps.id]) {
//console.log(state.sceneStates[ownProps.id], ownProps.id);
const id = state.sceneStates[ownProps.id].deviceId;
//console.log(id, state.devices[id].kind);
return state.devices[id].kind;
} else {
return "";
}
} else {
return null;
}
}, },
}); });
const DeviceContainer = connect(mapStateToProps, RemoteService)(Device); const DeviceContainer = connect(mapStateToProps, RemoteService)(Device);

View file

@ -297,13 +297,25 @@ export const RemoteService = {
* This also updates the devices attribute on values in the map rooms. * This also updates the devices attribute on values in the map rooms.
* @param {Number|null} roomId the rsoom to which fetch devices * @param {Number|null} roomId the rsoom to which fetch devices
* from, null to fetch from all rooms * from, null to fetch from all rooms
* @param {Number|null} hostId the user id of the owner of the devices to get
* (can be used for host view)
* @returns {Promise<Undefined, RemoteError>} promise that resolves to void and rejects * @returns {Promise<Undefined, RemoteError>} promise that resolves to void and rejects
* with user-fiendly errors as a RemoteError * with user-fiendly errors as a RemoteError
*/ */
fetchDevices: (roomId = null) => { fetchDevices: (roomId = null, hostId = null) => {
return (dispatch) => { return (dispatch) => {
return Endpoint.get(roomId ? `/room/${roomId}/device` : "/device") return Endpoint.get(
.then((res) => void dispatch(actions.devicesUpdate(roomId, res.data))) roomId ? `/room/${roomId}/device` : "/device",
hostId ? { hostId } : null
)
.then(
(res) =>
void dispatch(
!hostId
? actions.devicesUpdate(roomId, res.data, hostId)
: actions.hostDevicesUpdate(hostId, res.data)
)
)
.catch((err) => { .catch((err) => {
console.error(`Fetch devices roomId=${roomId} error`, err); console.error(`Fetch devices roomId=${roomId} error`, err);
throw new RemoteError(["Network error"]); throw new RemoteError(["Network error"]);

View file

@ -3,6 +3,7 @@ import thunk from "redux-thunk";
import update from "immutability-helper"; import update from "immutability-helper";
import reduxWebSocket, { connect } from "@giantmachines/redux-websocket"; import reduxWebSocket, { connect } from "@giantmachines/redux-websocket";
import { socketURL } from "./endpoint"; import { socketURL } from "./endpoint";
import actions from "./storeActions";
function reducer(previousState, action) { function reducer(previousState, action) {
let newState, change; let newState, change;
@ -255,7 +256,20 @@ function reducer(previousState, action) {
newState = update(newState, change); newState = update(newState, change);
break; break;
case "HOST_DEVICES_UPDATE":
change = {
hostDevices: {
[action.hostId]: { $set: {} },
},
};
const deviceMap = change.hostDevices[action.hostId].$set;
for (const device of action.devices) {
deviceMap[device.id] = device;
}
newState = update(previousState, change);
break;
case "AUTOMATION_UPDATE": case "AUTOMATION_UPDATE":
const automations = {}; const automations = {};
for (const automation of action.automations) { for (const automation of action.automations) {

View file

@ -58,6 +58,11 @@ const actions = {
devices, devices,
partial, partial,
}), }),
hostDevicesUpdate: (hostId, devices) => ({
type: "HOST_DEVICES_UPDATE",
hostId,
devices,
}),
stateDelete: (stateId) => ({ stateDelete: (stateId) => ({
type: "STATE_DELETE", type: "STATE_DELETE",
stateId, stateId,