summaryrefslogtreecommitdiffstats
path: root/sdnr/wt-odlux/odlux/apps/faultApp
diff options
context:
space:
mode:
Diffstat (limited to 'sdnr/wt-odlux/odlux/apps/faultApp')
-rw-r--r--sdnr/wt-odlux/odlux/apps/faultApp/.babelrc17
-rw-r--r--sdnr/wt-odlux/odlux/apps/faultApp/package.json46
-rw-r--r--sdnr/wt-odlux/odlux/apps/faultApp/pom.xml109
-rw-r--r--sdnr/wt-odlux/odlux/apps/faultApp/src/actions/clearStuckAlarmsAction.ts37
-rw-r--r--sdnr/wt-odlux/odlux/apps/faultApp/src/actions/notificationActions.ts33
-rw-r--r--sdnr/wt-odlux/odlux/apps/faultApp/src/actions/panelChangeActions.ts37
-rw-r--r--sdnr/wt-odlux/odlux/apps/faultApp/src/actions/statusActions.ts60
-rw-r--r--sdnr/wt-odlux/odlux/apps/faultApp/src/assets/icons/faultAppIcon.svg19
-rw-r--r--sdnr/wt-odlux/odlux/apps/faultApp/src/components/clearStuckAlarmsDialog.tsx138
-rw-r--r--sdnr/wt-odlux/odlux/apps/faultApp/src/components/dashboardHome.tsx473
-rw-r--r--sdnr/wt-odlux/odlux/apps/faultApp/src/components/faultStatus.tsx106
-rw-r--r--sdnr/wt-odlux/odlux/apps/faultApp/src/components/refreshAlarmLogDialog.tsx112
-rw-r--r--sdnr/wt-odlux/odlux/apps/faultApp/src/components/refreshCurrentAlarmsDialog.tsx113
-rw-r--r--sdnr/wt-odlux/odlux/apps/faultApp/src/handlers/alarmLogEntriesHandler.ts36
-rw-r--r--sdnr/wt-odlux/odlux/apps/faultApp/src/handlers/clearStuckAlarmsHandler.ts37
-rw-r--r--sdnr/wt-odlux/odlux/apps/faultApp/src/handlers/currentAlarmsHandler.ts36
-rw-r--r--sdnr/wt-odlux/odlux/apps/faultApp/src/handlers/faultAppRootHandler.ts63
-rw-r--r--sdnr/wt-odlux/odlux/apps/faultApp/src/handlers/faultStatusHandler.ts77
-rw-r--r--sdnr/wt-odlux/odlux/apps/faultApp/src/handlers/notificationsHandler.ts48
-rw-r--r--sdnr/wt-odlux/odlux/apps/faultApp/src/index.html26
-rw-r--r--sdnr/wt-odlux/odlux/apps/faultApp/src/models/fault.ts97
-rw-r--r--sdnr/wt-odlux/odlux/apps/faultApp/src/models/panelId.ts18
-rw-r--r--sdnr/wt-odlux/odlux/apps/faultApp/src/pluginFault.tsx171
-rw-r--r--sdnr/wt-odlux/odlux/apps/faultApp/src/services/faultStatusService.ts69
-rw-r--r--sdnr/wt-odlux/odlux/apps/faultApp/src/views/faultApplication.tsx247
-rw-r--r--sdnr/wt-odlux/odlux/apps/faultApp/tsconfig.json37
-rw-r--r--sdnr/wt-odlux/odlux/apps/faultApp/webpack.config.js166
27 files changed, 2428 insertions, 0 deletions
diff --git a/sdnr/wt-odlux/odlux/apps/faultApp/.babelrc b/sdnr/wt-odlux/odlux/apps/faultApp/.babelrc
new file mode 100644
index 000000000..3d8cd1260
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/faultApp/.babelrc
@@ -0,0 +1,17 @@
+{
+ "presets": [
+ ["@babel/preset-react"],
+ ["@babel/preset-env", {
+ "targets": {
+ "chrome": "66"
+ },
+ "spec": true,
+ "loose": false,
+ "modules": false,
+ "debug": false,
+ "useBuiltIns": "usage",
+ "forceAllTransforms": true
+ }]
+ ],
+ "plugins": []
+}
diff --git a/sdnr/wt-odlux/odlux/apps/faultApp/package.json b/sdnr/wt-odlux/odlux/apps/faultApp/package.json
new file mode 100644
index 000000000..953105584
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/faultApp/package.json
@@ -0,0 +1,46 @@
+{
+ "name": "@odlux/fault-app",
+ "version": "0.1.0",
+ "description": "A react based modular UI to demo the fault management.",
+ "main": "index.js",
+ "scripts": {
+ "start": "webpack-dev-server --env debug",
+ "build": "webpack --env release --config webpack.config.js",
+ "build:dev": "webpack --env debug --config webpack.config.js"
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://git.mfico.de/highstreet-technologies/odlux.git"
+ },
+ "keywords": [
+ "reactjs",
+ "redux",
+ "ui",
+ "framework"
+ ],
+ "author": "Matthias Fischer",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@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": "*",
+ "@fortawesome/free-solid-svg-icons": "5.6.3",
+ "@fortawesome/react-fontawesome": "0.1.14"
+ },
+ "peerDependencies": {
+ "@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.2",
+ "react-dom": "17.0.2",
+ "react-router-dom": "5.2.0",
+ "react-chartjs-2": "^3.0.3"
+ }
+}
diff --git a/sdnr/wt-odlux/odlux/apps/faultApp/pom.xml b/sdnr/wt-odlux/odlux/apps/faultApp/pom.xml
new file mode 100644
index 000000000..3e7491833
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/faultApp/pom.xml
@@ -0,0 +1,109 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ ============LICENSE_START=======================================================
+ ~ ONAP : SDNR ODLUX
+ ~ ================================================================================
+ ~ Copyright (C) 2020 AT&T 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=======================================================
+ ~
+ -->
+
+<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>
+
+ <groupId>org.onap.ccsdk.features.sdnr.odlux</groupId>
+ <artifactId>sdnr-odlux-app-faultApp</artifactId>
+ <version>1.7.0-SNAPSHOT</version>
+ <packaging>jar</packaging>
+
+ <name>SDNR ODLUX :: ${project.artifactId}</name>
+ <licenses>
+ <license>
+ <name>Apache License, Version 2.0</name>
+ <url>http://www.apache.org/licenses/LICENSE-2.0</url>
+ </license>
+ </licenses>
+
+ <properties>
+ <maven.javadoc.skip>true</maven.javadoc.skip>
+ </properties>
+
+ <build>
+ <resources>
+ <resource>
+ <directory>dist</directory>
+ <targetPath>odlux</targetPath>
+ </resource>
+ </resources>
+ <plugins>
+ <plugin>
+ <artifactId>maven-clean-plugin</artifactId>
+ <configuration>
+ <filesets>
+ <fileset>
+ <directory>dist</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ <fileset>
+ <directory>node</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ <fileset>
+ <directory>node_modules</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ <fileset>
+ <directory>../node_modules</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ <!-- eclipse bug build bin folder in basedir -->
+ <fileset>
+ <directory>bin</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ </filesets>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>de.jacks-it-lab</groupId>
+ <artifactId>frontend-maven-plugin</artifactId>
+ <version>1.7.2</version>
+ <executions>
+ <execution>
+ <id>install node and yarn</id>
+ <goals>
+ <goal>install-node-and-yarn</goal>
+ </goals>
+ <!-- optional: default phase is "generate-resources" -->
+ <phase>initialize</phase>
+ <configuration>
+ <nodeVersion>v16.17.0</nodeVersion>
+ <yarnVersion>v1.22.19</yarnVersion>
+ </configuration>
+ </execution>
+ <execution>
+ <id>yarn build</id>
+ <goals>
+ <goal>yarn</goal>
+ </goals>
+ <configuration>
+ <arguments>run build</arguments>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/sdnr/wt-odlux/odlux/apps/faultApp/src/actions/clearStuckAlarmsAction.ts b/sdnr/wt-odlux/odlux/apps/faultApp/src/actions/clearStuckAlarmsAction.ts
new file mode 100644
index 000000000..7aac8ba35
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/faultApp/src/actions/clearStuckAlarmsAction.ts
@@ -0,0 +1,37 @@
+/**
+ * ============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 { Dispatch } from '../../../../framework/src/flux/store';
+
+import { clearStuckAlarms } from '../services/faultStatusService';
+import { FaultApplicationBaseAction } from './notificationActions';
+
+export class AreStuckAlarmsCleared extends FaultApplicationBaseAction {
+ constructor(public isBusy: boolean) {
+ super();
+ }
+}
+
+
+export const clearStuckAlarmAsyncAction = (dispatch: Dispatch) => async (nodeNames: string[]) => {
+ dispatch(new AreStuckAlarmsCleared(true));
+ const result = await clearStuckAlarms(nodeNames).catch(error => { console.error(error); return undefined; });
+ dispatch(new AreStuckAlarmsCleared(false));
+ return result;
+}; \ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/faultApp/src/actions/notificationActions.ts b/sdnr/wt-odlux/odlux/apps/faultApp/src/actions/notificationActions.ts
new file mode 100644
index 000000000..584e7cd8b
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/faultApp/src/actions/notificationActions.ts
@@ -0,0 +1,33 @@
+/**
+ * ============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 { Action } from '../../../../framework/src/flux/action';
+
+import { FaultAlarmNotification } from '../models/fault';
+
+export class FaultApplicationBaseAction extends Action { }
+
+
+export class AddFaultNotificationAction extends FaultApplicationBaseAction {
+ constructor(public fault:FaultAlarmNotification) {
+ super();
+ }
+}
+
+export class ResetFaultNotificationsAction extends FaultApplicationBaseAction {
+
+}
diff --git a/sdnr/wt-odlux/odlux/apps/faultApp/src/actions/panelChangeActions.ts b/sdnr/wt-odlux/odlux/apps/faultApp/src/actions/panelChangeActions.ts
new file mode 100644
index 000000000..fb29e9c1b
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/faultApp/src/actions/panelChangeActions.ts
@@ -0,0 +1,37 @@
+/**
+ * ============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 { Action } from '../../../../framework/src/flux/action';
+
+import { PanelId } from '../models/panelId';
+
+export class SetPanelAction extends Action {
+ constructor(public panelId: PanelId) {
+ super();
+ }
+}
+
+export class RememberCurrentPanelAction extends Action {
+ constructor(public panelId: PanelId) {
+ super();
+ }
+}
+
+export const setPanelAction = (panelId: PanelId) => {
+ return new SetPanelAction(panelId);
+};
+
diff --git a/sdnr/wt-odlux/odlux/apps/faultApp/src/actions/statusActions.ts b/sdnr/wt-odlux/odlux/apps/faultApp/src/actions/statusActions.ts
new file mode 100644
index 000000000..8b631b96d
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/faultApp/src/actions/statusActions.ts
@@ -0,0 +1,60 @@
+/**
+ * ============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 { Dispatch } from '../../../../framework/src/flux/store';
+
+import { getFaultStateFromDatabase } from '../services/faultStatusService';
+import { FaultApplicationBaseAction } from './notificationActions';
+
+
+export class SetFaultStatusAction extends FaultApplicationBaseAction {
+ constructor(public criticalFaults: number, public majorFaults: number, public minorFaults: number, public warnings: number,
+ public isLoadingAlarmStatusChart: boolean, public ConnectedCount: number, public ConnectingCount: number, public DisconnectedCount: number,
+ public MountedCount: number, public UnableToConnectCount: number, public UndefinedCount: number, public UnmountedCount: number,
+ public totalCount: number, public isLoadingConnectionStatusChart: boolean) {
+ super();
+ }
+}
+
+
+export const refreshFaultStatusAsyncAction = async (dispatch: Dispatch) => {
+
+ // dispatch(new SetFaultStatusAction(0, 0, 0, 0, true, 0, 0, 0, 0, 0, 0, 0, 0, true));
+ const result = await getFaultStateFromDatabase().catch(_ => null);
+ if (result) {
+ const statusAction = new SetFaultStatusAction(
+ result.Critical || 0,
+ result.Major || 0,
+ result.Minor || 0,
+ result.Warning || 0,
+ false,
+ result.Connected || 0,
+ result.Connecting || 0,
+ result.Disconnected || 0,
+ result.Mounted || 0,
+ result.UnableToConnect || 0,
+ result.Undefined || 0,
+ result.Unmounted || 0,
+ result.total || 0,
+ false,
+ );
+ dispatch(statusAction);
+ return;
+ } else {
+ dispatch(new SetFaultStatusAction(0, 0, 0, 0, false, 0, 0, 0, 0, 0, 0, 0, 0, false));
+ }
+};
diff --git a/sdnr/wt-odlux/odlux/apps/faultApp/src/assets/icons/faultAppIcon.svg b/sdnr/wt-odlux/odlux/apps/faultApp/src/assets/icons/faultAppIcon.svg
new file mode 100644
index 000000000..aabbf4cf4
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/faultApp/src/assets/icons/faultAppIcon.svg
@@ -0,0 +1,19 @@
+<!-- highstreet technologies GmbH colour scheme
+ Grey #565656
+ LBlue #36A9E1
+ DBlue #246DA2
+ Green #003F2C / #006C4B
+ Yellw #C8D400
+ Red #D81036
+-->
+
+<svg viewBox="0 0 500 540" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" >
+ <g transform="matrix(27.7762,0,0,27.7762,-13.8603,-27.7762)">
+
+ <path fill="#565656" d="M 16.8 15.101 C 15.656 14.242 15 12.929 15 11.5 L 15 8.5 C 15 5.987 13.306 3.862 11 3.208 L 11 2.5 C 11 1.673 10.327 1 9.5 1 C 8.673 1 8 1.673 8 2.5 L 8 3.208 C 5.694 3.863 4 5.987 4 8.5 L 4 11.5 C 4 12.929 3.344 14.241 2.2 15.101 C 2.028 15.23 1.958 15.455 2.026 15.659 C 2.094 15.863 2.285 16.001 2.5 16.001 L 16.499 16.001 C 16.714 16.001 16.905 15.863 16.973 15.659 C 17.041 15.455 16.971 15.23 16.799 15.101 L 16.8 15.101 Z" />
+
+ <path fill="#D81036" d="m 7.05 17.001 c -0.033 0.164 -0.051 0.331 -0.051 0.5 c 0 1.378 1.122 2.5 2.5 2.5 c 1.378 0 2.5 -1.122 2.5 -2.5 c 0 -0.168 -0.017 -0.336 -0.05 -0.5 l -4.899 0 z" />
+
+
+ </g>
+</svg>
diff --git a/sdnr/wt-odlux/odlux/apps/faultApp/src/components/clearStuckAlarmsDialog.tsx b/sdnr/wt-odlux/odlux/apps/faultApp/src/components/clearStuckAlarmsDialog.tsx
new file mode 100644
index 000000000..e86b756a7
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/faultApp/src/components/clearStuckAlarmsDialog.tsx
@@ -0,0 +1,138 @@
+/**
+ * ============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 React from 'react';
+
+import { Button, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle } from '@mui/material';
+
+import { connect, Connect, IDispatcher } from '../../../../framework/src/flux/connect';
+
+import { clearStuckAlarmAsyncAction } from '../actions/clearStuckAlarmsAction';
+import { currentAlarmsReloadAction } from '../handlers/currentAlarmsHandler';
+
+export enum ClearStuckAlarmsDialogMode {
+ None = 'none',
+ Show = 'show',
+}
+
+const mapDispatch = (dispatcher: IDispatcher) => ({
+ clearStuckAlarmsAsync: clearStuckAlarmAsyncAction(dispatcher.dispatch),
+ reloadCurrentAlarmsAction: () => dispatcher.dispatch(currentAlarmsReloadAction),
+});
+
+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 && result['devicemanager:output'].nodenames && result['devicemanager:output'].nodenames.length !== this.props.stuckAlarms.length) { //show errormessage if not all devices were cleared
+ const undeletedAlarm = this.props.stuckAlarms.filter(item => !result['devicemanager: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: [] });
+ }
+
+ this.props.reloadCurrentAlarmsAction();
+ this.props.onClose();
+ };
+
+ onOk = (event: React.MouseEvent) => {
+
+ event.stopPropagation();
+ event.preventDefault();
+ if (this.state.unclearedAlarms.length > 0)
+ this.props.reloadCurrentAlarmsAction();
+ 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 color="inherit" onClick={this.onRefresh}>Yes</Button>
+ <Button color="inherit" onClick={this.onClose}>No</Button>
+ </>
+ }
+
+ {
+ !this.state.clearAlarmsSuccessful && <Button color="inherit" onClick={this.onOk}>Ok</Button>
+ }
+ </DialogActions>
+ </Dialog>
+ );
+ }
+}
+
+const ClearStuckAlarmsDialog = connect(undefined, mapDispatch)(ClearStuckAlarmsDialogComponent);
+export default ClearStuckAlarmsDialog;
diff --git a/sdnr/wt-odlux/odlux/apps/faultApp/src/components/dashboardHome.tsx b/sdnr/wt-odlux/odlux/apps/faultApp/src/components/dashboardHome.tsx
new file mode 100644
index 000000000..a3e32c42c
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/faultApp/src/components/dashboardHome.tsx
@@ -0,0 +1,473 @@
+/**
+ * ============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 React from 'react';
+import { RouteComponentProps, withRouter } from 'react-router-dom';
+
+import { WithStyles } from '@mui/styles';
+import createStyles from '@mui/styles/createStyles';
+import { Doughnut } from 'react-chartjs-2';
+import { connect, Connect, IDispatcher } from '../../../../framework/src/flux/connect';
+
+import { NavigateToApplication } from '../../../../framework/src/actions/navigationActions';
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+
+const styles = () => 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) => ({
+ alarmStatus: state.fault.faultStatus,
+});
+
+const mapDispatch = (dispatcher: IDispatcher) => ({
+ navigateToApplication: (applicationName: string, path?: string) => dispatcher.dispatch(new NavigateToApplication(applicationName, path)),
+});
+
+type HomeComponentProps = RouteComponentProps & Connect<typeof mapProps, typeof mapDispatch> & WithStyles<typeof styles>;
+
+class DashboardHome extends React.Component<HomeComponentProps> {
+ constructor(props: HomeComponentProps) {
+ super(props);
+ this.state = {
+ };
+ }
+
+ render(): JSX.Element {
+
+ if (!this.props.alarmStatus.isLoadingConnectionStatusChart) {
+ connectionStatusDataLoad = [
+ this.props.alarmStatus.Connected,
+ this.props.alarmStatus.Connecting,
+ this.props.alarmStatus.Disconnected,
+ this.props.alarmStatus.UnableToConnect,
+ this.props.alarmStatus.Undefined,
+ ];
+ connectionTotalCount = this.props.alarmStatus.Connected + this.props.alarmStatus.Connecting
+ + this.props.alarmStatus.Disconnected + this.props.alarmStatus.UnableToConnect + this.props.alarmStatus.Undefined;
+
+ }
+
+ 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: ' + this.props.alarmStatus.Connected,
+ 'Connecting: ' + this.props.alarmStatus.Connecting,
+ 'Disconnected: ' + this.props.alarmStatus.Disconnected,
+ 'UnableToConnect: ' + this.props.alarmStatus.UnableToConnect,
+ 'Undefined: ' + this.props.alarmStatus.Undefined,
+ ],
+ datasets: [{
+ labels: ['Connected', 'Connecting', 'Disconnected', 'UnableToConnect', 'Undefined'],
+ data: connectionStatusDataLoad,
+ backgroundColor: [
+ 'rgb(0, 153, 51)',
+ 'rgb(255, 102, 0)',
+ 'rgb(191, 191, 191)',
+ 'rgb(191, 191, 191)',
+ 'rgb(242, 240, 240)',
+ ],
+ }],
+ };
+
+
+ /** 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', 'Undefined'];
+ const connectionStatusOptions = {
+ tooltips: {
+ callbacks: {
+ label: (tooltipItem: any, data: any) => {
+ let label =
+ (data.datasets[tooltipItem.datasetIndex].labels &&
+ data.datasets[tooltipItem.datasetIndex].labels[
+ tooltipItem.index
+ ]) ||
+ data.labels[tooltipItem.index] ||
+ '';
+ if (label) {
+ label += ': ';
+ }
+ label +=
+ data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index] +
+ (data.datasets[tooltipItem.datasetIndex].labelSuffix || '');
+
+ return label;
+ },
+ },
+ },
+ 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 : ' + this.props.alarmStatus.critical,
+ 'Major : ' + this.props.alarmStatus.major,
+ 'Minor : ' + this.props.alarmStatus.minor,
+ 'Warning : ' + this.props.alarmStatus.warning,
+ ],
+ datasets: [{
+ labels: ['Critical', 'Major', 'Minor', 'Warning'],
+ 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 = {
+ tooltips: {
+ callbacks: {
+ label: (tooltipItem: any, data: any) => {
+ let label =
+ (data.datasets[tooltipItem.datasetIndex].labels &&
+ data.datasets[tooltipItem.datasetIndex].labels[
+ tooltipItem.index
+ ]) ||
+ data.labels[tooltipItem.index] ||
+ '';
+ if (label) {
+ label += ': ';
+ }
+ label +=
+ data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index] +
+ (data.datasets[tooltipItem.datasetIndex].labelSuffix || '');
+
+ return label;
+ },
+ },
+ },
+ 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 (
+ <>
+ <div style={scrollbar} >
+ <h1 aria-label="welcome-to-odlux">Welcome to ODLUX</h1>
+ <div style={{ width: '50%', float: 'left' }}>
+ {this.checkElementsAreLoaded() ?
+ this.checkConnectionStatus() && connectionTotalCount != 0 ?
+ <Doughnut
+ data={connectionStatusData}
+ type={Doughnut}
+ width={500}
+ height={500}
+ options={connectionStatusOptions}
+ plugins={connectionStatusPlugins}
+ />
+ : <Doughnut
+ data={connectionStatusUnavailableData}
+ type={Doughnut}
+ width={500}
+ height={500}
+ options={connectionStatusUnavailableOptions}
+ plugins={connectionStatusPlugins} />
+ : <Doughnut
+ data={connectionStatusisLoading}
+ type={Doughnut}
+ width={500}
+ height={500}
+ options={connectionStatusUnavailableOptions}
+ plugins={connectionStatusPlugins}
+ />
+ }
+ </div>
+ <div style={{ width: '50%', float: 'left' }}>
+ {this.checkAlarmsAreLoaded() ?
+ this.checkAlarmStatus() && alarmTotalCount != 0 ?
+ <Doughnut
+ data={alarmStatusData}
+ type={Doughnut}
+ width={500}
+ height={500}
+ options={alarmStatusOptions}
+ plugins={alarmStatusPlugins}
+ />
+ : <Doughnut
+ data={alarmStatusUnavailableData}
+ type={Doughnut}
+ width={500}
+ height={500}
+ options={alarmStatusUnavailableOptions}
+ plugins={alarmStatusPlugins}
+ />
+ : <Doughnut
+ data={alarmStatusisLoading}
+ type={Doughnut}
+ width={500}
+ height={500}
+ options={alarmStatusUnavailableOptions}
+ plugins={alarmStatusPlugins}
+ />
+ }
+ </div>
+ </div>
+ </>
+ );
+ }
+
+ /** Check if connection status data available */
+ public checkConnectionStatus = () => {
+ let statusCount = this.props.alarmStatus;
+ if (statusCount.isLoadingConnectionStatusChart) {
+ return true;
+ }
+ if (statusCount.Connected == 0 && statusCount.Connecting == 0 && statusCount.Disconnected == 0
+ && statusCount.UnableToConnect == 0 && statusCount.Undefined == 0) {
+ return false;
+ } else {
+ return true;
+ }
+ };
+
+ /** Check if connection status chart data is loaded */
+ public checkElementsAreLoaded = () => {
+ let isLoadingCheck = this.props.alarmStatus;
+ 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/odlux/apps/faultApp/src/components/faultStatus.tsx b/sdnr/wt-odlux/odlux/apps/faultApp/src/components/faultStatus.tsx
new file mode 100644
index 000000000..57374dd77
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/faultApp/src/components/faultStatus.tsx
@@ -0,0 +1,106 @@
+/**
+ * ============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 React from 'react';
+
+import { faExclamationTriangle } from '@fortawesome/free-solid-svg-icons'; // select app icon
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import Typography from '@mui/material/Typography';
+import { WithStyles } from '@mui/styles';
+import createStyles from '@mui/styles/createStyles';
+import withStyles from '@mui/styles/withStyles';
+import Tooltip from '@mui/material/Tooltip';
+
+import { connect, Connect } from '../../../../framework/src/flux/connect';
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+
+
+const styles = () => createStyles({
+ icon: {
+ marginLeft: 8,
+ marginRight: 8,
+ },
+ critical: {
+ color: 'red',
+ },
+ major: {
+ color: 'orange',
+ },
+ minor: {
+ color: '#f7f700',
+ },
+ warning: {
+ color: '#428bca',
+ },
+});
+
+const mapProps = (state: IApplicationStoreState) => ({
+ faultStatus: state.fault.faultStatus,
+});
+
+
+type FaultStatusComponentProps = & WithStyles<typeof styles> & Connect<typeof mapProps>;
+
+class FaultStatusComponent extends React.Component<FaultStatusComponentProps> {
+ render(): JSX.Element {
+ const { classes, faultStatus } = this.props;
+
+ return (
+ <>
+ <Typography variant="body1" color="inherit">
+ Alarm Status:
+ <Tooltip title="Critical Alarms" arrow>
+ <span aria-label="critical-alarms">
+ <FontAwesomeIcon className={`${classes.icon} ${classes.critical}`} icon={faExclamationTriangle} />
+ </span>
+ </Tooltip>
+ {faultStatus.critical} |
+ </Typography>
+
+ <Typography variant="body1" color="inherit">
+ <Tooltip title="Major Alarms" arrow>
+ <span aria-label="major-alarms">
+ <FontAwesomeIcon className={`${classes.icon} ${classes.major}`} icon={faExclamationTriangle} />
+ </span>
+ </Tooltip>
+ {faultStatus.major} |
+ </Typography>
+
+ <Typography variant="body1" color="inherit">
+ <Tooltip title="Minor Alarms" arrow>
+ <span aria-label="minor-alarms">
+ <FontAwesomeIcon className={`${classes.icon} ${classes.minor}`} icon={faExclamationTriangle} />
+ </span>
+ </Tooltip>
+ {faultStatus.minor} |
+ </Typography>
+
+ <Typography variant="body1" color="inherit">
+ <Tooltip title="Warning Alarms" arrow>
+ <span aria-label="warning-alarms">
+ <FontAwesomeIcon className={`${classes.icon} ${classes.warning}`} icon={faExclamationTriangle} />
+ </span>
+ </Tooltip>
+ {faultStatus.warning} |
+ </Typography>
+ </>
+ );
+ }
+}
+
+export const FaultStatus = withStyles(styles)(connect(mapProps)(FaultStatusComponent));
+export default FaultStatus; \ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/faultApp/src/components/refreshAlarmLogDialog.tsx b/sdnr/wt-odlux/odlux/apps/faultApp/src/components/refreshAlarmLogDialog.tsx
new file mode 100644
index 000000000..59657d8de
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/faultApp/src/components/refreshAlarmLogDialog.tsx
@@ -0,0 +1,112 @@
+/**
+ * ============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 Button from '@mui/material/Button';
+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 { connect, Connect, IDispatcher } from '../../../../framework/src/flux/connect';
+import { alarmLogEntriesReloadAction } from '../handlers/alarmLogEntriesHandler';
+import { Fault } from '../models/fault';
+
+export enum RefreshAlarmLogDialogMode {
+ None = 'none',
+ RefreshAlarmLogTable = 'RefreshAlarmLogTable',
+}
+
+const mapDispatch = (dispatcher: IDispatcher) => ({
+ refreshAlarmLog: () => dispatcher.dispatch(alarmLogEntriesReloadAction),
+});
+
+type DialogSettings = {
+ dialogTitle: string;
+ dialogDescription: string;
+ applyButtonText: string;
+ cancelButtonText: string;
+ enableMountIdEditor: boolean;
+ enableUsernameEditor: boolean;
+ enableExtendedEditor: boolean;
+};
+
+const settings: { [key: string]: DialogSettings } = {
+ [RefreshAlarmLogDialogMode.None]: {
+ dialogTitle: '',
+ dialogDescription: '',
+ applyButtonText: '',
+ cancelButtonText: '',
+ enableMountIdEditor: false,
+ enableUsernameEditor: false,
+ enableExtendedEditor: false,
+ },
+ [RefreshAlarmLogDialogMode.RefreshAlarmLogTable]: {
+ dialogTitle: 'Do you want to refresh the Alarm Log?',
+ dialogDescription: '',
+ applyButtonText: 'Yes',
+ cancelButtonText: 'Cancel',
+ enableMountIdEditor: true,
+ enableUsernameEditor: true,
+ enableExtendedEditor: true,
+ },
+};
+
+type RefreshAlarmLogDialogComponentProps = Connect<undefined, typeof mapDispatch> & {
+ mode: RefreshAlarmLogDialogMode;
+ onClose: () => void;
+};
+
+type RefreshAlarmLogDialogComponentState = Fault & { isNameValid: boolean; isHostSet: boolean };
+
+class RefreshAlarmLogDialogComponent extends React.Component<RefreshAlarmLogDialogComponentProps, RefreshAlarmLogDialogComponentState> {
+ render(): JSX.Element {
+ const setting = settings[this.props.mode];
+ return (
+ <Dialog open={this.props.mode !== RefreshAlarmLogDialogMode.None}>
+ <DialogTitle id="form-dialog-title" aria-label={`${setting.dialogTitle.replace(/ /g, '-').toLowerCase()}-dialog`}>{setting.dialogTitle}</DialogTitle>
+ <DialogContent>
+ <DialogContentText>
+ {setting.dialogDescription}
+ </DialogContentText>
+ </DialogContent>
+ <DialogActions>
+ <Button aria-label="dialog-confirm-button" onClick={() => {
+ this.onRefresh();
+ }} color="inherit" > {setting.applyButtonText} </Button>
+ <Button aria-label="dialog-cancel-button" onClick={() => {
+ this.onCancel();
+ }} color="secondary"> {setting.cancelButtonText} </Button>
+ </DialogActions>
+ </Dialog>
+ );
+ }
+
+ private onRefresh = () => {
+ this.props.refreshAlarmLog();
+ this.props.onClose();
+ };
+
+ private onCancel = () => {
+ this.props.onClose();
+ };
+}
+
+export const RefreshAlarmLogDialog = connect(undefined, mapDispatch)(RefreshAlarmLogDialogComponent);
+export default RefreshAlarmLogDialog; \ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/faultApp/src/components/refreshCurrentAlarmsDialog.tsx b/sdnr/wt-odlux/odlux/apps/faultApp/src/components/refreshCurrentAlarmsDialog.tsx
new file mode 100644
index 000000000..20cd514cd
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/faultApp/src/components/refreshCurrentAlarmsDialog.tsx
@@ -0,0 +1,113 @@
+/**
+ * ============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 Button from '@mui/material/Button';
+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 { connect, Connect, IDispatcher } from '../../../../framework/src/flux/connect';
+
+import { currentAlarmsReloadAction } from '../handlers/currentAlarmsHandler';
+import { Fault } from '../models/fault';
+
+export enum RefreshCurrentAlarmsDialogMode {
+ None = 'none',
+ RefreshCurrentAlarmsTable = 'RefreshCurrentAlarmsTable',
+}
+
+const mapDispatch = (dispatcher: IDispatcher) => ({
+ refreshCurrentAlarms: () => dispatcher.dispatch(currentAlarmsReloadAction),
+});
+
+type DialogSettings = {
+ dialogTitle: string;
+ dialogDescription: string;
+ applyButtonText: string;
+ cancelButtonText: string;
+ enableMountIdEditor: boolean;
+ enableUsernameEditor: boolean;
+ enableExtendedEditor: boolean;
+};
+
+const settings: { [key: string]: DialogSettings } = {
+ [RefreshCurrentAlarmsDialogMode.None]: {
+ dialogTitle: '',
+ dialogDescription: '',
+ applyButtonText: '',
+ cancelButtonText: '',
+ enableMountIdEditor: false,
+ enableUsernameEditor: false,
+ enableExtendedEditor: false,
+ },
+ [RefreshCurrentAlarmsDialogMode.RefreshCurrentAlarmsTable]: {
+ dialogTitle: 'Do you want to refresh the Current Alarms List?',
+ dialogDescription: '',
+ applyButtonText: 'Yes',
+ cancelButtonText: 'Cancel',
+ enableMountIdEditor: true,
+ enableUsernameEditor: true,
+ enableExtendedEditor: true,
+ },
+};
+
+type RefreshCurrentAlarmsDialogComponentProps = Connect<undefined, typeof mapDispatch> & {
+ mode: RefreshCurrentAlarmsDialogMode;
+ onClose: () => void;
+};
+
+type RefreshCurrentAlarmsDialogComponentState = Fault & { isNameValid: boolean; isHostSet: boolean };
+
+class RefreshCurrentAlarmsDialogComponent extends React.Component<RefreshCurrentAlarmsDialogComponentProps, RefreshCurrentAlarmsDialogComponentState> {
+ render(): JSX.Element {
+ const setting = settings[this.props.mode];
+ return (
+ <Dialog open={this.props.mode !== RefreshCurrentAlarmsDialogMode.None}>
+ <DialogTitle id="form-dialog-title" aria-label={`${setting.dialogTitle.replace(/ /g, '-').toLowerCase()}-dialog`}>{setting.dialogTitle}</DialogTitle>
+ <DialogContent>
+ <DialogContentText>
+ {setting.dialogDescription}
+ </DialogContentText>
+ </DialogContent>
+ <DialogActions>
+ <Button aria-label="dialog-confirm-button" onClick={() => {
+ this.onRefresh();
+ }} color="inherit" > {setting.applyButtonText} </Button>
+ <Button aria-label="dialog-cancel-button" onClick={() => {
+ this.onCancel();
+ }} color="secondary"> {setting.cancelButtonText} </Button>
+ </DialogActions>
+ </Dialog>
+ );
+ }
+
+ private onRefresh = () => {
+ this.props.refreshCurrentAlarms();
+ this.props.onClose();
+ };
+
+ private onCancel = () => {
+ this.props.onClose();
+ };
+}
+
+export const RefreshCurrentAlarmsDialog = connect(undefined, mapDispatch)(RefreshCurrentAlarmsDialogComponent);
+export default RefreshCurrentAlarmsDialog; \ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/faultApp/src/handlers/alarmLogEntriesHandler.ts b/sdnr/wt-odlux/odlux/apps/faultApp/src/handlers/alarmLogEntriesHandler.ts
new file mode 100644
index 000000000..bdd459669
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/faultApp/src/handlers/alarmLogEntriesHandler.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 { createExternal, IExternalTableState } from '../../../../framework/src/components/material-table/utilities';
+import { createSearchDataHandler } from '../../../../framework/src/utilities/elasticSearch';
+
+import { Fault } from '../models/fault';
+
+export interface IAlarmLogEntriesState extends IExternalTableState<Fault> { }
+
+// create eleactic search data fetch handler
+const alarmLogEntriesSearchHandler = createSearchDataHandler< Fault>('faultlog');
+
+export const {
+ actionHandler: alarmLogEntriesActionHandler,
+ createActions: createAlarmLogEntriesActions,
+ createProperties: createAlarmLogEntriesProperties,
+ reloadAction: alarmLogEntriesReloadAction,
+
+ // set value action, to change a value
+} = createExternal<Fault>(alarmLogEntriesSearchHandler, appState => appState.fault.alarmLogEntries);
+
diff --git a/sdnr/wt-odlux/odlux/apps/faultApp/src/handlers/clearStuckAlarmsHandler.ts b/sdnr/wt-odlux/odlux/apps/faultApp/src/handlers/clearStuckAlarmsHandler.ts
new file mode 100644
index 000000000..0d5a8c70d
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/faultApp/src/handlers/clearStuckAlarmsHandler.ts
@@ -0,0 +1,37 @@
+/**
+ * ============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/odlux/apps/faultApp/src/handlers/currentAlarmsHandler.ts b/sdnr/wt-odlux/odlux/apps/faultApp/src/handlers/currentAlarmsHandler.ts
new file mode 100644
index 000000000..70aa1c27e
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/faultApp/src/handlers/currentAlarmsHandler.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 { createExternal, IExternalTableState } from '../../../../framework/src/components/material-table/utilities';
+import { createSearchDataHandler } from '../../../../framework/src/utilities/elasticSearch';
+
+import { Fault } from '../models/fault';
+
+export interface ICurrentAlarmsState extends IExternalTableState<Fault> { }
+
+// create eleactic search data fetch handler
+const currentAlarmsSearchHandler = createSearchDataHandler<Fault>('faultcurrent');
+
+export const {
+ actionHandler: currentAlarmsActionHandler,
+ createActions: createCurrentAlarmsActions,
+ createProperties: createCurrentAlarmsProperties,
+ reloadAction: currentAlarmsReloadAction,
+
+ // set value action, to change a value
+} = createExternal<Fault>(currentAlarmsSearchHandler, appState => appState.fault.currentAlarms);
+
diff --git a/sdnr/wt-odlux/odlux/apps/faultApp/src/handlers/faultAppRootHandler.ts b/sdnr/wt-odlux/odlux/apps/faultApp/src/handlers/faultAppRootHandler.ts
new file mode 100644
index 000000000..e4a19ae5c
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/faultApp/src/handlers/faultAppRootHandler.ts
@@ -0,0 +1,63 @@
+/**
+ * ============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==========================================================================
+ */
+// main state handler
+
+import { IActionHandler } from '../../../../framework/src/flux/action';
+import { combineActionHandler } from '../../../../framework/src/flux/middleware';
+// ** do not remove **
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+
+import { SetPanelAction } from '../actions/panelChangeActions';
+import { PanelId } from '../models/panelId';
+import { alarmLogEntriesActionHandler, IAlarmLogEntriesState } from './alarmLogEntriesHandler';
+import { currentAlarmsActionHandler, ICurrentAlarmsState } from './currentAlarmsHandler';
+import { faultStatusHandler, IFaultStatus } from './faultStatusHandler';
+import { faultNotificationsHandler, IFaultNotifications } from './notificationsHandler';
+
+export interface IFaultAppStoreState {
+ currentAlarms: ICurrentAlarmsState;
+ faultNotifications: IFaultNotifications;
+ alarmLogEntries: IAlarmLogEntriesState;
+ currentOpenPanel: PanelId | null;
+ faultStatus: IFaultStatus;
+}
+
+const currentOpenPanelHandler: IActionHandler<PanelId | null> = (state = null, action) => {
+ if (action instanceof SetPanelAction) {
+ state = action.panelId;
+ }
+ return state;
+};
+
+declare module '../../../../framework/src/store/applicationStore' {
+ interface IApplicationStoreState {
+ fault: IFaultAppStoreState;
+ }
+}
+
+const actionHandlers = {
+ currentAlarms: currentAlarmsActionHandler,
+ faultNotifications: faultNotificationsHandler,
+ alarmLogEntries: alarmLogEntriesActionHandler,
+ currentOpenPanel: currentOpenPanelHandler,
+ faultStatus: faultStatusHandler,
+};
+
+export const faultAppRootHandler = combineActionHandler<IFaultAppStoreState>(actionHandlers);
+export default faultAppRootHandler;
diff --git a/sdnr/wt-odlux/odlux/apps/faultApp/src/handlers/faultStatusHandler.ts b/sdnr/wt-odlux/odlux/apps/faultApp/src/handlers/faultStatusHandler.ts
new file mode 100644
index 000000000..21b033e6a
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/faultApp/src/handlers/faultStatusHandler.ts
@@ -0,0 +1,77 @@
+/**
+ * ============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 { SetFaultStatusAction } from '../actions/statusActions';
+
+export interface IFaultStatus {
+ critical: number;
+ major: number;
+ minor: number;
+ warning: number;
+ isLoadingAlarmStatusChart: boolean;
+ Connected: number;
+ Connecting: number;
+ Disconnected: number;
+ Mounted: number;
+ UnableToConnect: number;
+ Undefined: number;
+ Unmounted: number;
+ total: number;
+ isLoadingConnectionStatusChart: boolean;
+}
+
+const faultStatusInit: IFaultStatus = {
+ critical: 0,
+ major: 0,
+ minor: 0,
+ warning: 0,
+ isLoadingAlarmStatusChart: false,
+ Connected: 0,
+ Connecting: 0,
+ Disconnected: 0,
+ Mounted: 0,
+ UnableToConnect: 0,
+ Undefined: 0,
+ Unmounted: 0,
+ total: 0,
+ isLoadingConnectionStatusChart: false,
+};
+
+export const faultStatusHandler: IActionHandler<IFaultStatus> = (state = faultStatusInit, action) => {
+ if (action instanceof SetFaultStatusAction) {
+ state = {
+ critical: action.criticalFaults,
+ major: action.majorFaults,
+ minor: action.minorFaults,
+ warning: action.warnings,
+ isLoadingAlarmStatusChart: action.isLoadingAlarmStatusChart,
+ Connected: action.ConnectedCount,
+ Connecting: action.ConnectingCount,
+ Disconnected: action.DisconnectedCount,
+ Mounted: action.MountedCount,
+ UnableToConnect: action.UnableToConnectCount,
+ Undefined: action.UndefinedCount,
+ Unmounted: action.UnmountedCount,
+ total: action.totalCount,
+ isLoadingConnectionStatusChart: action.isLoadingConnectionStatusChart,
+ };
+ }
+
+ return state;
+}; \ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/faultApp/src/handlers/notificationsHandler.ts b/sdnr/wt-odlux/odlux/apps/faultApp/src/handlers/notificationsHandler.ts
new file mode 100644
index 000000000..3d960bfc4
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/faultApp/src/handlers/notificationsHandler.ts
@@ -0,0 +1,48 @@
+/**
+ * ============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 { AddFaultNotificationAction, ResetFaultNotificationsAction } from '../actions/notificationActions';
+import { FaultAlarmNotification } from '../models/fault';
+
+export interface IFaultNotifications {
+ faults: FaultAlarmNotification[];
+ since: Date;
+}
+
+const faultNotoficationsInit: IFaultNotifications = {
+ faults: [],
+ since: new Date(),
+};
+
+export const faultNotificationsHandler: IActionHandler<IFaultNotifications> = (state = faultNotoficationsInit, action) => {
+ if (action instanceof AddFaultNotificationAction) {
+ state = {
+ ...state,
+ faults: [...state.faults, action.fault],
+ };
+ } else if (action instanceof ResetFaultNotificationsAction) {
+ state = {
+ ...state,
+ faults: [],
+ since: new Date(),
+ };
+ }
+
+ return state;
+}; \ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/faultApp/src/index.html b/sdnr/wt-odlux/odlux/apps/faultApp/src/index.html
new file mode 100644
index 000000000..c37968074
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/faultApp/src/index.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta http-equiv="X-UA-Compatible" content="ie=edge">
+ <!-- <link rel="stylesheet" href="./vendor.css"> -->
+ <title>Minimal App</title>
+</head>
+
+<body>
+ <div id="app"></div>
+ <script type="text/javascript" src="./require.js"></script>
+ <script type="text/javascript" src="./config.js"></script>
+ <script>
+ // run the application
+ require(["app", "faultApp", "connectApp" ], function (app, faultApp, connectApp) {
+ faultApp.register();
+ connectApp.register();
+ app("./app.tsx").runApplication();
+ });
+ </script>
+</body>
+
+</html> \ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/faultApp/src/models/fault.ts b/sdnr/wt-odlux/odlux/apps/faultApp/src/models/fault.ts
new file mode 100644
index 000000000..c70253e58
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/faultApp/src/models/fault.ts
@@ -0,0 +1,97 @@
+/**
+ * ============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==========================================================================
+ */
+export type Fault = {
+ id: string;
+ nodeId: string;
+ counter: number;
+ timestamp: string;
+ objectId: string;
+ problem: string;
+ severity: null | 'Warning' | 'Minor' | 'Major' | 'Critical' | 'NonAlarmed';
+ type: string;
+ sourceType?: string;
+};
+
+export type FaultAlarmNotification = {
+ id: string;
+ timeStamp: string;
+ nodeName: string;
+ counter: number;
+ objectId: string;
+ problem: string;
+ severity: string;
+};
+
+export type FaultAlarmNotificationWS = {
+ 'node-id': string;
+ 'data': {
+ 'counter': number;
+ 'time-stamp': string;
+ 'object-id-ref': string;
+ 'problem': string;
+ 'severity': null | 'Warning' | 'Minor' | 'Major' | 'Critical' | 'NonAlarmed';
+ };
+ 'type': {
+ 'namespace': string;
+ 'revision': string;
+ 'type': string;
+ };
+ 'event-time': string;
+};
+
+/**
+ * Fault status return type
+ */
+export type FaultsReturnType = {
+ criticals: number;
+ majors: number;
+ minors: number;
+ warnings: number;
+ Connected: number;
+ Connecting: number;
+ Disconnected: number;
+ Mounted: number;
+ UnableToConnect: number;
+ Undefined: number;
+ Unmounted: number;
+ total: number;
+};
+
+export type FaultType = {
+ Critical: number;
+ Major: number;
+ Minor: number;
+ Warning: number;
+ Connected: number;
+ Connecting: number;
+ Disconnected: number;
+ Mounted: number;
+ UnableToConnect: number;
+ Undefined: number;
+ Unmounted: number;
+ total: number;
+};
+
+export type Faults = {
+ faults: FaultsReturnType;
+ 'network-element-connections': FaultsReturnType;
+};
+
+export type DeletedStuckAlarms = {
+ nodenames: string[];
+}; \ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/faultApp/src/models/panelId.ts b/sdnr/wt-odlux/odlux/apps/faultApp/src/models/panelId.ts
new file mode 100644
index 000000000..daebad0e5
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/faultApp/src/models/panelId.ts
@@ -0,0 +1,18 @@
+/**
+ * ============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==========================================================================
+ */
+export type PanelId = null | 'CurrentAlarms' | 'AlarmNotifications' | 'AlarmLog'; \ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/faultApp/src/pluginFault.tsx b/sdnr/wt-odlux/odlux/apps/faultApp/src/pluginFault.tsx
new file mode 100644
index 000000000..2ef243c2d
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/faultApp/src/pluginFault.tsx
@@ -0,0 +1,171 @@
+/**
+ * ============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==========================================================================
+ */
+// app configuration and main entry point for the app
+
+import React from 'react';
+import { Redirect, Route, RouteComponentProps, Switch, withRouter } from 'react-router-dom';
+
+import { connect, Connect, IDispatcher } from '../../../framework/src/flux/connect';
+import applicationManager from '../../../framework/src/services/applicationManager';
+import { IFormatedMessage, subscribe } from '../../../framework/src/services/notificationService';
+import { IApplicationStoreState } from '../../../framework/src/store/applicationStore';
+
+import { AddFaultNotificationAction } from './actions/notificationActions';
+import { SetPanelAction } from './actions/panelChangeActions';
+import { refreshFaultStatusAsyncAction, SetFaultStatusAction } from './actions/statusActions';
+import DashboardHome from './components/dashboardHome';
+import { FaultStatus } from './components/faultStatus';
+import { createCurrentAlarmsActions, createCurrentAlarmsProperties, currentAlarmsReloadAction } from './handlers/currentAlarmsHandler';
+import { faultAppRootHandler } from './handlers/faultAppRootHandler';
+import { FaultAlarmNotificationWS } from './models/fault';
+import { PanelId } from './models/panelId';
+import { FaultApplication } from './views/faultApplication';
+
+const appIcon = require('./assets/icons/faultAppIcon.svg'); // select app icon
+
+let currentMountId: string | undefined = undefined;
+let currentSeverity: string | undefined = undefined;
+let refreshInterval: ReturnType<typeof window.setInterval> | null = null;
+
+const mapProps = (state: IApplicationStoreState) => ({
+ currentAlarmsProperties: createCurrentAlarmsProperties(state),
+});
+
+const mapDispatch = (dispatcher: IDispatcher) => ({
+ currentAlarmsActions: createCurrentAlarmsActions(dispatcher.dispatch, true),
+ setCurrentPanel: (panelId: PanelId) => dispatcher.dispatch(new SetPanelAction(panelId)),
+});
+
+const FaultApplicationRouteAdapter = connect(mapProps, mapDispatch)((props: RouteComponentProps<{ mountId?: string }> & Connect<typeof mapProps, typeof mapDispatch>) => {
+ if (currentMountId !== props.match.params.mountId) {
+ // route parameter has changed
+ currentMountId = props.match.params.mountId || undefined;
+ // Hint: This timeout is need, since it is not recommended to change the state while rendering is in progress !
+ window.setTimeout(() => {
+ if (currentMountId) {
+ props.setCurrentPanel('CurrentAlarms');
+ props.currentAlarmsActions.onFilterChanged('nodeId', currentMountId);
+ if (!props.currentAlarmsProperties.showFilter) {
+ props.currentAlarmsActions.onToggleFilter(false);
+ props.currentAlarmsActions.onRefresh();
+ } else
+ props.currentAlarmsActions.onRefresh();
+ }
+ });
+ }
+ return (
+ <FaultApplication />
+ );
+});
+
+const FaultApplicationAlarmStatusRouteAdapter = connect(mapProps, mapDispatch)((props: RouteComponentProps<{ severity?: string }> & Connect<typeof mapProps, typeof mapDispatch>) => {
+ if (currentSeverity !== props.match.params.severity) {
+ currentSeverity = props.match.params.severity || undefined;
+ window.setTimeout(() => {
+ if (currentSeverity) {
+ props.setCurrentPanel('CurrentAlarms');
+ props.currentAlarmsActions.onFilterChanged('severity', currentSeverity);
+ if (!props.currentAlarmsProperties.showFilter) {
+ props.currentAlarmsActions.onToggleFilter(false);
+ props.currentAlarmsActions.onRefresh();
+ } else
+ props.currentAlarmsActions.onRefresh();
+ }
+ });
+ }
+ return (
+ <FaultApplication />
+ );
+});
+
+const App = withRouter((props: RouteComponentProps) => (
+ <Switch>
+ <Route path={`${props.match.path}/alarmStatus/:severity?`} component={FaultApplicationAlarmStatusRouteAdapter} />
+ <Route path={`${props.match.path}/:mountId?`} component={FaultApplicationRouteAdapter} />
+ <Redirect to={`${props.match.path}`} />
+ </Switch>
+));
+
+export function register() {
+ const applicationApi = applicationManager.registerApplication({
+ name: 'fault',
+ icon: appIcon,
+ rootComponent: App,
+ rootActionHandler: faultAppRootHandler,
+ statusBarElement: FaultStatus,
+ dashbaordElement: DashboardHome,
+ menuEntry: 'Fault',
+ });
+
+ let counter = 0;
+ // subscribe to the websocket notifications
+ subscribe<FaultAlarmNotificationWS & IFormatedMessage>('problem-notification', (fault => {
+ const store = applicationApi && applicationApi.applicationStore;
+ if (fault && store) {
+
+ store.dispatch(new AddFaultNotificationAction({
+ id: String(counter++),
+ nodeName: fault['node-id'],
+ counter: +fault.data.counter,
+ objectId: fault.data['object-id-ref'],
+ problem: fault.data.problem,
+ severity: fault.data.severity || '',
+ timeStamp: fault.data['time-stamp'],
+ }));
+ }
+ }));
+
+ applicationApi.applicationStoreInitialized.then(store => {
+ store.dispatch(currentAlarmsReloadAction);
+ });
+
+ applicationApi.applicationStoreInitialized.then(store => {
+ store.dispatch(refreshFaultStatusAsyncAction);
+ });
+
+ applicationApi.logoutEvent.addHandler(()=>{
+
+ applicationApi.applicationStoreInitialized.then(store => {
+ store.dispatch(new SetFaultStatusAction(0, 0, 0, 0, false, 0, 0, 0, 0, 0, 0, 0, 0, false));
+ clearInterval(refreshInterval!);
+ });
+ });
+
+ function startRefreshInterval() {
+ const refreshFaultStatus = window.setInterval(() => {
+ applicationApi.applicationStoreInitialized.then(store => {
+
+ store.dispatch(refreshFaultStatusAsyncAction);
+ });
+ }, 15000);
+
+ return refreshFaultStatus;
+ }
+
+ applicationApi.loginEvent.addHandler(()=>{
+ if (refreshInterval) {
+ clearInterval(refreshInterval);
+ }
+ refreshInterval = startRefreshInterval() as any;
+ });
+
+ applicationApi.logoutEvent.addHandler(()=>{
+ refreshInterval && window.clearInterval(refreshInterval);
+ refreshInterval = null;
+ });
+}
diff --git a/sdnr/wt-odlux/odlux/apps/faultApp/src/services/faultStatusService.ts b/sdnr/wt-odlux/odlux/apps/faultApp/src/services/faultStatusService.ts
new file mode 100644
index 000000000..0c7a215f8
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/faultApp/src/services/faultStatusService.ts
@@ -0,0 +1,69 @@
+/**
+ * ============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 { Result } from '../../../../framework/src/models/elasticSearch';
+import { requestRest } from '../../../../framework/src/services/restService';
+
+import { Faults, FaultType } from '../models/fault';
+
+
+export const getFaultStateFromDatabase = async (): Promise<FaultType | null> => {
+ const path = 'rests/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,
+ Connected: 0,
+ Connecting: 0,
+ Disconnected: 0,
+ Mounted: 0,
+ UnableToConnect: 0,
+ Undefined: 0,
+ Unmounted: 0,
+ total: 0,
+ };
+ let faults: Faults[] | null = null;
+
+ if (result && result['data-provider:output'] && result['data-provider:output'].data) {
+ faults = result['data-provider:output'].data;
+ faultType = {
+ Critical: faults[0].faults.criticals,
+ Major: faults[0].faults.majors,
+ Minor: faults[0].faults.minors,
+ Warning: faults[0].faults.warnings,
+ Connected: faults[0]['network-element-connections'].Connected,
+ Connecting: faults[0]['network-element-connections'].Connecting,
+ Disconnected: faults[0]['network-element-connections'].Disconnected,
+ Mounted: faults[0]['network-element-connections'].Mounted,
+ UnableToConnect: faults[0]['network-element-connections'].UnableToConnect,
+ Undefined: faults[0]['network-element-connections'].Undefined,
+ Unmounted: faults[0]['network-element-connections'].Unmounted,
+ total: faults[0]['network-element-connections'].total,
+ };
+ }
+
+ return faultType;
+};
+
+export const clearStuckAlarms = async (nodeNames: string[]) => {
+ const path = 'rests/operations/devicemanager:clear-current-fault-by-nodename';
+ const result = await requestRest<any>(path, { method: 'Post', body: JSON.stringify({ input: { nodenames: nodeNames } }) });
+ return result;
+}; \ No newline at end of file
diff --git a/sdnr/wt-odlux/odlux/apps/faultApp/src/views/faultApplication.tsx b/sdnr/wt-odlux/odlux/apps/faultApp/src/views/faultApplication.tsx
new file mode 100644
index 000000000..b9f115ed7
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/faultApp/src/views/faultApplication.tsx
@@ -0,0 +1,247 @@
+/**
+ * ============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 React from 'react';
+import { RouteComponentProps, withRouter } from 'react-router-dom';
+
+import Refresh from '@mui/icons-material/Refresh';
+import Sync from '@mui/icons-material/Sync';
+import { AppBar, Tab, Tabs } from '@mui/material';
+
+import { ColumnType, MaterialTable, MaterialTableCtorType } from '../../../../framework/src/components/material-table';
+import { connect, Connect, IDispatcher } from '../../../../framework/src/flux/connect';
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+
+import { setPanelAction } from '../actions/panelChangeActions';
+import ClearStuckAlarmsDialog, { ClearStuckAlarmsDialogMode } from '../components/clearStuckAlarmsDialog';
+import RefreshAlarmLogDialog, { RefreshAlarmLogDialogMode } from '../components/refreshAlarmLogDialog';
+import RefreshCurrentAlarmsDialog, { RefreshCurrentAlarmsDialogMode } from '../components/refreshCurrentAlarmsDialog';
+import { alarmLogEntriesReloadAction, createAlarmLogEntriesActions, createAlarmLogEntriesProperties } from '../handlers/alarmLogEntriesHandler';
+import { createCurrentAlarmsActions, createCurrentAlarmsProperties, currentAlarmsReloadAction } from '../handlers/currentAlarmsHandler';
+import { Fault, FaultAlarmNotification } from '../models/fault';
+import { PanelId } from '../models/panelId';
+
+const mapProps = (state: IApplicationStoreState) => ({
+ panelId: state.fault.currentOpenPanel,
+ currentAlarmsProperties: createCurrentAlarmsProperties(state),
+ faultNotifications: state.fault.faultNotifications,
+ alarmLogEntriesProperties: createAlarmLogEntriesProperties(state),
+});
+
+const mapDisp = (dispatcher: IDispatcher) => ({
+ currentAlarmsActions: createCurrentAlarmsActions(dispatcher.dispatch),
+ alarmLogEntriesActions: createAlarmLogEntriesActions(dispatcher.dispatch),
+ reloadCurrentAlarms: () => dispatcher.dispatch(currentAlarmsReloadAction),
+ reloadAlarmLogEntries: () => dispatcher.dispatch(alarmLogEntriesReloadAction),
+ switchActivePanel: (panelId: PanelId) => {
+ dispatcher.dispatch(setPanelAction(panelId));
+ },
+});
+
+type FaultApplicationComponentProps = RouteComponentProps & Connect<typeof mapProps, typeof mapDisp>;
+
+type FaultApplicationState = {
+ clearAlarmDialogMode: ClearStuckAlarmsDialogMode;
+ stuckAlarms: string[];
+ refreshAlarmLogEditorMode: RefreshAlarmLogDialogMode;
+ refreshCurrentAlarmsEditorMode: RefreshCurrentAlarmsDialogMode;
+};
+
+
+const FaultTable = MaterialTable as MaterialTableCtorType<Fault>;
+const FaultAlarmNotificationTable = MaterialTable as MaterialTableCtorType<FaultAlarmNotification>;
+
+let currentAlarmsInitalSorted = false;
+let alarmLogInitialSorted = false;
+
+class FaultApplicationComponent extends React.Component<FaultApplicationComponentProps, FaultApplicationState> {
+ constructor(props: FaultApplicationComponentProps) {
+ super(props);
+ this.state = {
+ clearAlarmDialogMode: ClearStuckAlarmsDialogMode.None,
+ stuckAlarms: [],
+ refreshAlarmLogEditorMode: RefreshAlarmLogDialogMode.None,
+ refreshCurrentAlarmsEditorMode: RefreshCurrentAlarmsDialogMode.None,
+ };
+ }
+
+ onDialogClose = () => {
+ this.setState({ clearAlarmDialogMode: ClearStuckAlarmsDialogMode.None, stuckAlarms: [] });
+ };
+
+ onDialogOpen = () => {
+ const stuckAlarms = [...new Set(this.props.currentAlarmsProperties.rows.map(item => item.nodeId))];
+ this.setState({ clearAlarmDialogMode: ClearStuckAlarmsDialogMode.Show, stuckAlarms: stuckAlarms });
+ };
+
+ private onHandleTabChange = (event: React.SyntheticEvent, newValue: PanelId) => {
+ this.onToggleTabs(newValue);
+ };
+
+ private onToggleTabs = (panelId: PanelId) => {
+ const nextActivePanel = panelId;
+ this.props.switchActivePanel(nextActivePanel);
+ switch (nextActivePanel) {
+ case 'CurrentAlarms':
+ if (!currentAlarmsInitalSorted) {
+ currentAlarmsInitalSorted = true;
+ this.props.currentAlarmsActions.onHandleExplicitRequestSort('timestamp', 'desc');
+ } else {
+ this.props.reloadCurrentAlarms();
+ }
+ break;
+ case 'AlarmLog':
+ if (!alarmLogInitialSorted) {
+ alarmLogInitialSorted = true;
+ this.props.alarmLogEntriesActions.onHandleExplicitRequestSort('timestamp', 'desc');
+ } else {
+ this.props.reloadAlarmLogEntries();
+ }
+ break;
+ case 'AlarmNotifications':
+ case null:
+ default:
+ // nothing to do
+ break;
+ }
+ };
+
+
+
+ render(): JSX.Element {
+
+ const clearAlarmsAction = {
+ icon: Sync, tooltip: 'Clear stuck alarms', ariaLabel:'clear-stuck-alarms', onClick: this.onDialogOpen,
+ };
+
+ const refreshCurrentAlarmsAction = {
+ icon: Refresh, tooltip: 'Refresh Current Alarms List', ariaLabel:'refresh', onClick: () => {
+ this.setState({
+ refreshCurrentAlarmsEditorMode: RefreshCurrentAlarmsDialogMode.RefreshCurrentAlarmsTable,
+ });
+ },
+ };
+
+ const refreshAlarmLogAction = {
+ icon: Refresh, tooltip: 'Refresh Alarm log table', ariaLabel:'refresh', onClick: () => {
+ this.setState({
+ refreshAlarmLogEditorMode: RefreshAlarmLogDialogMode.RefreshAlarmLogTable,
+ });
+ },
+ };
+
+ const areFaultsAvailable = this.props.currentAlarmsProperties.rows && this.props.currentAlarmsProperties.rows.length > 0;
+ const customActions = areFaultsAvailable ? [clearAlarmsAction, refreshCurrentAlarmsAction] : [refreshCurrentAlarmsAction];
+
+ const { panelId: activePanelId } = this.props;
+
+ return (
+ <>
+ <AppBar enableColorOnDark position="static" >
+ <Tabs indicatorColor="secondary" textColor="inherit" value={activePanelId} onChange={this.onHandleTabChange} aria-label="fault-tabs">
+ <Tab aria-label="current-alarms-list-tab" label="Current Alarms" value="CurrentAlarms" />
+ <Tab aria-label="alarm-notifications-list-tab" label={`Alarm Notifications (${this.props.faultNotifications.faults.length})`} value="AlarmNotifications" />
+ <Tab aria-label="alarm-log-tab" label="Alarm Log" value="AlarmLog" />
+ </Tabs>
+ </AppBar>
+ {
+ activePanelId === 'CurrentAlarms' &&
+ <>
+ <FaultTable stickyHeader tableId="current-alarms-table" idProperty="id" customActionButtons={customActions} columns={[
+ // { property: "icon", title: "", type: ColumnType.custom, customControl: this.renderIcon },
+ { property: 'severity', title: 'Severity', type: ColumnType.text, width: '140px' },
+ { property: 'timestamp', type: ColumnType.text, title: 'Timestamp' },
+ { 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 },
+ ]} {...this.props.currentAlarmsProperties} {...this.props.currentAlarmsActions} />
+ <RefreshCurrentAlarmsDialog
+ mode={this.state.refreshCurrentAlarmsEditorMode}
+ onClose={this.onCloseRefreshCurrentAlarmsDialog}
+ />
+ </>
+ }
+ {activePanelId === 'AlarmNotifications' &&
+
+ <FaultAlarmNotificationTable stickyHeader tableId="alarm-notifications-table" idProperty="id" defaultSortColumn='timeStamp' defaultSortOrder='desc' rows={this.props.faultNotifications.faults} asynchronus columns={[
+ // { property: "icon", title: "", type: ColumnType.custom, customControl: this.renderIcon },
+ { property: 'severity', title: 'Severity', width: '140px', type: ColumnType.text },
+ { property: 'timeStamp', title: 'Timestamp', type: ColumnType.text },
+ { property: 'nodeName', title: 'Node Name', type: ColumnType.text },
+ { property: 'counter', title: 'Count', width: '100px', type: ColumnType.numeric },
+ { property: 'objectId', title: 'Object Id', type: ColumnType.text },
+ { property: 'problem', title: 'Alarm Type', type: ColumnType.text },
+ ]} />
+ }
+
+ {activePanelId === 'AlarmLog' &&
+ <>
+ <FaultTable stickyHeader idProperty={'id'} tableId="alarm-log-table" customActionButtons={[refreshAlarmLogAction]}
+ columns={[
+ // { property: "icon", title: "", type: ColumnType.custom, customControl: this.renderIcon },
+ { property: 'severity', title: 'Severity', width: '140px' },
+ { property: 'timestamp', title: 'Timestamp' },
+ { 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: 'sourceType', title: 'Source', width: '140px' },
+ ]} {...this.props.alarmLogEntriesProperties} {...this.props.alarmLogEntriesActions} />
+ <RefreshAlarmLogDialog
+ mode={this.state.refreshAlarmLogEditorMode}
+ onClose={this.onCloseRefreshAlarmLogDialog}
+ />
+ </>
+
+ }
+ {
+ this.state.clearAlarmDialogMode !== ClearStuckAlarmsDialogMode.None && <ClearStuckAlarmsDialog mode={this.state.clearAlarmDialogMode} numberDevices={this.state.stuckAlarms.length} stuckAlarms={this.state.stuckAlarms} onClose={this.onDialogClose} />
+ }
+ </>
+ );
+ }
+
+ public componentDidMount() {
+ if (this.props.panelId === null) { //set default tab if none is set
+ this.onToggleTabs('CurrentAlarms');
+ } else {
+ this.onToggleTabs(this.props.panelId);
+ }
+ }
+
+ // private renderIcon = (props: { rowData: Fault | FaultAlarmNotification }) => {
+ // return (
+ // <FontAwesomeIcon icon={faExclamationTriangle} />
+ // );
+ // };
+
+ private onCloseRefreshAlarmLogDialog = () => {
+ this.setState({
+ refreshAlarmLogEditorMode: RefreshAlarmLogDialogMode.None,
+ });
+ };
+
+ private onCloseRefreshCurrentAlarmsDialog = () => {
+ this.setState({
+ refreshCurrentAlarmsEditorMode: RefreshCurrentAlarmsDialogMode.None,
+ });
+ };
+}
+
+export const FaultApplication = withRouter(connect(mapProps, mapDisp)(FaultApplicationComponent));
+export default FaultApplication;
diff --git a/sdnr/wt-odlux/odlux/apps/faultApp/tsconfig.json b/sdnr/wt-odlux/odlux/apps/faultApp/tsconfig.json
new file mode 100644
index 000000000..ca65092e0
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/faultApp/tsconfig.json
@@ -0,0 +1,37 @@
+{
+ "compilerOptions": {
+ "baseUrl": "./src",
+ "outDir": "./dist",
+ "sourceMap": true,
+ "forceConsistentCasingInFileNames": true,
+ "allowSyntheticDefaultImports": true,
+ "allowUnreachableCode": false,
+ "allowUnusedLabels": false,
+ "noFallthroughCasesInSwitch": true,
+ "noImplicitAny": true,
+ "noImplicitReturns": true,
+ "noImplicitThis": true,
+ "strictNullChecks": true,
+ "pretty": true,
+ "newLine": "LF",
+ "module": "es2015",
+ "target": "es2016",
+ "moduleResolution": "node",
+ "experimentalDecorators": true,
+ "jsx": "preserve",
+ "lib": [
+ "dom",
+ "es2015",
+ "es2016"
+ ],
+ "types": [
+ "prop-types",
+ "react",
+ "react-dom"
+ ]
+ },
+ "exclude": [
+ "dist",
+ "node_modules"
+ ]
+}
diff --git a/sdnr/wt-odlux/odlux/apps/faultApp/webpack.config.js b/sdnr/wt-odlux/odlux/apps/faultApp/webpack.config.js
new file mode 100644
index 000000000..bc26de1cb
--- /dev/null
+++ b/sdnr/wt-odlux/odlux/apps/faultApp/webpack.config.js
@@ -0,0 +1,166 @@
+/**
+ * Webpack 4 configuration file
+ * see https://webpack.js.org/configuration/
+ * see https://webpack.js.org/configuration/dev-server/
+ */
+
+"use strict";
+
+const path = require("path");
+const webpack = require("webpack");
+const CopyWebpackPlugin = require("copy-webpack-plugin");
+const TerserPlugin = require('terser-webpack-plugin');
+
+// const __dirname = (path => path.replace(/^([a-z]\:)/, c => c.toUpperCase()))(process.__dirname());
+
+module.exports = (env) => {
+ const distPath = path.resolve(__dirname, env === "release" ? "." : "../..", "dist");
+ const frameworkPath = path.resolve(__dirname, env === "release" ? "../../framework" : "../..", "dist");
+ return [{
+ name: "App",
+
+ mode: "none", //disable default behavior
+
+ target: "web",
+
+ context: path.resolve(__dirname, "src"),
+
+ entry: {
+ faultApp: ["./pluginFault.tsx"]
+ },
+
+ devtool: env === "release" ? false : "source-map",
+
+ resolve: {
+ extensions: [".ts", ".tsx", ".js", ".jsx"]
+ },
+
+ output: {
+ path: distPath,
+ filename: "[name].js",
+ library: "[name]",
+ libraryTarget: "umd2",
+ chunkFilename: "[name].js"
+ },
+ module: {
+ rules: [{
+ test: /\.tsx?$/,
+ exclude: /node_modules/,
+ use: [{
+ loader: "babel-loader"
+ }, {
+ loader: "ts-loader"
+ }]
+ }, {
+ test: /\.jsx?$/,
+ exclude: /node_modules/,
+ use: [{
+ loader: "babel-loader"
+ }]
+ },{
+ //don't minify images
+ test: /\.(png|gif|jpg|svg)$/,
+ use: [{
+ loader: 'url-loader',
+ options: {
+ limit: 10,
+ name: './images/[name].[ext]'
+ }
+ }]
+ }]
+ },
+ optimization: {
+ noEmitOnErrors: true,
+ namedModules: env !== "release",
+ minimize: env === "release",
+ minimizer: env !== "release" ? [] : [new TerserPlugin({
+ terserOptions: {
+ warnings: false, // false, true, "verbose"
+ compress: {
+ drop_console: true,
+ drop_debugger: true,
+ }
+ }
+ })],
+ },
+ plugins: [
+ new webpack.DllReferencePlugin({
+ context: path.resolve(__dirname, "../../framework/src"),
+ manifest: require(path.resolve(frameworkPath, "vendor-manifest.json")),
+ sourceType: "umd2"
+ }),
+ new webpack.DllReferencePlugin({
+ context: path.resolve(__dirname, "../../framework/src"),
+ manifest: require(path.resolve(frameworkPath, "app-manifest.json")),
+ sourceType: "umd2"
+ }),
+ ...(env === "release" ? [
+ new webpack.DefinePlugin({
+ "process.env": {
+ NODE_ENV: "'production'",
+ VERSION: JSON.stringify(require("./package.json").version)
+ }
+ })
+ ] : [
+ new webpack.DefinePlugin({
+ "process.env": {
+ NODE_ENV: "'development'",
+ VERSION: JSON.stringify(require("./package.json").version)
+ }
+ }),
+ new CopyWebpackPlugin([{
+ from: 'index.html',
+ to: distPath
+ }]),
+ ])
+ ],
+
+ devServer: {
+ public: "http://localhost:3100",
+ contentBase: frameworkPath,
+
+ compress: true,
+ headers: {
+ "Access-Control-Allow-Origin": "*"
+ },
+ host: "0.0.0.0",
+ port: 3100,
+ disableHostCheck: true,
+ historyApiFallback: true,
+ inline: true,
+ hot: false,
+ quiet: false,
+ stats: {
+ colors: true
+ },
+ proxy: {
+ "/oauth2/": {
+ target: "http://sdnc-web:8080",
+ secure: false
+ },
+ "/database/": {
+ target: "http://sdnc-web:8080",
+ secure: false
+ },
+ "/restconf/": {
+ target: "http://sdnc-web:8080",
+ secure: false
+ },
+ "/rests/": {
+ target: "http://sdnc-web:8080",
+ secure: false
+ },
+ "/help/": {
+ target: "http://sdnc-web:8080",
+ secure: false
+ },
+ "/websocket": {
+ target: "http://sdnc-web:8080",
+ ws: true,
+ changeOrigin: true,
+ secure: false
+ }
+ }
+ }
+ }];
+}