From b3fe1c1ea9fbdb38ee60040306fe23e8928032c8 Mon Sep 17 00:00:00 2001 From: Jannis Mattheis Date: Thu, 15 Mar 2018 20:32:16 +0100 Subject: [PATCH] Add Applications Component --- ui/src/actions/AppAction.js | 27 ++++++ ui/src/pages/Applications.js | 154 +++++++++++++++++++++++++++++++++++ ui/src/stores/AppStore.js | 33 ++++++++ 3 files changed, 214 insertions(+) create mode 100644 ui/src/actions/AppAction.js create mode 100644 ui/src/pages/Applications.js create mode 100644 ui/src/stores/AppStore.js diff --git a/ui/src/actions/AppAction.js b/ui/src/actions/AppAction.js new file mode 100644 index 0000000..c70a5a2 --- /dev/null +++ b/ui/src/actions/AppAction.js @@ -0,0 +1,27 @@ +import dispatcher from '../stores/dispatcher'; +import config from 'react-global-configuration'; +import axios from 'axios'; + +/** Fetches all applications. */ +export function fetchApps() { + axios.get(config.get('url') + 'application').then((resp) => { + dispatcher.dispatch({type: 'UPDATE_APPS', payload: resp.data}); + }); +} + +/** + * Delete an application by id. + * @param {int} id the application id + */ +export function deleteApp(id) { + axios.delete(config.get('url') + 'application/' + id).then(fetchApps); +} + +/** + * Create an application + * @param {string} name the application name + * @param {string} description the description of the application. + */ +export function createApp(name, description) { + axios.post(config.get('url') + 'application', {name, description}).then(fetchApps); +} diff --git a/ui/src/pages/Applications.js b/ui/src/pages/Applications.js new file mode 100644 index 0000000..5f05c66 --- /dev/null +++ b/ui/src/pages/Applications.js @@ -0,0 +1,154 @@ +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, DialogContentText, DialogTitle} from 'material-ui/Dialog'; +import TextField from 'material-ui/TextField'; +import Tooltip from 'material-ui/Tooltip'; +import AppStore from '../stores/AppStore'; +import ToggleVisibility from '../component/ToggleVisibility'; +import ConfirmDialog from '../component/ConfirmDialog'; +import * as AppAction from '../actions/AppAction'; +import DefaultPage from '../component/DefaultPage'; +import PropTypes from 'prop-types'; +import Delete from 'material-ui-icons/Delete'; + +class Applications extends Component { + constructor() { + super(); + this.state = {apps: [], createDialog: false, deleteId: -1}; + } + + componentWillMount() { + AppStore.on('change', this.updateApps); + this.updateApps(); + } + + componentWillUnmount() { + AppStore.removeListener('change', this.updateApps); + } + + updateApps = () => this.setState({...this.state, apps: AppStore.get()}); + + showCreateDialog = () => this.setState({...this.state, createDialog: true}); + hideCreateDialog = () => this.setState({...this.state, createDialog: false}); + + showCloseDialog = (deleteId) => this.setState({...this.state, deleteId}); + hideCloseDialog = () => this.setState({...this.state, deleteId: -1}); + + render() { + const {apps, createDialog, deleteId} = this.state; + return ( + + + + + + + Name + Token + Description + + + + + {apps.map((app) => { + return ( + this.showCloseDialog(app.id)}/> + ); + })} + +
+
+
+ {createDialog && } + {deleteId !== -1 && AppAction.deleteApp(deleteId)} + />} +
+ ); + } +} + +class Row extends Component { + static propTypes = { + name: PropTypes.string.isRequired, + value: PropTypes.string.isRequired, + description: PropTypes.string.isRequired, + fDelete: PropTypes.func.isRequired, + }; + + render() { + const {name, value, description, fDelete} = this.props; + return ( + + {name} + + + + {description} + + + + + ); + } +} + +class AddDialog extends Component { + static propTypes = { + fClose: PropTypes.func.isRequired, + fOnSubmit: PropTypes.func.isRequired, + }; + + constructor() { + super(); + this.state = {name: '', description: ''}; + } + + handleChange(propertyName, event) { + const state = this.state; + state[propertyName] = event.target.value; + this.setState(state); + } + + render() { + const {fClose, fOnSubmit} = this.props; + const {name, description} = this.state; + const submitEnabled = this.state.name.length !== 0; + const submitAndClose = () => { + fOnSubmit(name, description); + fClose(); + }; + return ( + + Create an application + + An application is allowed to send messages. + + + + + + +
+ +
+
+
+
+ ); + } +} + +export default Applications; diff --git a/ui/src/stores/AppStore.js b/ui/src/stores/AppStore.js new file mode 100644 index 0000000..6f34263 --- /dev/null +++ b/ui/src/stores/AppStore.js @@ -0,0 +1,33 @@ +import {EventEmitter} from 'events'; +import dispatcher from './dispatcher'; + +class AppStore extends EventEmitter { + constructor() { + super(); + this.apps = []; + } + + get() { + return this.apps; + } + + getById(id) { + return this.apps.find((app) => app.id === id); + } + + getName(id) { + const app = this.getById(id); + return id === -1 ? 'All Messages' : app !== undefined ? app.name : 'unknown'; + } + + handle(data) { + if (data.type === 'UPDATE_APPS') { + this.apps = data.payload; + this.emit('change'); + } + } +} + +const store = new AppStore(); +dispatcher.register(store.handle.bind(store)); +export default store;