1 import * as React from 'react';
2 import { Theme, createStyles, WithStyles, withStyles, Tooltip } from '@material-ui/core';
4 import AddIcon from '@material-ui/icons/Add';
5 import IconButton from '@material-ui/core/IconButton';
6 import EditIcon from '@material-ui/icons/Edit';
7 import DeleteIcon from '@material-ui/icons/Delete';
8 import InfoIcon from '@material-ui/icons/Info';
9 import StartIcon from '@material-ui/icons/PlayArrow';
10 import StopIcon from '@material-ui/icons/Stop';
12 import CircularProgress from '@material-ui/core/CircularProgress'
14 import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
15 import connect, { Connect, IDispatcher } from '../../../../framework/src/flux/connect';
16 import MaterialTable, { MaterialTableCtorType, ColumnType } from '../../../../framework/src/components/material-table';
18 import { MediatorConfig, BusySymbol, MediatorConfigResponse } from '../models/mediatorServer';
19 import EditMediatorConfigDialog, { EditMediatorConfigDialogMode } from '../components/editMediatorConfigDialog';
20 import { startMediatorByNameAsyncActionCreator, stopMediatorByNameAsyncActionCreator } from '../actions/mediatorConfigActions';
21 import mediatorService from '../services/mediatorService';
23 const styles = (theme: Theme) => createStyles({
26 flexDirection: 'column',
30 margin: theme.spacing.unit,
39 marginLeft: theme.spacing.unit,
40 marginRight: theme.spacing.unit,
47 justifyContent: 'center',
52 const mapProps = (state: IApplicationStoreState) => ({
53 serverName: state.mediatorApp.mediatorServerState.name,
54 serverUrl: state.mediatorApp.mediatorServerState.url,
55 serverVersion: state.mediatorApp.mediatorServerState.serverVersion,
56 mediatorVersion: state.mediatorApp.mediatorServerState.mediatorVersion,
57 configurations: state.mediatorApp.mediatorServerState.configurations,
58 supportedDevices: state.mediatorApp.mediatorServerState.supportedDevices,
59 busy: state.mediatorApp.mediatorServerState.busy,
62 const mapDispatch = (dispatcher: IDispatcher) => ({
63 startMediator: (name: string) => dispatcher.dispatch(startMediatorByNameAsyncActionCreator(name)),
64 stopMediator: (name: string) => dispatcher.dispatch(stopMediatorByNameAsyncActionCreator(name)),
67 const emptyMediatorConfig: MediatorConfig = {
69 DeviceIp: "127.0.0.1",
80 const MediatorServerConfigurationsTable = MaterialTable as MaterialTableCtorType<MediatorConfigResponse>;
82 type MediatorApplicationComponentProps = Connect<typeof mapProps, typeof mapDispatch> & WithStyles<typeof styles>;
84 type MediatorServerSelectionComponentState = {
86 mediatorConfigToEdit: MediatorConfig,
87 mediatorConfigEditorMode: EditMediatorConfigDialogMode
90 class MediatorApplicationComponent extends React.Component<MediatorApplicationComponentProps, MediatorServerSelectionComponentState> {
92 constructor (props: MediatorApplicationComponentProps) {
97 mediatorConfigToEdit: emptyMediatorConfig,
98 mediatorConfigEditorMode: EditMediatorConfigDialogMode.None,
103 const { classes } = this.props;
105 const renderActions = (rowData: MediatorConfigResponse) => (
107 <div className={classes.spacer}>
108 <Tooltip title={"Start"} >
109 <IconButton disabled={rowData[BusySymbol]} className={classes.button}>
110 <StartIcon onClick={(event) => { event.preventDefault(); event.stopPropagation(); this.props.startMediator(rowData.Name); }} />
113 <Tooltip title={"Stop"} >
114 <IconButton disabled={rowData[BusySymbol]} className={classes.button}>
115 <StopIcon onClick={(event) => { event.preventDefault(); event.stopPropagation(); this.props.stopMediator(rowData.Name); }} />
119 <div className={classes.spacer}>
120 <Tooltip title={"Info"} ><IconButton className={classes.button}><InfoIcon /></IconButton></Tooltip>
122 <div className={classes.spacer}>
123 {process.env.NODE_ENV === "development" ? <Tooltip title={"Edit"} ><IconButton disabled={rowData[BusySymbol]} className={classes.button} onClick={event => this.onOpenEditConfigurationDialog(event, rowData)}><EditIcon /></IconButton></Tooltip> : null}
124 <Tooltip title={"Remove"} ><IconButton disabled={rowData[BusySymbol]} className={classes.button} onClick={event => this.onOpenRemoveConfigutationDialog(event, rowData)}><DeleteIcon /></IconButton></Tooltip>
129 const addMediatorConfigAction = { icon: AddIcon, tooltip: 'Add', onClick: this.onOpenAddConfigurationDialog };
131 <div className={classes.root}>
132 {this.props.busy || this.state.busy
133 ? <div className={classes.progress}> <CircularProgress color={"secondary"} size={48} /> </div>
134 : <MediatorServerConfigurationsTable title={this.props.serverName || ''} customActionButtons={[addMediatorConfigAction]} idProperty={"Name"} rows={this.props.configurations} asynchronus columns={[
135 { property: "Name", title: "Mediator", type: ColumnType.text },
136 { property: "Status", title: "Status", type: ColumnType.custom, customControl: ({ rowData }) => rowData.pid ? (<span>Running</span>) : (<span>Stopped</span>) },
137 { property: "DeviceIp", title: "IP Adress", type: ColumnType.text },
139 property: "Device", title: "Device", type: ColumnType.custom, customControl: ({ rowData }) => {
140 const dev = this.props.supportedDevices && this.props.supportedDevices.find(dev => dev.id === rowData.DeviceType);
142 <span> {dev && `${dev.vendor} - ${dev.device} (${dev.version || '0.0.0'})`} </span>
146 { property: "actions", title: "Actions", type: ColumnType.custom, customControl: ({ rowData }) => renderActions(rowData) },
150 <EditMediatorConfigDialog
151 mediatorConfig={this.state.mediatorConfigToEdit}
152 mode={this.state.mediatorConfigEditorMode}
153 onClose={this.onCloseEditMediatorConfigDialog} />
159 private onOpenAddConfigurationDialog = () => {
160 // Tries to determine a free port for netconf listener and snpm listener
161 // it it could not determine free ports the dialog will open any way
162 // those ports should not be configured from the fontend, furthermore
163 // the backend should auto configure them and tell the user the result
164 // after the creation process.
169 this.props.serverUrl && Promise.all([
170 mediatorService.getMediatorServerFreeNcPorts(this.props.serverUrl, 1),
171 mediatorService.getMediatorServerFreeSnmpPorts(this.props.serverUrl, 1),
172 ]).then(([freeNcPorts, freeSnmpPorts]) => {
173 if (freeNcPorts && freeSnmpPorts && freeNcPorts.length > 0 && freeSnmpPorts.length > 0) {
176 mediatorConfigEditorMode: EditMediatorConfigDialogMode.AddMediatorConfig,
177 mediatorConfigToEdit: {
178 ...emptyMediatorConfig,
179 NcPort: freeNcPorts[0],
180 TrapPort: freeSnmpPorts[0],
186 mediatorConfigEditorMode: EditMediatorConfigDialogMode.AddMediatorConfig,
187 mediatorConfigToEdit: { ...emptyMediatorConfig },
194 private onOpenEditConfigurationDialog = (event: React.MouseEvent<HTMLElement>, configEntry: MediatorConfig) => {
195 event.preventDefault();
196 event.stopPropagation();
198 mediatorConfigEditorMode: EditMediatorConfigDialogMode.EditMediatorConfig,
199 mediatorConfigToEdit: configEntry,
203 private onOpenRemoveConfigutationDialog = (event: React.MouseEvent<HTMLElement>, configEntry: MediatorConfig) => {
204 event.preventDefault();
205 event.stopPropagation();
207 mediatorConfigEditorMode: EditMediatorConfigDialogMode.RemoveMediatorConfig,
208 mediatorConfigToEdit: configEntry,
212 private onCloseEditMediatorConfigDialog = () => {
214 mediatorConfigEditorMode: EditMediatorConfigDialogMode.None,
215 mediatorConfigToEdit: emptyMediatorConfig,
220 export const MediatorApplication = withStyles(styles)(connect(mapProps, mapDispatch)(MediatorApplicationComponent));