Scene copy implemented

This commit is contained in:
Claudio Maggioni (maggicl) 2020-05-04 16:09:56 +02:00
parent da120b377e
commit 94ef7ef558
4 changed files with 73 additions and 17 deletions

View File

@ -7,6 +7,7 @@ import {
Responsive,
Form,
Input,
Dropdown,
} from "semantic-ui-react";
import SelectIcons from "./SelectIcons";
import { connect } from "react-redux";
@ -22,6 +23,15 @@ class SceneModal extends Component {
this.modifySceneModal = this.modifySceneModal.bind(this);
this.deleteScene = this.deleteScene.bind(this);
this.updateIcon = this.updateIcon.bind(this);
this.setCopyFrom = this.setCopyFrom.bind(this);
}
componentDidUpdate(oldProps) {
// this might bug out since we are just checking the length
// to see if the elements inside this.props.scenes are changing
if (this.props.scenes.length !== oldProps.scenes.length) {
this.setState({ ...this.state, scenes: this.scenes });
}
}
get initialState() {
@ -29,9 +39,19 @@ class SceneModal extends Component {
name: this.type === "new" ? "New Scene" : this.props.scene.name,
openModal: false,
selectedIcon: "home",
scenes: this.scenes,
copyFrom: null,
};
}
get scenes() {
return this.props.scenes.map((s) => ({
key: s.id,
text: s.name,
value: s.id,
}));
}
setInitialState() {
this.setState(this.initialState);
}
@ -47,7 +67,7 @@ class SceneModal extends Component {
};
this.props
.saveScene(data, null)
.saveScene(data, null, this.state.copyFrom)
.then(() => {
this.setInitialState();
this.closeModal();
@ -95,6 +115,10 @@ class SceneModal extends Component {
this.setState({ selectedIcon: e });
}
setCopyFrom(_, copyFrom) {
this.setState({ ...this.state, copyFrom: copyFrom.value });
}
render() {
const spaceDiv = {
background: "#f4f4f4",
@ -155,6 +179,7 @@ class SceneModal extends Component {
<p>Insert the name of the scene:</p>
<Form.Field>
<Input
required
label="Scene name"
placeholder="Scene Name"
name="name"
@ -164,7 +189,7 @@ class SceneModal extends Component {
/>
</Form.Field>
<div style={spaceDiv}>
<p>Select an icon:</p>
<label>Icon:</label>
<SelectIcons
updateIcon={this.updateIcon}
currentIcon={
@ -172,6 +197,19 @@ class SceneModal extends Component {
}
/>
</div>
{this.type === "new" && (
<Form.Field>
<label>Copy configuration from:</label>
<Dropdown
name="guests"
placeholder="Select scene to copy configuration form"
fluid
onChange={this.setCopyFrom}
options={this.state.scenes}
value={this.state.copyFrom}
/>
</Form.Field>
)}
</Form>
{this.type === "modify" ? (
@ -215,6 +253,7 @@ const setActiveScene = (activeScene) => {
const mapStateToProps = (state, ownProps) => ({
scene: ownProps.id ? state.scenes[ownProps.id] : null,
scenes: Object.values(state.scenes),
});
const SceneModalContainer = connect(
mapStateToProps,

View File

@ -40,8 +40,8 @@ class Videocam extends Component {
.catch((err) => console.error("videocamera update error", err));
} else {
this.props.updateState(
{ id: this.props.state.id, on: turn },
this.props.state.kind
{ id: this.props.stateOrDevice.id, on: turn },
this.props.stateOrDevice.kind
);
}
}
@ -72,11 +72,7 @@ class Videocam extends Component {
</Grid.Row>
</Grid>
<Checkbox
checked={
this.props.tab === "Devices"
? this.props.device.on
: this.props.state.on
}
checked={this.props.stateOrDevice.on}
toggle
onChange={(e, val) => this.setOnOff(val.checked)}
/>

View File

@ -447,11 +447,14 @@ export const RemoteService = {
* Creates/Updates a scene with the given data
* @param {String} data.name the scene's name,
* @param {Number|null} sceneId the scene's id if update, null for creation
* @param {Number|null} copyFrom the id of the scene from which the states must be copied from.
* (ignored for updates)
* @returns {Promise<Undefined, RemoteError>} promise that resolves to void and rejects
* with user-fiendly errors as a RemoteError
*/
saveScene: (data, sceneId = null) => {
saveScene: (data, sceneId = null, copyFrom = null) => {
return (dispatch) => {
copyFrom = sceneId === null ? copyFrom : null;
data = {
name: data.name,
icon: data.icon,
@ -461,12 +464,31 @@ export const RemoteService = {
? Endpoint.put(`/scene/${sceneId}`, {}, data)
: Endpoint.post(`/scene`, {}, data)
)
.then((res) => void dispatch(actions.sceneSave(res.data)))
.then(async (res) => {
let states = [];
if (copyFrom) {
const sceneId = res.data.id;
try {
const res = await Endpoint.post(
`/scene/${sceneId}/copyFrom/${copyFrom}`
);
states = res.data;
} catch (e) {
console.warn("Error in state cloning from scene " + copyFrom, e);
throw new RemoteError(["Network error"]);
}
}
dispatch(actions.sceneSave(res.data));
if (states.length > 0) {
dispatch(actions.statesUpdate(sceneId, states));
}
})
.catch(parseValidationErrors);
};
},
//
updateState: (data, type) => {
return (dispatch) => {
let url;

View File

@ -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;
@ -125,9 +124,9 @@ function reducer(previousState, action) {
//console.log(action.sceneStates);
change = null;
// if room is given, delete all devices in that room
// and remove any join between that room and deleted
// devices
// if scene is given, delete all sceneStates in that scene
// and remove any join between that scene and deleted
// sceneStates
change = {
scenes: { [action.sceneId]: { sceneStates: { $set: new Set() } } },
sceneStates: { $unset: [] },
@ -431,7 +430,7 @@ function reducer(previousState, action) {
// This update does not ensure the consistent update of switchId/dimmerId properties
// on output devices connected to an input device in this room. Please manually request
// all devices again if consistent update is desired
change = { states: { $unset: [] } };
change = { sceneStates: { $unset: [] } };
for (const id of previousState.scenes[action.sceneId].sceneStates) {
change.sceneStates.$unset.push(id);