This commit is contained in:
britea 2020-05-04 18:24:15 +02:00
commit fcd940e364
7 changed files with 1524 additions and 970 deletions

1
.mailmap Normal file
View file

@ -0,0 +1 @@
Claudio Maggioni <maggicl@usi.ch> Claudio Maggioni <maggicl@kolabnow.ch>

View file

@ -26,7 +26,7 @@ class RoomModal extends Component {
this.addRoomModal = this.addRoomModal.bind(this); this.addRoomModal = this.addRoomModal.bind(this);
this.updateIcon = this.updateIcon.bind(this); this.updateIcon = this.updateIcon.bind(this);
this.removeImage = this.removeImage.bind(this); this.unsetImage = this.unsetImage.bind(this);
} }
get initialState() { get initialState() {
@ -38,13 +38,9 @@ class RoomModal extends Component {
}; };
} }
removeImage(e) { unsetImage = (e) => {
e.preventDefault(); e.preventDefault();
this.setState( this.setState({ ...this.state, img: "" });
update(this.state, {
image: { $set: null },
})
);
} }
setInitialState() { setInitialState() {

View file

@ -7,6 +7,7 @@ import {
Responsive, Responsive,
Form, Form,
Input, Input,
Dropdown,
} from "semantic-ui-react"; } from "semantic-ui-react";
import SelectIcons from "./SelectIcons"; import SelectIcons from "./SelectIcons";
import { connect } from "react-redux"; import { connect } from "react-redux";
@ -22,6 +23,15 @@ class SceneModal extends Component {
this.modifySceneModal = this.modifySceneModal.bind(this); this.modifySceneModal = this.modifySceneModal.bind(this);
this.deleteScene = this.deleteScene.bind(this); this.deleteScene = this.deleteScene.bind(this);
this.updateIcon = this.updateIcon.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() { get initialState() {
@ -29,9 +39,19 @@ class SceneModal extends Component {
name: this.type === "new" ? "New Scene" : this.props.scene.name, name: this.type === "new" ? "New Scene" : this.props.scene.name,
openModal: false, openModal: false,
selectedIcon: "home", 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() { setInitialState() {
this.setState(this.initialState); this.setState(this.initialState);
} }
@ -47,7 +67,7 @@ class SceneModal extends Component {
}; };
this.props this.props
.saveScene(data, null) .saveScene(data, null, this.state.copyFrom)
.then(() => { .then(() => {
this.setInitialState(); this.setInitialState();
this.closeModal(); this.closeModal();
@ -95,6 +115,10 @@ class SceneModal extends Component {
this.setState({ selectedIcon: e }); this.setState({ selectedIcon: e });
} }
setCopyFrom(_, copyFrom) {
this.setState({ ...this.state, copyFrom: copyFrom.value });
}
render() { render() {
const spaceDiv = { const spaceDiv = {
background: "#f4f4f4", background: "#f4f4f4",
@ -155,6 +179,7 @@ class SceneModal extends Component {
<p>Insert the name of the scene:</p> <p>Insert the name of the scene:</p>
<Form.Field> <Form.Field>
<Input <Input
required
label="Scene name" label="Scene name"
placeholder="Scene Name" placeholder="Scene Name"
name="name" name="name"
@ -164,7 +189,7 @@ class SceneModal extends Component {
/> />
</Form.Field> </Form.Field>
<div style={spaceDiv}> <div style={spaceDiv}>
<p>Select an icon:</p> <label>Icon:</label>
<SelectIcons <SelectIcons
updateIcon={this.updateIcon} updateIcon={this.updateIcon}
currentIcon={ currentIcon={
@ -172,6 +197,19 @@ class SceneModal extends Component {
} }
/> />
</div> </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> </Form>
{this.type === "modify" ? ( {this.type === "modify" ? (
@ -215,6 +253,7 @@ const setActiveScene = (activeScene) => {
const mapStateToProps = (state, ownProps) => ({ const mapStateToProps = (state, ownProps) => ({
scene: ownProps.id ? state.scenes[ownProps.id] : null, scene: ownProps.id ? state.scenes[ownProps.id] : null,
scenes: Object.values(state.scenes),
}); });
const SceneModalContainer = connect( const SceneModalContainer = connect(
mapStateToProps, mapStateToProps,

View file

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

View file

@ -447,11 +447,14 @@ export const RemoteService = {
* Creates/Updates a scene with the given data * Creates/Updates a scene with the given data
* @param {String} data.name the scene's name, * @param {String} data.name the scene's name,
* @param {Number|null} sceneId the scene's id if update, null for creation * @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 * @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
*/ */
saveScene: (data, sceneId = null) => { saveScene: (data, sceneId = null, copyFrom = null) => {
return (dispatch) => { return (dispatch) => {
copyFrom = sceneId === null ? copyFrom : null;
data = { data = {
name: data.name, name: data.name,
icon: data.icon, icon: data.icon,
@ -461,12 +464,31 @@ export const RemoteService = {
? Endpoint.put(`/scene/${sceneId}`, {}, data) ? Endpoint.put(`/scene/${sceneId}`, {}, data)
: Endpoint.post(`/scene`, {}, 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); .catch(parseValidationErrors);
}; };
}, },
//
updateState: (data, type) => { updateState: (data, type) => {
return (dispatch) => { return (dispatch) => {
let url; let url;

View file

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

File diff suppressed because it is too large Load diff