Add data-provider
[ccsdk/features.git] / sdnr / wt / odlux / apps / mediatorApp / src / views / mediatorApplication.tsx
1 /**
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
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
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
15  * the License.
16  * ============LICENSE_END==========================================================================
17  */
18 import * as React from 'react';
19 import { Theme, createStyles, WithStyles, withStyles, Tooltip } from '@material-ui/core';
20
21 import AddIcon from '@material-ui/icons/Add';
22 import IconButton from '@material-ui/core/IconButton';
23 import EditIcon from '@material-ui/icons/Edit';
24 import DeleteIcon from '@material-ui/icons/Delete';
25 import InfoIcon from '@material-ui/icons/Info';
26 import StartIcon from '@material-ui/icons/PlayArrow';
27 import StopIcon from '@material-ui/icons/Stop';
28
29 import CircularProgress from '@material-ui/core/CircularProgress'
30
31 import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
32 import connect, { Connect, IDispatcher } from '../../../../framework/src/flux/connect';
33 import MaterialTable, { MaterialTableCtorType, ColumnType } from '../../../../framework/src/components/material-table';
34
35 import { MediatorConfig, BusySymbol, MediatorConfigResponse } from '../models/mediatorServer';
36 import EditMediatorConfigDialog, { EditMediatorConfigDialogMode } from '../components/editMediatorConfigDialog';
37 import { startMediatorByNameAsyncActionCreator, stopMediatorByNameAsyncActionCreator } from '../actions/mediatorConfigActions';
38 import mediatorService from '../services/mediatorService';
39
40 const styles = (theme: Theme) => createStyles({
41   root: {
42     display: 'flex',
43     flexDirection: 'column',
44     flex: '1',
45   },
46   formControl: {
47     margin: theme.spacing.unit,
48     minWidth: 300,
49   },
50   button: {
51     margin: 0,
52     padding: "6px 6px",
53     minWidth: 'unset'
54   },
55   spacer: {
56     marginLeft: theme.spacing.unit,
57     marginRight: theme.spacing.unit,
58     display: "inline"
59   },
60   progress: {
61     flex: '1 1 100%',
62     display: 'flex',
63     alignItems: 'center',
64     justifyContent: 'center',
65     pointerEvents: 'none'
66   }
67 });
68
69 const mapProps = (state: IApplicationStoreState) => ({
70   serverName: state.mediator.mediatorServerState.name,
71   serverUrl: state.mediator.mediatorServerState.url,
72   serverId: state.mediator.mediatorServerState.id,
73   serverVersion: state.mediator.mediatorServerState.serverVersion,
74   mediatorVersion: state.mediator.mediatorServerState.mediatorVersion,
75   configurations: state.mediator.mediatorServerState.configurations,
76   supportedDevices: state.mediator.mediatorServerState.supportedDevices,
77   busy: state.mediator.mediatorServerState.busy,
78 });
79
80 const mapDispatch = (dispatcher: IDispatcher) => ({
81   startMediator: (name: string) => dispatcher.dispatch(startMediatorByNameAsyncActionCreator(name)),
82   stopMediator: (name: string) => dispatcher.dispatch(stopMediatorByNameAsyncActionCreator(name)),
83 });
84
85 const emptyMediatorConfig: MediatorConfig = {
86   Name: "",
87   DeviceIp: "127.0.0.1",
88   DevicePort: 161,
89   NcUsername: "admin",
90   NcPassword: "admin",
91   DeviceType: -1,
92   NcPort: 4020,
93   TrapPort: 10020,
94   NeXMLFile: "",
95   ODLConfig: []
96 };
97
98 const MediatorServerConfigurationsTable = MaterialTable as MaterialTableCtorType<MediatorConfigResponse>;
99
100 type MediatorApplicationComponentProps = Connect<typeof mapProps, typeof mapDispatch> & WithStyles<typeof styles>;
101
102 type MediatorServerSelectionComponentState = {
103   busy: boolean,
104   mediatorConfigToEdit: MediatorConfig,
105   mediatorConfigEditorMode: EditMediatorConfigDialogMode
106 }
107
108 class MediatorApplicationComponent extends React.Component<MediatorApplicationComponentProps, MediatorServerSelectionComponentState> {
109
110   constructor(props: MediatorApplicationComponentProps) {
111     super(props);
112
113     this.state = {
114       busy: false,
115       mediatorConfigToEdit: emptyMediatorConfig,
116       mediatorConfigEditorMode: EditMediatorConfigDialogMode.None,
117     }
118   }
119
120   render() {
121     const { classes } = this.props;
122
123     const renderActions = (rowData: MediatorConfigResponse) => (
124       <>
125         <div className={classes.spacer}>
126           <Tooltip title={"Start"} >
127             <IconButton disabled={rowData[BusySymbol]} className={classes.button}>
128               <StartIcon onClick={(event) => { event.preventDefault(); event.stopPropagation(); this.props.startMediator(rowData.Name); }} />
129             </IconButton>
130           </Tooltip>
131           <Tooltip title={"Stop"} >
132             <IconButton disabled={rowData[BusySymbol]} className={classes.button}>
133               <StopIcon onClick={(event) => { event.preventDefault(); event.stopPropagation(); this.props.stopMediator(rowData.Name); }} />
134             </IconButton>
135           </Tooltip>
136         </div>
137         <div className={classes.spacer}>
138           <Tooltip title={"Info"} ><IconButton className={classes.button}><InfoIcon /></IconButton></Tooltip>
139         </div>
140         <div className={classes.spacer}>
141           {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}
142           <Tooltip title={"Remove"} ><IconButton disabled={rowData[BusySymbol]} className={classes.button} onClick={event => this.onOpenRemoveConfigutationDialog(event, rowData)}><DeleteIcon /></IconButton></Tooltip>
143         </div>
144       </>
145     );
146
147     const addMediatorConfigAction = { icon: AddIcon, tooltip: 'Add', onClick: this.onOpenAddConfigurationDialog };
148     return (
149       <div className={classes.root}>
150         {this.props.busy || this.state.busy
151           ? <div className={classes.progress}> <CircularProgress color={"secondary"} size={48} /> </div>
152           : <MediatorServerConfigurationsTable title={this.props.serverName || ''} customActionButtons={[addMediatorConfigAction]} idProperty={"Name"} rows={this.props.configurations} asynchronus columns={[
153             { property: "Name", title: "Mediator", type: ColumnType.text },
154             { property: "Status", title: "Status", type: ColumnType.custom, customControl: ({ rowData }) => rowData.pid ? (<span>Running</span>) : (<span>Stopped</span>) },
155             { property: "DeviceIp", title: "IP Adress", type: ColumnType.text },
156             {
157               property: "Device", title: "Device", type: ColumnType.custom, customControl: ({ rowData }) => {
158                 const dev = this.props.supportedDevices && this.props.supportedDevices.find(dev => dev.id === rowData.DeviceType);
159                 return (
160                   <span> {dev && `${dev.vendor} - ${dev.device} (${dev.version || '0.0.0'})`} </span>
161                 )
162               }
163             },
164             { property: "actions", title: "Actions", type: ColumnType.custom, customControl: ({ rowData }) => renderActions(rowData) },
165           ]} />
166         }
167
168         <EditMediatorConfigDialog
169           mediatorConfig={this.state.mediatorConfigToEdit}
170           mode={this.state.mediatorConfigEditorMode}
171           onClose={this.onCloseEditMediatorConfigDialog} />
172
173       </div>
174     );
175   }
176
177   private onOpenAddConfigurationDialog = () => {
178     // Tries to determine a free port for netconf listener and snpm listener
179     // it it could not determine free ports the dialog will open any way
180     // those ports should not be configured from the fontend, furthermore
181     // the backend should auto configure them and tell the user the result
182     // after the creation process.
183
184     this.setState({
185       busy: true,
186     });
187     this.props.serverId && Promise.all([
188       mediatorService.getMediatorServerFreeNcPorts(this.props.serverId, 1),
189       mediatorService.getMediatorServerFreeSnmpPorts(this.props.serverId, 1),
190     ]).then(([freeNcPorts, freeSnmpPorts]) => {
191       if (freeNcPorts && freeSnmpPorts && freeNcPorts.length > 0 && freeSnmpPorts.length > 0) {
192         this.setState({
193           busy: false,
194           mediatorConfigEditorMode: EditMediatorConfigDialogMode.AddMediatorConfig,
195           mediatorConfigToEdit: {
196             ...emptyMediatorConfig,
197             NcPort: freeNcPorts[0],
198             TrapPort: freeSnmpPorts[0],
199           },
200         });
201       } else {
202         this.setState({
203           busy: false,
204           mediatorConfigEditorMode: EditMediatorConfigDialogMode.AddMediatorConfig,
205           mediatorConfigToEdit: { ...emptyMediatorConfig },
206         });
207       }
208     })
209
210   }
211
212   private onOpenEditConfigurationDialog = (event: React.MouseEvent<HTMLElement>, configEntry: MediatorConfig) => {
213     event.preventDefault();
214     event.stopPropagation();
215     this.setState({
216       mediatorConfigEditorMode: EditMediatorConfigDialogMode.EditMediatorConfig,
217       mediatorConfigToEdit: configEntry,
218     });
219   }
220
221   private onOpenRemoveConfigutationDialog = (event: React.MouseEvent<HTMLElement>, configEntry: MediatorConfig) => {
222     event.preventDefault();
223     event.stopPropagation();
224     this.setState({
225       mediatorConfigEditorMode: EditMediatorConfigDialogMode.RemoveMediatorConfig,
226       mediatorConfigToEdit: configEntry,
227     });
228   }
229
230   private onCloseEditMediatorConfigDialog = () => {
231     this.setState({
232       mediatorConfigEditorMode: EditMediatorConfigDialogMode.None,
233       mediatorConfigToEdit: emptyMediatorConfig,
234     });
235   }
236 }
237
238 export const MediatorApplication = withStyles(styles)(connect(mapProps, mapDispatch)(MediatorApplicationComponent));