diff --git a/ui/src/actions/ClientAction.ts b/ui/src/actions/ClientAction.ts deleted file mode 100644 index 83cc543..0000000 --- a/ui/src/actions/ClientAction.ts +++ /dev/null @@ -1,36 +0,0 @@ -import axios, {AxiosResponse} from 'axios'; -import * as config from '../config'; -import dispatcher from '../stores/dispatcher'; -import {snack} from './GlobalAction'; - -/** Fetches all clients. */ -export function fetchClients() { - axios.get(config.get('url') + 'client').then((resp: AxiosResponse) => { - dispatcher.dispatch({ - type: 'UPDATE_CLIENTS', - payload: resp.data, - }); - }); -} - -/** - * Delete a client by id. - * @param {int} id the client id - */ -export function deleteClient(id: number) { - axios - .delete(config.get('url') + 'client/' + id) - .then(fetchClients) - .then(() => snack('Client deleted')); -} - -/** - * Create a client. - * @param {string} name the client name - */ -export function createClient(name: string) { - axios - .post(config.get('url') + 'client', {name}) - .then(fetchClients) - .then(() => snack('Client created')); -} diff --git a/ui/src/pages/Clients.tsx b/ui/src/pages/Clients.tsx index a70e4a5..36ccfbd 100644 --- a/ui/src/pages/Clients.tsx +++ b/ui/src/pages/Clients.tsx @@ -8,39 +8,33 @@ import TableHead from '@material-ui/core/TableHead'; import TableRow from '@material-ui/core/TableRow'; import Delete from '@material-ui/icons/Delete'; import React, {Component, SFC} from 'react'; -import * as ClientAction from '../actions/ClientAction'; import ConfirmDialog from '../component/ConfirmDialog'; import DefaultPage from '../component/DefaultPage'; import ToggleVisibility from '../component/ToggleVisibility'; -import ClientStore from '../stores/ClientStore'; import AddClientDialog from './dialog/AddClientDialog'; +import ClientStore from '../stores/ClientStore'; +import {observer} from 'mobx-react'; +import {observable} from 'mobx'; -interface IState { - clients: IClient[]; - showDialog: boolean; - deleteId: number; -} +@observer +class Clients extends Component { + @observable + private showDialog = false; + @observable + private deleteId: false | number = false; -class Clients extends Component<{}, IState> { - public state = {clients: [], showDialog: false, deleteId: -1}; - - public componentWillMount() { - ClientStore.on('change', this.updateClients); - this.updateClients(); - } - - public componentWillUnmount() { - ClientStore.removeListener('change', this.updateClients); - } + public componentDidMount = ClientStore.refresh; public render() { - const {clients, deleteId, showDialog} = this.state; + const {deleteId, showDialog} = this; + const clients = ClientStore.getItems(); + return ( + fButton={() => (this.showDialog = true)}> @@ -58,7 +52,7 @@ class Clients extends Component<{}, IState> { key={client.id} name={client.name} value={client.token} - fDelete={() => this.showDeleteDialog(client.id)} + fDelete={() => (this.deleteId = client.id)} /> ); })} @@ -68,31 +62,21 @@ class Clients extends Component<{}, IState> { {showDialog && ( (this.showDialog = false)} + fOnSubmit={ClientStore.create} /> )} - {deleteId !== -1 && ( + {deleteId !== false && ( (this.deleteId = false)} + fOnSubmit={() => ClientStore.remove(deleteId)} /> )} ); } - - private deleteClient = () => ClientAction.deleteClient(this.state.deleteId); - - private updateClients = () => this.setState({...this.state, clients: ClientStore.get()}); - private showCreateDialog = () => this.setState({...this.state, showDialog: true}); - - private hideCreateDialog = () => this.setState({...this.state, showDialog: false}); - private showDeleteDialog = (deleteId: number) => this.setState({...this.state, deleteId}); - - private hideDeleteDelete = () => this.setState({...this.state, deleteId: -1}); } interface IRowProps { diff --git a/ui/src/stores/ClientStore.ts b/ui/src/stores/ClientStore.ts index 0f948b8..8e7c32f 100644 --- a/ui/src/stores/ClientStore.ts +++ b/ui/src/stores/ClientStore.ts @@ -1,34 +1,36 @@ -import {EventEmitter} from 'events'; -import {default as dispatcher, IEvent} from './dispatcher'; +import {BaseStore} from './BaseStore'; +import axios from 'axios'; +import * as config from '../config'; +import {action} from 'mobx'; +import SnackManager, {SnackReporter} from './SnackManager'; -class ClientStore extends EventEmitter { - private clients: IClient[] = []; - - public get(): IClient[] { - return this.clients; +class ClientStore extends BaseStore { + public constructor(private readonly snack: SnackReporter) { + super(); } - public getById(id: number): IClient { - const client = this.clients.find((c) => c.id === id); - if (!client) { - throw new Error('client is required to exist'); - } - return client; + protected requestItems = (): Promise => { + return axios.get(`${config.get('url')}client`).then((response) => response.data); + }; + + protected requestDelete(id: number): Promise { + return axios + .delete(`${config.get('url')}client/${id}`) + .then(() => this.snack('Client deleted')); } - public getIdByToken(token: string): number { - const client = this.clients.find((c) => c.token === token); - return client !== undefined ? client.id : -1; - } + @action + public createNoNotifcation = async (name: string): Promise => { + const client = await axios.post(`${config.get('url')}client`, {name}); + await this.refresh(); + return client.data; + }; - public handle(data: IEvent): void { - if (data.type === 'UPDATE_CLIENTS') { - this.clients = data.payload; - this.emit('change'); - } - } + @action + public create = async (name: string): Promise => { + await this.createNoNotifcation(name); + this.snack('Client added'); + }; } -const store = new ClientStore(); -dispatcher.register(store.handle.bind(store)); -export default store; +export default new ClientStore(SnackManager.snack);