Guest selection panel working

This commit is contained in:
Claudio Maggioni (maggicl) 2020-05-02 22:37:20 +02:00
parent a6fbd1a5d2
commit 9b2253b161
7 changed files with 166 additions and 161 deletions

View file

@ -1,43 +1,71 @@
import React, { Component } from "react";
import { Button, Header, Modal, Icon, Responsive } from "semantic-ui-react";
import {
Button,
Header,
Modal,
Icon,
Form,
Responsive,
Dropdown,
} from "semantic-ui-react";
import { connect } from "react-redux";
import { RemoteService } from "../remote";
import { RemoteService, Forms } from "../remote";
import { appActions } from "../storeActions";
//import { update } from "immutability-helper";
class HostModal extends Component {
constructor(props) {
super(props);
this.state = this.initialState;
this.state = { guests: [], users: [] };
this.props
.fetchGuests()
.then(() => {
this.setState({
...this.state,
guests: this.props.guests.map((u) => u.id),
});
})
.catch(console.error);
Forms.fetchAllUsers()
.then((users) =>
this.setState({
...this.state,
users: users.map((u) => ({
key: u.id,
text: `@${u.username} (${u.name})`,
value: u.id,
})),
})
)
.catch(console.error);
this.saveGuestSettings = this.saveGuestSettings.bind(this);
this.closeModal = this.closeModal.bind(this);
this.openModal = this.openModal.bind(this);
this.setGuests = this.setGuests.bind(this);
this.saveGuestSettings = this.saveGuestSettings.bind(this);
}
get initialState() {
return {
//INITIAL STATE HERE
};
setGuests(_, guests) {
this.setState({ guests: guests.value });
}
setInitialState() {
this.setState(this.initialState);
}
changeSomething = (event) => {
let nam = event.target.name;
let val = event.target.value;
this.setState({ [nam]: val });
};
closeModal = (e) => {
closeModal() {
this.setState({ openModal: false });
};
}
openModal = (e) => {
openModal() {
this.setState({ openModal: true });
};
}
saveGuestSettings() {}
saveGuestSettings() {
this.props
.updateGuests(this.state.guests)
.then(this.closeModal)
.catch(console.error);
}
render() {
return (
@ -49,17 +77,10 @@ class HostModal extends Component {
</Button>
</Responsive>
<Responsive maxWidth={768}>
{this.type === "new" ? (
<Button icon fluid labelPosition="left" onClick={this.openModal}>
<Icon name="plus" size="small" />
Invitation settings
</Button>
) : (
<Button icon fluid labelPosition="left" onClick={this.openModal}>
<Icon name="pencil" size="small" />
EDIT AUTOMATION
</Button>
)}
<Button icon fluid labelPosition="left" onClick={this.openModal}>
<Icon name="plus" size="small" />
Invitation settings
</Button>
</Responsive>
<Modal closeIcon onClose={this.closeModal} open={this.state.openModal}>
@ -68,6 +89,22 @@ class HostModal extends Component {
<marquee scrollamount="50">
<h1>Spaghetti!</h1>
</marquee>
<Modal.Content>
<Form>
<Form.Field style={{ marginTop: "1rem" }}>
<label>Select which users are your guests: </label>
<Dropdown
name="guests"
placeholder="Select Guests"
fluid
multiple
onChange={this.setGuests}
options={this.state.users}
value={this.state.guests}
/>
</Form.Field>
</Form>
</Modal.Content>
</Modal.Content>
<Modal.Actions>
<Button color="red" onClick={this.closeModal}>
@ -88,8 +125,8 @@ const setActiveHost = (activeHost) => {
return (dispatch) => dispatch(appActions.setActiveHost(activeHost));
};
const mapStateToProps = (state, ownProps) => ({
hostss: ownProps.id ? state.hostss[ownProps.id] : null,
const mapStateToProps = (state) => ({
guests: state.guests,
});
const HostModalContainer = connect(
mapStateToProps,

View file

@ -1,9 +1,7 @@
import React, { Component } from "react";
import { connect } from "react-redux";
import { RemoteService } from "../../remote";
import { Grid } from "semantic-ui-react";
import Device from "./devices/Device";
import NewSceneDevice from "./NewSceneDevice";
import { Card, Segment, Header, Icon } from "semantic-ui-react";
class HostsPanel extends Component {
constructor(props) {
@ -12,32 +10,22 @@ class HostsPanel extends Component {
render() {
return (
<Grid doubling columns={2} divided="vertically">
{!this.props.isActiveDefaultHost
? Object.values(this.props.hostDevices).map((e, i) => {
return (
<Grid.Column key={i}>
<Device tab={this.props.tab} id={e} />
</Grid.Column>
);
})
: null}
{!this.props.isActiveDefaultHost ? (
<Grid.Column>
<NewSceneDevice />
</Grid.Column>
) : (
<Grid.Column>
Welcome to the Host View, select a host to view their devices.
</Grid.Column>
<Card.Group centered style={{ paddingTop: "3rem" }}>
{this.props.isActiveDefaultHost && (
<Segment placeholder>
<Header icon>
<Icon name="folder open" />
Please select a host to visit on the left.
</Header>
</Segment>
)}
</Grid>
</Card.Group>
);
}
}
const mapStateToProps = (state, _) => ({
activeTab: state.active.activeTab,
isActiveDefaultHost: state.active.activeHost === -1,
activeHost: state.active.activeHost,
hostDevices: state.hostDevices,
});

View file

@ -48,6 +48,7 @@ class NewSceneDevice extends Component {
handleOpen = () => {
this.setState({ openModal: true });
};
handleClose = () => {
this.setState({ openModal: false });
};

View file

@ -351,10 +351,10 @@ export const RemoteService = {
* @returns {Promise<Undefined, RemoteError>} promise that resolves to void and rejects
* with user-fiendly errors as a RemoteError
*/
fetchAllHosts: () => {
fetchHosts: () => {
return (dispatch) => {
return Endpoint.get(`/user/hosts`)
.then((res) => void dispatch(actions.getHosts(res.data)))
.then((res) => void dispatch(actions.hostsUpdate(res.data)))
.catch((err) => {
console.error(`Fetch hosts error`, err);
throw new RemoteError(["Network error"]);
@ -363,17 +363,32 @@ export const RemoteService = {
},
/**
* Adds the current user as a guest to another user
* identified through a host id.
* @param {Number} hostId the host to add.
* @param {String} username the username of the guest to add.
* Fetches all guests of a particular user.
* @returns {Promise<Undefined, RemoteError>} promise that resolves to void and rejects
* with user-fiendly errors as a RemoteError
*/
addUserAsGuest: (hostId, username) => {
fetchGuests: () => {
return (dispatch) => {
return Endpoint.post(`/user/guest`)
.then((res) => void dispatch(actions.guestSave(res.data)))
return Endpoint.get(`/user/guests`)
.then((res) => void dispatch(actions.guestsUpdate(res.data)))
.catch((err) => {
console.error(`Fetch guests error`, err);
throw new RemoteError(["Network error"]);
});
};
},
/**
* Adds the current user as a guest to another user
* identified through a user id.
* @param {Number[]} userId the users to add.
* @returns {Promise<Undefined, RemoteError>} promise that resolves to void and rejects
* with user-fiendly errors as a RemoteError
*/
updateGuests: (userIds) => {
return (dispatch) => {
return Endpoint.put(`/user/guests`, {}, { ids: userIds })
.then((res) => void dispatch(actions.guestsUpdate(res.data)))
.catch((err) => {
console.error(`Guest save error`, err);
throw new RemoteError(["Network Error"]);
@ -828,6 +843,15 @@ for (const key in RemoteService) {
}
export class Forms {
static fetchAllUsers() {
return Endpoint.get(`/user`)
.then((res) => res.data)
.catch((err) => {
console.error(`Fetch users error`, err);
throw new RemoteError(["Network error"]);
});
}
/**
* Attempts to create a new user from the given data.
* This method does not update the global state,

View file

@ -433,47 +433,11 @@ function reducer(previousState, action) {
case "LOGOUT":
newState = update(initState, {});
break;
case "SET_ACTIVE_ROOM":
case "SET_ACTIVE":
newState = update(previousState, {
active: {
activeRoom: {
$set: action.activeRoom,
},
},
});
break;
case "SET_ACTIVE_TAB":
newState = update(previousState, {
active: {
activeTab: {
$set: action.activeTab,
},
},
});
break;
case "SET_ACTIVE_SCENE":
newState = update(previousState, {
active: {
activeScene: {
$set: action.activeScene,
},
},
});
break;
case "SET_ACTIVE_AUTOMATION":
newState = update(previousState, {
active: {
activeAutomation: {
$set: action.activeAutomation,
},
},
});
break;
case "SET_ACTIVE_HOST":
newState = update(previousState, {
active: {
activeHost: {
$set: action.activeHost,
[action.key]: {
$set: action.value,
},
},
});
@ -488,14 +452,10 @@ function reducer(previousState, action) {
devices,
});
break;
case "HOSTS_UPDATE":
change = {
hosts: {},
};
for (const host of action.hosts) {
change.hosts[host.id] = { $set: host };
}
newState = update(previousState, change);
case "HG_UPDATE":
newState = update(previousState, {
[action.key]: { $set: action.value },
});
break;
default:
console.warn(`Action type ${action.type} unknown`, action);
@ -532,10 +492,10 @@ const initState = {
devices: {},
/** @type {[integer]SceneState} */
sceneStates: {},
/** @type {[integer]Guest} */
guests: {},
/** @type {[integer]Host} */
hosts: {},
/** @type {User[]} */
guests: [],
/** @type {User[]} */
hosts: [],
/** @type {[integer]HostDevice} */
hostDevices: {},
};

View file

@ -91,54 +91,48 @@ const actions = {
type: "DEVICE_DELETE",
deviceId,
}),
hostsUpdate: (hosts) => ({
type: "HOSTS_UPDATE",
hosts,
type: "HG_UPDATE",
key: "hosts",
value: hosts,
}),
guestsUpdate: (hosts) => ({
type: "HG_UPDATE",
key: "guests",
value: hosts,
}),
getHostDevices: (host) => ({
type: "GET_HOST_DEVICES",
host,
}),
guestSave: (guest) => ({
type: "GUEST_SAVE",
guest,
}),
guestUpdate: (guest) => ({
type: "GUEST_UPDATE",
guest,
}),
guestDelete: (guest) => ({
type: "GUEST_DELETE",
guest,
guestUpdate: (guests) => ({
type: "HG_UPDATE",
key: "guests",
value: guests,
}),
};
export const appActions = {
// -1 for home view
setActiveRoom: (activeRoom = -1) => ({
type: "SET_ACTIVE_ROOM",
activeRoom,
type: "SET_ACTIVE",
key: "activeRoom",
value: activeRoom,
}),
setActiveTab: (activeTab) => ({
type: "SET_ACTIVE_TAB",
activeTab,
type: "SET_ACTIVE",
key: "activeTab",
value: activeTab,
}),
setActiveScene: (activeScene = -1) => ({
type: "SET_ACTIVE_SCENE",
activeScene,
type: "SET_ACTIVE",
key: "activeScene",
value: activeScene,
}),
setActiveAutomations: (activeAutomation = -1) => ({
type: "SET_ACTIVE_AUTOMATION",
activeAutomation,
}),
setActiveHosts: (activeHost = -1) => ({
type: "SET_ACTIVE_HOST",
activeHost,
setActiveHost: (activeHost = -1) => ({
type: "SET_ACTIVE",
key: "activeHost",
value: activeHost,
}),
};

View file

@ -20,28 +20,29 @@ class HostsNavbar extends Component {
};
this.getHosts();
this.selectHosts = this.selectHosts.bind(this);
}
getHosts() {
this.props.fetchAllHosts().catch(console.error);
this.props.fetchHosts().catch(console.error);
}
get activeItemHost() {
selectHosts(_, { id }) {
this.props.setActiveHost(id || -1);
}
get activeItem() {
return this.props.activeHost;
}
set activeItemHost(item) {
this.props.setActiveHost(item);
}
get activeItemHostsName() {
if (this.props.activeHost === -1) return "Home";
if (this.props.activeItem === -1) return "Home";
return this.props.hosts[this.props.activeHost].name;
}
render() {
return (
<div style={{ background: "#1b1c1d!important", padding: "0 20px" }}>
<div>
<Responsive minWidth={768}>
<Grid style={{ margin: "1em -1em 0 1em" }}>
<Grid.Row>
@ -50,7 +51,7 @@ class HostsNavbar extends Component {
key={-1}
id={null}
name="hosts"
active={this.activeItemHost === -1}
active={this.activeItem === -1}
onClick={this.selectHosts}
>
<strong>Hosts</strong>
@ -61,7 +62,7 @@ class HostsNavbar extends Component {
id={e.id}
key={i}
name={e.name}
active={this.activeItemHost === e.id}
active={this.activeItem === e.id}
onClick={this.selectHosts}
>
{e.name}
@ -84,7 +85,7 @@ class HostsNavbar extends Component {
key={-1}
id={null}
name="scene"
active={this.activeItemHost === -1}
active={this.activeItem === -1}
onClick={this.selectHosts}
>
<strong>Hosts</strong>
@ -96,7 +97,7 @@ class HostsNavbar extends Component {
id={e.id}
key={i}
name={e.name}
active={this.activeItemHost === e.id}
active={this.activeItem === e.id}
onClick={this.selectHosts}
>
{e.name}