From 1a868116614dd9996c78e69941b537e9da19460b Mon Sep 17 00:00:00 2001 From: Aijana Schumann Date: Tue, 1 Feb 2022 13:18:42 +0100 Subject: Update ODLUX Updated to Material-ui 5, updated dashboard view, removed NetworkMap, LinkCalculator and LineOfSightApp, small bugfixes Issue-ID: CCSDK-3580 Signed-off-by: Aijana Schumann Change-Id: Id0fc148673e23a755cafc2be1c489248c38ff47c --- sdnr/wt/odlux/apps/connectApp/package.json | 23 +- .../src/actions/networkElementsActions.ts | 2 +- .../src/components/connectionStatusLog.tsx | 2 +- .../connectApp/src/components/dashboardHome.tsx | 425 +++++++++++++++++++++ .../src/components/editNetworkElementDialog.tsx | 45 +-- .../src/components/infoNetworkElementDialog.tsx | 8 +- .../connectApp/src/components/networkElements.tsx | 90 ++--- .../refreshConnectionStatusLogDialog.tsx | 16 +- .../components/refreshNetworkElementsDialog.tsx | 16 +- .../wt/odlux/apps/connectApp/src/pluginConnect.tsx | 18 +- .../apps/connectApp/src/views/connectView.tsx | 8 +- .../resources/OSGI-INF/blueprint/blueprint.xml | 2 +- sdnr/wt/odlux/apps/connectApp/webpack.config.js | 4 +- 13 files changed, 547 insertions(+), 112 deletions(-) create mode 100644 sdnr/wt/odlux/apps/connectApp/src/components/dashboardHome.tsx (limited to 'sdnr/wt/odlux/apps/connectApp') diff --git a/sdnr/wt/odlux/apps/connectApp/package.json b/sdnr/wt/odlux/apps/connectApp/package.json index a6b23df84..9ecdaf853 100644 --- a/sdnr/wt/odlux/apps/connectApp/package.json +++ b/sdnr/wt/odlux/apps/connectApp/package.json @@ -21,20 +21,25 @@ "author": "Matthias Fischer", "license": "Apache-2.0", "dependencies": { - "@odlux/framework": "*" + "@emotion/react": "^11.7.0", + "@emotion/styled": "^11.6.0", + "@mui/icons-material": "^5.2.0", + "@mui/material": "^5.2.2", + "@mui/styles": "^5.2.2", + "@odlux/framework": "*", + "react-chartjs-2": "2.7.6", + "chart.js": "2.8.0" }, "peerDependencies": { - "@types/react": "17.0.3", - "@types/react-dom": "17.0.2", - "@types/react-router-dom": "5.1.7", - "@material-ui/core": "4.11.4", - "@material-ui/icons": "4.11.2", "@types/classnames": "2.2.6", "@types/flux": "3.1.8", "@types/jquery": "3.3.10", + "@types/react": "17.0.37", + "@types/react-dom": "17.0.11", + "@types/react-router-dom": "5.1.7", "jquery": "3.3.1", - "react": "17.0.1", - "react-dom": "17.0.1", + "react": "17.0.2", + "react-dom": "17.0.2", "react-router-dom": "5.2.0" } -} \ No newline at end of file +} diff --git a/sdnr/wt/odlux/apps/connectApp/src/actions/networkElementsActions.ts b/sdnr/wt/odlux/apps/connectApp/src/actions/networkElementsActions.ts index 1e569a196..041cff9da 100644 --- a/sdnr/wt/odlux/apps/connectApp/src/actions/networkElementsActions.ts +++ b/sdnr/wt/odlux/apps/connectApp/src/actions/networkElementsActions.ts @@ -37,7 +37,7 @@ export const addNewNetworkElementAsyncActionCreator = (element: NetworkElementCo /** Represents an async thunk action creator to edit network element. */ export const editNetworkElementAsyncActionCreator = (element: UpdateNetworkElement) => async (dispatch: Dispatch) => { - const connectionStatus: ConnectionStatus[] = await connectService.getNetworkElementConnectionStatus(element.id).then(ne => (ne)) || []; + const connectionStatus: ConnectionStatus[] = (await connectService.getNetworkElementConnectionStatus(element.id).then(ne => (ne))) || []; const currentConnectionStatus = connectionStatus[0].status; if (currentConnectionStatus === "Disconnected") { const res = await connectService.deleteNetworkElement(element); diff --git a/sdnr/wt/odlux/apps/connectApp/src/components/connectionStatusLog.tsx b/sdnr/wt/odlux/apps/connectApp/src/components/connectionStatusLog.tsx index 5a5ebcc45..a7d96d072 100644 --- a/sdnr/wt/odlux/apps/connectApp/src/components/connectionStatusLog.tsx +++ b/sdnr/wt/odlux/apps/connectApp/src/components/connectionStatusLog.tsx @@ -19,7 +19,7 @@ import * as React from 'react'; import connect, { IDispatcher, Connect } from '../../../../framework/src/flux/connect'; import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore'; import { MaterialTable, ColumnType, MaterialTableCtorType } from '../../../../framework/src/components/material-table'; -import Refresh from '@material-ui/icons/Refresh'; +import Refresh from '@mui/icons-material/Refresh'; import { createConnectionStatusLogActions, createConnectionStatusLogProperties } from '../handlers/connectionStatusLogHandler'; import { NetworkElementConnectionLog } from '../models/networkElementConnectionLog'; diff --git a/sdnr/wt/odlux/apps/connectApp/src/components/dashboardHome.tsx b/sdnr/wt/odlux/apps/connectApp/src/components/dashboardHome.tsx new file mode 100644 index 000000000..683c59623 --- /dev/null +++ b/sdnr/wt/odlux/apps/connectApp/src/components/dashboardHome.tsx @@ -0,0 +1,425 @@ +/** + * ============LICENSE_START======================================================================== + * ONAP : ccsdk feature sdnr wt odlux + * ================================================================================================= + * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved. + * ================================================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + * ============LICENSE_END========================================================================== + */ +import * as React from 'react'; + +import { withRouter, RouteComponentProps } from 'react-router-dom'; +import connect, { Connect, IDispatcher } from '../../../../framework/src/flux/connect';; +import { Theme } from '@mui/material'; +import { WithStyles } from '@mui/styles'; +import createStyles from '@mui/styles/createStyles'; +import withStyles from '@mui/styles/withStyles'; +import { Doughnut } from 'react-chartjs-2'; +import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore'; +import { NavigateToApplication } from '../../../../framework/src/actions/navigationActions'; + +const styles = (theme: Theme) => createStyles({ + pageWidthSettings: { + width: '50%', + float: 'left' + }, +}) + +const scrollbar = { overflow: "auto", paddingRight: "20px" } + +let connectionStatusinitialLoad = true; +let connectionStatusinitialStateChanged = false; +let connectionStatusDataLoad: number[] = [0, 0, 0, 0]; +let connectionTotalCount = 0; + +let alarmStatusinitialLoad = true; +let alarmStatusinitialStateChanged = false; +let alarmStatusDataLoad: number[] = [0, 0, 0, 0]; +let alarmTotalCount = 0; + +const mapProps = (state: IApplicationStoreState) => ({ + connectionStatusCount: state.connect.connectionStatusCount, + alarmStatus: state.fault.faultStatus +}); + +const mapDispatch = (dispatcher: IDispatcher) => ({ + navigateToApplication: (applicationName: string, path?: string) => dispatcher.dispatch(new NavigateToApplication(applicationName, path)), +}); + +type HomeComponentProps = RouteComponentProps & Connect & WithStyles; + +class DashboardHome extends React.Component { + constructor(props: HomeComponentProps) { + super(props); + this.state = { + } + } + + render(): JSX.Element { + const { classes } = this.props; + + if (!this.props.connectionStatusCount.isLoadingConnectionStatusChart) { + connectionStatusDataLoad = [ + this.props.connectionStatusCount.Connected, + this.props.connectionStatusCount.Connecting, + this.props.connectionStatusCount.Disconnected, + this.props.connectionStatusCount.UnableToConnect + ]; + connectionTotalCount = this.props.connectionStatusCount.Connected + this.props.connectionStatusCount.Connecting + + this.props.connectionStatusCount.Disconnected + this.props.connectionStatusCount.UnableToConnect; + + } + + if (!this.props.alarmStatus.isLoadingAlarmStatusChart) { + alarmStatusDataLoad = [ + this.props.alarmStatus.critical, + this.props.alarmStatus.major, + this.props.alarmStatus.minor, + this.props.alarmStatus.warning + ]; + alarmTotalCount = this.props.alarmStatus.critical + this.props.alarmStatus.major + + this.props.alarmStatus.minor + this.props.alarmStatus.warning; + } + + /** Available Network Connection Status chart data */ + const connectionStatusData = { + labels: ['Connected', 'Connecting', 'Disconnected', 'UnableToConnect'], + datasets: [{ + data: connectionStatusDataLoad, + backgroundColor: [ + 'rgb(0, 153, 51)', + 'rgb(255, 102, 0)', + 'rgb(191, 191, 191)', + 'rgb(191, 191, 191)' + ] + }] + }; + + + /** No Devices available */ + const connectionStatusUnavailableData = { + labels: ['No Devices available'], + datasets: [{ + data: [1], + backgroundColor: [ + 'rgb(255, 255, 255)' + ] + }] + }; + + /** Loading Connection Status chart */ + const connectionStatusisLoading = { + labels: ['Loading chart...'], + datasets: [{ + data: [1], + backgroundColor: [ + 'rgb(255, 255, 255)' + ] + }] + }; + + /** Loading Alarm Status chart */ + const alarmStatusisLoading = { + labels: ['Loading chart...'], + datasets: [{ + data: [1], + backgroundColor: [ + 'rgb(255, 255, 255)' + ] + }] + }; + + /** Connection status options */ + let labels: String[] = ['Connected', 'Connecting', 'Disconnected', 'UnableToConnect']; + const connectionStatusOptions = { + responsive: true, + maintainAspectRatio: false, + animation: { + duration: 0 + }, + plugins: { + legend: { + display: true, + position: 'top' + } + }, + onClick: (event: MouseEvent, item: any) => { + if (item[0]) { + let connectionStatus = labels[item[0]._index] + ''; + this.props.navigateToApplication("connect", '/connectionStatus/' + connectionStatus); + } + } + } + + /** Connection status unavailable options */ + const connectionStatusUnavailableOptions = { + responsive: true, + maintainAspectRatio: false, + animation: { + duration: 0 + }, + plugins: { + legend: { + display: true, + position: 'top' + }, + tooltip: { + enabled: false + } + } + } + + /** Add text inside the doughnut chart for Connection Status */ + const connectionStatusPlugins = [{ + beforeDraw: function (chart: any) { + var width = chart.width, + height = chart.height, + ctx = chart.ctx; + ctx.restore(); + var fontSize = (height / 480).toFixed(2); + ctx.font = fontSize + "em sans-serif"; + ctx.textBaseline = "top"; + var text = "Network Connection Status", + textX = Math.round((width - ctx.measureText(text).width) / 2), + textY = height / 2; + ctx.fillText(text, textX, textY); + ctx.save(); + } + }] + + /** Alarm status Data */ + const alarmStatusData = { + labels: [ + 'Critical', + 'Major', + 'Minor', + 'Warning' + ], + datasets: [{ + data: alarmStatusDataLoad, + backgroundColor: [ + 'rgb(240, 25, 10)', + 'rgb(240, 133, 10)', + 'rgb(240, 240, 10)', + 'rgb(46, 115, 176)' + ], + }] + } + + /** No Alarm status available */ + const alarmStatusUnavailableData = { + labels: ['No Alarms available'], + datasets: [{ + data: [1], + backgroundColor: [ + 'rgb(0, 153, 51)' + ] + }] + }; + + /** Alarm status Options */ + let alarmLabels: String[] = ['Critical', 'Major', 'Minor', 'Warning']; + const alarmStatusOptions = { + responsive: true, + maintainAspectRatio: false, + animation: { + duration: 0 + }, + plugins: { + legend: { + display: true, + position: 'top' + } + }, + onClick: (event: MouseEvent, item: any) => { + if (item[0]) { + let severity = alarmLabels[item[0].index] + ''; + this.props.navigateToApplication("fault", '/alarmStatus/' + severity); + } + }, + }; + + /** Alarm status unavailable options */ + const alarmStatusUnavailableOptions = { + responsive: true, + maintainAspectRatio: false, + animation: { + duration: 0 + }, + plugins: { + legend: { + display: true, + position: 'top' + }, + tooltip: { + enabled: false + } + } + } + /** Add text inside the doughnut chart for Alarm Status */ + const alarmStatusPlugins = [{ + beforeDraw: function (chart: any) { + var width = chart.width, + height = chart.height, + ctx = chart.ctx; + ctx.restore(); + var fontSize = (height / 480).toFixed(2); + ctx.font = fontSize + "em sans-serif"; + ctx.textBaseline = "top"; + var text = "Network Alarm Status", + textX = Math.round((width - ctx.measureText(text).width) / 2), + textY = height / 2; + ctx.fillText(text, textX, textY); + ctx.save(); + } + }] + + return ( + <> +
+

Welcome to ODLUX

+
+ {this.checkElementsAreLoaded() ? + this.checkConnectionStatus() && connectionTotalCount != 0 ? + + : + : + } +
+
+ {this.checkAlarmsAreLoaded() ? + this.checkAlarmStatus() && alarmTotalCount != 0 ? + + : + : + } +
+
+ + ) + } + + /** Check if connection status data available */ + public checkConnectionStatus = () => { + let statusCount = this.props.connectionStatusCount; + if (statusCount.isLoadingConnectionStatusChart) { + return true; + } + if (statusCount.Connected == 0 && statusCount.Connecting == 0 && statusCount.Disconnected == 0 + && statusCount.UnableToConnect == 0) { + return false; + } else { + return true; + } + } + + /** Check if connection status chart data is loaded */ + public checkElementsAreLoaded = () => { + let isLoadingCheck = this.props.connectionStatusCount; + if (connectionStatusinitialLoad && !isLoadingCheck.isLoadingConnectionStatusChart) { + if (this.checkConnectionStatus()) { + connectionStatusinitialLoad = false; + return true; + } + return false; + } else if (connectionStatusinitialLoad && isLoadingCheck.isLoadingConnectionStatusChart) { + connectionStatusinitialLoad = false; + connectionStatusinitialStateChanged = true; + return !isLoadingCheck.isLoadingConnectionStatusChart; + } else if (connectionStatusinitialStateChanged) { + if (!isLoadingCheck.isLoadingConnectionStatusChart) { + connectionStatusinitialStateChanged = false; + } + return !isLoadingCheck.isLoadingConnectionStatusChart; + } + return true; + } + + /** Check if alarms data available */ + public checkAlarmStatus = () => { + let alarmCount = this.props.alarmStatus; + if (alarmCount.isLoadingAlarmStatusChart) { + return true; + } + if (alarmCount.critical == 0 && alarmCount.major == 0 && alarmCount.minor == 0 && alarmCount.warning == 0) { + return false; + } + else { + return true; + } + } + + /** Check if alarm status chart data is loaded */ + public checkAlarmsAreLoaded = () => { + let isLoadingCheck = this.props.alarmStatus; + if (alarmStatusinitialLoad && !isLoadingCheck.isLoadingAlarmStatusChart) { + if (this.checkAlarmStatus()) { + alarmStatusinitialLoad = false; + return true; + } + return false; + } else if (alarmStatusinitialLoad && isLoadingCheck.isLoadingAlarmStatusChart) { + alarmStatusinitialLoad = false; + alarmStatusinitialStateChanged = true; + return !isLoadingCheck.isLoadingAlarmStatusChart; + } else if (alarmStatusinitialStateChanged) { + if (!isLoadingCheck.isLoadingAlarmStatusChart) { + alarmStatusinitialStateChanged = false; + } + return !isLoadingCheck.isLoadingAlarmStatusChart; + } + return true; + } +} + +export default (withRouter(connect(mapProps, mapDispatch)(DashboardHome))); \ No newline at end of file diff --git a/sdnr/wt/odlux/apps/connectApp/src/components/editNetworkElementDialog.tsx b/sdnr/wt/odlux/apps/connectApp/src/components/editNetworkElementDialog.tsx index 061303976..7324ffab8 100644 --- a/sdnr/wt/odlux/apps/connectApp/src/components/editNetworkElementDialog.tsx +++ b/sdnr/wt/odlux/apps/connectApp/src/components/editNetworkElementDialog.tsx @@ -17,14 +17,14 @@ */ import * as React from 'react'; -import Button from '@material-ui/core/Button'; -import TextField from '@material-ui/core/TextField'; -import Dialog from '@material-ui/core/Dialog'; -import DialogActions from '@material-ui/core/DialogActions'; -import DialogContent from '@material-ui/core/DialogContent'; -import DialogContentText from '@material-ui/core/DialogContentText'; -import DialogTitle from '@material-ui/core/DialogTitle'; -import { FormControl, InputLabel, Select, MenuItem, Typography, Radio, RadioGroup, Options, FormLabel, FormControlLabel } from '@material-ui/core'; +import Button from '@mui/material/Button'; +import TextField from '@mui/material/TextField'; +import Dialog from '@mui/material/Dialog'; +import DialogActions from '@mui/material/DialogActions'; +import DialogContent from '@mui/material/DialogContent'; +import DialogContentText from '@mui/material/DialogContentText'; +import DialogTitle from '@mui/material/DialogTitle'; +import { FormControl, InputLabel, Select, MenuItem, Typography, Radio, RadioGroup, Options, FormLabel, FormControlLabel } from '@mui/material'; import { loadAllTlsKeyListAsync } from '../actions/tlsKeyActions'; import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore'; @@ -222,32 +222,32 @@ class EditNetworkElementDialogComponent extends React.Component {setting.dialogDescription} - { this.setState({ nodeId: event.target.value }); }} /> + { this.setState({ nodeId: event.target.value }); }} /> {!this.state.isNameValid && Name cannot be empty.} - { this.setState({ host: event.target.value }); }} /> + { this.setState({ host: event.target.value }); }} /> {!this.state.isHostSet && IP Adress cannot be empty.} - { this.setState({ port: +event.target.value }); }} /> - {setting.enableUsernameEditor && { this.setState({ username: event.target.value }); }} /> || null} + { this.setState({ port: +event.target.value }); }} /> + {setting.enableUsernameEditor && { this.setState({ username: event.target.value }); }} /> || null} {setting.enableUsernameEditor && - } label="Password" onChange={this.onRadioSelect} /> - } label="TlsKey" onChange={this.onRadioSelect} /> + } label="Password" onChange={this.onRadioSelect} /> + } label="TlsKey" onChange={this.onRadioSelect} /> || null} {setting.enableUsernameEditor && showPasswordTextField && - { this.setState({ password: event.target.value }); }} /> || null} - + {setting.enableUsernameEditor && showTlsDropdown &&
--Select tls-key-- - { +