diff options
Diffstat (limited to 'sdnr/wt/odlux/apps/faultApp')
17 files changed, 405 insertions, 125 deletions
diff --git a/sdnr/wt/odlux/apps/faultApp/package.json b/sdnr/wt/odlux/apps/faultApp/package.json index be7bf6d02..909626303 100644 --- a/sdnr/wt/odlux/apps/faultApp/package.json +++ b/sdnr/wt/odlux/apps/faultApp/package.json @@ -20,21 +20,21 @@ ], "author": "Matthias Fischer", "license": "Apache-2.0", - "dependencies": { - "@odlux/framework": "*" - }, + "dependencies": { + "@odlux/framework": "*" + }, "peerDependencies": { - "@types/react": "16.4.14", - "@types/react-dom": "16.0.8", + "@types/react": "16.9.11", + "@types/react-dom": "16.9.4", "@types/react-router-dom": "4.3.1", - "@material-ui/core": "3.8.3", - "@material-ui/icons": "3.0.2", + "@material-ui/core": "4.6.1", + "@material-ui/icons": "4.5.1", "@types/classnames": "2.2.6", "@types/flux": "3.1.8", "@types/jquery": "3.3.10", "jquery": "3.3.1", - "react": "16.5.2", - "react-dom": "16.5.2", + "react": "16.11.0", + "react-dom": "16.11.0", "react-router-dom": "4.3.1" } }
\ No newline at end of file diff --git a/sdnr/wt/odlux/apps/faultApp/pom.xml b/sdnr/wt/odlux/apps/faultApp/pom.xml index b748b7d19..1c616a40b 100644 --- a/sdnr/wt/odlux/apps/faultApp/pom.xml +++ b/sdnr/wt/odlux/apps/faultApp/pom.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.onap.ccsdk.parent</groupId> @@ -8,18 +9,19 @@ <relativePath/> </parent> - <modelVersion>4.0.0</modelVersion> <groupId>org.onap.ccsdk.features.sdnr.wt</groupId> <artifactId>sdnr-wt-odlux-app-faultApp</artifactId> <version>0.7.0-SNAPSHOT</version> <packaging>bundle</packaging> - <name>sdnr-wt-odlux-app-faultApp</name> + + <name>ccsdk-features :: ${project.artifactId}</name> <licenses> <license> <name>Apache License, Version 2.0</name> <url>http://www.apache.org/licenses/LICENSE-2.0</url> </license> </licenses> + <dependencies> <dependency> <groupId>${project.groupId}</groupId> @@ -38,8 +40,21 @@ <scope>test</scope> </dependency> </dependencies> + <build> <sourceDirectory>src2/main/java</sourceDirectory> + <resources> + <resource> + <directory>dist</directory> + <targetPath>odlux</targetPath> + </resource> + <resource> + <directory>src2/main/resources</directory> + </resource> + <resource> + <directory>src2/test/resources</directory> + </resource> + </resources> <plugins> <plugin> <artifactId>maven-clean-plugin</artifactId> @@ -62,10 +77,10 @@ <followSymlinks>false</followSymlinks> </fileset> <!-- eclipse bug build bin folder in basedir --> - <fileset> - <directory>bin</directory> - <followSymlinks>false</followSymlinks> - </fileset> + <fileset> + <directory>bin</directory> + <followSymlinks>false</followSymlinks> + </fileset> </filesets> </configuration> </plugin> @@ -88,7 +103,7 @@ </executions> </plugin> <plugin> - <groupId>de.jacksitlab</groupId> + <groupId>de.jacks-it-lab</groupId> <artifactId>frontend-maven-plugin</artifactId> <version>1.7.1</version> <executions> @@ -100,8 +115,8 @@ <!-- optional: default phase is "generate-resources" --> <phase>initialize</phase> <configuration> - <nodeVersion>v8.10.0</nodeVersion> - <yarnVersion>v1.12.3</yarnVersion> + <nodeVersion>v10.16.3</nodeVersion> + <yarnVersion>v1.19.0</yarnVersion> </configuration> </execution> <execution> @@ -131,27 +146,5 @@ </configuration> </plugin> </plugins> - <resources> - <resource> - <directory>dist</directory> - <targetPath>odlux</targetPath> - </resource> - <resource> - <directory>src2/main/resources</directory> - </resource> - <resource> - <directory>src2/test/resources</directory> - </resource> - </resources> </build> - <pluginRepositories> - <pluginRepository> - <id>highstreet repo</id> - <url>https://cloud-highstreet-technologies.com/mvn/</url> - <snapshots> - <enabled>true</enabled> - <updatePolicy>always</updatePolicy> - </snapshots> - </pluginRepository> - </pluginRepositories> </project> diff --git a/sdnr/wt/odlux/apps/faultApp/src/actions/clearStuckAlarmsAction.ts b/sdnr/wt/odlux/apps/faultApp/src/actions/clearStuckAlarmsAction.ts new file mode 100644 index 000000000..ba1a24822 --- /dev/null +++ b/sdnr/wt/odlux/apps/faultApp/src/actions/clearStuckAlarmsAction.ts @@ -0,0 +1,36 @@ +/** + * ============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 { clearStuckAlarms } from "../services/faultStatusService" +import { Dispatch } from "../../../../framework/src/flux/store"; +import { FaultApplicationBaseAction } from "./notificationActions"; + +export class AreStuckAlarmsCleared extends FaultApplicationBaseAction { + constructor(public isBusy: boolean) { + super(); + } +} + + +export const clearStuckAlarmAsyncAction = (dispatcher: Dispatch) => async (nodeNames: string[]) => { + dispatcher(new AreStuckAlarmsCleared(true)) + const result = await clearStuckAlarms(nodeNames).catch(error => { console.error(error); return undefined }); + dispatcher(new AreStuckAlarmsCleared(false)) + return result; +}
\ No newline at end of file diff --git a/sdnr/wt/odlux/apps/faultApp/src/actions/notificationActions.ts b/sdnr/wt/odlux/apps/faultApp/src/actions/notificationActions.ts index b990536e4..584e7cd8b 100644 --- a/sdnr/wt/odlux/apps/faultApp/src/actions/notificationActions.ts +++ b/sdnr/wt/odlux/apps/faultApp/src/actions/notificationActions.ts @@ -17,13 +17,13 @@ */ import { Action } from '../../../../framework/src/flux/action'; -import { Fault } from '../models/fault'; +import { FaultAlarmNotification } from '../models/fault'; export class FaultApplicationBaseAction extends Action { } export class AddFaultNotificationAction extends FaultApplicationBaseAction { - constructor(public fault:Fault) { + constructor(public fault:FaultAlarmNotification) { super(); } } diff --git a/sdnr/wt/odlux/apps/faultApp/src/components/clearStuckAlarmsDialog.tsx b/sdnr/wt/odlux/apps/faultApp/src/components/clearStuckAlarmsDialog.tsx new file mode 100644 index 000000000..3b8b9b684 --- /dev/null +++ b/sdnr/wt/odlux/apps/faultApp/src/components/clearStuckAlarmsDialog.tsx @@ -0,0 +1,136 @@ +/** + * ============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 { DialogContent, DialogActions, Button, Dialog, DialogTitle, DialogContentText } from '@material-ui/core'; +import { currentProblemsReloadAction } from '../handlers/currentProblemsHandler'; +import { clearStuckAlarmAsyncAction } from '../actions/clearStuckAlarmsAction'; +import connect, { IDispatcher, Connect } from '../../../../framework/src/flux/connect'; + +export enum ClearStuckAlarmsDialogMode { + None = "none", + Show = "show" +} + +const mapDispatch = (dispatcher: IDispatcher) => ({ + clearStuckAlarmsAsync: clearStuckAlarmAsyncAction(dispatcher.dispatch), + reloadCurrentProblemsAction: () => dispatcher.dispatch(currentProblemsReloadAction) +}) + +type clearStuckAlarmsProps = Connect<typeof undefined, typeof mapDispatch> & { + numberDevices: Number, + mode: ClearStuckAlarmsDialogMode, + stuckAlarms: string[] + onClose: () => void +} + +type ClearStuckAlarmsState = { + clearAlarmsSuccessful: boolean, + errormessage: string, + unclearedAlarms: string[] +} + +class ClearStuckAlarmsDialogComponent extends React.Component<clearStuckAlarmsProps, ClearStuckAlarmsState>{ + constructor(props: clearStuckAlarmsProps) { + super(props); + this.state = { clearAlarmsSuccessful: true, errormessage: '', unclearedAlarms: [] } + } + + onClose = (event: React.MouseEvent) => { + event.stopPropagation(); + event.preventDefault(); + this.props.onClose(); + } + + onRefresh = async (event: React.MouseEvent) => { + event.stopPropagation(); + event.preventDefault(); + const result = await this.props.clearStuckAlarmsAsync(this.props.stuckAlarms); + + if (result) { + if (result.output.nodenames) { + if (result.output.nodenames.length !== this.props.stuckAlarms.length) { //show errormessage if not all devices were cleared + const undeletedAlarm = this.props.stuckAlarms.filter(item => !result.output.nodenames.includes(item)) + const error = "The alarms of the following devices couldn't be refreshed: "; + this.setState({ clearAlarmsSuccessful: false, errormessage: error, unclearedAlarms: undeletedAlarm }) + return; + } + } + } + else { //show errormessage if no devices were cleared + this.setState({ clearAlarmsSuccessful: false, errormessage: "Alarms couldn't be refreshed.", unclearedAlarms: [] }) + return; + } + + this.props.reloadCurrentProblemsAction(); + this.props.onClose(); + } + + onOk = (event: React.MouseEvent) => { + + event.stopPropagation(); + event.preventDefault(); + if (this.state.unclearedAlarms.length > 0) + this.props.reloadCurrentProblemsAction(); + this.props.onClose(); + } + + render() { + console.log(this.props.stuckAlarms); + const device = this.props.numberDevices > 1 ? 'devices' : 'device' + const defaultMessage = "Are you sure you want to refresh all alarms for " + this.props.numberDevices + " " + device + "?" + const message = this.state.clearAlarmsSuccessful ? defaultMessage : this.state.errormessage; + + const defaultTitle = "Refresh Confirmation" + const title = this.state.clearAlarmsSuccessful ? defaultTitle : 'Refresh Result'; + + return ( + <Dialog open={this.props.mode !== ClearStuckAlarmsDialogMode.None}> + <DialogTitle>{title}</DialogTitle> + <DialogContent> + <DialogContentText> + {message} + </DialogContentText> + { + this.state.unclearedAlarms.map(item => + <DialogContentText> + {item} + </DialogContentText> + ) + } + </DialogContent> + <DialogActions> + { + this.state.clearAlarmsSuccessful && + <> + <Button onClick={this.onRefresh}>Yes</Button> + <Button onClick={this.onClose}>No</Button> + </> + } + + { + !this.state.clearAlarmsSuccessful && <Button onClick={this.onOk}>Ok</Button> + } + </DialogActions> + </Dialog> + ) + } +} + +const ClearStuckAlarmsDialog = connect(undefined, mapDispatch)(ClearStuckAlarmsDialogComponent) +export default ClearStuckAlarmsDialog; diff --git a/sdnr/wt/odlux/apps/faultApp/src/components/faultStatus.tsx b/sdnr/wt/odlux/apps/faultApp/src/components/faultStatus.tsx index 780e61d7a..1ec463f47 100644 --- a/sdnr/wt/odlux/apps/faultApp/src/components/faultStatus.tsx +++ b/sdnr/wt/odlux/apps/faultApp/src/components/faultStatus.tsx @@ -58,7 +58,7 @@ class FaultStatusComponent extends React.Component<FaultStatusComponentProps> { return ( <Typography variant="body1" color="inherit" > - Alarm status: <FontAwesomeIcon className={`${classes.icon} ${classes.critical}`} icon={faExclamationTriangle} /> { faultStatus.critical } | + Alarm Status: <FontAwesomeIcon className={`${classes.icon} ${classes.critical}`} icon={faExclamationTriangle} /> { faultStatus.critical } | <FontAwesomeIcon className={`${classes.icon} ${classes.major}`} icon={faExclamationTriangle} /> { faultStatus.major } | <FontAwesomeIcon className={`${classes.icon} ${classes.minor}`} icon={faExclamationTriangle} /> { faultStatus.minor } | <FontAwesomeIcon className={`${classes.icon} ${classes.warning}`} icon={faExclamationTriangle} /> { faultStatus.warning } | diff --git a/sdnr/wt/odlux/apps/faultApp/src/handlers/alarmLogEntriesHandler.ts b/sdnr/wt/odlux/apps/faultApp/src/handlers/alarmLogEntriesHandler.ts index be41a51b2..31b8259b2 100644 --- a/sdnr/wt/odlux/apps/faultApp/src/handlers/alarmLogEntriesHandler.ts +++ b/sdnr/wt/odlux/apps/faultApp/src/handlers/alarmLogEntriesHandler.ts @@ -18,17 +18,12 @@ import { createExternal,IExternalTableState } from '../../../../framework/src/components/material-table/utilities'; import { createSearchDataHandler } from '../../../../framework/src/utilities/elasticSearch'; -import { Fault, FaultLog } from '../models/fault'; +import { Fault } from '../models/fault'; export interface IAlarmLogEntriesState extends IExternalTableState<Fault> { } -// create eleactic search material data fetch handler -const alarmLogEntriesSearchHandler = createSearchDataHandler<FaultLog, Fault>( - 'sdnevents/faultlog', - null, - (hit) => ({ _id: hit._id, ...hit._source.fault }), - (name) => `fault.${ name }` -); +// create eleactic search data fetch handler +const alarmLogEntriesSearchHandler = createSearchDataHandler< Fault>('faultlog'); export const { actionHandler: alarmLogEntriesActionHandler, diff --git a/sdnr/wt/odlux/apps/faultApp/src/handlers/clearStuckAlarmsHandler.ts b/sdnr/wt/odlux/apps/faultApp/src/handlers/clearStuckAlarmsHandler.ts new file mode 100644 index 000000000..14634b4c4 --- /dev/null +++ b/sdnr/wt/odlux/apps/faultApp/src/handlers/clearStuckAlarmsHandler.ts @@ -0,0 +1,36 @@ +/** + * ============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 { IActionHandler } from "../../../../framework/src/flux/action" +import { AreStuckAlarmsCleared } from "../actions/clearStuckAlarmsAction"; + +export interface IStuckAlarms { + areAlarmsCleared: boolean +} + +const initialState: IStuckAlarms = { + areAlarmsCleared: false +} + +export const stuckAlarmHandler: IActionHandler<IStuckAlarms> = (state = initialState, action) => { + if (action instanceof AreStuckAlarmsCleared) { + state = { ...state, areAlarmsCleared: action.isBusy } + } + + return state; +}
\ No newline at end of file diff --git a/sdnr/wt/odlux/apps/faultApp/src/handlers/currentProblemsHandler.ts b/sdnr/wt/odlux/apps/faultApp/src/handlers/currentProblemsHandler.ts index 760dbeadc..3698a2798 100644 --- a/sdnr/wt/odlux/apps/faultApp/src/handlers/currentProblemsHandler.ts +++ b/sdnr/wt/odlux/apps/faultApp/src/handlers/currentProblemsHandler.ts @@ -18,17 +18,12 @@ import { createExternal,IExternalTableState } from '../../../../framework/src/components/material-table/utilities'; import { createSearchDataHandler } from '../../../../framework/src/utilities/elasticSearch'; -import { FaultResult, Fault } from '../models/fault'; +import { Fault } from '../models/fault'; export interface ICurrentProblemsState extends IExternalTableState<Fault> { } -// create eleactic search material data fetch handler -const currentProblemsSearchHandler = createSearchDataHandler<FaultResult, Fault>( - 'sdnevents/faultcurrent', - null, - (hit) => ({ _id: hit._id, ...hit._source.faultCurrent }), - (name) => `faultCurrent.${name}` - ); +// create eleactic search data fetch handler +const currentProblemsSearchHandler = createSearchDataHandler<Fault>('faultcurrent'); export const { actionHandler: currentProblemsActionHandler, diff --git a/sdnr/wt/odlux/apps/faultApp/src/handlers/faultAppRootHandler.ts b/sdnr/wt/odlux/apps/faultApp/src/handlers/faultAppRootHandler.ts index 22a9a58a2..dddb4a247 100644 --- a/sdnr/wt/odlux/apps/faultApp/src/handlers/faultAppRootHandler.ts +++ b/sdnr/wt/odlux/apps/faultApp/src/handlers/faultAppRootHandler.ts @@ -28,12 +28,13 @@ import { ICurrentProblemsState, currentProblemsActionHandler } from './currentPr import { IAlarmLogEntriesState, alarmLogEntriesActionHandler } from './alarmLogEntriesHandler'; import { SetPanelAction } from '../actions/panelChangeActions'; import { IFaultStatus, faultStatusHandler } from './faultStatusHandler'; +import { stuckAlarmHandler } from './clearStuckAlarmsHandler'; export interface IFaultAppStoreState { currentProblems: ICurrentProblemsState; faultNotifications: IFaultNotifications; alarmLogEntries: IAlarmLogEntriesState; - currentOpenPanel: string|null; + currentOpenPanel: string | null; faultStatus: IFaultStatus; } @@ -55,7 +56,8 @@ const actionHandlers = { faultNotifications: faultNotificationsHandler, alarmLogEntries: alarmLogEntriesActionHandler, currentOpenPanel: currentOpenPanelHandler, - faultStatus: faultStatusHandler + faultStatus: faultStatusHandler, + stuckAlarms: stuckAlarmHandler }; export const faultAppRootHandler = combineActionHandler<IFaultAppStoreState>(actionHandlers); diff --git a/sdnr/wt/odlux/apps/faultApp/src/handlers/notificationsHandler.ts b/sdnr/wt/odlux/apps/faultApp/src/handlers/notificationsHandler.ts index 4377a1b0a..aa92d2a1c 100644 --- a/sdnr/wt/odlux/apps/faultApp/src/handlers/notificationsHandler.ts +++ b/sdnr/wt/odlux/apps/faultApp/src/handlers/notificationsHandler.ts @@ -17,10 +17,10 @@ */ import { IActionHandler } from '../../../../framework/src/flux/action'; import { AddFaultNotificationAction, ResetFaultNotificationsAction } from '../actions/notificationActions'; -import { Fault } from '../models/fault'; +import { FaultAlarmNotification } from '../models/fault'; export interface IFaultNotifications { - faults: Fault[]; + faults: FaultAlarmNotification[]; since: Date; } diff --git a/sdnr/wt/odlux/apps/faultApp/src/index.html b/sdnr/wt/odlux/apps/faultApp/src/index.html index a2a0830b3..cd315f0b7 100644 --- a/sdnr/wt/odlux/apps/faultApp/src/index.html +++ b/sdnr/wt/odlux/apps/faultApp/src/index.html @@ -15,12 +15,8 @@ <script type="text/javascript" src="./config.js"></script> <script> // run the application - require(["app", "connectApp", "faultApp", "maintenanceApp", "configurationApp", "helpApp"], function (app, connectApp, faultApp, maintenanceApp, configurationApp, helpApp) { - connectApp.register(); + require(["app", "faultApp" ], function (app, faultApp) { faultApp.register(); - configurationApp.register(); - maintenanceApp.register(); - helpApp.register(); app("./app.tsx").runApplication(); }); </script> diff --git a/sdnr/wt/odlux/apps/faultApp/src/models/fault.ts b/sdnr/wt/odlux/apps/faultApp/src/models/fault.ts index 153e8def3..c65734437 100644 --- a/sdnr/wt/odlux/apps/faultApp/src/models/fault.ts +++ b/sdnr/wt/odlux/apps/faultApp/src/models/fault.ts @@ -15,17 +15,53 @@ * the License. * ============LICENSE_END========================================================================== */ -export type FaultType = { +export type Fault = { + id: string; + nodeId: string; + counter: number; + timestamp: string; + objectId: string; + problem: string; + severity: null | 'Warning' | 'Minor' | 'Major' | 'Critical'; + type: string; + sourceType: string; +} + +export type FaultAlarmNotification = { + id: string; nodeName: string; - counter: string; + counter: number; timeStamp: string; objectId: string; problem: string; - severity: null | 'Warning' | 'Minor' | 'Major' | 'Critical' ; + severity: null | 'Warning' | 'Minor' | 'Major' | 'Critical'; type: string; + sourceType: string; } -export type FaultResult = { faultCurrent: FaultType }; -export type FaultLog = { fault: FaultType }; +/** + * Fault status return type + */ +export type FaultsReturnType = { + criticals: number, + majors: number, + minors: number, + warnings: number +}; + +export type FaultType = { + Critical: number, + Major: number, + Minor: number, + Warning: number +}; + +export type Faults = { + faults: FaultsReturnType +}; -export type Fault = FaultType & { _id: string }; +export type DeletedStuckAlarms = { + output: { + nodenames: string[] + } +}
\ No newline at end of file diff --git a/sdnr/wt/odlux/apps/faultApp/src/plugin.tsx b/sdnr/wt/odlux/apps/faultApp/src/pluginFault.tsx index eec8c0821..02dde90f7 100644 --- a/sdnr/wt/odlux/apps/faultApp/src/plugin.tsx +++ b/sdnr/wt/odlux/apps/faultApp/src/pluginFault.tsx @@ -31,7 +31,7 @@ import { IApplicationStoreState } from "../../../framework/src/store/application import { faultAppRootHandler } from './handlers/faultAppRootHandler'; import { FaultApplication } from "./views/faultApplication"; -import { Fault } from "./models/fault"; +import { FaultAlarmNotification } from "./models/fault"; import { PanelId } from "./models/panelId"; import { SetPanelAction } from "./actions/panelChangeActions"; @@ -60,8 +60,8 @@ const FaultApplicationRouteAdapter = connect(mapProps, mapDisp)((props: RouteCom window.setTimeout(() => { if (currentMountId) { props.setCurrentPanel("CurrentProblem"); - props.currentProblemsActions.onFilterChanged("objectId", currentMountId); - props.currentProblemsProperties.showFilter || (props.currentProblemsActions.onToggleFilter()); + props.currentProblemsActions.onFilterChanged("nodeId", currentMountId); + props.currentProblemsProperties.showFilter; // || (props.currentProblemsActions.onToggleFilter()); props.currentProblemsActions.onRefresh(); } }); @@ -89,7 +89,7 @@ export function register() { }); // subscribe to the websocket notifications - subscribe<Fault & IFormatedMessage>("ProblemNotification", (fault => { + subscribe<FaultAlarmNotification & IFormatedMessage>("ProblemNotification", (fault => { const store = applicationApi && applicationApi.applicationStore; if (fault && store) { store.dispatch(new AddFaultNotificationAction(fault)); diff --git a/sdnr/wt/odlux/apps/faultApp/src/services/faultStatusService.ts b/sdnr/wt/odlux/apps/faultApp/src/services/faultStatusService.ts index ed1f3f919..d3409e095 100644 --- a/sdnr/wt/odlux/apps/faultApp/src/services/faultStatusService.ts +++ b/sdnr/wt/odlux/apps/faultApp/src/services/faultStatusService.ts @@ -16,24 +16,38 @@ * ============LICENSE_END========================================================================== */ import { requestRest } from "../../../../framework/src/services/restService"; -import { Result } from "../../../../framework/src/models/elasticSearch"; +import { Result, PostResponse } from "../../../../framework/src/models/elasticSearch"; +import { FaultType, Faults, DeletedStuckAlarms } from "../models/fault"; -export const getFaultStateFromDatabase = async (): Promise < { [key: string]: number } | null > => { - const path = 'database/sdnevents/faultcurrent/_search'; - const query = { - "size": 0, - "aggregations": { - "severity": { - "terms": { - "field": "faultCurrent.severity" - } - } + +export const getFaultStateFromDatabase = async (): Promise<FaultType | null> => { + const path = 'restconf/operations/data-provider:read-status'; + const result = await requestRest<Result<Faults>>(path, { method: "POST" }); + + let faultType: FaultType = { + Critical: 0, + Major: 0, + Minor: 0, + Warning: 0 + } + let faults: Faults[] | null = null; + + if (result && result.output && result.output.data) { + faults = result.output.data; + faultType = { + Critical: faults[0].faults.criticals, + Major: faults[0].faults.majors, + Minor: faults[0].faults.minors, + Warning: faults[0].faults.warnings } - }; + } + + return faultType; +} + +export const clearStuckAlarms = async (nodeNames: string[]) => { + const path = 'restconf/operations/devicemanager:clear-current-fault-by-nodename' + const result = await requestRest<DeletedStuckAlarms>(path, { method: 'Post', body: JSON.stringify({ input: { nodenames: nodeNames } }) }) + return result; - const result = await requestRest<Result<{ severity: { buckets: { key: string, doc_count: number }[] } }>>(path, { method: "POST", body: JSON.stringify(query) }); - return result && result.aggregations && result.aggregations["severity"].buckets.reduce<{ [key: string]: number }>((acc, cur) => { - acc[cur.key] = cur.doc_count; - return acc; - }, {}) || null; }
\ No newline at end of file diff --git a/sdnr/wt/odlux/apps/faultApp/src/views/faultApplication.tsx b/sdnr/wt/odlux/apps/faultApp/src/views/faultApplication.tsx index 9faa3566b..fd1c48ac5 100644 --- a/sdnr/wt/odlux/apps/faultApp/src/views/faultApplication.tsx +++ b/sdnr/wt/odlux/apps/faultApp/src/views/faultApplication.tsx @@ -28,12 +28,15 @@ import { Panel } from '../../../../framework/src/components/material-ui'; import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore'; import connect, { Connect, IDispatcher } from '../../../../framework/src/flux/connect'; -import { Fault } from '../models/fault'; +import { Fault, FaultAlarmNotification } from '../models/fault'; import { PanelId } from '../models/panelId'; import { createCurrentProblemsProperties, createCurrentProblemsActions, currentProblemsReloadAction } from '../handlers/currentProblemsHandler'; import { createAlarmLogEntriesProperties, createAlarmLogEntriesActions, alarmLogEntriesReloadAction } from '../handlers/alarmLogEntriesHandler'; import { SetPanelAction } from '../actions/panelChangeActions'; +import { Tooltip, IconButton } from '@material-ui/core'; +import RefreshIcon from '@material-ui/icons/Refresh'; +import ClearStuckAlarmsDialog, { ClearStuckAlarmsDialogMode } from '../components/clearStuckAlarmsDialog'; const mapProps = (state: IApplicationStoreState) => ({ activePanel: state.fault.currentOpenPanel, @@ -47,18 +50,50 @@ const mapDisp = (dispatcher: IDispatcher) => ({ alarmLogEntriesActions: createAlarmLogEntriesActions(dispatcher.dispatch), reloadCurrentProblems: () => dispatcher.dispatch(currentProblemsReloadAction), reloadAlarmLogEntries: () => dispatcher.dispatch(alarmLogEntriesReloadAction), - setCurrentPanel: (panelId: PanelId) => dispatcher.dispatch(new SetPanelAction(panelId)) + setCurrentPanel: (panelId: PanelId) => dispatcher.dispatch(new SetPanelAction(panelId)), }); type FaultApplicationComponentProps = RouteComponentProps & Connect<typeof mapProps, typeof mapDisp>; +type FaultApplicationState = { + clearAlarmDialogMode: ClearStuckAlarmsDialogMode, + stuckAlarms: string[] +} + const FaultTable = MaterialTable as MaterialTableCtorType<Fault>; +const FaultAlarmNotificationTable = MaterialTable as MaterialTableCtorType<FaultAlarmNotification>; + + +class FaultApplicationComponent extends React.Component<FaultApplicationComponentProps, FaultApplicationState>{ + + /** + * + */ + constructor(props: FaultApplicationComponentProps) { + super(props); + this.state = { clearAlarmDialogMode: ClearStuckAlarmsDialogMode.None, stuckAlarms: [] } + } + + onDialogClose = () => { + this.setState({ clearAlarmDialogMode: ClearStuckAlarmsDialogMode.None, stuckAlarms: [] }) + } + + onDialogOpen = () => { + const stuckAlarms = [...new Set(this.props.currentProblemsProperties.rows.map(item => item.nodeId))]; + this.setState({ clearAlarmDialogMode: ClearStuckAlarmsDialogMode.Show, stuckAlarms: stuckAlarms }) + } + -class FaultApplicationComponent extends React.Component<FaultApplicationComponentProps>{ render(): JSX.Element { + const refreshButton = { + icon: RefreshIcon, tooltip: 'Clear stuck alarms', onClick: this.onDialogOpen + }; + const areFaultsAvailable = this.props.currentProblemsProperties.rows && this.props.currentProblemsProperties.rows.length > 0 + const customAction = areFaultsAvailable ? [refreshButton] : []; + const { activePanel } = this.props; const onTogglePanel = (panelId: PanelId) => { @@ -82,19 +117,19 @@ class FaultApplicationComponent extends React.Component<FaultApplicationComponen return ( <> - <Panel activePanel={ activePanel } panelId={ 'CurrentProblem' } onToggle={ onTogglePanel } title={ 'Current Problem List' }> - <FaultTable idProperty={ '_id' } columns={ [ - { property: "icon", title: "", type: ColumnType.custom, customControl: this.renderIcon }, - { property: "timeStamp", type: ColumnType.text, title: "Time Stamp" }, - { property: "nodeName", title: "Node Name", type: ColumnType.text }, - { property: "counter", title: "Count", type: ColumnType.numeric, width: "100px" }, - { property: "objectId", title: "Object Id", type: ColumnType.text } , - { property: "problem", title: "Alarm Type", type: ColumnType.text }, - { property: "severity", title: "Severity", type: ColumnType.text, width: "140px" }, - ] } { ...this.props.currentProblemsProperties } { ...this.props.currentProblemsActions } /> + <Panel activePanel={activePanel} panelId={'CurrentProblem'} onToggle={onTogglePanel} title={'Current Problem List'}> + <FaultTable idProperty={'id'} customActionButtons={customAction} columns={[ + { property: "icon", title: "", type: ColumnType.custom, customControl: this.renderIcon }, + { property: "timestamp", type: ColumnType.text, title: "Time Stamp" }, + { property: "nodeId", title: "Node Name", type: ColumnType.text }, + { property: "counter", title: "Count", type: ColumnType.numeric, width: "100px" }, + { property: "objectId", title: "Object Id", type: ColumnType.text }, + { property: "problem", title: "Alarm Type", type: ColumnType.text }, + { property: "severity", title: "Severity", type: ColumnType.text, width: "140px" }, + ]} {...this.props.currentProblemsProperties} {...this.props.currentProblemsActions} /> </Panel> - <Panel activePanel={ activePanel } panelId={ 'AlarmNotifications' } onToggle={ onTogglePanel } title={ `Alarm Notifications ${this.props.faultNotifications.faults.length} since ${this.props.faultNotifications.since}` }> - <FaultTable rows={ this.props.faultNotifications.faults } asynchronus columns={ [ + <Panel activePanel={activePanel} panelId={'AlarmNotifications'} onToggle={onTogglePanel} title={`Alarm Notifications ${this.props.faultNotifications.faults.length} since ${this.props.faultNotifications.since}`}> + <FaultAlarmNotificationTable rows={this.props.faultNotifications.faults} asynchronus columns={[ { property: "icon", title: "", type: ColumnType.custom, customControl: this.renderIcon }, { property: "timeStamp", title: "Time Stamp" }, { property: "nodeName", title: "Node Name" }, @@ -102,19 +137,25 @@ class FaultApplicationComponent extends React.Component<FaultApplicationComponen { property: "objectId", title: "Object Id" }, { property: "problem", title: "Alarm Type" }, { property: "severity", title: "Severity", width: "140px" }, - ] } idProperty={ '_id' } /> + ]} idProperty={'id'} /> </Panel> - <Panel activePanel={ activePanel } panelId={ 'AlarmLog' } onToggle={ onTogglePanel } title={ 'Alarm Log' }> - <FaultTable idProperty={ '_id' } columns={ [ + <Panel activePanel={activePanel} panelId={'AlarmLog'} onToggle={onTogglePanel} title={'Alarm Log'}> + <FaultTable idProperty={'id'} columns={[ { property: "icon", title: "", type: ColumnType.custom, customControl: this.renderIcon }, - { property: "timeStamp", title: "Time Stamp" }, - { property: "nodeName", title: "Node Name" }, + { property: "timestamp", title: "Time Stamp" }, + { property: "nodeId", title: "Node Name" }, { property: "counter", title: "Count", type: ColumnType.numeric, width: "100px" }, { property: "objectId", title: "Object Id" }, { property: "problem", title: "Alarm Type" }, { property: "severity", title: "Severity", width: "140px" }, - ] } { ...this.props.alarmLogEntriesProperties } { ...this.props.alarmLogEntriesActions }/> - </Panel> + { property: "sourceType", title: "Source", width: "140px" }, + ]} {...this.props.alarmLogEntriesProperties} {...this.props.alarmLogEntriesActions} /> + </Panel> + { + this.state.clearAlarmDialogMode !== ClearStuckAlarmsDialogMode.None && <ClearStuckAlarmsDialog mode={this.state.clearAlarmDialogMode} numberDevices={this.state.stuckAlarms.length} stuckAlarms={this.state.stuckAlarms} onClose={this.onDialogClose} /> + + } + </> ); }; @@ -123,9 +164,9 @@ class FaultApplicationComponent extends React.Component<FaultApplicationComponen this.props.alarmLogEntriesActions.onToggleFilter(); this.props.currentProblemsActions.onToggleFilter(); } - private renderIcon = (props: { rowData: Fault }) => { + private renderIcon = (props: { rowData: Fault | FaultAlarmNotification }) => { return ( - <FontAwesomeIcon icon={ faExclamationTriangle } /> + <FontAwesomeIcon icon={faExclamationTriangle} /> ); }; diff --git a/sdnr/wt/odlux/apps/faultApp/webpack.config.js b/sdnr/wt/odlux/apps/faultApp/webpack.config.js index bbf33ea2f..66926edfb 100644 --- a/sdnr/wt/odlux/apps/faultApp/webpack.config.js +++ b/sdnr/wt/odlux/apps/faultApp/webpack.config.js @@ -26,7 +26,7 @@ module.exports = (env) => { context: path.resolve(__dirname, "src"), entry: { - faultApp: ["./plugin.tsx"] + faultApp: ["./pluginFault.tsx"] }, devtool: env === "release" ? false : "source-map", @@ -125,23 +125,23 @@ module.exports = (env) => { }, proxy: { "/oauth2/": { - target: "http://localhost:3000", + target: "http://10.20.6.29:28181/", secure: false }, "/database/": { - target: "http://localhost:3000", + target: "http://10.20.6.29:28181/", secure: false }, "/restconf/": { - target: "http://localhost:3000", + target: "http://10.20.6.29:28181/", secure: false }, "/help/": { - target: "http://localhost:3000", + target: "http://10.20.6.29:28181/", secure: false }, "/websocket/": { - target: "http://localhost:3000", + target: "http://10.20.6.29:28181/", ws: true, changeOrigin: true, secure: false |