Merge branch '96-when-creating-a-scene-users-can-t-copy-the-configuration-from-another-scene' into 'dev'
Resolve "When creating a scene, users can't copy the configuration from another scene." Closes #96 See merge request sa4-2020/the-sanmarinoes/frontend!118
This commit is contained in:
commit
88dca6b144
4 changed files with 73 additions and 17 deletions
|
@ -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,
|
||||
|
|
|
@ -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)}
|
||||
/>
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue