Create wt-odlux directory
[ccsdk/features.git] / sdnr / wt-odlux / odlux / apps / performanceHistoryApp / src / views / performanceHistoryApplication.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 React from 'react';
19 import { connect, Connect, IDispatcher } from '../../../../framework/src/flux/connect';
20
21 import { Theme } from '@mui/material/styles';
22 import { WithStyles } from '@mui/styles';
23 import createStyles from '@mui/styles/createStyles';
24 import withStyles from '@mui/styles/withStyles';
25
26
27 import { NavigateToApplication } from '../../../../framework/src/actions/navigationActions';
28 import { Dispatch } from '../../../../framework/src/flux/store';
29 import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
30
31 import { loadAllDeviceListAsync } from '../actions/deviceListActions';
32 import { loadDistinctLtpsbyNetworkElementAsync, ResetLtpsAction } from '../actions/ltpAction';
33 import { SetPanelAction } from '../actions/panelChangeActions';
34 import { TimeChangeAction } from '../actions/timeChangeAction';
35 import AdaptiveModulation from '../components/adaptiveModulation';
36 import CrossPolarDiscrimination from '../components/crossPolarDiscrimination';
37 import PerformanceData from '../components/performanceData';
38 import ReceiveLevel from '../components/receiveLevel';
39 import SignalToInterference from '../components/signalToInterference';
40 import Temperature from '../components/temperature';
41 import TransmissionPower from '../components/transmissionPower';
42 import { adaptiveModulationReloadAction, createAdaptiveModulationActions, createAdaptiveModulationPreActions } from '../handlers/adaptiveModulationHandler';
43 import { createCrossPolarDiscriminationActions, createCrossPolarDiscriminationPreActions, crossPolarDiscriminationReloadAction } from '../handlers/crossPolarDiscriminationHandler';
44 import { createPerformanceDataActions, createPerformanceDataPreActions, performanceDataReloadAction } from '../handlers/performanceDataHandler';
45 import { createReceiveLevelActions, createReceiveLevelPreActions, receiveLevelReloadAction } from '../handlers/receiveLevelHandler';
46 import { createSignalToInterferenceActions, createSignalToInterferencePreActions, signalToInterferenceReloadAction } from '../handlers/signalToInterferenceHandler';
47 import { createTemperatureActions, createTemperaturePreActions, temperatureReloadAction } from '../handlers/temperatureHandler';
48 import { createTransmissionPowerActions, createTransmissionPowerPreActions, transmissionPowerReloadAction } from '../handlers/transmissionPowerHandler';
49 import { PanelId } from '../models/panelId';
50 import { PmDataInterval } from '../models/performanceDataType';
51
52 import { AppBar, SelectChangeEvent, Tab, Tabs } from '@mui/material';
53 import { MaterialTable, MaterialTableCtorType } from '../../../../framework/src/components/material-table';
54 import { ReloadAction } from '../actions/reloadAction';
55 import { ResetAllSubViewsAction } from '../actions/toggleActions';
56 import LtpSelection from '../components/ltpSelection';
57
58 const PerformanceHistoryComponentStyles = (theme: Theme) => createStyles({
59   root: {
60     display: 'flex',
61     flexWrap: 'wrap',
62   },
63   margin: {
64     margin: theme.spacing(1),
65   },
66 });
67
68 const mapProps = (state: IApplicationStoreState) => ({
69   ...state.performanceHistory,
70   activePanel: state.performanceHistory.currentOpenPanel,
71   availableLtps: state.performanceHistory.ltps.distinctLtps,
72   networkElements: state.performanceHistory.networkElements.deviceList,
73   initialLoaded: state.performanceHistory.ltps.loadedOnce,
74   error: state.performanceHistory.ltps.error,
75   shouldReload: state.performanceHistory.isReloadSchedueled,
76 });
77
78 const mapDispatcher = (dispatcher: IDispatcher) => ({
79   enableFilterPerformanceData: createPerformanceDataActions(dispatcher.dispatch),
80   enableFilterReceiveLevel: createReceiveLevelActions(dispatcher.dispatch),
81   enableFilterTransmissionPower: createTransmissionPowerActions(dispatcher.dispatch),
82   enableFilterAdaptiveModulation: createAdaptiveModulationActions(dispatcher.dispatch),
83   enableFilterTemperature: createTemperatureActions(dispatcher.dispatch),
84   enableFilterSinr: createSignalToInterferenceActions(dispatcher.dispatch),
85   enableFilterCpd: createCrossPolarDiscriminationActions(dispatcher.dispatch),
86   reloadPerformanceData: () => dispatcher.dispatch(performanceDataReloadAction),
87   reloadReceiveLevel: () => dispatcher.dispatch(receiveLevelReloadAction),
88   reloadTransmissionPower: () => dispatcher.dispatch(transmissionPowerReloadAction),
89   reloadAdaptiveModulation: () => dispatcher.dispatch(adaptiveModulationReloadAction),
90   reloadTemperature: () => dispatcher.dispatch(temperatureReloadAction),
91   reloadSignalToInterference: () => dispatcher.dispatch(signalToInterferenceReloadAction),
92   reloadCrossPolarDiscrimination: () => dispatcher.dispatch(crossPolarDiscriminationReloadAction),
93   performanceDataPreActions: createPerformanceDataPreActions(dispatcher.dispatch),
94   receiveLevelPreActions: createReceiveLevelPreActions(dispatcher.dispatch),
95   transmissionPowerPreActions: createTransmissionPowerPreActions(dispatcher.dispatch),
96   adaptiveModulationPreActions: createAdaptiveModulationPreActions(dispatcher.dispatch),
97   temperaturePreActions: createTemperaturePreActions(dispatcher.dispatch),
98   signalToInterferencePreActions: createSignalToInterferencePreActions(dispatcher.dispatch),
99   crossPolarDiscriminationPreActions: createCrossPolarDiscriminationPreActions(dispatcher.dispatch),
100   getAllDevicesPMdata: async () => {
101     await dispatcher.dispatch(loadAllDeviceListAsync);
102   },
103   getDistinctLtpsIds: (
104     selectedNetworkElement: string, 
105     selectedTimePeriod: string, 
106     selectedLtp: string, 
107     selectFirstLtp?: Function, 
108     resetLTP?: Function,
109   ) => dispatcher.dispatch(loadDistinctLtpsbyNetworkElementAsync(selectedNetworkElement, selectedTimePeriod, selectedLtp, selectFirstLtp, resetLTP)),
110   setCurrentPanel: (panelId: PanelId) => dispatcher.dispatch(new SetPanelAction(panelId)),
111   timeIntervalChange: (time: PmDataInterval) => dispatcher.dispatch(new TimeChangeAction(time)),
112   changeNode: (nodeId: string) => dispatcher.dispatch((dispatch: Dispatch) => {
113     dispatch(new NavigateToApplication('performanceHistory', nodeId));
114   }),
115   resetLtps: () => dispatcher.dispatch((dispatch: Dispatch) => { dispatch(new ResetLtpsAction()); }),
116   resetSubViews: () => dispatcher.dispatch(new ResetAllSubViewsAction()),
117   setShouldReload: (show: boolean) => dispatcher.dispatch(new ReloadAction(show)),
118 });
119
120 export type NetworkElementType = {
121   nodeId: string;
122 };
123
124 const NetworkElementTable = MaterialTable as MaterialTableCtorType<NetworkElementType>;
125
126 type PerformanceHistoryComponentProps = Connect<typeof mapProps, typeof mapDispatcher> & WithStyles<typeof PerformanceHistoryComponentStyles>;
127
128 type PerformanceHistoryComponentState = {
129   selectedNetworkElement: string;
130   selectedTimePeriod: string;
131   selectedLtp: string;
132   showNetworkElementsTable: boolean;
133   showLtps: boolean;
134   showPanels: boolean;
135   preFilter:
136   {
137     'node-name': string;
138     'uuid-interface': string;
139   } | {};
140 };
141
142 /**
143 * Represents the component for Performance history application.
144 */
145 class PerformanceHistoryComponent extends React.Component<PerformanceHistoryComponentProps, PerformanceHistoryComponentState> {
146   /**
147   * Initialises this instance
148   */
149   constructor(props: PerformanceHistoryComponentProps) {
150     super(props);
151     this.state = {
152       selectedNetworkElement: props.nodeId !== '' ? props.nodeId : '-1',
153       selectedTimePeriod: '15min',
154       selectedLtp: '-1',
155       showNetworkElementsTable: true,
156       showLtps: false,
157       showPanels: false,
158       preFilter: {},
159     };
160   }
161
162   onChangeTabs = (event: React.SyntheticEvent, newValue: PanelId) => {
163     const nextActivePanel = newValue;
164     this.changeTabs(nextActivePanel);
165   };
166
167   changeTabs = (nextActivePanel: PanelId) => {
168     this.props.setCurrentPanel(nextActivePanel);
169     const preFilter = this.state.preFilter;
170     switch (nextActivePanel) {
171       case 'PerformanceData':
172         if (this.props.performanceData.preFilter !== {} && this.props.performanceData.preFilter === preFilter) {
173           this.props.reloadPerformanceData();
174         } else {
175           this.props.performanceDataPreActions.onPreFilterChanged(preFilter);
176         }
177         break;
178       case 'ReceiveLevel':
179         if (this.props.receiveLevel.preFilter !== {} && this.props.receiveLevel.preFilter === preFilter) {
180           this.props.reloadReceiveLevel();
181         } else {
182           this.props.receiveLevelPreActions.onPreFilterChanged(preFilter);
183         }
184         break;
185       case 'TransmissionPower':
186         if (this.props.transmissionPower.preFilter !== {} && this.props.transmissionPower.preFilter === preFilter) {
187           this.props.reloadTransmissionPower();
188         } else {
189           this.props.transmissionPowerPreActions.onPreFilterChanged(preFilter);
190         }
191         break;
192       case 'AdaptiveModulation':
193         if (this.props.adaptiveModulation.preFilter !== {} && this.props.adaptiveModulation.preFilter === preFilter) {
194           this.props.reloadAdaptiveModulation();
195         } else {
196           this.props.adaptiveModulationPreActions.onPreFilterChanged(preFilter);
197         }
198         break;
199       case 'Temperature':
200         if (this.props.temperature.preFilter !== {} && this.props.temperature.preFilter === preFilter) {
201           this.props.reloadTemperature();
202         } else {
203           this.props.temperaturePreActions.onPreFilterChanged(preFilter);
204         }
205         break;
206       case 'SINR':
207         if (this.props.signalToInterference.preFilter !== {} && this.props.signalToInterference.preFilter === preFilter) {
208           this.props.reloadSignalToInterference();
209         } else {
210           this.props.signalToInterferencePreActions.onPreFilterChanged(preFilter);
211         }
212         break;
213       case 'CPD':
214         if (this.props.crossPolarDiscrimination.preFilter !== {} && this.props.crossPolarDiscrimination.preFilter === preFilter) {
215           this.props.reloadCrossPolarDiscrimination();
216         } else {
217           this.props.crossPolarDiscriminationPreActions.onPreFilterChanged(preFilter);
218         }
219         break;
220       default:
221         // do nothing if all panels are closed
222         break;
223     }
224   };
225
226   render(): JSX.Element {
227     const { activePanel, nodeId } = this.props;
228     if (nodeId === '') {
229       return (
230         <>
231           <NetworkElementTable tableId="performance-data-element-selection-table" defaultSortColumn={'nodeId'} defaultSortOrder="asc" stickyHeader title={'Please select the network element!'} idProperty={'nodeId'} rows={this.props.networkElements} asynchronus
232             onHandleClick={(event, rowData) => { this.handleNetworkElementSelect(rowData.nodeId); }} columns={
233               [{ property: 'nodeId', title: 'Node Name' }]
234             } />
235         </>
236       );
237     } else {
238       this.handleURLChange(nodeId);
239       return (
240         <>
241           {this.state.showLtps &&
242
243             <LtpSelection error={this.props.error} selectedNE={this.state.selectedNetworkElement} selectedLtp={this.state.selectedLtp} selectedTimePeriod={this.state.selectedTimePeriod}
244               availableLtps={this.props.availableLtps} finishedLoading={this.props.initialLoaded} onChangeTimePeriod={this.handleTimePeriodChange}
245               onChangeLtp={this.handleLtpChange}
246             />
247           }
248           {this.state.showPanels &&
249             <>
250
251               <AppBar enableColorOnDark position="static" >
252                 <Tabs indicatorColor="secondary" textColor="inherit" value={activePanel} onChange={this.onChangeTabs} variant="scrollable" scrollButtons="auto" aria-label="performance-data-tabs">
253                   <Tab label="Performance Data" value="PerformanceData" aria-label="performance-data" />
254                   <Tab label="Receive Level" value="ReceiveLevel" aria-label="receive-level" />
255                   <Tab label="Transmission Power" value="TransmissionPower" aria-label="transmission-power" />
256                   <Tab label="Adaptive Modulation" value="AdaptiveModulation" aria-label="adaptive-modulation" />
257                   <Tab label="Temperature" value="Temperature" aria-label="temperature"  />
258                   <Tab label="Signal-to-interference-plus-noise ratio (SINR)" value="SINR" aria-label="sinr" />
259                   <Tab label="Cross Polar Discrimination" value="CPD" aria-label="cross-polar-discrimination" />
260                 </Tabs>
261               </AppBar>
262               {
263                 activePanel === 'PerformanceData' &&
264                 <PerformanceData selectedTimePeriod={this.state.selectedTimePeriod} />
265               }
266
267               {
268                 activePanel === 'ReceiveLevel' &&
269                 <ReceiveLevel selectedTimePeriod={this.state.selectedTimePeriod} />
270               }
271
272               {
273                 activePanel === 'TransmissionPower' &&
274                 <TransmissionPower selectedTimePeriod={this.state.selectedTimePeriod} />
275               }
276
277               {
278                 activePanel === 'AdaptiveModulation' &&
279                 <AdaptiveModulation selectedTimePeriod={this.state.selectedTimePeriod} />
280               }
281               {
282                 activePanel === 'Temperature' &&
283                 <Temperature selectedTimePeriod={this.state.selectedTimePeriod} />
284               }
285
286               {
287                 activePanel === 'SINR' &&
288                 <SignalToInterference selectedTimePeriod={this.state.selectedTimePeriod} />
289               }
290
291               {
292                 activePanel === 'CPD' &&
293                 <CrossPolarDiscrimination selectedTimePeriod={this.state.selectedTimePeriod} />
294               }
295             </>
296           }
297         </>
298       );
299     }
300   }
301
302
303   public componentDidMount() {
304     this.props.setCurrentPanel(null);
305     this.props.getAllDevicesPMdata();
306   }
307
308   /**
309   * Function which selects the first ltp returned from the database on selection of network element.
310   */
311   private selectFirstLtp = (firstLtp: string) => {
312     this.setState({
313       showPanels: true,
314       selectedLtp: firstLtp,
315     });
316     this.preFilterChangeAndReload(this.state.selectedNetworkElement, this.state.selectedTimePeriod, firstLtp);
317     this.changeTabs('PerformanceData');
318   };
319
320   /**
321   * A function which reloads the visible table, if available, based on prefilters defined by network element and ltp on selected time period.
322   */
323   private preFilterChangeAndReload = (networkElement: string, timePeriod: string, ltp: string) => {
324     const newPreFilter = {
325       'node-name': networkElement,
326       'uuid-interface': ltp,
327     };
328
329     const activePanel = this.props.activePanel;
330
331     if (this.props.activePanel !== null) {
332       // set prefilter and reload data if panel is open
333
334       switch (activePanel) {
335         case 'PerformanceData':
336           this.props.performanceDataPreActions.onPreFilterChanged(newPreFilter);
337           break;
338         case 'ReceiveLevel':
339           this.props.receiveLevelPreActions.onPreFilterChanged(newPreFilter);
340           break;
341         case 'TransmissionPower':
342           this.props.transmissionPowerPreActions.onPreFilterChanged(newPreFilter);
343           break;
344         case 'AdaptiveModulation':
345           this.props.adaptiveModulationPreActions.onPreFilterChanged(newPreFilter);
346           break;
347         case 'Temperature':
348           this.props.temperaturePreActions.onPreFilterChanged(newPreFilter);
349           break;
350         case 'SINR':
351           this.props.signalToInterferencePreActions.onPreFilterChanged(newPreFilter);
352           break;
353         case 'CPD':
354           this.props.crossPolarDiscriminationPreActions.onPreFilterChanged(newPreFilter);
355           break;
356         default:
357           // do nothing if all panels are closed
358           break;
359       }
360     }
361
362     // set prefilter
363     this.setState({ preFilter: newPreFilter });
364
365   };
366
367   /**
368    * Function which handles network element changes.
369    */
370   private handleNetworkElementSelect = (selectedNetworkElement: string) => {
371
372     this.setState({
373       showLtps: true,
374       selectedNetworkElement: selectedNetworkElement,
375       showNetworkElementsTable: false,
376       showPanels: false,
377       selectedLtp: '-1',
378     });
379
380     this.props.resetSubViews();
381     this.props.resetLtps();
382     this.setState({ preFilter: {} });
383     this.props.changeNode(selectedNetworkElement);
384     this.props.getDistinctLtpsIds(selectedNetworkElement, this.state.selectedTimePeriod, '-1', this.selectFirstLtp);
385   };
386
387   private handleURLChange = (selectedNetworkElement: string) => {
388
389     if (this.props.shouldReload) {
390
391       this.setState({
392         showLtps: true,
393         selectedNetworkElement: selectedNetworkElement,
394         showPanels: false,
395         selectedLtp: '-1',
396       });
397       this.props.getDistinctLtpsIds(selectedNetworkElement, this.state.selectedTimePeriod, '-1', this.selectFirstLtp);
398       this.props.setShouldReload(false);
399     }
400   };
401
402   /**
403     * Function which resets the ltps to "--select--" in the state if the passed parameter @ltpNotSelected is true.
404     * @param ltpNotSelected: true, if existing selected is not available in the given time period, else false
405     */
406   private resetLtpDropdown = (ltpNotSelected: boolean) => {
407     if (ltpNotSelected) {
408       this.setState({
409         selectedLtp: '-1',
410         showPanels: false,
411       });
412     }
413   };
414
415   /**
416   * Function which handles the time period changes.
417   */
418   private handleTimePeriodChange = (event: SelectChangeEvent<HTMLSelectElement>) => {
419
420     const selectedTimeInterval = event.target.value === '15min'
421       ? PmDataInterval.pmInterval15Min
422       : PmDataInterval.pmInterval24Hours;
423
424     this.setState({
425       selectedTimePeriod: event.target.value as string,
426     });
427
428     this.props.timeIntervalChange(selectedTimeInterval);
429     this.props.getDistinctLtpsIds(this.state.selectedNetworkElement, event.target.value as string, this.state.selectedLtp, undefined, this.resetLtpDropdown);
430     this.preFilterChangeAndReload(this.state.selectedNetworkElement, event.target.value as string, this.state.selectedLtp);
431   };
432
433   /**
434   * Function which handles the ltp changes.
435   */
436   private handleLtpChange = (event:SelectChangeEvent<HTMLSelectElement> ) => {
437
438     if (event.target.value === '-1') {
439       this.setState({
440         showPanels: false,
441         selectedLtp: event.target.value,
442       });
443
444     } else if (event.target.value !== this.state.selectedLtp) {
445       this.setState({
446         showPanels: true,
447         selectedLtp: event.target.value as string,
448       });
449       this.preFilterChangeAndReload(this.state.selectedNetworkElement, this.state.selectedTimePeriod, event.target.value as string);
450
451     }
452   };
453 }
454
455 const PerformanceHistoryApplication = withStyles(PerformanceHistoryComponentStyles)(connect(mapProps, mapDispatcher)(PerformanceHistoryComponent));
456 export default PerformanceHistoryApplication;