From 3b08e6ade318298f301c5ec8ebb23bf17e830f87 Mon Sep 17 00:00:00 2001 From: Jannis Mattheis Date: Thu, 15 Mar 2018 20:32:27 +0100 Subject: [PATCH] Add Clients Component --- ui/src/actions/ClientAction.js | 29 +++++++ ui/src/pages/Clients.js | 146 +++++++++++++++++++++++++++++++++ ui/src/stores/ClientStore.js | 34 ++++++++ 3 files changed, 209 insertions(+) create mode 100644 ui/src/actions/ClientAction.js create mode 100644 ui/src/pages/Clients.js create mode 100644 ui/src/stores/ClientStore.js diff --git a/ui/src/actions/ClientAction.js b/ui/src/actions/ClientAction.js new file mode 100644 index 0000000..17ba0e9 --- /dev/null +++ b/ui/src/actions/ClientAction.js @@ -0,0 +1,29 @@ +import dispatcher from '../stores/dispatcher'; +import config from 'react-global-configuration'; +import axios from 'axios'; + +/** Fetches all clients. */ +export function fetchClients() { + axios.get(config.get('url') + 'client').then((resp) => { + dispatcher.dispatch({ + type: 'UPDATE_CLIENTS', + payload: resp.data, + }); + }); +} + +/** + * Delete a client by id. + * @param {int} id the client id + */ +export function deleteClient(id) { + axios.delete(config.get('url') + 'client/' + id).then(fetchClients); +} + +/** + * Create a client. + * @param {string} name the client name + */ +export function createClient(name) { + axios.post(config.get('url') + 'client', {name}).then(fetchClients); +} diff --git a/ui/src/pages/Clients.js b/ui/src/pages/Clients.js new file mode 100644 index 0000000..0082d81 --- /dev/null +++ b/ui/src/pages/Clients.js @@ -0,0 +1,146 @@ +import React, {Component} from 'react'; +import Grid from 'material-ui/Grid'; +import Table, {TableBody, TableCell, TableHead, TableRow} from 'material-ui/Table'; +import Paper from 'material-ui/Paper'; +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 ClientStore from '../stores/ClientStore'; +import ToggleVisibility from '../component/ToggleVisibility'; +import * as ClientAction from '../actions/ClientAction'; +import DefaultPage from '../component/DefaultPage'; +import ConfirmDialog from '../component/ConfirmDialog'; +import PropTypes from 'prop-types'; +import Delete from 'material-ui-icons/Delete'; + +class Clients extends Component { + constructor() { + super(); + this.state = {clients: [], showDialog: false, deleteId: -1}; + } + + componentWillMount() { + ClientStore.on('change', this.updateClients); + this.updateClients(); + } + + componentWillUnmount() { + ClientStore.removeListener('change', this.updateClients); + } + + updateClients = () => this.setState({...this.state, clients: ClientStore.get()}); + + showCreateDialog = () => this.setState({...this.state, showDialog: true}); + hideCreateDialog = () => this.setState({...this.state, showDialog: false}); + + showDeleteDialog = (deleteId) => this.setState({...this.state, deleteId}); + hideDeleteDelete = () => this.setState({...this.state, deleteId: -1}); + + render() { + const {clients, deleteId, showDialog} = this.state; + return ( + + + + + + + Name + token + + + + + {clients.map((client) => { + return ( + this.showDeleteDialog(client.id)}/> + ); + })} + +
+
+
+ {showDialog && } + {deleteId !== -1 && ClientAction.deleteClient(deleteId)}/>} +
+ ); + } +} + +class Row extends Component { + static propTypes = { + name: PropTypes.string.isRequired, + value: PropTypes.string.isRequired, + fDelete: PropTypes.func.isRequired, + }; + + render() { + const {name, value, fDelete} = this.props; + return ( + + {name} + + + + + + + + ); + } +} + +class AddDialog extends Component { + static propTypes = { + fClose: PropTypes.func.isRequired, + fOnSubmit: PropTypes.func.isRequired, + }; + + constructor() { + super(); + this.state = {name: ''}; + } + + handleChange(propertyName, event) { + const state = this.state; + state[propertyName] = event.target.value; + this.setState(state); + } + + render() { + const {fClose, fOnSubmit} = this.props; + const {name} = this.state; + const submitEnabled = this.state.name.length !== 0; + const submitAndClose = () => { + fOnSubmit(name); + fClose(); + }; + return ( + + Create a client + + + + + + +
+ +
+
+
+
+ ); + } +} + +export default Clients; diff --git a/ui/src/stores/ClientStore.js b/ui/src/stores/ClientStore.js new file mode 100644 index 0000000..0396455 --- /dev/null +++ b/ui/src/stores/ClientStore.js @@ -0,0 +1,34 @@ +import {EventEmitter} from 'events'; +import dispatcher from './dispatcher'; + +class ClientStore extends EventEmitter { + constructor() { + super(); + this.clients = []; + } + + get() { + return this.clients; + } + + getById(id) { + return this.clients.find((client) => client.id === id); + } + + getIdByToken(token) { + const client = this.clients.find((client) => client.token === token); + return client !== undefined ? client.id : ''; + } + + handle(data) { + if (data.type === 'UPDATE_CLIENTS') { + this.clients = data.payload; + this.emit('change'); + } + } +} + + +const store = new ClientStore(); +dispatcher.register(store.handle.bind(store)); +export default store;