0be28b748bdcf1d7ca6abfbdce6de21f1a5b0169
[ccsdk/features.git] / sdnr / wt / odlux / apps / maintenanceApp / src / views / maintenenceView.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
20 import { Theme, createStyles, WithStyles, withStyles, Tooltip } from '@material-ui/core';
21
22 import { faBan } from '@fortawesome/free-solid-svg-icons';
23 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
24
25 import AddIcon from '@material-ui/icons/Add';
26 import EditIcon from '@material-ui/icons/Edit';
27 import RemoveIcon from '@material-ui/icons/RemoveCircleOutline';
28 import Refresh from '@material-ui/icons/Refresh';
29 import { MenuItem, Divider, Typography } from '@material-ui/core';
30
31 import connect, { IDispatcher, Connect } from '../../../../framework/src/flux/connect';
32 import MaterialTable, { MaterialTableCtorType, ColumnType } from '../../../../framework/src/components/material-table';
33 import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
34
35 import { MaintenenceEntry, spoofSymbol } from '../models/maintenenceEntryType';
36
37 import EditMaintenenceEntryDialog, { EditMaintenenceEntryDialogMode } from '../components/editMaintenenceEntryDialog';
38 import RefreshMaintenanceEntriesDialog, { RefreshMaintenanceEntriesDialogMode } from '../components/refreshMaintenanceEntries';
39 import { convertToLocaleString } from '../utils/timeUtils';
40 import { createmaintenanceEntriesActions, createmaintenanceEntriesProperties, maintenanceEntriesReloadAction } from '../handlers/maintenenceEntriesHandler';
41
42 const styles = (theme: Theme) => createStyles({
43   button: {
44     margin: 0,
45     padding: "6px 6px",
46     minWidth: 'unset'
47   },
48   spacer: {
49     marginLeft: theme.spacing(1),
50     marginRight: theme.spacing(1),
51     display: "inline"
52   }
53 });
54
55 const MaintenenceEntriesTable = MaterialTable as MaterialTableCtorType<MaintenenceEntry>;
56
57 const mapProps = (state: IApplicationStoreState) => ({
58   maintenanceEntriesProperties: createmaintenanceEntriesProperties(state)
59 });
60
61 const mapDispatcher = (dispatcher: IDispatcher) => ({
62   maintenanceEntriesActions: createmaintenanceEntriesActions(dispatcher.dispatch),
63   onLoadMaintenanceEntries: async () => {
64     await dispatcher.dispatch(maintenanceEntriesReloadAction)
65   }
66 });
67
68 const emptyMaintenenceEntry: MaintenenceEntry = {
69   _id: '',
70   nodeId: '',
71   description: '',
72   start: convertToLocaleString(new Date().valueOf()),
73   end: convertToLocaleString(new Date().valueOf()),
74   active: false,
75 };
76
77 type MaintenenceViewComponentProps = Connect<typeof mapProps, typeof mapDispatcher> & WithStyles<typeof styles> & {
78
79 }
80
81 type MaintenenceViewComponentState = {
82   maintenenceEntryToEdit: MaintenenceEntry;
83   maintenenceEntryEditorMode: EditMaintenenceEntryDialogMode;
84   refreshMaintenenceEntriesEditorMode: RefreshMaintenanceEntriesDialogMode;
85 };
86
87 let initialSorted = false;
88
89 class MaintenenceViewComponent extends React.Component<MaintenenceViewComponentProps, MaintenenceViewComponentState> {
90
91   constructor(props: MaintenenceViewComponentProps) {
92     super(props);
93
94     this.state = {
95       maintenenceEntryToEdit: emptyMaintenenceEntry,
96       maintenenceEntryEditorMode: EditMaintenenceEntryDialogMode.None,
97       refreshMaintenenceEntriesEditorMode: RefreshMaintenanceEntriesDialogMode.None
98     };
99
100   }
101
102   getContextMenu(rowData: MaintenenceEntry): JSX.Element[] {
103     let buttonArray = [
104       <MenuItem aria-label={"1hr-from-now"} onClick={event => this.onOpenPlus1hEditMaintenenceEntryDialog(event, rowData)}><Typography>+1h</Typography></MenuItem>,
105       <MenuItem aria-label={"8hr-from-now"} onClick={event => this.onOpenPlus8hEditMaintenenceEntryDialog(event, rowData)}><Typography>+8h</Typography></MenuItem>,
106       <Divider />,
107       <MenuItem aria-label={"edit"} onClick={event => this.onOpenEditMaintenenceEntryDialog(event, rowData)}><EditIcon /><Typography>Edit</Typography></MenuItem>,
108       <MenuItem aria-label={"remove"} onClick={event => this.onOpenRemoveMaintenenceEntryDialog(event, rowData)}><RemoveIcon /><Typography>Remove</Typography></MenuItem>
109     ];
110     return buttonArray;
111   }
112
113   render() {
114     const { classes } = this.props;
115     const addMaintenenceEntryAction = {
116       icon: AddIcon, tooltip: 'Add', ariaLabel:'add-element', onClick: () => {
117         const startTime = (new Date().valueOf());
118         const endTime = startTime;
119         this.setState({
120           maintenenceEntryToEdit: {
121             ...emptyMaintenenceEntry,
122             start: convertToLocaleString(startTime),
123             end: convertToLocaleString(endTime),
124           },
125           maintenenceEntryEditorMode: EditMaintenenceEntryDialogMode.AddMaintenenceEntry
126         });
127       }
128     };
129
130     const refreshMaintenanceEntriesAction = {
131       icon: Refresh, tooltip: 'Refresh Maintenance Entries', ariaLabel: 'refresh', onClick: () => {
132         this.setState({
133           refreshMaintenenceEntriesEditorMode: RefreshMaintenanceEntriesDialogMode.RefreshMaintenanceEntriesTable
134         });
135       }
136     };
137
138     const now = new Date().valueOf();
139     return (
140       <>
141         <MaintenenceEntriesTable stickyHeader tableId="maintenance-table" title={"Maintenance"} customActionButtons={[refreshMaintenanceEntriesAction, addMaintenenceEntryAction]} columns={
142           [
143             { property: "nodeId", title: "Node Name", type: ColumnType.text },
144             {
145               property: "notifications", title: "Notification", width: 50, align: "center", type: ColumnType.custom, customControl: ({ rowData }) => (
146                 rowData.active && (Date.parse(rowData.start).valueOf() <= now) && (Date.parse(rowData.end).valueOf() >= now) && <FontAwesomeIcon icon={faBan} /> || null
147               )
148             },
149             { property: "active", title: "Activation State", type: ColumnType.boolean, labels: { "true": "active", "false": "not active" }, },
150             { property: "start", title: "Start Date (UTC)", type: ColumnType.text },
151             { property: "end", title: "End Date (UTC)", type: ColumnType.text }
152           ]
153         } idProperty={'_id'}{...this.props.maintenanceEntriesActions} {...this.props.maintenanceEntriesProperties} asynchronus createContextMenu={rowData => {
154           return this.getContextMenu(rowData);
155         }} >
156         </MaintenenceEntriesTable>
157         <EditMaintenenceEntryDialog initialMaintenenceEntry={this.state.maintenenceEntryToEdit} mode={this.state.maintenenceEntryEditorMode}
158           onClose={this.onCloseEditMaintenenceEntryDialog} />
159         <RefreshMaintenanceEntriesDialog mode={this.state.refreshMaintenenceEntriesEditorMode}
160           onClose={this.onCloseRefreshMaintenenceEntryDialog} />
161       </>
162     );
163   }
164
165   public componentDidMount() {
166
167     if (!initialSorted) {
168       initialSorted = true;
169       this.props.maintenanceEntriesActions.onHandleRequestSort("node-id");
170     } else {
171       this.props.onLoadMaintenanceEntries();
172     }
173
174
175   }
176
177   private onOpenPlus1hEditMaintenenceEntryDialog = (event: React.MouseEvent<HTMLElement>, entry: MaintenenceEntry) => {
178     // event.preventDefault();
179     // event.stopPropagation();
180     const startTime = (new Date().valueOf());
181     const endTime = startTime + (1 * 60 * 60 * 1000);
182     this.setState({
183       maintenenceEntryToEdit: {
184         ...entry,
185         start: convertToLocaleString(startTime),
186         end: convertToLocaleString(endTime),
187       },
188       maintenenceEntryEditorMode: EditMaintenenceEntryDialogMode.EditMaintenenceEntry
189     });
190   }
191
192   private onOpenPlus8hEditMaintenenceEntryDialog = (event: React.MouseEvent<HTMLElement>, entry: MaintenenceEntry) => {
193     // event.preventDefault();
194     // event.stopPropagation();
195     const startTime = (new Date().valueOf());
196     const endTime = startTime + (8 * 60 * 60 * 1000);
197     this.setState({
198       maintenenceEntryToEdit: {
199         ...entry,
200         start: convertToLocaleString(startTime),
201         end: convertToLocaleString(endTime),
202       },
203       maintenenceEntryEditorMode: EditMaintenenceEntryDialogMode.EditMaintenenceEntry
204     });
205   }
206
207   private onOpenEditMaintenenceEntryDialog = (event: React.MouseEvent<HTMLElement>, entry: MaintenenceEntry) => {
208     // event.preventDefault();
209     // event.stopPropagation();
210     const startTime = (new Date().valueOf());
211     const endTime = startTime;
212     this.setState({
213       maintenenceEntryToEdit: {
214         ...entry,
215         ...(entry.start && endTime)
216           ? { start: convertToLocaleString(entry.start), end: convertToLocaleString(entry.end) }
217           : { start: convertToLocaleString(startTime), end: convertToLocaleString(endTime) }
218       },
219       maintenenceEntryEditorMode: EditMaintenenceEntryDialogMode.EditMaintenenceEntry
220     });
221   }
222
223   private onOpenRemoveMaintenenceEntryDialog = (event: React.MouseEvent<HTMLElement>, entry: MaintenenceEntry) => {
224     // event.preventDefault();
225     // event.stopPropagation();
226     const startTime = (new Date().valueOf());
227     const endTime = startTime;
228     this.setState({
229       maintenenceEntryToEdit: {
230         ...entry,
231         ...(entry.start && endTime)
232           ? { start: convertToLocaleString(entry.start), end: convertToLocaleString(entry.end) }
233           : { start: convertToLocaleString(startTime), end: convertToLocaleString(endTime) }
234       },
235       maintenenceEntryEditorMode: EditMaintenenceEntryDialogMode.RemoveMaintenenceEntry
236     });
237   }
238
239   private onCloseEditMaintenenceEntryDialog = () => {
240     this.setState({
241       maintenenceEntryToEdit: emptyMaintenenceEntry,
242       maintenenceEntryEditorMode: EditMaintenenceEntryDialogMode.None,
243     });
244   }
245
246   private onCloseRefreshMaintenenceEntryDialog = () => {
247     this.setState({
248       refreshMaintenenceEntriesEditorMode: RefreshMaintenanceEntriesDialogMode.None,
249     });
250   }
251 }
252
253 export const MaintenenceView = withStyles(styles)(connect(mapProps, mapDispatcher)(MaintenenceViewComponent));
254 export default MaintenenceView;