Create wt-odlux directory
[ccsdk/features.git] / sdnr / wt-odlux / odlux / apps / faultApp / src / views / faultApplication.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 { RouteComponentProps, withRouter } from 'react-router-dom';
20
21 import Refresh from '@mui/icons-material/Refresh';
22 import Sync from '@mui/icons-material/Sync';
23 import { AppBar, Tab, Tabs } from '@mui/material';
24
25 import { ColumnType, MaterialTable, MaterialTableCtorType } from '../../../../framework/src/components/material-table';
26 import { connect, Connect, IDispatcher } from '../../../../framework/src/flux/connect';
27 import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
28
29 import { setPanelAction } from '../actions/panelChangeActions';
30 import ClearStuckAlarmsDialog, { ClearStuckAlarmsDialogMode } from '../components/clearStuckAlarmsDialog';
31 import RefreshAlarmLogDialog, { RefreshAlarmLogDialogMode } from '../components/refreshAlarmLogDialog';
32 import RefreshCurrentAlarmsDialog, { RefreshCurrentAlarmsDialogMode } from '../components/refreshCurrentAlarmsDialog';
33 import { alarmLogEntriesReloadAction, createAlarmLogEntriesActions, createAlarmLogEntriesProperties } from '../handlers/alarmLogEntriesHandler';
34 import { createCurrentAlarmsActions, createCurrentAlarmsProperties, currentAlarmsReloadAction } from '../handlers/currentAlarmsHandler';
35 import { Fault, FaultAlarmNotification } from '../models/fault';
36 import { PanelId } from '../models/panelId';
37
38 const mapProps = (state: IApplicationStoreState) => ({
39   panelId: state.fault.currentOpenPanel,
40   currentAlarmsProperties: createCurrentAlarmsProperties(state),
41   faultNotifications: state.fault.faultNotifications,
42   alarmLogEntriesProperties: createAlarmLogEntriesProperties(state),
43 });
44
45 const mapDisp = (dispatcher: IDispatcher) => ({
46   currentAlarmsActions: createCurrentAlarmsActions(dispatcher.dispatch),
47   alarmLogEntriesActions: createAlarmLogEntriesActions(dispatcher.dispatch),
48   reloadCurrentAlarms: () => dispatcher.dispatch(currentAlarmsReloadAction),
49   reloadAlarmLogEntries: () => dispatcher.dispatch(alarmLogEntriesReloadAction),
50   switchActivePanel: (panelId: PanelId) => {
51     dispatcher.dispatch(setPanelAction(panelId));
52   },
53 });
54
55 type FaultApplicationComponentProps = RouteComponentProps & Connect<typeof mapProps, typeof mapDisp>;
56
57 type FaultApplicationState = {
58   clearAlarmDialogMode: ClearStuckAlarmsDialogMode;
59   stuckAlarms: string[];
60   refreshAlarmLogEditorMode: RefreshAlarmLogDialogMode;
61   refreshCurrentAlarmsEditorMode: RefreshCurrentAlarmsDialogMode;
62 };
63
64
65 const FaultTable = MaterialTable as MaterialTableCtorType<Fault>;
66 const FaultAlarmNotificationTable = MaterialTable as MaterialTableCtorType<FaultAlarmNotification>;
67
68 let currentAlarmsInitalSorted = false;
69 let alarmLogInitialSorted = false;
70
71 class FaultApplicationComponent extends React.Component<FaultApplicationComponentProps, FaultApplicationState> {
72   constructor(props: FaultApplicationComponentProps) {
73     super(props);
74     this.state = {
75       clearAlarmDialogMode: ClearStuckAlarmsDialogMode.None,
76       stuckAlarms: [],
77       refreshAlarmLogEditorMode: RefreshAlarmLogDialogMode.None,
78       refreshCurrentAlarmsEditorMode: RefreshCurrentAlarmsDialogMode.None,
79     };
80   }
81
82   onDialogClose = () => {
83     this.setState({ clearAlarmDialogMode: ClearStuckAlarmsDialogMode.None, stuckAlarms: [] });
84   };
85
86   onDialogOpen = () => {
87     const stuckAlarms = [...new Set(this.props.currentAlarmsProperties.rows.map(item => item.nodeId))];
88     this.setState({ clearAlarmDialogMode: ClearStuckAlarmsDialogMode.Show, stuckAlarms: stuckAlarms });
89   };
90
91   private onHandleTabChange = (event: React.SyntheticEvent, newValue: PanelId) => {
92     this.onToggleTabs(newValue);
93   };
94
95   private onToggleTabs = (panelId: PanelId) => {
96     const nextActivePanel = panelId;
97     this.props.switchActivePanel(nextActivePanel);
98     switch (nextActivePanel) {
99       case 'CurrentAlarms':
100         if (!currentAlarmsInitalSorted) {
101           currentAlarmsInitalSorted = true;
102           this.props.currentAlarmsActions.onHandleExplicitRequestSort('timestamp', 'desc');
103         } else {
104           this.props.reloadCurrentAlarms();
105         }
106         break;
107       case 'AlarmLog':
108         if (!alarmLogInitialSorted) {
109           alarmLogInitialSorted = true;
110           this.props.alarmLogEntriesActions.onHandleExplicitRequestSort('timestamp', 'desc');
111         } else {
112           this.props.reloadAlarmLogEntries();
113         }
114         break;
115       case 'AlarmNotifications':
116       case null:
117       default:
118         // nothing to do
119         break;
120     }
121   };
122
123
124
125   render(): JSX.Element {
126
127     const clearAlarmsAction = {
128       icon: Sync, tooltip: 'Clear stuck alarms', ariaLabel:'clear-stuck-alarms', onClick: this.onDialogOpen,
129     };
130
131     const refreshCurrentAlarmsAction = {
132       icon: Refresh, tooltip: 'Refresh Current Alarms List', ariaLabel:'refresh', onClick: () => {
133         this.setState({
134           refreshCurrentAlarmsEditorMode: RefreshCurrentAlarmsDialogMode.RefreshCurrentAlarmsTable,
135         });
136       },
137     };
138
139     const refreshAlarmLogAction = {
140       icon: Refresh, tooltip: 'Refresh Alarm log table', ariaLabel:'refresh', onClick: () => {
141         this.setState({
142           refreshAlarmLogEditorMode: RefreshAlarmLogDialogMode.RefreshAlarmLogTable,
143         });
144       },
145     };
146
147     const areFaultsAvailable = this.props.currentAlarmsProperties.rows && this.props.currentAlarmsProperties.rows.length > 0;
148     const customActions = areFaultsAvailable ? [clearAlarmsAction, refreshCurrentAlarmsAction] : [refreshCurrentAlarmsAction];
149
150     const { panelId: activePanelId } = this.props;
151
152     return (
153       <>
154         <AppBar enableColorOnDark position="static" >
155           <Tabs indicatorColor="secondary" textColor="inherit" value={activePanelId} onChange={this.onHandleTabChange} aria-label="fault-tabs">
156             <Tab aria-label="current-alarms-list-tab" label="Current Alarms" value="CurrentAlarms" />
157             <Tab aria-label="alarm-notifications-list-tab" label={`Alarm Notifications (${this.props.faultNotifications.faults.length})`} value="AlarmNotifications" />
158             <Tab aria-label="alarm-log-tab" label="Alarm Log" value="AlarmLog" />
159           </Tabs>
160         </AppBar>
161         {
162           activePanelId === 'CurrentAlarms' &&
163           <>
164             <FaultTable stickyHeader tableId="current-alarms-table" idProperty="id" customActionButtons={customActions} columns={[
165               // { property: "icon", title: "", type: ColumnType.custom, customControl: this.renderIcon },
166               { property: 'severity', title: 'Severity', type: ColumnType.text, width: '140px' },
167               { property: 'timestamp', type: ColumnType.text, title: 'Timestamp' },
168               { property: 'nodeId', title: 'Node Name', type: ColumnType.text },
169               { property: 'counter', title: 'Count', type: ColumnType.numeric, width: '100px' },
170               { property: 'objectId', title: 'Object Id', type: ColumnType.text },
171               { property: 'problem', title: 'Alarm Type', type: ColumnType.text },
172             ]} {...this.props.currentAlarmsProperties} {...this.props.currentAlarmsActions} />
173             <RefreshCurrentAlarmsDialog
174               mode={this.state.refreshCurrentAlarmsEditorMode}
175               onClose={this.onCloseRefreshCurrentAlarmsDialog}
176             />
177           </>
178         }
179         {activePanelId === 'AlarmNotifications' &&
180
181           <FaultAlarmNotificationTable stickyHeader tableId="alarm-notifications-table" idProperty="id" defaultSortColumn='timeStamp' defaultSortOrder='desc' rows={this.props.faultNotifications.faults} asynchronus columns={[
182             // { property: "icon", title: "", type: ColumnType.custom, customControl: this.renderIcon },
183             { property: 'severity', title: 'Severity', width: '140px', type: ColumnType.text },
184             { property: 'timeStamp', title: 'Timestamp', type: ColumnType.text },
185             { property: 'nodeName', title: 'Node Name', type: ColumnType.text },
186             { property: 'counter', title: 'Count', width: '100px', type: ColumnType.numeric },
187             { property: 'objectId', title: 'Object Id', type: ColumnType.text },
188             { property: 'problem', title: 'Alarm Type', type: ColumnType.text },
189           ]} />
190         }
191
192         {activePanelId === 'AlarmLog' &&
193           <>
194             <FaultTable stickyHeader idProperty={'id'} tableId="alarm-log-table" customActionButtons={[refreshAlarmLogAction]}
195               columns={[
196                 // { property: "icon", title: "", type: ColumnType.custom, customControl: this.renderIcon },
197                 { property: 'severity', title: 'Severity', width: '140px' },
198                 { property: 'timestamp', title: 'Timestamp' },
199                 { property: 'nodeId', title: 'Node Name' },
200                 { property: 'counter', title: 'Count', type: ColumnType.numeric, width: '100px' },
201                 { property: 'objectId', title: 'Object Id' },
202                 { property: 'problem', title: 'Alarm Type' },
203                 { property: 'sourceType', title: 'Source', width: '140px' },
204               ]} {...this.props.alarmLogEntriesProperties} {...this.props.alarmLogEntriesActions} />
205             <RefreshAlarmLogDialog
206               mode={this.state.refreshAlarmLogEditorMode}
207               onClose={this.onCloseRefreshAlarmLogDialog}
208             />
209           </>
210
211         }
212         {
213           this.state.clearAlarmDialogMode !== ClearStuckAlarmsDialogMode.None && <ClearStuckAlarmsDialog mode={this.state.clearAlarmDialogMode} numberDevices={this.state.stuckAlarms.length} stuckAlarms={this.state.stuckAlarms} onClose={this.onDialogClose} />
214         }
215       </>
216     );
217   }
218
219   public componentDidMount() {
220     if (this.props.panelId === null) { //set default tab if none is set
221       this.onToggleTabs('CurrentAlarms');
222     } else {
223       this.onToggleTabs(this.props.panelId);
224     }
225   }
226
227   // private renderIcon = (props: { rowData: Fault | FaultAlarmNotification }) => {
228   //   return (
229   //     <FontAwesomeIcon icon={faExclamationTriangle} />
230   //   );
231   // };
232
233   private onCloseRefreshAlarmLogDialog = () => {
234     this.setState({
235       refreshAlarmLogEditorMode: RefreshAlarmLogDialogMode.None,
236     });
237   };
238
239   private onCloseRefreshCurrentAlarmsDialog = () => {
240     this.setState({
241       refreshCurrentAlarmsEditorMode: RefreshCurrentAlarmsDialogMode.None,
242     });
243   };
244 }
245
246 export const FaultApplication = withRouter(connect(mapProps, mapDisp)(FaultApplicationComponent));
247 export default FaultApplication;