diff --git a/ui/src/pages/Users.js b/ui/src/pages/Users.js new file mode 100644 index 0000000..f6c0d1a --- /dev/null +++ b/ui/src/pages/Users.js @@ -0,0 +1,202 @@ +import React, {Component} from 'react'; +import Grid from 'material-ui/Grid'; +import {withStyles} from 'material-ui/styles'; +import Table, {TableBody, TableCell, TableHead, TableRow} from 'material-ui/Table'; +import Paper from 'material-ui/Paper'; +import Switch from 'material-ui/Switch'; +import Button from 'material-ui/Button'; +import IconButton from 'material-ui/IconButton'; +import Dialog, {DialogActions, DialogContent, DialogTitle} from 'material-ui/Dialog'; +import TextField from 'material-ui/TextField'; +import Tooltip from 'material-ui/Tooltip'; +import UserStore from '../stores/UserStore'; +import * as UserAction from '../actions/UserAction'; +import {FormControlLabel} from 'material-ui/Form'; +import ConfirmDialog from '../component/ConfirmDialog'; +import DefaultPage from '../component/DefaultPage'; +import Delete from 'material-ui-icons/Delete'; +import Edit from 'material-ui-icons/Edit'; +import PropTypes from 'prop-types'; + +const styles = () => ({ + wrapper: { + margin: '0 auto', + maxWidth: 700, + }, +}); + +class UserRow extends Component { + static propTypes = { + name: PropTypes.string.isRequired, + admin: PropTypes.bool.isRequired, + fDelete: PropTypes.func.isRequired, + fEdit: PropTypes.func.isRequired, + }; + + render() { + const {name, admin, fDelete, fEdit} = this.props; + return ( + + {name} + {admin ? 'Yes' : 'No'} + + + + + + ); + } +} + +class Users extends Component { + constructor() { + super(); + this.state = {users: [], createDialog: false, deleteId: -1, editId: -1}; + } + + componentWillMount() { + UserStore.on('change', this.updateUsers); + this.updateUsers(); + } + + componentWillUnmount() { + UserStore.removeListener('change', this.updateUsers); + } + + updateUsers = () => this.setState({...this.state, users: UserStore.get()}); + + showCreateDialog = () => this.setState({...this.state, createDialog: true}); + hideCreateDialog = () => this.setState({...this.state, createDialog: false}); + + showEditDialog = (editId) => this.setState({...this.state, editId}); + hideEditDialog = () => this.setState({...this.state, editId: -1}); + + showDeleteDialog = (deleteId) => this.setState({...this.state, deleteId}); + hideDeleteDialog = () => this.setState({...this.state, deleteId: -1}); + + render() { + const {users, deleteId, editId} = this.state; + return ( + + + + + + + Name + Admin + + + + + {users.map((user) => { + return ( + this.showDeleteDialog(user.id)} + fEdit={() => this.showEditDialog(user.id)}/> + ); + })} + + + + + {this.state.createDialog && } + {editId !== -1 && } + {deleteId !== -1 && UserAction.deleteUser(this.state.deleteId)} + />} + + ); + } +} + +class AddEditDialog extends Component { + static defaultProps = { + name: '', + pass: '', + admin: '', + isEdit: false, + }; + + static propTypes = { + name: PropTypes.string.isRequired, + admin: PropTypes.bool.isRequired, + fClose: PropTypes.func.isRequired, + fOnSubmit: PropTypes.func.isRequired, + isEdit: PropTypes.bool.isRequired, + }; + + constructor() { + super(); + this.state = { + name: '', + pass: '', + admin: false, + }; + } + + componentWillMount() { + const {name, admin} = this.props; + this.setState({...this.state, name, admin: admin}); + } + + + handleChange(propertyName, event) { + const state = this.state; + state[propertyName] = event.target.value; + this.setState(state); + } + + handleChecked(propertyName, event) { + const state = this.state; + state[propertyName] = event.target.checked; + this.setState(state); + } + + render() { + const {fClose, fOnSubmit, isEdit} = this.props; + const {name, pass, admin} = this.state; + const namePresent = this.state.name.length !== 0; + const passPresent = this.state.pass.length !== 0 || isEdit; + const submitAndClose = () => { + fOnSubmit(name, pass, admin); + fClose(); + }; + return ( + + {isEdit ? 'Edit ' + this.props.name : 'Add a user'} + + + + } label="has administrator rights"/> + + + Cancel + + + + {isEdit ? 'Save' : 'Create'} + + + + + + ); + } +} + +export default withStyles(styles)(Users); diff --git a/ui/src/stores/UserStore.js b/ui/src/stores/UserStore.js new file mode 100644 index 0000000..b8573be --- /dev/null +++ b/ui/src/stores/UserStore.js @@ -0,0 +1,28 @@ +import {EventEmitter} from 'events'; +import dispatcher from './dispatcher'; + +class UserStore extends EventEmitter { + constructor() { + super(); + this.users = []; + } + + get() { + return this.users; + } + + getById(id) { + return this.users.find((app) => app.id === id); + } + + handle(data) { + if (data.type === 'UPDATE_USERS') { + this.users = data.payload; + this.emit('change'); + } + } +} + +const store = new UserStore(); +dispatcher.register(store.handle.bind(store)); +export default store;