2 * ============LICENSE_START========================================================================
3 * ONAP : ccsdk feature sdnr wt odlux
4 * =================================================================================================
5 * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
6 * =================================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
8 * in compliance with the License. You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software distributed under the License
13 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
14 * or implied. See the License for the specific language governing permissions and limitations under
16 * ============LICENSE_END==========================================================================
18 import React from 'react';
19 import { Theme, Tooltip } from '@mui/material';
21 import { WithStyles } from '@mui/styles';
22 import createStyles from '@mui/styles/createStyles';
23 import withStyles from '@mui/styles/withStyles';
25 import AddIcon from '@mui/icons-material/Add';
26 import IconButton from '@mui/material/IconButton';
27 import EditIcon from '@mui/icons-material/Edit';
28 import DeleteIcon from '@mui/icons-material/Delete';
29 import InfoIcon from '@mui/icons-material/Info';
30 import StartIcon from '@mui/icons-material/PlayArrow';
31 import StopIcon from '@mui/icons-material/Stop';
33 import CircularProgress from '@mui/material/CircularProgress'
35 import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
36 import { connect, Connect, IDispatcher } from '../../../../framework/src/flux/connect';
37 import MaterialTable, { MaterialTableCtorType, ColumnType } from '../../../../framework/src/components/material-table';
39 import { MediatorConfig, BusySymbol, MediatorConfigResponse } from '../models/mediatorServer';
40 import EditMediatorConfigDialog, { EditMediatorConfigDialogMode } from '../components/editMediatorConfigDialog';
41 import { startMediatorByNameAsyncActionCreator, stopMediatorByNameAsyncActionCreator } from '../actions/mediatorConfigActions';
42 import mediatorService from '../services/mediatorService';
43 import { ShowMediatorInfoDialog, MediatorInfoDialogMode } from '../components/showMeditaorInfoDialog'
45 const styles = (theme: Theme) => createStyles({
48 flexDirection: 'column',
52 margin: theme.spacing(1),
61 marginLeft: theme.spacing(1),
62 marginRight: theme.spacing(1),
69 justifyContent: 'center',
74 const mapProps = (state: IApplicationStoreState) => ({
75 serverName: state.mediator.mediatorServerState.name,
76 serverUrl: state.mediator.mediatorServerState.url,
77 serverId: state.mediator.mediatorServerState.id,
78 serverVersion: state.mediator.mediatorServerState.serverVersion,
79 mediatorVersion: state.mediator.mediatorServerState.mediatorVersion,
80 configurations: state.mediator.mediatorServerState.configurations,
81 supportedDevices: state.mediator.mediatorServerState.supportedDevices,
82 busy: state.mediator.mediatorServerState.busy,
83 isReachable: state.mediator.mediatorServerState.isReachable
86 const mapDispatch = (dispatcher: IDispatcher) => ({
87 startMediator: (name: string) => dispatcher.dispatch(startMediatorByNameAsyncActionCreator(name)),
88 stopMediator: (name: string) => dispatcher.dispatch(stopMediatorByNameAsyncActionCreator(name)),
91 const emptyMediatorConfig: MediatorConfig = {
93 DeviceIp: "127.0.0.1",
104 const MediatorServerConfigurationsTable = MaterialTable as MaterialTableCtorType<MediatorConfigResponse>;
105 const MediatorServerUnreachableTable = MaterialTable as MaterialTableCtorType<{ Name: string, status: string, ipAdress: string, device: string, actions: string }>
107 type MediatorApplicationComponentProps = Connect<typeof mapProps, typeof mapDispatch> & WithStyles<typeof styles>;
109 type MediatorServerSelectionComponentState = {
111 mediatorConfigToEdit: MediatorConfig,
112 mediatorConfigEditorMode: EditMediatorConfigDialogMode,
113 mediatorShowInfoMode: MediatorInfoDialogMode,
114 mediatorConfigToDisplay: MediatorConfigResponse | null
117 class MediatorApplicationComponent extends React.Component<MediatorApplicationComponentProps, MediatorServerSelectionComponentState> {
119 constructor(props: MediatorApplicationComponentProps) {
124 mediatorConfigToEdit: emptyMediatorConfig,
125 mediatorConfigEditorMode: EditMediatorConfigDialogMode.None,
126 mediatorShowInfoMode: MediatorInfoDialogMode.None,
127 mediatorConfigToDisplay: null
132 const { classes } = this.props;
134 const renderActions = (rowData: MediatorConfigResponse) => (
136 <div className={classes.spacer}>
137 <Tooltip disableInteractive title={"Start"} >
138 <IconButton disabled={rowData[BusySymbol]} className={classes.button} size="large">
139 <StartIcon onClick={(event) => { event.preventDefault(); event.stopPropagation(); this.props.startMediator(rowData.Name); }} />
142 <Tooltip disableInteractive title={"Stop"} >
143 <IconButton disabled={rowData[BusySymbol]} className={classes.button} size="large">
144 <StopIcon onClick={(event) => { event.preventDefault(); event.stopPropagation(); this.props.stopMediator(rowData.Name); }} />
148 <div className={classes.spacer}>
149 <Tooltip disableInteractive title={"Info"} ><IconButton
150 className={classes.button}
151 onClick={(event) => { this.onOpenInfoDialog(event, rowData) }}
152 size="large"><InfoIcon /></IconButton></Tooltip>
154 <div className={classes.spacer}>
155 {process.env.NODE_ENV === "development" ? <Tooltip disableInteractive title={"Edit"} ><IconButton
156 disabled={rowData[BusySymbol]}
157 className={classes.button}
158 onClick={event => this.onOpenEditConfigurationDialog(event, rowData)}
159 size="large"><EditIcon /></IconButton></Tooltip> : null}
160 <Tooltip disableInteractive title={"Remove"} ><IconButton
161 disabled={rowData[BusySymbol]}
162 className={classes.button}
163 onClick={event => this.onOpenRemoveConfigutationDialog(event, rowData)}
164 size="large"><DeleteIcon /></IconButton></Tooltip>
169 const addMediatorConfigAction = { icon: AddIcon, tooltip: 'Add', ariaLabel: 'add-element', onClick: this.onOpenAddConfigurationDialog };
172 <div className={classes.root}>
173 {this.props.busy || this.state.busy
174 ? <div className={classes.progress}> <CircularProgress color={"secondary"} size={48} /> </div>
177 this.props.isReachable ?
179 <MediatorServerConfigurationsTable defaultSortColumn={"Name"} tableId={null} defaultSortOrder="asc" stickyHeader title={this.props.serverName || ''} customActionButtons={[addMediatorConfigAction]} idProperty={"Name"} rows={this.props.configurations} asynchronus columns={[
180 { property: "Name", title: "Mediator", type: ColumnType.text },
181 { property: "Status", title: "Status", type: ColumnType.custom, customControl: ({ rowData }) => rowData.pid ? (<span>Running</span>) : (<span>Stopped</span>) },
182 { property: "DeviceIp", title: "IP Adress", type: ColumnType.text },
184 property: "Device", title: "Device", type: ColumnType.custom, customControl: ({ rowData }) => {
185 const dev = this.props.supportedDevices && this.props.supportedDevices.find(dev => dev.id === rowData.DeviceType);
187 <span> {dev && `${dev.vendor} - ${dev.device} (${dev.version || '0.0.0'})`} </span>
191 { property: "actions", title: "Actions", type: ColumnType.custom, customControl: ({ rowData }) => renderActions(rowData) },
194 <MediatorServerUnreachableTable title={this.props.serverName || ''} tableId={null} idProperty={"Name"} disableFilter={true} disableSorting={true} enableSelection={false} rows={[{ Name: '', status: "Mediator server not found.", ipAdress: '', device: '', actions: '' }]} columns={[
195 { property: "Name", title: "Mediator", type: ColumnType.text },
196 { property: "status", title: "Status", type: ColumnType.text },
197 { property: "ipAdress", title: "IP Adress", type: ColumnType.text },
198 { property: "device", title: "Device", type: ColumnType.text },
199 { property: "actions", title: "Actions", type: ColumnType.text },
204 <EditMediatorConfigDialog
205 mediatorConfig={this.state.mediatorConfigToEdit}
206 mode={this.state.mediatorConfigEditorMode}
207 onClose={this.onCloseEditMediatorConfigDialog} />
211 this.state.mediatorShowInfoMode != MediatorInfoDialogMode.None &&
212 <ShowMediatorInfoDialog
213 config={this.state.mediatorConfigToDisplay as MediatorConfigResponse}
214 mode={this.state.mediatorShowInfoMode}
215 onClose={this.onCloseInfoDialog} />
221 private onOpenInfoDialog = (event: React.MouseEvent<HTMLElement>, configEntry: MediatorConfigResponse) => {
222 event.stopPropagation();
223 event.preventDefault();
224 this.setState({ mediatorShowInfoMode: MediatorInfoDialogMode.ShowDetails, mediatorConfigToDisplay: configEntry })
227 private onCloseInfoDialog = () => {
228 this.setState({ mediatorShowInfoMode: MediatorInfoDialogMode.None, mediatorConfigToDisplay: null })
231 private onOpenAddConfigurationDialog = () => {
232 // Tries to determine a free port for netconf listener and snpm listener
233 // it it could not determine free ports the dialog will open any way
234 // those ports should not be configured from the fontend, furthermore
235 // the backend should auto configure them and tell the user the result
236 // after the creation process.
240 this.props.serverId && Promise.all([
241 mediatorService.getMediatorServerFreeNcPorts(this.props.serverId, 1),
242 mediatorService.getMediatorServerFreeSnmpPorts(this.props.serverId, 1),
243 ]).then(([freeNcPorts, freeSnmpPorts]) => {
244 if (freeNcPorts && freeSnmpPorts && freeNcPorts.length > 0 && freeSnmpPorts.length > 0) {
247 mediatorConfigEditorMode: EditMediatorConfigDialogMode.AddMediatorConfig,
248 mediatorConfigToEdit: {
249 ...emptyMediatorConfig,
250 NcPort: freeNcPorts[0],
251 TrapPort: freeSnmpPorts[0],
257 mediatorConfigEditorMode: EditMediatorConfigDialogMode.AddMediatorConfig,
258 mediatorConfigToEdit: { ...emptyMediatorConfig },
265 private onOpenEditConfigurationDialog = (event: React.MouseEvent<HTMLElement>, configEntry: MediatorConfig) => {
266 event.preventDefault();
267 event.stopPropagation();
269 mediatorConfigEditorMode: EditMediatorConfigDialogMode.EditMediatorConfig,
270 mediatorConfigToEdit: configEntry,
274 private onOpenRemoveConfigutationDialog = (event: React.MouseEvent<HTMLElement>, configEntry: MediatorConfig) => {
275 event.preventDefault();
276 event.stopPropagation();
278 mediatorConfigEditorMode: EditMediatorConfigDialogMode.RemoveMediatorConfig,
279 mediatorConfigToEdit: configEntry,
283 private onCloseEditMediatorConfigDialog = () => {
285 mediatorConfigEditorMode: EditMediatorConfigDialogMode.None,
286 mediatorConfigToEdit: emptyMediatorConfig,
291 export const MediatorApplication = withStyles(styles)(connect(mapProps, mapDispatch)(MediatorApplicationComponent));