Odlux Update
Add eslint and custom icons update
Issue-ID: CCSDK-3871
Signed-off-by: sai-neetha <sai-neetha.phulmali@highstreet-technologies.com>
Change-Id: If6b676128cc9cff0437a5dc54f85eaafd3b8c586
Signed-off-by: highstreetherbert <herbert.eiselt@highstreet-technologies.com>
diff --git a/sdnr/wt/odlux/apps/apiDemo/package.json b/sdnr/wt/odlux/apps/apiDemo/package.json
index f01a396..ff9e3c4 100644
--- a/sdnr/wt/odlux/apps/apiDemo/package.json
+++ b/sdnr/wt/odlux/apps/apiDemo/package.json
@@ -23,6 +23,9 @@
"dependencies": {
"@emotion/react": "^11.7.0",
"@emotion/styled": "^11.6.0",
+ "@fortawesome/fontawesome-svg-core": "1.2.35",
+ "@fortawesome/free-solid-svg-icons": "5.6.3",
+ "@fortawesome/react-fontawesome": "0.1.14",
"@mui/icons-material": "^5.2.0",
"@mui/material": "^5.2.2",
"@mui/styles": "^5.2.2",
diff --git a/sdnr/wt/odlux/apps/apiDemo/pom.xml b/sdnr/wt/odlux/apps/apiDemo/pom.xml
index b6dc53e..97f7faa 100644
--- a/sdnr/wt/odlux/apps/apiDemo/pom.xml
+++ b/sdnr/wt/odlux/apps/apiDemo/pom.xml
@@ -19,6 +19,7 @@
~ ============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>
@@ -139,7 +140,7 @@
<!-- optional: default phase is "generate-resources" -->
<phase>initialize</phase>
<configuration>
- <nodeVersion>v12.13.0</nodeVersion>
+ <nodeVersion>v12.22.0</nodeVersion>
<yarnVersion>v1.22.10</yarnVersion>
</configuration>
</execution>
diff --git a/sdnr/wt/odlux/apps/apiDemo/src/handlers/apiDemoRootHandler.ts b/sdnr/wt/odlux/apps/apiDemo/src/handlers/apiDemoRootHandler.ts
index 36688b3..128a032 100644
--- a/sdnr/wt/odlux/apps/apiDemo/src/handlers/apiDemoRootHandler.ts
+++ b/sdnr/wt/odlux/apps/apiDemo/src/handlers/apiDemoRootHandler.ts
@@ -18,22 +18,23 @@
import { combineActionHandler } from '../../../../framework/src/flux/middleware';
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
import { moduleHandler, IModules } from './modulesHandler';
export interface IApiDemoStoreState {
- modules: IModules
+ modules: IModules;
}
declare module '../../../../framework/src/store/applicationStore' {
interface IApplicationStoreState {
- apiDemo: IApiDemoStoreState
+ apiDemo: IApiDemoStoreState;
}
}
const actionHandlers = {
- modules: moduleHandler
+ modules: moduleHandler,
};
export const apiDemoRootHandler = combineActionHandler<IApiDemoStoreState>(actionHandlers);
diff --git a/sdnr/wt/odlux/apps/apiDemo/src/handlers/modulesHandler.ts b/sdnr/wt/odlux/apps/apiDemo/src/handlers/modulesHandler.ts
index 8777355..1984a2d 100644
--- a/sdnr/wt/odlux/apps/apiDemo/src/handlers/modulesHandler.ts
+++ b/sdnr/wt/odlux/apps/apiDemo/src/handlers/modulesHandler.ts
@@ -20,7 +20,7 @@
import { ModulesRequestSuccess } from '../actions/modulesSuccess';
import { Module } from '../models/module';
-export type IModules = Module[]
+export type IModules = Module[];
const modulesInit: IModules = [];
diff --git a/sdnr/wt/odlux/apps/apiDemo/src/models/module.ts b/sdnr/wt/odlux/apps/apiDemo/src/models/module.ts
index abf86b7..48772a7 100644
--- a/sdnr/wt/odlux/apps/apiDemo/src/models/module.ts
+++ b/sdnr/wt/odlux/apps/apiDemo/src/models/module.ts
@@ -19,10 +19,10 @@
name: string;
revision: string;
namespace: string;
-}
+};
export type ModuleResult = {
modules: {
- module: Module[]
- }
-}
\ No newline at end of file
+ module: Module[];
+ };
+};
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/apiDemo/src/plugin.tsx b/sdnr/wt/odlux/apps/apiDemo/src/plugin.tsx
index 076eb5c..2f70d8e 100644
--- a/sdnr/wt/odlux/apps/apiDemo/src/plugin.tsx
+++ b/sdnr/wt/odlux/apps/apiDemo/src/plugin.tsx
@@ -15,20 +15,20 @@
* the License.
* ============LICENSE_END==========================================================================
*/
-import * as React from "react";
-import { withRouter, RouteComponentProps, Route, Switch, Redirect } from 'react-router-dom';
+import React from 'react';
+import { withRouter, RouteComponentProps } from 'react-router-dom';
-import { faNewspaper } from '@fortawesome/free-solid-svg-icons';
+import { faNewspaper } from '@fortawesome/free-solid-svg-icons/faNewspaper';
import applicationManager from '../../../framework/src/services/applicationManager';
-import connect, { Connect } from '../../../framework/src/flux/connect';
+import { connect, Connect } from '../../../framework/src/flux/connect';
import { ApiAction } from '../../../framework/src/middleware/api'; // for RestConf
import { apiDemoRootHandler } from './handlers/apiDemoRootHandler';
import { ModulesRequestSuccess } from './actions/modulesSuccess';
import { Module } from './models/module';
-type AppProps = RouteComponentProps & Connect & { modules: Module[], requestModules: () => void };
+type AppProps = RouteComponentProps & Connect & { modules: Module[]; requestModules: () => void };
const App = (props: AppProps ) => (
<>
@@ -38,16 +38,16 @@
);
const FinalApp = withRouter(connect((state) => ({
- modules: state.apiDemo.modules
+ modules: state.apiDemo.modules,
}), (dispatcher => ({
- requestModules: () => { dispatcher.dispatch(new ApiAction('restconf/modules', ModulesRequestSuccess, true)) }
+ requestModules: () => { dispatcher.dispatch(new ApiAction('restconf/modules', ModulesRequestSuccess, true)); },
})))(App));
applicationManager.registerApplication({
- name: "apiDemo",
+ name: 'apiDemo',
icon: faNewspaper,
rootComponent: FinalApp,
rootActionHandler: apiDemoRootHandler,
- menuEntry: "API Demo"
+ menuEntry: 'API Demo',
});
diff --git a/sdnr/wt/odlux/apps/apiDemo/tsconfig.json b/sdnr/wt/odlux/apps/apiDemo/tsconfig.json
index a66b5d8..ca65092 100644
--- a/sdnr/wt/odlux/apps/apiDemo/tsconfig.json
+++ b/sdnr/wt/odlux/apps/apiDemo/tsconfig.json
@@ -4,7 +4,7 @@
"outDir": "./dist",
"sourceMap": true,
"forceConsistentCasingInFileNames": true,
- "allowSyntheticDefaultImports": false,
+ "allowSyntheticDefaultImports": true,
"allowUnreachableCode": false,
"allowUnusedLabels": false,
"noFallthroughCasesInSwitch": true,
diff --git a/sdnr/wt/odlux/apps/configurationApp/package.json b/sdnr/wt/odlux/apps/configurationApp/package.json
index afd5456..b1d7d95 100644
--- a/sdnr/wt/odlux/apps/configurationApp/package.json
+++ b/sdnr/wt/odlux/apps/configurationApp/package.json
@@ -26,7 +26,11 @@
"@mui/icons-material": "^5.2.0",
"@mui/material": "^5.2.2",
"@mui/styles": "^5.2.2",
- "@odlux/framework": "*"
+ "@odlux/framework": "*",
+ "@fortawesome/fontawesome-svg-core": "1.2.35",
+ "@fortawesome/free-solid-svg-icons": "5.6.3",
+ "@fortawesome/react-fontawesome": "0.1.14",
+ "material-ui-confirm": "3.0.2"
},
"peerDependencies": {
"@types/classnames": "2.2.6",
diff --git a/sdnr/wt/odlux/apps/configurationApp/pom.xml b/sdnr/wt/odlux/apps/configurationApp/pom.xml
index 6347562..9703e29 100644
--- a/sdnr/wt/odlux/apps/configurationApp/pom.xml
+++ b/sdnr/wt/odlux/apps/configurationApp/pom.xml
@@ -19,6 +19,7 @@
~ ============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>
@@ -139,7 +140,7 @@
<!-- optional: default phase is "generate-resources" -->
<phase>initialize</phase>
<configuration>
- <nodeVersion>v12.13.0</nodeVersion>
+ <nodeVersion>v12.22.0</nodeVersion>
<yarnVersion>v1.22.10</yarnVersion>
</configuration>
</execution>
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/actions/deviceActions.ts b/sdnr/wt/odlux/apps/configurationApp/src/actions/deviceActions.ts
index 3758378..5213713 100644
--- a/sdnr/wt/odlux/apps/configurationApp/src/actions/deviceActions.ts
+++ b/sdnr/wt/odlux/apps/configurationApp/src/actions/deviceActions.ts
@@ -1,15 +1,30 @@
import { Action } from '../../../../framework/src/flux/action';
import { Dispatch } from '../../../../framework/src/flux/store';
-import { IApplicationStoreState } from "../../../../framework/src/store/applicationStore";
-import { PushAction, ReplaceAction } from "../../../../framework/src/actions/navigationActions";
-import { AddErrorInfoAction } from "../../../../framework/src/actions/errorActions";
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+import { PushAction, ReplaceAction } from '../../../../framework/src/actions/navigationActions';
+import { AddErrorInfoAction } from '../../../../framework/src/actions/errorActions';
import { DisplayModeType, DisplaySpecification } from '../handlers/viewDescriptionHandler';
-import { restService } from "../services/restServices";
-import { YangParser } from "../yang/yangParser";
-import { Module } from "../models/yang";
-import { ViewSpecification, ViewElement, isViewElementReference, isViewElementList, isViewElementObjectOrList, isViewElementRpc, isViewElementChoise, ViewElementChoiseCase, ViewElementString } from "../models/uiModels";
+import { restService } from '../services/restServices';
+import { YangParser } from '../yang/yangParser';
+import { Module } from '../models/yang';
+import {
+ ViewSpecification,
+ ViewElement,
+ isViewElementReference,
+ isViewElementList,
+ ViewElementString,
+} from '../models/uiModels';
+
+import {
+ checkResponseCode,
+ splitVPath,
+ filterViewElements,
+ flattenViewElements,
+ getReferencedDataList,
+ resolveViewDescription,
+} from '../utilities/viewEngineHelper';
export class EnableValueSelector extends Action {
constructor(public listSpecification: ViewSpecification, public listData: any[], public keyProperty: string, public onValueSelected : (value: any) => void ) {
@@ -30,42 +45,26 @@
}
export class UpdateDeviceDescription extends Action {
- constructor( public nodeId: string, public modules: { [name:string]: Module}, public views: ViewSpecification[]) {
+ constructor( public nodeId: string, public modules: { [name:string]: Module }, public views: ViewSpecification[]) {
super();
}
}
-export class UpdatViewDescription extends Action {
- constructor (public vPath: string, public viewData: any, public displaySpecification: DisplaySpecification = { displayMode: DisplayModeType.doNotDisplay }) {
+export class UpdateViewDescription extends Action {
+ constructor(public vPath: string, public viewData: any, public displaySpecification: DisplaySpecification = { displayMode: DisplayModeType.doNotDisplay }) {
super();
}
}
-export class UpdatOutputData extends Action {
- constructor (public outputData: any) {
+export class UpdateOutputData extends Action {
+ constructor(public outputData: any) {
super();
}
}
-type HttpResult = {
- status: number;
- message?: string | undefined;
- data: {
- [key: string]: any;
- } | null | undefined;
-};
+export const updateNodeIdAsyncActionCreator = (nodeId: string) => async (dispatch: Dispatch, _getState: () => IApplicationStoreState ) => {
-const checkResponseCode = (restResult: HttpResult) =>{
-
- //403 gets handled by the framework from now on
-
- return restResult.status !== 403 && ( restResult.status < 200 || restResult.status > 299);
-
-}
-
-export const updateNodeIdAsyncActionCreator = (nodeId: string) => async (dispatch: Dispatch, getState: () => IApplicationStoreState ) => {
-
- dispatch(new UpdateDeviceDescription("", {}, []));
+ dispatch(new UpdateDeviceDescription('', {}, []));
dispatch(new SetCollectingSelectionData(true));
const { availableCapabilities, unavailableCapabilities, importOnlyModules } = await restService.getCapabilitiesByMountId(nodeId);
@@ -73,16 +72,24 @@
if (!availableCapabilities || availableCapabilities.length <= 0) {
dispatch(new SetCollectingSelectionData(false));
dispatch(new UpdateDeviceDescription(nodeId, {}, []));
- dispatch(new UpdatViewDescription("", [], {
+ dispatch(new UpdateViewDescription('', [], {
displayMode: DisplayModeType.displayAsMessage,
- renderMessage: `NetworkElement : "${nodeId}" has no capabilities.`
+ renderMessage: `NetworkElement : "${nodeId}" has no capabilities.`,
}));
throw new Error(`NetworkElement : [${nodeId}] has no capabilities.`);
}
- const parser = new YangParser(unavailableCapabilities || undefined, importOnlyModules || undefined, nodeId);
+ const parser = new YangParser(
+ nodeId,
+ availableCapabilities.reduce((acc, cur) => {
+ acc[cur.capability] = cur.version;
+ return acc;
+ }, {} as { [key: string]: string }),
+ unavailableCapabilities || undefined,
+ importOnlyModules || undefined,
+ );
- for (let i = 0; i < availableCapabilities.length; ++i){
+ for (let i = 0; i < availableCapabilities.length; ++i) {
const capRaw = availableCapabilities[i];
try {
await parser.addCapability(capRaw.capability, capRaw.version);
@@ -95,184 +102,28 @@
dispatch(new SetCollectingSelectionData(false));
- if (process.env.NODE_ENV === "development" ) {
- console.log(parser, parser.modules, parser.views);
+ if (process.env.NODE_ENV === 'development' ) {
+ console.log(parser, parser.modules, parser.views);
}
return dispatch(new UpdateDeviceDescription(nodeId, parser.modules, parser.views));
-}
+};
-export const splitVPath = (vPath: string, vPathParser : RegExp): [string, string?][] => {
- const pathParts: [string, string?][] = [];
- let partMatch: RegExpExecArray | null;
- if (vPath) do {
- partMatch = vPathParser.exec(vPath);
- if (partMatch) {
- pathParts.push([partMatch[1], partMatch[2] || undefined]);
- }
- } while (partMatch)
- return pathParts;
-}
-
-const getReferencedDataList = async (refPath: string, dataPath: string, modules: { [name: string]: Module }, views: ViewSpecification[]) => {
- const pathParts = splitVPath(refPath, /(?:(?:([^\/\:]+):)?([^\/]+))/g); // 1 = opt: namespace / 2 = property
- const defaultNS = pathParts[0][0];
- let referencedModule = modules[defaultNS];
-
- let dataMember: string;
- let view: ViewSpecification;
- let currentNS: string | null = null;
- let dataUrls = [dataPath];
- let data: any;
-
- for (let i = 0; i < pathParts.length; ++i) {
- const [pathPartNS, pathPart] = pathParts[i];
- const namespace = pathPartNS != null ? (currentNS = pathPartNS) : currentNS;
-
- const viewElement = i === 0
- ? views[0].elements[`${referencedModule.name}:${pathPart}`]
- : view!.elements[`${pathPart}`] || view!.elements[`${namespace}:${pathPart}`];
-
- if (!viewElement) throw new Error(`Could not find ${pathPart} in ${refPath}`);
- if (i < pathParts.length - 1) {
- if (!isViewElementObjectOrList(viewElement)) {
- throw Error(`Module: [${referencedModule.name}].[${viewElement.label}]. Viewelement is not list or object.`);
- }
- view = views[+viewElement.viewId];
- const resultingDataUrls : string[] = [];
- if (isViewElementList(viewElement)) {
- for (let j = 0; j < dataUrls.length; ++j) {
- const dataUrl = dataUrls[j];
- const restResult = (await restService.getConfigData(dataUrl));
- if (restResult.data == null || checkResponseCode(restResult)) {
- const message = restResult.data && restResult.data.errors && restResult.data.errors.error && restResult.data.errors.error[0] && restResult.data.errors.error[0]["error-message"] || "";
- throw new Error(`Server Error. Status: [${restResult.status}]\n${message || restResult.message || ''}`);
- }
-
- let dataRaw = restResult.data[`${defaultNS}:${dataMember!}`];
- if (dataRaw === undefined) {
- dataRaw = restResult.data[dataMember!];
- }
- dataRaw = dataRaw instanceof Array
- ? dataRaw[0]
- : dataRaw;
-
- data = dataRaw && dataRaw[viewElement.label] || [];
- const keys: string[] = data.map((entry: { [key: string]: any } )=> entry[viewElement.key!]);
- resultingDataUrls.push(...keys.map(key => `${dataUrl}/${viewElement.label.replace(/\//ig, "%2F")}=${key.replace(/\//ig, "%2F")}`));
- }
- dataMember = viewElement.label;
- } else {
- // just a member, not a list
- const pathSegment = (i === 0
- ? `/${referencedModule.name}:${viewElement.label.replace(/\//ig, "%2F")}`
- : `/${viewElement.label.replace(/\//ig, "%2F")}`);
- resultingDataUrls.push(...dataUrls.map(dataUrl => dataUrl + pathSegment));
- dataMember = viewElement.label;
- }
- dataUrls = resultingDataUrls;
- } else {
- data = [];
- for (let j = 0; j < dataUrls.length; ++j) {
- const dataUrl = dataUrls[j];
- const restResult = (await restService.getConfigData(dataUrl));
- if (restResult.data == null || checkResponseCode(restResult)) {
- const message = restResult.data && restResult.data.errors && restResult.data.errors.error && restResult.data.errors.error[0] && restResult.data.errors.error[0]["error-message"] || "";
- throw new Error(`Server Error. Status: [${restResult.status}]\n${message || restResult.message || ''}`);
- }
- let dataRaw = restResult.data[`${defaultNS}:${dataMember!}`];
- if (dataRaw === undefined) {
- dataRaw = restResult.data[dataMember!];
- }
- dataRaw = dataRaw instanceof Array
- ? dataRaw[0]
- : dataRaw;
- data.push(dataRaw);
- }
- // BUG UUID ist nicht in den elements enthalten !!!!!!
- const key = viewElement && viewElement.label || pathPart;
- return {
- view: view!,
- data: data,
- key: key,
- };
- }
+export const postProcessDisplaySpecificationActionCreator = (vPath: string, viewData: any, displaySpecification: DisplaySpecification) => async (dispatch: Dispatch, _getState: () => IApplicationStoreState) => {
+
+ if (displaySpecification.displayMode === DisplayModeType.displayAsObject) {
+ displaySpecification = {
+ ...displaySpecification,
+ viewSpecification: await filterViewElements(vPath, viewData, displaySpecification.viewSpecification),
+ };
}
- return null;
-}
-const resolveViewDescription = (defaultNS: string | null, vPath: string, view: ViewSpecification): ViewSpecification =>{
-
- // check if-feature | when | and resolve all references.
- view = { ...view };
- view.elements = Object.keys(view.elements).reduce<{ [name: string]: ViewElement }>((acc, cur) => {
- const resolveHistory : ViewElement[] = [];
- let elm = view.elements[cur];
- const key = defaultNS && cur.replace(new RegExp(`^${defaultNS}:`, "i"),"") || cur;
- while (isViewElementReference(elm)) {
- const result = (elm.ref(vPath));
- if (result) {
- const [referencedElement, referencedPath] = result;
- if (resolveHistory.some(hist => hist === referencedElement)) {
- console.error(`Circle reference found at: ${vPath}`, resolveHistory);
- break;
- }
- elm = referencedElement;
- vPath = referencedPath;
- resolveHistory.push(elm);
- }
- }
-
- acc[key] = { ...elm, id: key };
-
- return acc;
- }, {});
- return view;
-}
-
-const flatenViewElements = (defaultNS: string | null, parentPath: string, elements: { [name: string]: ViewElement }, views: ViewSpecification[], currentPath: string ): { [name: string]: ViewElement } => {
- if (!elements) return {};
- return Object.keys(elements).reduce<{ [name: string]: ViewElement }>((acc, cur) => {
- const elm = elements[cur];
-
- // remove the detault namespace, and only the default namespace, sine it seems that this is also not in the restconf response
- const elmKey = defaultNS && elm.id.replace(new RegExp(`^${defaultNS}:`, "i"), "") || elm.id;
- const key = parentPath ? `${parentPath}.${elmKey}` : elmKey;
-
- if (isViewElementRpc(elm)) {
- console.warn(`Flaten of RFC not supported ! [${currentPath}][${elm.label}]`);
- return acc;
- } else if (isViewElementObjectOrList(elm)) {
- const view = views[+elm.viewId];
- const inner = view && flatenViewElements(defaultNS, key, view.elements, views, `${currentPath}/${view.name}`);
- inner && Object.keys(inner).forEach(k => (acc[k] = inner[k]));
- } else if (isViewElementChoise(elm)) {
- acc[key] = {
- ...elm,
- id: key,
- cases: Object.keys(elm.cases).reduce<{ [name: string]: ViewElementChoiseCase }>((accCases, curCases) => {
- const caseElement = elm.cases[curCases];
- accCases[curCases] = {
- ...caseElement,
- // Hint: do not use key it contains elmKey, which shell be omitted for cases.
- elements: flatenViewElements(defaultNS, /*key*/ parentPath, caseElement.elements, views, `${currentPath}/${elm.label}`)
- };
- return accCases;
- }, {}),
- };
- } else {
- acc[key] = {
- ...elm,
- id: key,
- };
- }
- return acc;
- }, {});
+ dispatch(new UpdateViewDescription(vPath, viewData, displaySpecification));
};
export const updateViewActionAsyncCreator = (vPath: string) => async (dispatch: Dispatch, getState: () => IApplicationStoreState) => {
const pathParts = splitVPath(vPath, /(?:([^\/\["]+)(?:\[([^\]]*)\])?)/g); // 1 = property / 2 = optional key
- const { configuration: { deviceDescription: { nodeId, modules, views } }, framework: { navigationState } } = getState();
+ const { configuration: { deviceDescription: { nodeId, modules, views } } } = getState();
let dataPath = `/rests/data/network-topology:network-topology/topology=topology-netconf/node=${nodeId}/yang-ext:mount`;
let inputViewSpecification: ViewSpecification | undefined = undefined;
@@ -291,26 +142,26 @@
try {
for (let ind = 0; ind < pathParts.length; ++ind) {
const [property, key] = pathParts[ind];
- const namespaceInd = property && property.indexOf(":") || -1;
+ const namespaceInd = property && property.indexOf(':') || -1;
const namespace: string | null = namespaceInd > -1 ? (currentNS = property.slice(0, namespaceInd)) : currentNS;
- if (ind === 0) { defaultNS = namespace };
+ if (ind === 0) { defaultNS = namespace; }
viewElement = viewSpecification.elements[property] || viewSpecification.elements[`${namespace}:${property}`];
- if (!viewElement) throw Error("Property [" + property + "] does not exist.");
+ if (!viewElement) throw Error('Property [' + property + '] does not exist.');
if (viewElement.isList && !key) {
if (pathParts.length - 1 > ind) {
dispatch(new SetCollectingSelectionData(false));
- throw new Error("No key for list [" + property + "]");
- } else if (vPath.endsWith("[]") && pathParts.length - 1 === ind) {
+ throw new Error('No key for list [' + property + ']');
+ } else if (vPath.endsWith('[]') && pathParts.length - 1 === ind) {
// empty key is used for new element
- if (viewElement && "viewId" in viewElement) viewSpecification = views[+viewElement.viewId];
+ if (viewElement && 'viewId' in viewElement) viewSpecification = views[+viewElement.viewId];
const data = Object.keys(viewSpecification.elements).reduce<{ [name: string]: any }>((acc, cur) => {
const elm = viewSpecification.elements[cur];
if (elm.default) {
- acc[elm.id] = elm.default || ""
+ acc[elm.id] = elm.default || '';
}
return acc;
}, {});
@@ -319,13 +170,13 @@
const ds: DisplaySpecification = {
displayMode: DisplayModeType.displayAsObject,
viewSpecification: resolveViewDescription(defaultNS, vPath, viewSpecification),
- keyProperty: isViewElementList(viewElement!) && viewElement.key || undefined
+ keyProperty: isViewElementList(viewElement!) && viewElement.key || undefined,
};
// update display specification
- return dispatch(new UpdatViewDescription(vPath, data, ds));
+ return dispatch(postProcessDisplaySpecificationActionCreator(vPath, data, ds));
}
- if (viewElement && isViewElementList(viewElement) && viewSpecification.parentView === "0") {
+ if (viewElement && isViewElementList(viewElement) && viewSpecification.parentView === '0') {
// check if there is a reference as key
const listSpecification = views[+viewElement.viewId];
const keyElement = viewElement.key && listSpecification.elements[viewElement.key];
@@ -338,35 +189,35 @@
throw new Error(`Key property not found for [${keyElement.referencePath}].`);
}
dispatch(new EnableValueSelector(refList.view, refList.data, refList.key, (refKey) => {
- window.setTimeout(() => dispatch(new PushAction(`${vPath}[${refKey.replace(/\//ig, "%2F")}]`)));
+ window.setTimeout(() => dispatch(new PushAction(`${vPath}[${refKey.replace(/\//ig, '%2F')}]`)));
}));
} else {
- // Found a list at root level of a module w/o a refenrece key.
+ // Found a list at root level of a module w/o a reference key.
dataPath += `?content=config&fields=${encodeURIComponent(viewElement.id)}(${encodeURIComponent(viewElement.key || '')})`;
const restResult = (await restService.getConfigData(dataPath));
- if (restResult && restResult.status === 200 && restResult.data && restResult.data[viewElement.id] ){
- // spoof the not existing view here
- const refData = restResult.data[viewElement.id];
- const refView : ViewSpecification = {
- id: "-1",
- canEdit: false,
+ if (restResult && restResult.status === 200 && restResult.data && restResult.data[viewElement.id] ) {
+ // spoof the not existing view here
+ const refData = restResult.data[viewElement.id];
+ const refView : ViewSpecification = {
+ id: '-1',
+ canEdit: false,
+ config: false,
+ language: 'en-US',
+ elements: {
+ [viewElement.key!] : {
+ uiType: 'string',
config: false,
- language: "en-US",
- elements: {
- [viewElement.key!] : {
- uiType: "string",
- config: false,
- id: viewElement.key,
- label: viewElement.key,
- isList: true,
- } as ViewElementString
- }
- };
- dispatch(new EnableValueSelector(refView, refData, viewElement.key!, (refKey) => {
- window.setTimeout(() => dispatch(new PushAction(`${vPath}[${refKey.replace(/\//ig, "%2F")}]`)));
- }));
+ id: viewElement.key,
+ label: viewElement.key,
+ isList: true,
+ } as ViewElementString,
+ },
+ };
+ dispatch(new EnableValueSelector(refView, refData, viewElement.key!, (refKey) => {
+ window.setTimeout(() => dispatch(new PushAction(`${vPath}[${refKey.replace(/\//ig, '%2F')}]`)));
+ }));
} else {
- throw new Error("Found a list at root level of a module and could not determine the keys.");
+ throw new Error('Found a list at root level of a module and could not determine the keys.');
}
dispatch(new SetCollectingSelectionData(false));
}
@@ -374,31 +225,30 @@
}
extractList = true;
} else {
- // normal case
+ // normal case & replaces unicode %2C if present
+ dataPath += `/${property}${key ? `=${key.replace(/\%2C/g, ',').replace(/\//ig, '%2F')}` : ''}`;
+
// in case of the root element the required namespace will be added later,
// while extracting the data
-
- dataPath += `/${property}${key ? `=${key.replace(/\%2C/g, ",").replace(/\//ig, "%2F")}` : ""}`;
-
dataMember = namespace === defaultNS
? viewElement.label
: `${namespace}:${viewElement.label}`;
extractList = false;
}
- if (viewElement && "viewId" in viewElement) {
+ if (viewElement && 'viewId' in viewElement) {
viewSpecification = views[+viewElement.viewId];
- } else if (viewElement.uiType === "rpc") {
+ } else if (viewElement.uiType === 'rpc') {
viewSpecification = views[+(viewElement.inputViewId || 0)];
// create new instance & flaten
inputViewSpecification = viewElement.inputViewId != null && {
...views[+(viewElement.inputViewId || 0)],
- elements: flatenViewElements(defaultNS, "", views[+(viewElement.inputViewId || 0)].elements, views, viewElement.label),
+ elements: flattenViewElements(defaultNS, '', views[+(viewElement.inputViewId || 0)].elements, views, viewElement.label),
} || undefined;
outputViewSpecification = viewElement.outputViewId != null && {
...views[+(viewElement.outputViewId || 0)],
- elements: flatenViewElements(defaultNS, "", views[+(viewElement.outputViewId || 0)].elements, views, viewElement.label),
+ elements: flattenViewElements(defaultNS, '', views[+(viewElement.outputViewId || 0)].elements, views, viewElement.label),
} || undefined;
}
@@ -406,7 +256,7 @@
let data: any = {};
// do not get any data from netconf if there is no view specified || this is the root element [0] || this is an rpc
- if (viewSpecification && !(viewSpecification.id === "0" || viewElement!.uiType === "rpc")) {
+ if (viewSpecification && !(viewSpecification.id === '0' || viewElement!.uiType === 'rpc')) {
const restResult = (await restService.getConfigData(dataPath));
if (!restResult.data) {
// special case: if this is a list without any response
@@ -418,21 +268,21 @@
const ds: DisplaySpecification = {
displayMode: extractList ? DisplayModeType.displayAsList : DisplayModeType.displayAsObject,
viewSpecification: resolveViewDescription(defaultNS, vPath, viewSpecification),
- keyProperty: viewElement.key
+ keyProperty: viewElement.key,
};
// update display specification
- return dispatch(new UpdatViewDescription(vPath, [], ds));
+ return dispatch(postProcessDisplaySpecificationActionCreator(vPath, [], ds));
}
throw new Error(`Did not get response from Server. Status: [${restResult.status}]`);
} else if (checkResponseCode(restResult)) {
- const message = restResult.data.errors && restResult.data.errors.error && restResult.data.errors.error[0] && restResult.data.errors.error[0]["error-message"] || "";
+ const message = restResult.data.errors && restResult.data.errors.error && restResult.data.errors.error[0] && restResult.data.errors.error[0]['error-message'] || '';
throw new Error(`Server Error. Status: [${restResult.status}]\n${message}`);
} else {
- // https://tools.ietf.org/html/rfc7951#section-4 the root element may countain a namesapce or not !
+ // https://tools.ietf.org/html/rfc7951#section-4 the root element may contain a namespace or not !
data = restResult.data[`${defaultNS}:${dataMember!}`];
if (data === undefined) {
- data = restResult.data[dataMember!]; // extract dataMember w/o namespace
+ data = restResult.data[dataMember!]; // extract dataMember w/o namespace
}
}
@@ -446,19 +296,21 @@
? data[viewElement!.id] || data[viewElement!.label] || [] // if the list is empty, it does not exist
: data;
- } else if (viewElement! && viewElement!.uiType === "rpc") {
+ } else if (viewElement! && viewElement!.uiType === 'rpc') {
// set data to defaults
data = {};
- inputViewSpecification && Object.keys(inputViewSpecification.elements).forEach(key => {
- const elm = inputViewSpecification && inputViewSpecification.elements[key];
- if (elm && elm.default != undefined) {
- data[elm.id] = elm.default;
- }
- });
+ if (inputViewSpecification) {
+ Object.keys(inputViewSpecification.elements).forEach(key => {
+ const elm = inputViewSpecification && inputViewSpecification.elements[key];
+ if (elm && elm.default != undefined) {
+ data[elm.id] = elm.default;
+ }
+ });
+ }
}
// create display specification
- const ds: DisplaySpecification = viewElement! && viewElement!.uiType === "rpc"
+ const ds: DisplaySpecification = viewElement! && viewElement!.uiType === 'rpc'
? {
dataPath,
displayMode: DisplayModeType.displayAsRPC,
@@ -470,16 +322,18 @@
displayMode: extractList ? DisplayModeType.displayAsList : DisplayModeType.displayAsObject,
viewSpecification: resolveViewDescription(defaultNS, vPath, viewSpecification),
keyProperty: isViewElementList(viewElement!) && viewElement.key || undefined,
- apidocPath: isViewElementList(viewElement!) && `/apidoc/explorer/index.html?urls.primaryName=$$$standard$$$#/mounted%20${nodeId}%20${viewElement!.module || 'MODULE_NOT_DEFINED'}/$$$action$$$_${dataPath.replace(/^\//,'').replace(/[\/=\-\:]/g,'_')}_${viewElement! != null ? `${viewElement.id.replace(/[\/=\-\:]/g,'_')}_` : '' }` || undefined,
+
+ // eslint-disable-next-line max-len
+ apidocPath: isViewElementList(viewElement!) && `/apidoc/explorer/index.html?urls.primaryName=$$$standard$$$#/mounted%20${nodeId}%20${viewElement!.module || 'MODULE_NOT_DEFINED'}/$$$action$$$_${dataPath.replace(/^\//, '').replace(/[\/=\-\:]/g, '_')}_${viewElement! != null ? `${viewElement.id.replace(/[\/=\-\:]/g, '_')}_` : '' }` || undefined,
};
// update display specification
- return dispatch(new UpdatViewDescription(vPath, data, ds));
- // https://beta.just-run.it/#/configuration/Sim12600/core-model:network-element/ltp[LTP-MWPS-TTP-01]
- // https://beta.just-run.it/#/configuration/Sim12600/core-model:network-element/ltp[LTP-MWPS-TTP-01]/lp
+ return dispatch(postProcessDisplaySpecificationActionCreator(vPath, data, ds));
+ // https://server.com/#/configuration/Sim12600/core-model:network-element/ltp[LTP-MWPS-TTP-01]
+ // https://server.com/#/configuration/Sim12600/core-model:network-element/ltp[LTP-MWPS-TTP-01]/lp
} catch (error) {
history.back();
- dispatch(new AddErrorInfoAction({ title: "Problem", message: error.message || `Could not process ${dataPath}` }));
+ dispatch(new AddErrorInfoAction({ title: 'Problem', message: error.message || `Could not process ${dataPath}` }));
dispatch(new SetCollectingSelectionData(false));
} finally {
return;
@@ -503,63 +357,63 @@
try {
for (let ind = 0; ind < pathParts.length; ++ind) {
let [property, key] = pathParts[ind];
- const namespaceInd = property && property.indexOf(":") || -1;
+ const namespaceInd = property && property.indexOf(':') || -1;
const namespace: string | null = namespaceInd > -1 ? (currentNS = property.slice(0, namespaceInd)) : currentNS;
- if (ind === 0) { defaultNS = namespace };
+ if (ind === 0) { defaultNS = namespace; }
viewElement = viewSpecification.elements[property] || viewSpecification.elements[`${namespace}:${property}`];
- if (!viewElement) throw Error("Property [" + property + "] does not exist.");
+ if (!viewElement) throw Error('Property [' + property + '] does not exist.');
if (isViewElementList(viewElement) && !key) {
embedList = true;
- if (viewElement && viewElement.isList && viewSpecification.parentView === "0") {
- throw new Error("Found a list at root level of a module w/o a refenrece key.");
+ if (viewElement && viewElement.isList && viewSpecification.parentView === '0') {
+ throw new Error('Found a list at root level of a module w/o a refenrece key.');
}
if (pathParts.length - 1 > ind) {
dispatch(new SetCollectingSelectionData(false));
- throw new Error("No key for list [" + property + "]");
- } else if (vPath.endsWith("[]") && pathParts.length - 1 === ind) {
+ throw new Error('No key for list [' + property + ']');
+ } else if (vPath.endsWith('[]') && pathParts.length - 1 === ind) {
// handle new element with any number of arguments
- let keyList = viewElement.key?.split(" ");
- let dataPathParam = keyList?.map(id => data[id]).join(",");
- key = viewElement.key && String(dataPathParam) || "";
+ let keyList = viewElement.key?.split(' ');
+ let dataPathParam = keyList?.map(id => data[id]).join(',');
+ key = viewElement.key && String(dataPathParam) || '';
isNew = key;
if (!key) {
dispatch(new SetCollectingSelectionData(false));
- throw new Error("No value for key [" + viewElement.key + "] in list [" + property + "]");
+ throw new Error('No value for key [' + viewElement.key + '] in list [' + property + ']');
}
}
}
- dataPath += `/${property}${key ? `=${key.replace(/\//ig, "%2F")}` : ""}`;
+ dataPath += `/${property}${key ? `=${key.replace(/\//ig, '%2F')}` : ''}`;
dataMember = viewElement.label;
embedList = false;
- if (viewElement && "viewId" in viewElement) {
+ if (viewElement && 'viewId' in viewElement) {
viewSpecification = views[+viewElement.viewId];
}
}
// remove read-only elements
- const removeReadOnlyElements = (viewSpecification: ViewSpecification, isList: boolean, data: any) => {
+ const removeReadOnlyElements = (pViewSpecification: ViewSpecification, isList: boolean, pData: any) => {
if (isList) {
- return data.map((elm : any) => removeReadOnlyElements(viewSpecification, false, elm));
+ return pData.map((elm : any) => removeReadOnlyElements(pViewSpecification, false, elm));
} else {
- return Object.keys(data).reduce<{[key: string]: any}>((acc, cur)=>{
- const [nsOrName, name] = cur.split(':',1);
- const element = viewSpecification.elements[cur] || viewSpecification.elements[nsOrName] || viewSpecification.elements[name];
- if (!element && process.env.NODE_ENV === "development" ) {
- throw new Error("removeReadOnlyElements: Could not determine elment for data.");
+ return Object.keys(pData).reduce<{ [key: string]: any }>((acc, cur)=>{
+ const [nsOrName, name] = cur.split(':', 1);
+ const element = pViewSpecification.elements[cur] || pViewSpecification.elements[nsOrName] || pViewSpecification.elements[name];
+ if (!element && process.env.NODE_ENV === 'development' ) {
+ throw new Error('removeReadOnlyElements: Could not determine elment for data.');
}
if (element && element.config) {
- if (element.uiType==="object") {
+ if (element.uiType === 'object') {
const view = views[+element.viewId];
if (!view) {
- throw new Error("removeReadOnlyElements: Internal Error could not determine viewId: "+element.viewId);
+ throw new Error('removeReadOnlyElements: Internal Error could not determine viewId: ' + element.viewId);
}
- acc[cur] = removeReadOnlyElements(view, element.isList != null && element.isList, data[cur]);
+ acc[cur] = removeReadOnlyElements(view, element.isList != null && element.isList, pData[cur]);
} else {
- acc[cur] = data[cur];
+ acc[cur] = pData[cur];
}
}
return acc;
@@ -580,10 +434,10 @@
: data;
// do not extract root member (0)
- if (viewSpecification && viewSpecification.id !== "0") {
+ if (viewSpecification && viewSpecification.id !== '0') {
const updateResult = await restService.setConfigData(dataPath, { [`${currentNS}:${dataMember!}`]: data }); // addDataMember using currentNS
if (checkResponseCode(updateResult)) {
- const message = updateResult.data && updateResult.data.errors && updateResult.data.errors.error && updateResult.data.errors.error[0] && updateResult.data.errors.error[0]["error-message"] || "";
+ const message = updateResult.data && updateResult.data.errors && updateResult.data.errors.error && updateResult.data.errors.error[0] && updateResult.data.errors.error[0]['error-message'] || '';
throw new Error(`Server Error. Status: [${updateResult.status}]\n${message || updateResult.message || ''}`);
}
}
@@ -600,10 +454,10 @@
};
// update display specification
- return dispatch(new UpdatViewDescription(vPath, data, ds));
+ return dispatch(new UpdateViewDescription(vPath, data, ds));
} catch (error) {
history.back();
- dispatch(new AddErrorInfoAction({ title: "Problem", message: error.message || `Could not change ${dataPath}` }));
+ dispatch(new AddErrorInfoAction({ title: 'Problem', message: error.message || `Could not change ${dataPath}` }));
} finally {
dispatch(new SetCollectingSelectionData(false));
@@ -619,57 +473,53 @@
let viewElement: ViewElement;
let currentNS: string | null = null;
- let defaultNS: string | null = null;
-
+
dispatch(new SetCollectingSelectionData(true));
try {
for (let ind = 0; ind < pathParts.length; ++ind) {
let [property, key] = pathParts[ind];
- const namespaceInd = property && property.indexOf(":") || -1;
+ const namespaceInd = property && property.indexOf(':') || -1;
const namespace: string | null = namespaceInd > -1 ? (currentNS = property.slice(0, namespaceInd)) : currentNS;
- if (ind === 0) { defaultNS = namespace };
viewElement = viewSpecification.elements[property] || viewSpecification.elements[`${namespace}:${property}`];
- if (!viewElement) throw Error("Property [" + property + "] does not exist.");
+ if (!viewElement) throw Error('Property [' + property + '] does not exist.');
if (isViewElementList(viewElement) && !key) {
- if (viewElement && viewElement.isList && viewSpecification.parentView === "0") {
- throw new Error("Found a list at root level of a module w/o a refenrece key.");
+ if (viewElement && viewElement.isList && viewSpecification.parentView === '0') {
+ throw new Error('Found a list at root level of a module w/o a reference key.');
}
if (pathParts.length - 1 > ind) {
dispatch(new SetCollectingSelectionData(false));
- throw new Error("No key for list [" + property + "]");
- } else if (vPath.endsWith("[]") && pathParts.length - 1 === ind) {
+ throw new Error('No key for list [' + property + ']');
+ } else if (vPath.endsWith('[]') && pathParts.length - 1 === ind) {
// remove the whole table
}
}
- dataPath += `/${property}${key ? `=${key.replace(/\//ig, "%2F")}` : ""}`;
+ dataPath += `/${property}${key ? `=${key.replace(/\//ig, '%2F')}` : ''}`;
- if (viewElement && "viewId" in viewElement) {
+ if (viewElement && 'viewId' in viewElement) {
viewSpecification = views[+viewElement.viewId];
- } else if (viewElement.uiType === "rpc") {
+ } else if (viewElement.uiType === 'rpc') {
viewSpecification = views[+(viewElement.inputViewId || 0)];
}
}
const updateResult = await restService.removeConfigElement(dataPath);
if (checkResponseCode(updateResult)) {
- const message = updateResult.data && updateResult.data.errors && updateResult.data.errors.error && updateResult.data.errors.error[0] && updateResult.data.errors.error[0]["error-message"] || "";
+ const message = updateResult.data && updateResult.data.errors && updateResult.data.errors.error && updateResult.data.errors.error[0] && updateResult.data.errors.error[0]['error-message'] || '';
throw new Error(`Server Error. Status: [${updateResult.status}]\n${message || updateResult.message || ''}`);
}
} catch (error) {
- dispatch(new AddErrorInfoAction({ title: "Problem", message: error.message || `Could not remove ${dataPath}` }));
+ dispatch(new AddErrorInfoAction({ title: 'Problem', message: error.message || `Could not remove ${dataPath}` }));
} finally {
dispatch(new SetCollectingSelectionData(false));
}
-
-
};
export const executeRpcActionAsyncCreator = (vPath: string, data: any) => async (dispatch: Dispatch, getState: () => IApplicationStoreState) => {
const pathParts = splitVPath(vPath, /(?:([^\/\["]+)(?:\[([^\]]*)\])?)/g); // 1 = property / 2 = optional key
- const { configuration: { deviceDescription: { nodeId, views }, viewDescription: oldViewDescription } } = getState();
+ const { configuration: { deviceDescription: { nodeId, views } } } = getState();
let dataPath = `/rests/operations/network-topology:network-topology/topology=topology-netconf/node=${nodeId}/yang-ext:mount`;
let viewSpecification: ViewSpecification = views[0];
let viewElement: ViewElement;
@@ -684,17 +534,17 @@
try {
for (let ind = 0; ind < pathParts.length; ++ind) {
let [property, key] = pathParts[ind];
- const namespaceInd = property && property.indexOf(":") || -1;
+ const namespaceInd = property && property.indexOf(':') || -1;
const namespace: string | null = namespaceInd > -1 ? (currentNS = property.slice(0, namespaceInd)) : currentNS;
- if (ind === 0) { defaultNS = namespace };
+ if (ind === 0) { defaultNS = namespace; }
viewElement = viewSpecification.elements[property] || viewSpecification.elements[`${namespace}:${property}`];
- if (!viewElement) throw Error("Property [" + property + "] does not exist.");
+ if (!viewElement) throw Error('Property [' + property + '] does not exist.');
if (isViewElementList(viewElement) && !key) {
embedList = true;
// if (viewElement && viewElement.isList && viewSpecification.parentView === "0") {
- // throw new Error("Found a list at root level of a module w/o a refenrece key.");
+ // throw new Error("Found a list at root level of a module w/o a reference key.");
// }
// if (pathParts.length - 1 > ind) {
// dispatch(new SetCollectingSelectionData(false));
@@ -710,28 +560,28 @@
// }
}
- dataPath += `/${property}${key ? `=${key.replace(/\//ig, "%2F")}` : ""}`;
+ dataPath += `/${property}${key ? `=${key.replace(/\//ig, '%2F')}` : ''}`;
dataMember = viewElement.label;
embedList = false;
- if (viewElement && "viewId" in viewElement) {
+ if (viewElement && 'viewId' in viewElement) {
viewSpecification = views[+viewElement.viewId];
- } else if (viewElement.uiType === "rpc") {
+ } else if (viewElement.uiType === 'rpc') {
viewSpecification = views[+(viewElement.inputViewId || 0)];
}
}
// re-inflate formerly flatten rpc data
data = data && Object.keys(data).reduce < { [name: string ]: any }>((acc, cur) => {
- const pathParts = cur.split(".");
+ const innerPathParts = cur.split('.');
let pos = 0;
const updatePath = (obj: any, key: string) => {
- obj[key] = (pos >= pathParts.length)
+ obj[key] = (pos >= innerPathParts.length)
? data[cur]
- : updatePath(obj[key] || {}, pathParts[pos++]);
+ : updatePath(obj[key] || {}, innerPathParts[pos++]);
return obj;
- }
- updatePath(acc, pathParts[pos++]);
+ };
+ updatePath(acc, innerPathParts[pos++]);
return acc;
}, {}) || null;
@@ -746,22 +596,22 @@
: data;
// do not post root member (0)
- if ((viewSpecification && viewSpecification.id !== "0") || (dataMember! && !data)) {
+ if ((viewSpecification && viewSpecification.id !== '0') || (dataMember! && !data)) {
const updateResult = await restService.executeRpc(dataPath, { [`${defaultNS}:input`]: data || {} });
if (checkResponseCode(updateResult)) {
- const message = updateResult.data && updateResult.data.errors && updateResult.data.errors.error && updateResult.data.errors.error[0] && updateResult.data.errors.error[0]["error-message"] || "";
+ const message = updateResult.data && updateResult.data.errors && updateResult.data.errors.error && updateResult.data.errors.error[0] && updateResult.data.errors.error[0]['error-message'] || '';
throw new Error(`Server Error. Status: [${updateResult.status}]\n${message || updateResult.message || ''}`);
}
- dispatch(new UpdatOutputData(updateResult.data));
+ dispatch(new UpdateOutputData(updateResult.data));
} else {
- throw new Error(`There is NO RPC specified.`);
+ throw new Error('There is NO RPC specified.');
}
// // update display specification
// return
} catch (error) {
- dispatch(new AddErrorInfoAction({ title: "Problem", message: error.message || `Could not change ${dataPath}` }));
+ dispatch(new AddErrorInfoAction({ title: 'Problem', message: error.message || `Could not change ${dataPath}` }));
} finally {
dispatch(new SetCollectingSelectionData(false));
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/assets/icons/configurationAppIcon.svg b/sdnr/wt/odlux/apps/configurationApp/src/assets/icons/configurationAppIcon.svg
new file mode 100644
index 0000000..1b74cc4
--- /dev/null
+++ b/sdnr/wt/odlux/apps/configurationApp/src/assets/icons/configurationAppIcon.svg
@@ -0,0 +1,20 @@
+<!-- highstreet technologies GmbH colour scheme
+ Grey #565656
+ LBlue #36A9E1
+ DBlue #246DA2
+ Green #003F2C / #006C4B
+ Yellw #C8D400
+ Red #D81036
+-->
+
+
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 142 140" >
+<g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" transform="scale(10,10)">
+
+
+ <path fill="#565656" d="M7.887,9.025 C7.799,8.449 7.569,7.92 7.229,7.475 L7.995,6.71 L7.307,6.023 L6.536,6.794 C6.093,6.467 5.566,6.245 4.994,6.161 L4.994,5.066 L4.021,5.066 L4.021,6.155 C3.444,6.232 2.913,6.452 2.461,6.777 L1.709,6.024 L1.021,6.712 L1.761,7.452 C1.411,7.901 1.175,8.437 1.087,9.024 L0.062,9.024 L0.062,9.025 L0.062,9.998 L1.08,9.998 C1.162,10.589 1.396,11.132 1.744,11.587 L1.02,12.31 L1.708,12.997 L2.437,12.268 C2.892,12.604 3.432,12.83 4.02,12.91 L4.02,13.958 L4.993,13.958 L4.993,12.904 C5.576,12.818 6.11,12.589 6.56,12.252 L7.306,12.999 L7.994,12.311 L7.248,11.564 C7.586,11.115 7.812,10.581 7.893,10 L8.952,10 L8.952,9.998 L8.952,9.026 L7.887,9.026 L7.887,9.025 Z M4.496,11.295 C3.512,11.295 2.715,10.497 2.715,9.512 C2.715,8.528 3.512,7.73 4.496,7.73 C5.481,7.73 6.28,8.528 6.28,9.512 C6.28,10.497 5.481,11.295 4.496,11.295 L4.496,11.295 Z" ></path>
+
+ <path fill="#C8D400" d="m 12.231 4.17 l 1.09 -0.281 l -0.252 -0.979 l -1.091 0.282 c -0.118 -0.24 -0.265 -0.47 -0.461 -0.672 c -0.192 -0.196 -0.415 -0.344 -0.647 -0.464 l 0.301 -1.079 l -0.973 -0.271 l -0.299 1.072 c -0.541 -0.043 -1.091 0.078 -1.566 0.382 l -0.76 -0.776 l -0.721 0.707 l 0.756 0.77 c -0.326 0.47 -0.469 1.024 -0.441 1.575 l -1.04 0.268 l 0.252 0.977 l 1.038 -0.268 c 0.117 0.243 0.266 0.475 0.465 0.678 c 0.203 0.208 0.439 0.362 0.686 0.485 l -0.289 1.039 l 0.971 0.271 l 0.293 -1.048 c 0.542 0.033 1.092 -0.1 1.563 -0.415 l 0.771 0.786 l 0.72 -0.707 l -0.776 -0.791 c 0.307 -0.465 0.439 -1.006 0.41 -1.541 l 0 0 z m -2.517 1.617 c -0.823 0 -1.491 -0.669 -1.491 -1.493 c 0 -0.822 0.668 -1.489 1.491 -1.489 c 0.822 0 1.49 0.667 1.49 1.489 c 0 0.824 -0.668 1.493 -1.49 1.493 l 0 0 z" ></path>
+
+</g>
+</svg>
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/components/baseProps.ts b/sdnr/wt/odlux/apps/configurationApp/src/components/baseProps.ts
index 26c3944..7187c0a 100644
--- a/sdnr/wt/odlux/apps/configurationApp/src/components/baseProps.ts
+++ b/sdnr/wt/odlux/apps/configurationApp/src/components/baseProps.ts
@@ -16,13 +16,13 @@
* ============LICENSE_END==========================================================================
*/
-import { ViewElement } from "../models/uiModels";
+import { ViewElement } from '../models/uiModels';
export type BaseProps<TValue = string> = {
- value: ViewElement,
- inputValue: TValue,
- readOnly: boolean,
- disabled: boolean,
- onChange(newValue: TValue): void;
- isKey?: boolean
+ value: ViewElement;
+ inputValue: TValue;
+ readOnly: boolean;
+ disabled: boolean;
+ onChange(newValue: TValue): void;
+ isKey?: boolean;
};
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/components/ifWhenTextInput.tsx b/sdnr/wt/odlux/apps/configurationApp/src/components/ifWhenTextInput.tsx
index 8ce3106..b176e5d 100644
--- a/sdnr/wt/odlux/apps/configurationApp/src/components/ifWhenTextInput.tsx
+++ b/sdnr/wt/odlux/apps/configurationApp/src/components/ifWhenTextInput.tsx
@@ -16,82 +16,86 @@
* ============LICENSE_END==========================================================================
*/
-import { ViewElementBase } from "models/uiModels";
-import {
- TextField,
- InputAdornment,
- Input,
- Tooltip,
- Divider,
- IconButton,
- InputBase,
- Paper,
- Theme,
- FormControl,
- InputLabel,
- FormHelperText,
-} from "@mui/material";
+import React from 'react';
+import InputAdornment from '@mui/material/InputAdornment';
+import Input, { InputProps } from '@mui/material/Input';
+import Tooltip from '@mui/material/Tooltip';
+import FormControl from '@mui/material/FormControl';
+import InputLabel from '@mui/material/InputLabel';
+import FormHelperText from '@mui/material/FormHelperText';
+
import makeStyles from '@mui/styles/makeStyles';
import createStyles from '@mui/styles/createStyles';
-import * as React from 'react';
-import { faAdjust } from "@fortawesome/free-solid-svg-icons";
-import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
-import { InputProps } from "@mui/material/Input";
-const useStyles = makeStyles((theme: Theme) =>
+import { faAdjust } from '@fortawesome/free-solid-svg-icons/faAdjust';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+
+import { ViewElementBase } from '../models/uiModels';
+
+const useStyles = makeStyles(() =>
createStyles({
iconDark: {
- color: '#ff8800'
+ color: '#ff8800',
},
iconLight: {
- color: 'orange'
+ color: 'orange',
},
padding: {
paddingLeft: 10,
- paddingRight: 10
+ paddingRight: 10,
},
}),
);
-type IfwhenProps = InputProps & {
+type IfWhenProps = InputProps & {
label: string;
element: ViewElementBase;
helperText: string;
error: boolean;
- onChangeTooltipVisuability(value: boolean): void;
+ onChangeTooltipVisibility(value: boolean): void;
};
-export const IfWhenTextInput = (props: IfwhenProps) => {
+export const IfWhenTextInput = (props: IfWhenProps) => {
- const { element, onChangeTooltipVisuability: toogleTooltip, id, label, helperText: errorText, error, style, ...otherProps } = props;
+ const { element, id, label, helperText: errorText, error, style, ...otherProps } = props;
const classes = useStyles();
-
const ifFeature = element.ifFeature
? (
- <Tooltip disableInteractive onMouseMove={e => props.onChangeTooltipVisuability(false)} onMouseOut={e => props.onChangeTooltipVisuability(true)} title={element.ifFeature}>
+ <Tooltip
+ title={element.ifFeature}
+ disableInteractive
+ onMouseMove={() => props.onChangeTooltipVisibility(false)}
+ onMouseOut={() => props.onChangeTooltipVisibility(true)}
+ >
<InputAdornment position="start">
<FontAwesomeIcon icon={faAdjust} className={classes.iconDark} />
</InputAdornment>
</Tooltip>
- )
+ )
: null;
const whenFeature = element.when
? (
- <Tooltip disableInteractive className={classes.padding} onMouseMove={() => props.onChangeTooltipVisuability(false)} onMouseOut={() => props.onChangeTooltipVisuability(true)} title={element.when}>
+ <Tooltip
+ title={element.when}
+ disableInteractive
+ className={classes.padding}
+ onMouseMove={() => props.onChangeTooltipVisibility(false)}
+ onMouseOut={() => props.onChangeTooltipVisibility(true)}
+ >
<InputAdornment className={classes.padding} position="end">
<FontAwesomeIcon icon={faAdjust} className={classes.iconLight}/>
</InputAdornment>
</Tooltip>
- )
+ )
: null;
return (
<FormControl variant="standard" error={error} style={style}>
<InputLabel htmlFor={id} >{label}</InputLabel>
- <Input id={id} inputProps={{'aria-label': label+'-input'}} endAdornment={<div>{ifFeature}{whenFeature}</div>} {...otherProps} />
+ <Input id={id} inputProps={{ 'aria-label': label + '-input' }} endAdornment={<div>{ifFeature}{whenFeature}</div>} {...otherProps} />
<FormHelperText>{errorText}</FormHelperText>
</FormControl>
);
-}
\ No newline at end of file
+};
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementBoolean.tsx b/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementBoolean.tsx
index 81c9d6d..56fb93c 100644
--- a/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementBoolean.tsx
+++ b/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementBoolean.tsx
@@ -16,43 +16,48 @@
* ============LICENSE_END==========================================================================
*/
-import * as React from "react"
-import { MenuItem, FormHelperText, Select, FormControl, InputLabel } from "@mui/material";
+import React from 'react';
-import { ViewElementBoolean } from "../models/uiModels";
-import { BaseProps } from "./baseProps";
+import MenuItem from '@mui/material/MenuItem';
+import FormHelperText from '@mui/material/FormHelperText';
+import Select from '@mui/material/Select';
+import FormControl from '@mui/material/FormControl';
+import InputLabel from '@mui/material/InputLabel';
+
+import { ViewElementBoolean } from '../models/uiModels';
+import { BaseProps } from './baseProps';
type BooleanInputProps = BaseProps<boolean>;
export const UiElementBoolean = (props: BooleanInputProps) => {
- const element = props.value as ViewElementBoolean;
+ const element = props.value as ViewElementBoolean;
- const value = String(props.inputValue).toLowerCase();
- const mandetoryError = element.mandatory && value !== 'true' && value !== 'false';
+ const value = String(props.inputValue).toLowerCase();
+ const mandatoryError = element.mandatory && value !== 'true' && value !== 'false';
- return (!props.readOnly || element.id != null
- ? (<FormControl variant="standard" style={{ width: 485, marginLeft: 20, marginRight: 20 }}>
+ return (!props.readOnly || element.id != null
+ ? (<FormControl variant="standard" style={{ width: 485, marginLeft: 20, marginRight: 20 }}>
<InputLabel htmlFor={`select-${element.id}`} >{element.label}</InputLabel>
<Select variant="standard"
- aria-label={element.label+'-selection'}
+ aria-label={element.label + '-selection'}
required={!!element.mandatory}
- error={mandetoryError}
- onChange={(e) => { props.onChange(e.target.value === 'true') }}
+ error={mandatoryError}
+ onChange={(e) => { props.onChange(e.target.value === 'true'); }}
readOnly={props.readOnly}
disabled={props.disabled}
value={value}
inputProps={{
- name: element.id,
- id: `select-${element.id}`,
+ name: element.id,
+ id: `select-${element.id}`,
}}
>
<MenuItem value={'true'} aria-label="true">{element.trueValue || 'True'}</MenuItem>
<MenuItem value={'false'} aria-label="false">{element.falseValue || 'False'}</MenuItem>
</Select>
- <FormHelperText>{mandetoryError ? "Value is mandetory" : ""}</FormHelperText>
+ <FormHelperText>{mandatoryError ? 'Value is mandatory' : ''}</FormHelperText>
</FormControl>)
- : null
- );
-}
\ No newline at end of file
+ : null
+ );
+};
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementLeafList.tsx b/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementLeafList.tsx
index 5937ed7..669ddff 100644
--- a/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementLeafList.tsx
+++ b/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementLeafList.tsx
@@ -16,19 +16,23 @@
* ============LICENSE_END==========================================================================
*/
-import * as React from "react"
-import { FormControl, InputLabel, Paper, Chip, FormHelperText, Dialog, DialogTitle, DialogContentText, DialogActions, Button, DialogContent } from "@mui/material";
+import React from 'react';
+import FormControl from '@mui/material/FormControl';
+import InputLabel from '@mui/material/InputLabel';
+import Chip from '@mui/material/Chip';
+import Dialog from '@mui/material/Dialog';
+import DialogTitle from '@mui/material/DialogTitle';
+import DialogContent from '@mui/material/DialogContent';
+import DialogActions from '@mui/material/DialogActions';
+import Button from '@mui/material/Button';
+
import makeStyles from '@mui/styles/makeStyles';
import AddIcon from '@mui/icons-material/Add';
import { Theme } from '@mui/material/styles';
-import { ViewElement } from "../models/uiModels";
+import { ViewElement } from '../models/uiModels';
-import { BaseProps } from "./baseProps";
-
-type LeafListProps = BaseProps<any []> & {
- getEditorForViewElement: (uiElement: ViewElement) => (null | React.ComponentType<BaseProps<any>>)
-};
+import { BaseProps } from './baseProps';
const useStyles = makeStyles((theme: Theme) => {
const light = theme.palette.mode === 'light';
@@ -50,93 +54,93 @@
margin: theme.spacing(0.5),
},
underline: {
- '&:after': {
- borderBottom: `2px solid ${theme.palette.primary.main}`,
- left: 0,
- bottom: 0,
- // Doing the other way around crash on IE 11 "''" https://github.com/cssinjs/jss/issues/242
- content: '""',
- position: 'absolute',
- right: 0,
- transform: 'scaleX(0)',
- transition: theme.transitions.create('transform', {
- duration: theme.transitions.duration.shorter,
- easing: theme.transitions.easing.easeOut,
- }),
- pointerEvents: 'none', // Transparent to the hover style.
- },
- '&.Mui-focused:after': {
- transform: 'scaleX(1)',
- },
- '&.Mui-error:after': {
- borderBottomColor: theme.palette.error.main,
- transform: 'scaleX(1)', // error is always underlined in red
- },
- '&:before': {
+ '&:after': {
+ borderBottom: `2px solid ${theme.palette.primary.main}`,
+ left: 0,
+ bottom: 0,
+ // Doing the other way around crash on IE 11 "''" https://github.com/cssinjs/jss/issues/242
+ content: '""',
+ position: 'absolute',
+ right: 0,
+ transform: 'scaleX(0)',
+ transition: theme.transitions.create('transform', {
+ duration: theme.transitions.duration.shorter,
+ easing: theme.transitions.easing.easeOut,
+ }),
+ pointerEvents: 'none', // Transparent to the hover style.
+ },
+ '&.Mui-focused:after': {
+ transform: 'scaleX(1)',
+ },
+ '&.Mui-error:after': {
+ borderBottomColor: theme.palette.error.main,
+ transform: 'scaleX(1)', // error is always underlined in red
+ },
+ '&:before': {
+ borderBottom: `1px solid ${bottomLineColor}`,
+ left: 0,
+ bottom: 0,
+ // Doing the other way around crash on IE 11 "''" https://github.com/cssinjs/jss/issues/242
+ content: '"\\00a0"',
+ position: 'absolute',
+ right: 0,
+ transition: theme.transitions.create('border-bottom-color', {
+ duration: theme.transitions.duration.shorter,
+ }),
+ pointerEvents: 'none', // Transparent to the hover style.
+ },
+ '&:hover:not($disabled):before': {
+ borderBottom: `2px solid ${theme.palette.text.primary}`,
+ // Reset on touch devices, it doesn't add specificity
+ // eslint-disable-next-line @typescript-eslint/naming-convention
+ '@media (hover: none)': {
borderBottom: `1px solid ${bottomLineColor}`,
- left: 0,
- bottom: 0,
- // Doing the other way around crash on IE 11 "''" https://github.com/cssinjs/jss/issues/242
- content: '"\\00a0"',
- position: 'absolute',
- right: 0,
- transition: theme.transitions.create('border-bottom-color', {
- duration: theme.transitions.duration.shorter,
- }),
- pointerEvents: 'none', // Transparent to the hover style.
- },
- '&:hover:not($disabled):before': {
- borderBottom: `2px solid ${theme.palette.text.primary}`,
- // Reset on touch devices, it doesn't add specificity
- '@media (hover: none)': {
- borderBottom: `1px solid ${bottomLineColor}`,
- },
- },
- '&.Mui-disabled:before': {
- borderBottomStyle: 'dotted',
},
},
- })
+ '&.Mui-disabled:before': {
+ borderBottomStyle: 'dotted',
+ },
+ },
+ });
});
+type LeafListProps = BaseProps<any []> & {
+ getEditorForViewElement: (uiElement: ViewElement) => (null | React.ComponentType<BaseProps<any>>);
+};
+
export const UiElementLeafList = (props: LeafListProps) => {
const { value: element, inputValue, onChange } = props;
const classes = useStyles();
const [open, setOpen] = React.useState(false);
- const [editorValue, setEditorValue] = React.useState("");
+ const [editorValue, setEditorValue] = React.useState('');
const [editorValueIndex, setEditorValueIndex] = React.useState(-1);
-
- const handleClickOpen = () => {
- setOpen(true);
- };
-
const handleClose = () => {
setOpen(false);
};
const onApplyButton = () => {
- if (editorValue != null && editorValue != "" && editorValueIndex < 0) {
- props.onChange([
- ...inputValue,
- editorValue,
- ]);
- } else if (editorValue != null && editorValue != "") {
- props.onChange([
- ...inputValue.slice(0, editorValueIndex),
- editorValue,
- ...inputValue.slice(editorValueIndex+1),
- ]);
- }
- setOpen(false);
+ if (editorValue != null && editorValue != '' && editorValueIndex < 0) {
+ props.onChange([
+ ...inputValue,
+ editorValue,
+ ]);
+ } else if (editorValue != null && editorValue != '') {
+ props.onChange([
+ ...inputValue.slice(0, editorValueIndex),
+ editorValue,
+ ...inputValue.slice(editorValueIndex + 1),
+ ]);
+ }
+ setOpen(false);
};
const onDelete = (index : number) => {
const newValue : any[] = [
...inputValue.slice(0, index),
- ...inputValue.slice(index+1),
+ ...inputValue.slice(index + 1),
];
onChange(newValue);
};
@@ -151,15 +155,15 @@
{ !props.readOnly ? <li>
<Chip
icon={<AddIcon />}
- label={"Add"}
+ label={'Add'}
className={classes.chip}
size="small"
color="secondary"
onClick={ () => {
setOpen(true);
- setEditorValue("");
+ setEditorValue('');
setEditorValueIndex(-1);
- }
+ }
}
/>
</li> : null }
@@ -172,24 +176,24 @@
label={String(val)}
onDelete={ !props.readOnly ? () => { onDelete(ind); } : undefined }
onClick={ !props.readOnly ? () => {
- setOpen(true);
- setEditorValue(val);
- setEditorValueIndex(ind);
- } : undefined
+ setOpen(true);
+ setEditorValue(val);
+ setEditorValueIndex(ind);
+ } : undefined
}
/>
</li>
- ))
+ ))
}
</ul>
{/* <FormHelperText>{ "Value is mandetory"}</FormHelperText> */}
</FormControl>
<Dialog open={open} onClose={handleClose} aria-labelledby="form-dialog-title">
- <DialogTitle id="form-dialog-title">{editorValueIndex < 0 ? "Add new value" : "Edit value" } </DialogTitle>
+ <DialogTitle id="form-dialog-title">{editorValueIndex < 0 ? 'Add new value' : 'Edit value' } </DialogTitle>
<DialogContent>
{ ValueEditor && <ValueEditor
inputValue={ editorValue }
- value={{ ...element, isList: false}}
+ value={{ ...element, isList: false }}
disabled={false}
readOnly={props.readOnly}
onChange={ setEditorValue }
@@ -197,7 +201,7 @@
</DialogContent>
<DialogActions>
<Button color="inherit" onClick={ handleClose }> Cancel </Button>
- <Button disabled={editorValue == null || editorValue === "" } onClick={ onApplyButton } color="secondary"> {editorValueIndex < 0 ? "Add" : "Apply"} </Button>
+ <Button disabled={editorValue == null || editorValue === '' } onClick={ onApplyButton } color="secondary"> {editorValueIndex < 0 ? 'Add' : 'Apply'} </Button>
</DialogActions>
</Dialog>
</>
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementNumber.tsx b/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementNumber.tsx
index 76c11f6..b034278 100644
--- a/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementNumber.tsx
+++ b/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementNumber.tsx
@@ -16,14 +16,14 @@
* ============LICENSE_END==========================================================================
*/
-import { ViewElementNumber } from "models/uiModels";
+import React from 'react';
+import { ViewElementNumber } from "../models/uiModels";
import { Tooltip, InputAdornment } from "@mui/material";
-import * as React from 'react';
import { BaseProps } from "./baseProps";
import { IfWhenTextInput } from "./ifWhenTextInput";
-import { checkRange } from "./verifyer";
+import { checkRange } from "../utilities/verifyer";
-type numberInputProps = BaseProps<any>;
+type numberInputProps = BaseProps<number>;
export const UiElementNumber = (props: numberInputProps) => {
@@ -49,12 +49,12 @@
setError(true);
setHelperText("Input is not a number.");
}
- props.onChange(data);
+ props.onChange(num);
}
return (
<Tooltip disableInteractive title={isTooltipVisible ? element.description || '' : ''}>
- <IfWhenTextInput element={element} onChangeTooltipVisuability={setTooltipVisibility}
+ <IfWhenTextInput element={element} onChangeTooltipVisibility={setTooltipVisibility}
spellCheck={false} autoFocus margin="dense"
id={element.id} label={element.label} type="text" value={props.inputValue}
style={{ width: 485, marginLeft: 20, marginRight: 20 }}
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementReference.tsx b/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementReference.tsx
index 9e863f0..e3bb8f0 100644
--- a/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementReference.tsx
+++ b/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementReference.tsx
@@ -17,16 +17,16 @@
*/
import React, { useState } from 'react';
-import { Tooltip, Button, FormControl, Theme } from '@mui/material';
+import { Tooltip, Button, FormControl } from '@mui/material';
import createStyles from '@mui/styles/createStyles';
import makeStyles from '@mui/styles/makeStyles';
import { ViewElement } from '../models/uiModels';
-const useStyles = makeStyles((theme: Theme) => createStyles({
+const useStyles = makeStyles(() => createStyles({
button: {
- "justifyContent": "left"
+ 'justifyContent': 'left',
},
}));
@@ -37,16 +37,31 @@
};
export const UIElementReference: React.FC<UIElementReferenceProps> = (props) => {
- const classes = useStyles();
- const [disabled, setDisabled] = useState(true);
const { element } = props;
+ const [disabled, setDisabled] = useState(true);
+ const classes = useStyles();
return (
- <FormControl variant="standard" key={element.id} style={{ width: 485, marginLeft: 20, marginRight: 20 }} onMouseDown={(ev) => { ev.preventDefault(); ev.stopPropagation(); ev.button === 1 && setDisabled(!disabled) }}>
+ <FormControl
+ variant="standard"
+ key={element.id}
+ style={{ width: 485, marginLeft: 20, marginRight: 20 }}
+ onMouseDown={(ev) => {
+ ev.preventDefault();
+ ev.stopPropagation();
+ if (ev.button === 1) {
+ setDisabled(!disabled);
+ }
+ }}>
<Tooltip disableInteractive title={element.description || element.path || ''}>
- <Button className={classes.button} aria-label={element.label+'-button'} color="secondary" disabled={props.disabled && disabled} onClick={() => {
- props.onOpenReference(element);
- }} >{`${element.label}`}</Button>
+ <Button
+ className={classes.button}
+ aria-label={element.label + '-button'}
+ color="secondary"
+ disabled={props.disabled && disabled}
+ onClick={() => {
+ props.onOpenReference(element);
+ }} >{`${element.label}`}</Button>
</Tooltip>
</FormControl>
);
-}
\ No newline at end of file
+};
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementSelection.tsx b/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementSelection.tsx
index fdf8034..ebd04da 100644
--- a/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementSelection.tsx
+++ b/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementSelection.tsx
@@ -16,45 +16,54 @@
* ============LICENSE_END==========================================================================
*/
-import * as React from 'react';
+import React from 'react';
import { BaseProps } from './baseProps';
-import { ViewElementSelection } from '../models/uiModels'
+import { ViewElementSelection } from '../models/uiModels';
import { FormControl, InputLabel, Select, FormHelperText, MenuItem, Tooltip } from '@mui/material';
type selectionProps = BaseProps;
export const UiElementSelection = (props: selectionProps) => {
- const element = props.value as ViewElementSelection;
+ const element = props.value as ViewElementSelection;
- let error = "";
- const value = String(props.inputValue);
- if (element.mandatory && Boolean(!value)) {
- error = "Error";
- }
+ let error = '';
+ const value = String(props.inputValue);
+ if (element.mandatory && Boolean(!value)) {
+ error = 'Error';
+ }
- return (props.readOnly || props.inputValue != null
- ? (<FormControl variant="standard" style={{ width: 485, marginLeft: 20, marginRight: 20 }}>
- <InputLabel htmlFor={`select-${element.id}`} >{element.label}</InputLabel>
+ return (props.readOnly || props.inputValue != null
+ ? (<FormControl variant="standard" style={{ width: 485, marginLeft: 20, marginRight: 20 }}>
+ <InputLabel htmlFor={`select-${element.id}`} >{element.label}</InputLabel>
<Select variant="standard"
required={!!element.mandatory}
error={!!error}
- onChange={(e) => { props.onChange(e.target.value as string) }}
+ onChange={(e) => { props.onChange(e.target.value as string); }}
readOnly={props.readOnly}
disabled={props.disabled}
value={value.toString()}
- aria-label={element.label+'-selection'}
+ aria-label={element.label + '-selection'}
inputProps={{
- name: element.id,
- id: `select-${element.id}`,
+ name: element.id,
+ id: `select-${element.id}`,
}}
>
- {element.options.map(option => (
- <MenuItem key={option.key} value={option.key} aria-label={option.key}><Tooltip disableInteractive title={option.description || '' }><div style={{width:"100%"}}>{option.key}</div></Tooltip></MenuItem>
- ))}
+ {element.options.map(option => (
+ <MenuItem
+ key={option.key}
+ value={option.key}
+ aria-label={option.key}>
+ <Tooltip disableInteractive title={option.description || ''}>
+ <div style={{ width: '100%' }}>
+ {option.key}
+ </div>
+ </Tooltip>
+ </MenuItem>
+ ))}
</Select>
<FormHelperText>{error}</FormHelperText>
</FormControl>)
- : null
- );
-}
\ No newline at end of file
+ : null
+ );
+};
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementString.tsx b/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementString.tsx
index 4908c41..8381d99 100644
--- a/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementString.tsx
+++ b/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementString.tsx
@@ -21,7 +21,7 @@
import { ViewElementString } from "../models/uiModels";
import { BaseProps } from "./baseProps";
import { IfWhenTextInput } from "./ifWhenTextInput";
-import { checkRange, checkPattern } from "./verifyer";
+import { checkRange, checkPattern } from "../utilities/verifyer";
type stringEntryProps = BaseProps ;
@@ -69,7 +69,7 @@
return (
<Tooltip disableInteractive title={isTooltipVisible ? element.description || '' : ''}>
- <IfWhenTextInput element={element} onChangeTooltipVisuability={setTooltipVisibility}
+ <IfWhenTextInput element={element} onChangeTooltipVisibility={setTooltipVisibility}
spellCheck={false} autoFocus margin="dense"
id={element.id} label={props?.isKey ? "🔑 " + element.label : element.label} type="text" value={props.inputValue}
style={{ width: 485, marginLeft: 20, marginRight: 20 }}
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementUnion.tsx b/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementUnion.tsx
index 67cd998..8d232f5 100644
--- a/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementUnion.tsx
+++ b/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementUnion.tsx
@@ -21,7 +21,7 @@
import { Tooltip } from '@mui/material';
import { IfWhenTextInput } from './ifWhenTextInput';
import { ViewElementUnion, isViewElementString, isViewElementNumber, isViewElementObject, ViewElementNumber } from '../models/uiModels';
-import { checkRange, checkPattern } from './verifyer';
+import { checkRange, checkPattern } from '../utilities/verifyer';
type UiElementUnionProps = { isKey: boolean } & BaseProps;
@@ -77,7 +77,7 @@
};
return <Tooltip disableInteractive title={isTooltipVisible ? element.description || '' : ''}>
- <IfWhenTextInput element={element} onChangeTooltipVisuability={setTooltipVisibility}
+ <IfWhenTextInput element={element} onChangeTooltipVisibility={setTooltipVisibility}
spellCheck={false} autoFocus margin="dense"
id={element.id} label={props.isKey ? "🔑 " + element.label : element.label} type="text" value={props.inputValue}
onChange={(e: any) => { verifyValues(e.target.value) }}
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/components/verifyer.ts b/sdnr/wt/odlux/apps/configurationApp/src/components/verifyer.ts
deleted file mode 100644
index 0a95cd8..0000000
--- a/sdnr/wt/odlux/apps/configurationApp/src/components/verifyer.ts
+++ /dev/null
@@ -1,280 +0,0 @@
-/**
- * ============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 { Expression, YangRange, Operator, ViewElementNumber, ViewElementString, isViewElementNumber, isViewElementString } from '../models/uiModels';
-
-export type validated = { isValid: boolean, error?: string }
-
-export type validatedRange = { isValid: boolean, error?: string };
-
-
-const rangeErrorStartNumber = "The entered number must be";
-const rangeErrorinnerMinTextNumber = "greater or equals than";
-const rangeErrorinnerMaxTextNumber = "less or equals than";
-const rangeErrorEndTextNumber = ".";
-
-const rangeErrorStartString = "The entered text must have";
-const rangeErrorinnerMinTextString = "no more than";
-const rangeErrorinnerMaxTextString = "less than";
-const rangeErrorEndTextString = " characters.";
-
-let errorMessageStart = "";
-let errorMessageMiddleMinPart = "";
-let errorMessageMiddleMaxPart = "";
-let errorMessageEnd = "";
-
-
-export function checkRange(element: ViewElementNumber | ViewElementString, data: number): string {
-
- //let test1: Operator<YangRange> = { operation: "AND", arguments: [{ operation: "OR", arguments: [{ operation: "AND", arguments: [new RegExp("^z", "g"), new RegExp("z$", "g")] }, new RegExp("^abc", "g"), new RegExp("^123", "g")] }, new RegExp("^def", "g"), new RegExp("^ppp", "g"), new RegExp("^aaa", "g")] };
- //let test1: Operator<YangRange> = { operation: "AND", arguments: [{ operation: "OR", arguments: [{ operation: "AND", arguments: [{ min: -5, max: 10 }, { min: -30, max: -20 }] }, { min: 8, max: 15 }] }] };
- //let test1: Operator<YangRange> = { operation: "OR", arguments: [{ operation: "OR", arguments: [{ min: -50, max: -40 }] }, { min: -30, max: -20 }, { min: 8, max: 15 }] };
- //let test1: Operator<YangRange> = { operation: "AND", arguments: [{ operation: "OR", arguments: [{ min: -5, max: 10 }, { min: 17, max: 23 }] }] };
-
- const number = data;
-
- var expression = undefined;
-
- if (isViewElementString(element)) {
- expression = element.length;
-
- errorMessageStart = rangeErrorStartString;
- errorMessageMiddleMaxPart = rangeErrorinnerMaxTextString;
- errorMessageMiddleMinPart = rangeErrorinnerMinTextString;
- errorMessageEnd = rangeErrorEndTextString;
-
- } else if (isViewElementNumber(element)) {
- expression = element.range;
-
- errorMessageStart = rangeErrorStartNumber;
- errorMessageMiddleMaxPart = rangeErrorinnerMaxTextNumber;
- errorMessageMiddleMinPart = rangeErrorinnerMinTextNumber;
- errorMessageEnd = rangeErrorEndTextNumber;
- }
-
- if (expression) {
- if (isYangOperator(expression)) {
-
- const errorMessage = getRangeErrorMessages(expression, data);
- return errorMessage;
-
- } else
- if (isYangRange(expression)) {
-
- if (!isNaN(expression.min)) {
- if (number < expression.min) {
- return `${errorMessageStart} ${errorMessageMiddleMinPart} ${expression.min}${errorMessageEnd}`;
- }
- }
-
- if (!isNaN(expression.max)) {
- if (number > expression.max) {
- return `${errorMessageStart} ${errorMessageMiddleMaxPart} ${expression.max}${errorMessageEnd}`;
- }
- }
- }
- }
-
-
- return "";
-}
-
-function isYangRange(val: YangRange | Operator<YangRange>): val is YangRange {
- return (val as YangRange).min !== undefined;
-}
-
-function isYangOperator(val: YangRange | Operator<YangRange>): val is Operator<YangRange> {
- return (val as Operator<YangRange>).operation !== undefined;
-}
-
-function getRangeErrorMessagesRecursively(value: Operator<YangRange>, data: number): string[] {
- let currentItteration: string[] = [];
- console.log(value);
-
- // itterate over all elements
- for (let i = 0; i < value.arguments.length; i++) {
- const element = value.arguments[i];
-
- let min = undefined;
- let max = undefined;
-
- let isNumberCorrect = false;
-
- if (isYangRange(element)) {
-
- //check found min values
- if (!isNaN(element.min)) {
- if (data < element.min) {
- min = element.min;
- } else {
- isNumberCorrect = true;
- }
- }
-
- // check found max values
- if (!isNaN(element.max)) {
- if (data > element.max) {
- max = element.max;
- } else {
- isNumberCorrect = true;
- }
- }
-
- // construct error messages
- if (min != undefined) {
- currentItteration.push(`${value.operation.toLocaleLowerCase()} ${errorMessageMiddleMinPart} ${min}`);
- } else if (max != undefined) {
- currentItteration.push(`${value.operation.toLocaleLowerCase()} ${errorMessageMiddleMaxPart} ${max}`);
-
- }
-
- } else if (isYangOperator(element)) {
-
- //get errormessages from expression
- const result = getRangeErrorMessagesRecursively(element, data);
- if (result.length === 0) {
- isNumberCorrect = true;
- }
- currentItteration = currentItteration.concat(result);
- }
-
- // if its an OR operation, the number has been checked and min/max are empty (thus not violated)
- // delete everything found (because at least one found is correct, therefore all are correct) and break from loop
- if (min === undefined && max === undefined && isNumberCorrect && value.operation === "OR") {
-
- currentItteration.splice(0, currentItteration.length);
- break;
- }
- }
-
- return currentItteration;
-}
-
-function getRangeErrorMessages(value: Operator<YangRange>, data: number): string {
-
- const currentItteration = getRangeErrorMessagesRecursively(value, data);
-
- // build complete error message from found parts
- let errormessage = "";
- if (currentItteration.length > 1) {
-
- currentItteration.forEach((element, index) => {
- if (index === 0) {
- errormessage = createStartMessage(element);
- } else if (index === currentItteration.length - 1) {
- errormessage += ` ${element}${errorMessageEnd}`;
- } else {
- errormessage += `, ${element}`
- }
- });
- } else if (currentItteration.length == 1) {
- errormessage = `${createStartMessage(currentItteration[0])}${errorMessageEnd}`;
- }
-
- return errormessage;
-}
-
-function createStartMessage(element: string) {
-
- //remove leading or or and from text
- if (element.startsWith("and"))
- element = element.replace("and", "");
- else if (element.startsWith("or"))
- element = element.replace("or", "");
-
- return `${errorMessageStart} ${element}`;
-}
-
-export const checkPattern = (expression: RegExp | Operator<RegExp> | undefined, data: string): validated => {
-
- if (expression) {
- if (isRegExp(expression)) {
- const isValid = expression.test(data);
- if (!isValid)
- return { isValid: isValid, error: "The input is in a wrong format." };
-
- } else if (isRegExpOperator(expression)) {
- const result = isPatternValid(expression, data);
-
- if (!result) {
- return { isValid: false, error: "The input is in a wrong format." };
- }
- }
- }
-
- return { isValid: true }
-}
-
-function getRegexRecursively(value: Operator<RegExp>, data: string): boolean[] {
- let currentItteration: boolean[] = [];
- for (let i = 0; i < value.arguments.length; i++) {
- const element = value.arguments[i];
- if (isRegExp(element)) {
- // if regex is found, add it to list
- currentItteration.push(element.test(data))
- } else if (isRegExpOperator(element)) {
- //if RegexExpression is found, try to get regex from it
- currentItteration = currentItteration.concat(getRegexRecursively(element, data));
- }
- }
-
- if (value.operation === "OR") {
- // if one is true, all are true, all found items can be discarded
- let result = currentItteration.find(element => element);
- if (result) {
- return [];
- }
- }
- return currentItteration;
-}
-
-function isPatternValid(value: Operator<RegExp>, data: string): boolean {
-
-
- // get all regex
- const result = getRegexRecursively(value, data);
- console.log(value);
-
-
- if (value.operation === "AND") {
- // if AND operation is executed...
- // no element can be false
- const check = result.find(element => element !== true);
- if (check)
- return false;
- else
- return true;
- } else {
- // if OR operation is executed...
- // ... just one element must be true
- const check = result.find(element => element === true);
- if (check)
- return true;
- else
- return false;
-
- }
-}
-
-function isRegExp(val: RegExp | Operator<RegExp>): val is RegExp {
- return (val as RegExp).source !== undefined;
-}
-
-function isRegExpOperator(val: RegExp | Operator<RegExp>): val is Operator<RegExp> {
- return (val as Operator<RegExp>).operation !== undefined;
-}
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/handlers/configurationAppRootHandler.ts b/sdnr/wt/odlux/apps/configurationApp/src/handlers/configurationAppRootHandler.ts
index 1af699a..9cbd916 100644
--- a/sdnr/wt/odlux/apps/configurationApp/src/handlers/configurationAppRootHandler.ts
+++ b/sdnr/wt/odlux/apps/configurationApp/src/handlers/configurationAppRootHandler.ts
@@ -19,9 +19,9 @@
import { combineActionHandler } from '../../../../framework/src/flux/middleware';
import { IConnectedNetworkElementsState, connectedNetworkElementsActionHandler } from './connectedNetworkElementsHandler';
-import { IDeviceDescriptionState, deviceDescriptionHandler } from "./deviceDescriptionHandler";
-import { IViewDescriptionState, viewDescriptionHandler } from "./viewDescriptionHandler";
-import { IValueSelectorState, valueSelectorHandler } from "./valueSelectorHandler";
+import { IDeviceDescriptionState, deviceDescriptionHandler } from './deviceDescriptionHandler';
+import { IViewDescriptionState, viewDescriptionHandler } from './viewDescriptionHandler';
+import { IValueSelectorState, valueSelectorHandler } from './valueSelectorHandler';
interface IConfigurationAppStoreState {
connectedNetworkElements: IConnectedNetworkElementsState; // used for ne selection
@@ -32,7 +32,7 @@
declare module '../../../../framework/src/store/applicationStore' {
interface IApplicationStoreState {
- configuration: IConfigurationAppStoreState,
+ configuration: IConfigurationAppStoreState;
}
}
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/handlers/connectedNetworkElementsHandler.ts b/sdnr/wt/odlux/apps/configurationApp/src/handlers/connectedNetworkElementsHandler.ts
index 8ca8fdf..d2863dd 100644
--- a/sdnr/wt/odlux/apps/configurationApp/src/handlers/connectedNetworkElementsHandler.ts
+++ b/sdnr/wt/odlux/apps/configurationApp/src/handlers/connectedNetworkElementsHandler.ts
@@ -25,8 +25,8 @@
export interface IConnectedNetworkElementsState extends IExternalTableState<NetworkElementConnection> { }
-// create eleactic search material data fetch handler
-const connectedNetworkElementsSearchHandler = createSearchDataHandler<NetworkElementConnection>('network-element-connection', false, { status: "Connected" });
+// create elastic search material data fetch handler
+const connectedNetworkElementsSearchHandler = createSearchDataHandler<NetworkElementConnection>('network-element-connection', false, { status: 'Connected' });
export const {
actionHandler: connectedNetworkElementsActionHandler,
@@ -41,5 +41,5 @@
const neUrl = restService.getNetworkElementUri(ne.id);
const policy = getAccessPolicyByUrl(neUrl);
return !(policy.GET && policy.POST);
- }
+ },
);
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/handlers/deviceDescriptionHandler.ts b/sdnr/wt/odlux/apps/configurationApp/src/handlers/deviceDescriptionHandler.ts
index 408399d..cd01b09 100644
--- a/sdnr/wt/odlux/apps/configurationApp/src/handlers/deviceDescriptionHandler.ts
+++ b/sdnr/wt/odlux/apps/configurationApp/src/handlers/deviceDescriptionHandler.ts
@@ -16,23 +16,23 @@
* ============LICENSE_END==========================================================================
*/
-import { Module } from "../models/yang";
-import { ViewSpecification } from "../models/uiModels";
-import { IActionHandler } from "../../../../framework/src/flux/action";
-import { UpdateDeviceDescription } from "../actions/deviceActions";
+import { Module } from '../models/yang';
+import { ViewSpecification } from '../models/uiModels';
+import { IActionHandler } from '../../../../framework/src/flux/action';
+import { UpdateDeviceDescription } from '../actions/deviceActions';
export interface IDeviceDescriptionState {
- nodeId: string,
+ nodeId: string;
modules: {
- [name: string]: Module
- },
- views: ViewSpecification[],
+ [name: string]: Module;
+ };
+ views: ViewSpecification[];
}
const deviceDescriptionStateInit: IDeviceDescriptionState = {
- nodeId: "",
+ nodeId: '',
modules: {},
- views: []
+ views: [],
};
export const deviceDescriptionHandler: IActionHandler<IDeviceDescriptionState> = (state = deviceDescriptionStateInit, action) => {
@@ -41,7 +41,7 @@
...state,
nodeId: action.nodeId,
modules: action.modules,
- views: action.views
+ views: action.views,
};
}
return state;
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/handlers/valueSelectorHandler.ts b/sdnr/wt/odlux/apps/configurationApp/src/handlers/valueSelectorHandler.ts
index 5b2d55e..70d5eb2 100644
--- a/sdnr/wt/odlux/apps/configurationApp/src/handlers/valueSelectorHandler.ts
+++ b/sdnr/wt/odlux/apps/configurationApp/src/handlers/valueSelectorHandler.ts
@@ -16,9 +16,9 @@
* ============LICENSE_END==========================================================================
*/
-import { IActionHandler } from "../../../../framework/src/flux/action";
-import { ViewSpecification } from "../models/uiModels";
-import { EnableValueSelector, SetSelectedValue, UpdateDeviceDescription, SetCollectingSelectionData, UpdatViewDescription, UpdatOutputData } from "../actions/deviceActions";
+import { IActionHandler } from '../../../../framework/src/flux/action';
+import { ViewSpecification } from '../models/uiModels';
+import { EnableValueSelector, SetSelectedValue, UpdateDeviceDescription, SetCollectingSelectionData, UpdateViewDescription, UpdateOutputData } from '../actions/deviceActions';
export interface IValueSelectorState {
collectingData: boolean;
@@ -28,13 +28,13 @@
onValueSelected: (value: any) => void;
}
-const nc = (val: React.SyntheticEvent) => { };
+const dummyFunc = () => { };
const valueSelectorStateInit: IValueSelectorState = {
collectingData: false,
keyProperty: undefined,
listSpecification: null,
listData: [],
- onValueSelected: nc,
+ onValueSelected: dummyFunc,
};
export const valueSelectorHandler: IActionHandler<IValueSelectorState> = (state = valueSelectorStateInit, action) => {
@@ -53,22 +53,24 @@
listData: action.listData,
};
} else if (action instanceof SetSelectedValue) {
- state.keyProperty && state.onValueSelected(action.value[state.keyProperty]);
+ if (state.keyProperty) {
+ state.onValueSelected(action.value[state.keyProperty]);
+ }
state = {
...state,
collectingData: false,
keyProperty: undefined,
listSpecification: null,
- onValueSelected: nc,
+ onValueSelected: dummyFunc,
listData: [],
};
- } else if (action instanceof UpdateDeviceDescription || action instanceof UpdatViewDescription || action instanceof UpdatOutputData) {
+ } else if (action instanceof UpdateDeviceDescription || action instanceof UpdateViewDescription || action instanceof UpdateOutputData) {
state = {
...state,
collectingData: false,
keyProperty: undefined,
listSpecification: null,
- onValueSelected: nc,
+ onValueSelected: dummyFunc,
listData: [],
};
}
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/handlers/viewDescriptionHandler.ts b/sdnr/wt/odlux/apps/configurationApp/src/handlers/viewDescriptionHandler.ts
index ff85a97..39b47be 100644
--- a/sdnr/wt/odlux/apps/configurationApp/src/handlers/viewDescriptionHandler.ts
+++ b/sdnr/wt/odlux/apps/configurationApp/src/handlers/viewDescriptionHandler.ts
@@ -16,18 +16,18 @@
* ============LICENSE_END==========================================================================
*/
-import { IActionHandler } from "../../../../framework/src/flux/action";
+import { IActionHandler } from '../../../../framework/src/flux/action';
-import { UpdatViewDescription, UpdatOutputData } from "../actions/deviceActions";
-import { ViewSpecification } from "../models/uiModels";
+import { UpdateViewDescription, UpdateOutputData } from '../actions/deviceActions';
+import { ViewSpecification } from '../models/uiModels';
export enum DisplayModeType {
doNotDisplay = 0,
displayAsObject = 1,
displayAsList = 2,
displayAsRPC = 3,
- displayAsMessage = 4
-};
+ displayAsMessage = 4,
+}
export type DisplaySpecification = {
displayMode: DisplayModeType.doNotDisplay;
@@ -45,13 +45,13 @@
} | {
displayMode: DisplayModeType.displayAsMessage;
renderMessage: string;
-}
+};
export interface IViewDescriptionState {
vPath: string | null;
displaySpecification: DisplaySpecification;
- viewData: any,
- outputData?: any,
+ viewData: any;
+ outputData?: any;
}
const viewDescriptionStateInit: IViewDescriptionState = {
@@ -64,7 +64,7 @@
};
export const viewDescriptionHandler: IActionHandler<IViewDescriptionState> = (state = viewDescriptionStateInit, action) => {
- if (action instanceof UpdatViewDescription) {
+ if (action instanceof UpdateViewDescription) {
state = {
...state,
vPath: action.vPath,
@@ -72,7 +72,7 @@
outputData: undefined,
displaySpecification: action.displaySpecification,
};
- } else if (action instanceof UpdatOutputData) {
+ } else if (action instanceof UpdateOutputData) {
state = {
...state,
outputData: action.outputData,
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/models/networkElementConnection.ts b/sdnr/wt/odlux/apps/configurationApp/src/models/networkElementConnection.ts
index 88f7018..e1ef1ea 100644
--- a/sdnr/wt/odlux/apps/configurationApp/src/models/networkElementConnection.ts
+++ b/sdnr/wt/odlux/apps/configurationApp/src/models/networkElementConnection.ts
@@ -24,7 +24,7 @@
username?: string;
password?: string;
isRequired?: boolean;
- status?: "connected" | "mounted" | "unmounted" | "connecting" | "disconnected" | "idle";
+ status?: 'connected' | 'mounted' | 'unmounted' | 'connecting' | 'disconnected' | 'idle';
coreModelCapability?: string;
deviceType?: string;
nodeDetails?: {
@@ -33,5 +33,5 @@
failureReason: string;
capability: string;
}[];
- }
-}
+ };
+};
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/models/uiModels.ts b/sdnr/wt/odlux/apps/configurationApp/src/models/uiModels.ts
index 29484d8..7d9e63c 100644
--- a/sdnr/wt/odlux/apps/configurationApp/src/models/uiModels.ts
+++ b/sdnr/wt/odlux/apps/configurationApp/src/models/uiModels.ts
@@ -16,128 +16,130 @@
* ============LICENSE_END==========================================================================
*/
+import type { WhenAST } from '../yang/whenParser';
+
export type ViewElementBase = {
- "id": string;
- "label": string;
- "module": string;
- "path": string;
- "config": boolean;
- "ifFeature"?: string;
- "when"?: string;
- "mandatory"?: boolean;
- "description"?: string;
- "isList"?: boolean;
- "default"?: string;
- "status"?: "current" | "deprecated" | "obsolete",
- "reference"?: string, // https://tools.ietf.org/html/rfc7950#section-7.21.4
-}
+ 'id': string;
+ 'label': string;
+ 'module': string;
+ 'path': string;
+ 'config': boolean;
+ 'ifFeature'?: string;
+ 'when'?: WhenAST;
+ 'mandatory'?: boolean;
+ 'description'?: string;
+ 'isList'?: boolean;
+ 'default'?: string;
+ 'status'?: 'current' | 'deprecated' | 'obsolete';
+ 'reference'?: string; // https://tools.ietf.org/html/rfc7950#section-7.21.4
+};
// https://tools.ietf.org/html/rfc7950#section-9.8
export type ViewElementBinary = ViewElementBase & {
- "uiType": "binary";
- "length"?: Expression<YangRange>; // number of octets
-}
+ 'uiType': 'binary';
+ 'length'?: Expression<YangRange>; // number of octets
+};
// https://tools.ietf.org/html/rfc7950#section-9.7.4
export type ViewElementBits = ViewElementBase & {
- "uiType": "bits";
- "flags": {
+ 'uiType': 'bits';
+ 'flags': {
[name: string]: number | undefined; // 0 - 4294967295
- }
-}
+ };
+};
// https://tools.ietf.org/html/rfc7950#section-9
export type ViewElementString = ViewElementBase & {
- "uiType": "string";
- "pattern"?: Expression<RegExp>;
- "length"?: Expression<YangRange>;
- "invertMatch"?: true;
-}
+ 'uiType': 'string';
+ 'pattern'?: Expression<RegExp>;
+ 'length'?: Expression<YangRange>;
+ 'invertMatch'?: true;
+};
// special case derived from
export type ViewElementDate = ViewElementBase & {
- "uiType": "date";
- "pattern"?: Expression<RegExp>;
- "length"?: Expression<YangRange>;
- "invertMatch"?: true;
-}
+ 'uiType': 'date';
+ 'pattern'?: Expression<RegExp>;
+ 'length'?: Expression<YangRange>;
+ 'invertMatch'?: true;
+};
// https://tools.ietf.org/html/rfc7950#section-9.3
export type ViewElementNumber = ViewElementBase & {
- "uiType": "number";
- "min": number;
- "max": number;
- "range"?: Expression<YangRange>;
- "units"?: string;
- "format"?: string;
- "fDigits"?: number;
-}
+ 'uiType': 'number';
+ 'min': number;
+ 'max': number;
+ 'range'?: Expression<YangRange>;
+ 'units'?: string;
+ 'format'?: string;
+ 'fDigits'?: number;
+};
// https://tools.ietf.org/html/rfc7950#section-9.5
export type ViewElementBoolean = ViewElementBase & {
- "uiType": "boolean";
- "trueValue"?: string;
- "falseValue"?: string;
-}
+ 'uiType': 'boolean';
+ 'trueValue'?: string;
+ 'falseValue'?: string;
+};
// https://tools.ietf.org/html/rfc7950#section-9.6.4
export type ViewElementSelection = ViewElementBase & {
- "uiType": "selection";
- "multiSelect"?: boolean
- "options": {
- "key": string;
- "value": string;
- "description"?: string,
- "status"?: "current" | "deprecated" | "obsolete",
- "reference"?: string,
+ 'uiType': 'selection';
+ 'multiSelect'?: boolean;
+ 'options': {
+ 'key': string;
+ 'value': string;
+ 'description'?: string;
+ 'status'?: 'current' | 'deprecated' | 'obsolete';
+ 'reference'?: string;
}[];
-}
+};
// is a list if isList is true ;-)
export type ViewElementObject = ViewElementBase & {
- "uiType": "object";
- "isList"?: false;
- "viewId": string;
-}
+ 'uiType': 'object';
+ 'isList'?: false;
+ 'viewId': string;
+};
// Hint: read only lists do not need a key
export type ViewElementList = (ViewElementBase & {
- "uiType": "object";
- "isList": true;
- "viewId": string;
- "key"?: string;
+ 'uiType': 'object';
+ 'isList': true;
+ 'viewId': string;
+ 'key'?: string;
});
export type ViewElementReference = ViewElementBase & {
- "uiType": "reference";
- "referencePath": string;
- "ref": (currentPath: string) => [ViewElement , string] | undefined;
-}
+ 'uiType': 'reference';
+ 'referencePath': string;
+ 'ref': (currentPath: string) => [ViewElement, string] | undefined;
+};
export type ViewElementUnion = ViewElementBase & {
- "uiType": "union";
- "elements": ViewElement[];
-}
+ 'uiType': 'union';
+ 'elements': ViewElement[];
+};
-export type ViewElementChoiseCase = { id: string, label: string, description?: string, elements: { [name: string]: ViewElement } };
+export type ViewElementChoiceCase = { id: string; label: string; description?: string; elements: { [name: string]: ViewElement } };
-export type ViewElementChoise = ViewElementBase & {
- "uiType": "choise";
- "cases": {
- [name: string]: ViewElementChoiseCase;
- }
-}
+export type ViewElementChoice = ViewElementBase & {
+ 'uiType': 'choice';
+ 'cases': {
+ [name: string]: ViewElementChoiceCase;
+ };
+};
// https://tools.ietf.org/html/rfc7950#section-7.14.1
export type ViewElementRpc = ViewElementBase & {
- "uiType": "rpc";
- "inputViewId"?: string;
- "outputViewId"?: string;
-}
+ 'uiType': 'rpc';
+ 'inputViewId'?: string;
+ 'outputViewId'?: string;
+};
export type ViewElementEmpty = ViewElementBase & {
- "uiType": "empty";
-}
+ 'uiType': 'empty';
+};
export type ViewElement =
| ViewElementEmpty
@@ -152,88 +154,88 @@
| ViewElementSelection
| ViewElementReference
| ViewElementUnion
- | ViewElementChoise
+ | ViewElementChoice
| ViewElementRpc;
export const isViewElementString = (viewElement: ViewElement): viewElement is ViewElementString => {
- return viewElement && (viewElement.uiType === "string" || viewElement.uiType === "date");
-}
+ return viewElement && (viewElement.uiType === 'string' || viewElement.uiType === 'date');
+};
export const isViewElementDate = (viewElement: ViewElement): viewElement is ViewElementDate => {
- return viewElement && (viewElement.uiType === "date");
-}
+ return viewElement && (viewElement.uiType === 'date');
+};
export const isViewElementNumber = (viewElement: ViewElement): viewElement is ViewElementNumber => {
- return viewElement && viewElement.uiType === "number";
-}
+ return viewElement && viewElement.uiType === 'number';
+};
export const isViewElementBoolean = (viewElement: ViewElement): viewElement is ViewElementBoolean => {
- return viewElement && viewElement.uiType === "boolean";
-}
+ return viewElement && viewElement.uiType === 'boolean';
+};
export const isViewElementObject = (viewElement: ViewElement): viewElement is ViewElementObject => {
- return viewElement && viewElement.uiType === "object" && viewElement.isList === false;
-}
+ return viewElement && viewElement.uiType === 'object' && viewElement.isList === false;
+};
export const isViewElementList = (viewElement: ViewElement): viewElement is ViewElementList => {
- return viewElement && viewElement.uiType === "object" && viewElement.isList === true;
-}
+ return viewElement && viewElement.uiType === 'object' && viewElement.isList === true;
+};
export const isViewElementObjectOrList = (viewElement: ViewElement): viewElement is ViewElementObject | ViewElementList => {
- return viewElement && viewElement.uiType === "object";
-}
+ return viewElement && viewElement.uiType === 'object';
+};
export const isViewElementSelection = (viewElement: ViewElement): viewElement is ViewElementSelection => {
- return viewElement && viewElement.uiType === "selection";
-}
+ return viewElement && viewElement.uiType === 'selection';
+};
export const isViewElementReference = (viewElement: ViewElement): viewElement is ViewElementReference => {
- return viewElement && viewElement.uiType === "reference";
-}
+ return viewElement && viewElement.uiType === 'reference';
+};
export const isViewElementUnion = (viewElement: ViewElement): viewElement is ViewElementUnion => {
- return viewElement && viewElement.uiType === "union";
-}
+ return viewElement && viewElement.uiType === 'union';
+};
-export const isViewElementChoise = (viewElement: ViewElement): viewElement is ViewElementChoise => {
- return viewElement && viewElement.uiType === "choise";
-}
+export const isViewElementChoice = (viewElement: ViewElement): viewElement is ViewElementChoice => {
+ return viewElement && viewElement.uiType === 'choice';
+};
export const isViewElementRpc = (viewElement: ViewElement): viewElement is ViewElementRpc => {
- return viewElement && viewElement.uiType === "rpc";
-}
+ return viewElement && viewElement.uiType === 'rpc';
+};
export const isViewElementEmpty = (viewElement: ViewElement): viewElement is ViewElementRpc => {
- return viewElement && viewElement.uiType === "empty";
-}
+ return viewElement && viewElement.uiType === 'empty';
+};
-export const ResolveFunction = Symbol("IsResolved");
+export const ResolveFunction = Symbol('IsResolved');
export type ViewSpecification = {
- "id": string;
- "ns"?: string;
- "name"?: string;
- "title"?: string;
- "parentView"?: string;
- "language": string;
- "ifFeature"?: string;
- "when"?: string;
- "uses"?: (string[]) & { [ResolveFunction]?: (parent: string) => void };
- "elements": { [name: string]: ViewElement };
- "config": boolean;
- readonly "canEdit": boolean;
-}
+ id: string;
+ ns?: string;
+ name?: string;
+ title?: string;
+ parentView?: string;
+ language: string;
+ ifFeature?: string;
+ when?: WhenAST;
+ uses?: (string[]) & { [ResolveFunction]?: (parent: string) => void };
+ elements: { [name: string]: ViewElement };
+ config: boolean;
+ readonly canEdit: boolean;
+};
export type YangRange = {
- min: number,
- max: number,
-}
+ min: number;
+ max: number;
+};
export type Expression<T> =
| T
| Operator<T>;
export type Operator<T> = {
- operation: "AND" | "OR";
+ operation: 'AND' | 'OR';
arguments: Expression<T>[];
-}
\ No newline at end of file
+};
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/models/yang.ts b/sdnr/wt/odlux/apps/configurationApp/src/models/yang.ts
index 79704ae..e4e59fb 100644
--- a/sdnr/wt/odlux/apps/configurationApp/src/models/yang.ts
+++ b/sdnr/wt/odlux/apps/configurationApp/src/models/yang.ts
@@ -16,7 +16,7 @@
* ============LICENSE_END==========================================================================
*/
-import { ViewElement, ViewSpecification } from "./uiModels";
+import { ViewElement, ViewSpecification } from './uiModels';
export enum ModuleState {
stable,
@@ -30,27 +30,27 @@
value: string;
start: number;
end: number;
-}
+};
export type Statement = {
key: string;
arg?: string;
sub?: Statement[];
-}
+};
export type Identity = {
- id: string,
- label: string,
- base?: string,
- description?: string,
- reference?: string,
- children?: Identity[],
- values?: Identity[],
-}
+ id: string;
+ label: string;
+ base?: string;
+ description?: string;
+ reference?: string;
+ children?: Identity[];
+ values?: Identity[];
+};
export type Revision = {
- description?: string,
- reference?: string
+ description?: string;
+ reference?: string;
};
export type Module = {
@@ -68,4 +68,4 @@
views: { [view: string]: ViewSpecification };
elements: { [view: string]: ViewElement };
executionOrder?: number;
-}
\ No newline at end of file
+};
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/pluginConfiguration.tsx b/sdnr/wt/odlux/apps/configurationApp/src/pluginConfiguration.tsx
index e378791..7dd2d6a 100644
--- a/sdnr/wt/odlux/apps/configurationApp/src/pluginConfiguration.tsx
+++ b/sdnr/wt/odlux/apps/configurationApp/src/pluginConfiguration.tsx
@@ -16,71 +16,74 @@
* ============LICENSE_END==========================================================================
*/
-import * as React from "react";
+import React from 'react';
import { withRouter, RouteComponentProps, Route, Switch, Redirect } from 'react-router-dom';
-import { faAdjust } from '@fortawesome/free-solid-svg-icons'; // select app icon
-
-import connect, { Connect, IDispatcher } from '../../../framework/src/flux/connect';
+import { connect, Connect, IDispatcher } from '../../../framework/src/flux/connect';
import applicationManager from '../../../framework/src/services/applicationManager';
-import { IApplicationStoreState } from "../../../framework/src/store/applicationStore";
-import { configurationAppRootHandler } from "./handlers/configurationAppRootHandler";
-import { NetworkElementSelector } from "./views/networkElementSelector";
-import ConfigurationApplication from "./views/configurationApplication";
-import { updateNodeIdAsyncActionCreator, updateViewActionAsyncCreator } from "./actions/deviceActions";
-import { DisplayModeType } from "./handlers/viewDescriptionHandler";
-import { ViewSpecification } from "./models/uiModels";
+import { configurationAppRootHandler } from './handlers/configurationAppRootHandler';
+import { NetworkElementSelector } from './views/networkElementSelector';
+
+import ConfigurationApplication from './views/configurationApplication';
+import { updateNodeIdAsyncActionCreator, updateViewActionAsyncCreator } from './actions/deviceActions';
+import { DisplayModeType } from './handlers/viewDescriptionHandler';
+import { ViewSpecification } from './models/uiModels';
+
+const appIcon = require('./assets/icons/configurationAppIcon.svg'); // select app icon
let currentNodeId: string | null | undefined = undefined;
let currentVirtualPath: string | null | undefined = undefined;
let lastUrl: string | undefined = undefined;
-const mapDisp = (dispatcher: IDispatcher) => ({
+const mapDispatch = (dispatcher: IDispatcher) => ({
updateNodeId: (nodeId: string) => dispatcher.dispatch(updateNodeIdAsyncActionCreator(nodeId)),
updateView: (vPath: string) => dispatcher.dispatch(updateViewActionAsyncCreator(vPath)),
});
-const ConfigurationApplicationRouteAdapter = connect(undefined, mapDisp)((props: RouteComponentProps<{ nodeId?: string, 0: string }> & Connect<undefined, typeof mapDisp>) => {
+// eslint-disable-next-line @typescript-eslint/naming-convention
+const ConfigurationApplicationRouteAdapter = connect(undefined, mapDispatch)((props: RouteComponentProps<{ nodeId?: string; 0: string }> & Connect<undefined, typeof mapDispatch>) => {
React.useEffect(() => {
return () => {
lastUrl = undefined;
currentNodeId = undefined;
currentVirtualPath = undefined;
- }
+ };
}, []);
if (props.location.pathname !== lastUrl) {
- // ensure the asynchronus update will only be called once per path
+ // ensure the asynchronous update will only be called once per path
lastUrl = props.location.pathname;
window.setTimeout(async () => {
// check if the nodeId has changed
- let dump = false;
+ let enableDump = false;
if (currentNodeId !== props.match.params.nodeId) {
currentNodeId = props.match.params.nodeId || undefined;
- if (currentNodeId && currentNodeId.endsWith("|dump")) {
- dump = true;
+ if (currentNodeId && currentNodeId.endsWith('|dump')) {
+ enableDump = true;
currentNodeId = currentNodeId.replace(/\|dump$/i, '');
}
currentVirtualPath = null;
- currentNodeId && (await props.updateNodeId(currentNodeId));
+ if (currentNodeId) {
+ await props.updateNodeId(currentNodeId);
+ }
}
if (currentVirtualPath !== props.match.params[0]) {
currentVirtualPath = props.match.params[0];
- if (currentVirtualPath && currentVirtualPath.endsWith("|dump")) {
- dump = true;
+ if (currentVirtualPath && currentVirtualPath.endsWith('|dump')) {
+ enableDump = true;
currentVirtualPath = currentVirtualPath.replace(/\|dump$/i, '');
}
await props.updateView(currentVirtualPath);
}
- if (dump) {
+ if (enableDump) {
const device = props.state.configuration.deviceDescription;
const ds = props.state.configuration.viewDescription.displaySpecification;
const createDump = (view: ViewSpecification | null, level: number = 0) => {
- if (view === null) return "Empty";
+ if (view === null) return 'Empty';
const indention = Array(level * 4).fill(' ').join('');
let result = '';
@@ -88,24 +91,24 @@
// result += `${indention} [${view.canEdit ? 'rw' : 'ro'}] ${view.ns}:${view.name} ${ds.displayMode === DisplayModeType.displayAsList ? '[LIST]' : ''}\r\n`;
result += Object.keys(view.elements).reduce((acc, cur) => {
const elm = view.elements[cur];
- acc += `${indention} [${elm.uiType === "rpc" ? "x" : elm.config ? 'rw' : 'ro'}:${elm.id}] (${elm.module}:${elm.label}) {${elm.uiType}} ${elm.uiType === "object" && elm.isList ? `as LIST with KEY [${elm.key}]` : ""}\r\n`;
- // acc += `${indention} +${elm.mandatory ? "mandetory" : "none"} - ${elm.path} \r\n`;
+ acc += `${indention} [${elm.uiType === 'rpc' ? 'x' : elm.config ? 'rw' : 'ro'}:${elm.id}] (${elm.module}:${elm.label}) {${elm.uiType}} ${elm.uiType === 'object' && elm.isList ? `as LIST with KEY [${elm.key}]` : ''}\r\n`;
+ // acc += `${indention} +${elm.mandatory ? "mandatory" : "none"} - ${elm.path} \r\n`;
switch (elm.uiType) {
- case "object":
+ case 'object':
acc += createDump(device.views[(elm as any).viewId], level + 1);
break;
default:
}
return acc;
- }, "");
+ }, '');
return `${result}`;
- }
+ };
const dump = createDump(ds.displayMode === DisplayModeType.displayAsObject || ds.displayMode === DisplayModeType.displayAsList ? ds.viewSpecification : null, 0);
- var element = document.createElement('a');
+ const element = document.createElement('a');
element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(dump));
- element.setAttribute('download', currentNodeId + ".txt");
+ element.setAttribute('download', currentNodeId + '.txt');
element.style.display = 'none';
document.body.appendChild(element);
@@ -133,10 +136,10 @@
export function register() {
applicationManager.registerApplication({
- name: "configuration",
- icon: faAdjust,
+ name: 'configuration',
+ icon: appIcon,
rootComponent: App,
rootActionHandler: configurationAppRootHandler,
- menuEntry: "Configuration"
+ menuEntry: 'Configuration',
});
}
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/services/restServices.ts b/sdnr/wt/odlux/apps/configurationApp/src/services/restServices.ts
index 02060ef..07e2635 100644
--- a/sdnr/wt/odlux/apps/configurationApp/src/services/restServices.ts
+++ b/sdnr/wt/odlux/apps/configurationApp/src/services/restServices.ts
@@ -16,79 +16,79 @@
* ============LICENSE_END==========================================================================
*/
-import { requestRest, requestRestExt } from "../../../../framework/src/services/restService";
-import { convertPropertyNames, replaceHyphen } from "../../../../framework/src/utilities/yangHelper";
+import { requestRest, requestRestExt } from '../../../../framework/src/services/restService';
+import { convertPropertyNames, replaceHyphen } from '../../../../framework/src/utilities/yangHelper';
-import { NetworkElementConnection } from "../models/networkElementConnection";
+import { NetworkElementConnection } from '../models/networkElementConnection';
type ImportOnlyResponse = {
- "ietf-yang-library:yang-library": {
- "module-set": {
- "import-only-module": {
- "name": string,
- "revision": string,
- }[],
- }[],
- },
-}
+ 'ietf-yang-library:yang-library': {
+ 'module-set': {
+ 'import-only-module': {
+ 'name': string;
+ 'revision': string;
+ }[];
+ }[];
+ };
+};
type CapabilityResponse = {
- "network-topology:node": {
- "node-id": string,
- "netconf-node-topology:available-capabilities": {
- "available-capability": {
- "capability-origin": string,
- "capability": string,
- }[]
- },
- "netconf-node-topology:unavailable-capabilities": {
- "unavailable-capability": {
- "capability": string,
- "failure-reason": string,
- }[]
- }
- }[]
-}
+ 'network-topology:node': {
+ 'node-id': string;
+ 'netconf-node-topology:available-capabilities': {
+ 'available-capability': {
+ 'capability-origin': string;
+ 'capability': string;
+ }[];
+ };
+ 'netconf-node-topology:unavailable-capabilities': {
+ 'unavailable-capability': {
+ 'capability': string;
+ 'failure-reason': string;
+ }[];
+ };
+ }[];
+};
type CapabilityAnswer = {
availableCapabilities: {
- capabilityOrigin: string,
- capability: string,
- version: string,
- }[] | null,
+ capabilityOrigin: string;
+ capability: string;
+ version: string;
+ }[] | null;
unavailableCapabilities: {
- failureReason: string,
- capability: string,
- version: string,
- }[] | null,
+ failureReason: string;
+ capability: string;
+ version: string;
+ }[] | null;
importOnlyModules: {
- name: string,
- revision: string,
- }[] | null
-}
+ name: string;
+ revision: string;
+ }[] | null;
+};
const capParser = /^\(.*\?revision=(\d{4}-\d{2}-\d{2})\)(\S+)$/i;
class RestService {
public getNetworkElementUri = (nodeId: string) => '/rests/data/network-topology:network-topology/topology=topology-netconf/node=' + nodeId;
- public async getImportOnlyModules(nodeId: string): Promise<{ name: string, revision: string }[]> {
+ public async getImportOnlyModules(nodeId: string): Promise<{ name: string; revision: string }[]> {
const path = `${this.getNetworkElementUri(nodeId)}/yang-ext:mount/ietf-yang-library:yang-library?content=nonconfig&fields=module-set(import-only-module(name;revision))`;
- const importOnlyResult = await requestRest<ImportOnlyResponse>(path, { method: "GET" });
+ const importOnlyResult = await requestRest<ImportOnlyResponse>(path, { method: 'GET' });
const importOnlyModules = importOnlyResult
- ? importOnlyResult["ietf-yang-library:yang-library"]["module-set"][0]["import-only-module"]
+ ? importOnlyResult['ietf-yang-library:yang-library']['module-set'][0]['import-only-module']
: [];
return importOnlyModules;
}
public async getCapabilitiesByMountId(nodeId: string): Promise<CapabilityAnswer> {
const path = this.getNetworkElementUri(nodeId);
- const capabilitiesResult = await requestRest<CapabilityResponse>(path, { method: "GET" });
- const availableCapabilities = capabilitiesResult && capabilitiesResult["network-topology:node"] && capabilitiesResult["network-topology:node"].length > 0 &&
- (capabilitiesResult["network-topology:node"][0]["netconf-node-topology:available-capabilities"] &&
- capabilitiesResult["network-topology:node"][0]["netconf-node-topology:available-capabilities"]["available-capability"] &&
- capabilitiesResult["network-topology:node"][0]["netconf-node-topology:available-capabilities"]["available-capability"].map<any>(obj => convertPropertyNames(obj, replaceHyphen)) || [])
+ const capabilitiesResult = await requestRest<CapabilityResponse>(path, { method: 'GET' });
+ const availableCapabilities = capabilitiesResult && capabilitiesResult['network-topology:node'] && capabilitiesResult['network-topology:node'].length > 0 &&
+ (capabilitiesResult['network-topology:node'][0]['netconf-node-topology:available-capabilities'] &&
+ capabilitiesResult['network-topology:node'][0]['netconf-node-topology:available-capabilities']['available-capability'] &&
+ capabilitiesResult['network-topology:node'][0]['netconf-node-topology:available-capabilities']['available-capability'].map<any>(obj => convertPropertyNames(obj, replaceHyphen)) || [])
.map(cap => {
const capMatch = cap && capParser.exec(cap.capability);
return capMatch ? {
@@ -98,20 +98,20 @@
} : null ;
}).filter((cap) => cap != null) || [] as any;
- const unavailableCapabilities = capabilitiesResult && capabilitiesResult["network-topology:node"] && capabilitiesResult["network-topology:node"].length > 0 &&
- (capabilitiesResult["network-topology:node"][0]["netconf-node-topology:unavailable-capabilities"] &&
- capabilitiesResult["network-topology:node"][0]["netconf-node-topology:unavailable-capabilities"]["unavailable-capability"] &&
- capabilitiesResult["network-topology:node"][0]["netconf-node-topology:unavailable-capabilities"]["unavailable-capability"].map<any>(obj => convertPropertyNames(obj, replaceHyphen)) || [])
- .map(cap => {
- const capMatch = cap && capParser.exec(cap.capability);
- return capMatch ? {
- failureReason: cap.failureReason,
- capability: capMatch && capMatch[2] || '',
- version: capMatch && capMatch[1] || '',
- } : null ;
- }).filter((cap) => cap != null) || [] as any;
+ const unavailableCapabilities = capabilitiesResult && capabilitiesResult['network-topology:node'] && capabilitiesResult['network-topology:node'].length > 0 &&
+ (capabilitiesResult['network-topology:node'][0]['netconf-node-topology:unavailable-capabilities'] &&
+ capabilitiesResult['network-topology:node'][0]['netconf-node-topology:unavailable-capabilities']['unavailable-capability'] &&
+ capabilitiesResult['network-topology:node'][0]['netconf-node-topology:unavailable-capabilities']['unavailable-capability'].map<any>(obj => convertPropertyNames(obj, replaceHyphen)) || [])
+ .map(cap => {
+ const capMatch = cap && capParser.exec(cap.capability);
+ return capMatch ? {
+ failureReason: cap.failureReason,
+ capability: capMatch && capMatch[2] || '',
+ version: capMatch && capMatch[1] || '',
+ } : null ;
+ }).filter((cap) => cap != null) || [] as any;
- const importOnlyModules = availableCapabilities && availableCapabilities.findIndex((ac: {capability: string }) => ac.capability && ac.capability.toLowerCase() === "ietf-yang-library") > -1
+ const importOnlyModules = availableCapabilities && availableCapabilities.findIndex((ac: { capability: string }) => ac.capability && ac.capability.toLowerCase() === 'ietf-yang-library') > -1
? await this.getImportOnlyModules(nodeId)
: null;
@@ -123,11 +123,11 @@
// const connectedNetworkElement = await requestRest<NetworkElementConnection>(path, { method: "GET" });
// return connectedNetworkElement || null;
- const path = "/rests/operations/data-provider:read-network-element-connection-list";
- const body = { "data-provider:input": { "filter": [{ "property": "node-id", "filtervalue": nodeId }], "sortorder": [], "pagination": { "size": 1, "page": 1 } } };
- const networkElementResult = await requestRest<{ "data-provider:output": { data: NetworkElementConnection[] } }>(path, { method: "POST", body: JSON.stringify(body) });
- return networkElementResult && networkElementResult["data-provider:output"] && networkElementResult["data-provider:output"].data &&
- networkElementResult["data-provider:output"].data.map(obj => convertPropertyNames(obj, replaceHyphen))[0] || null;
+ const path = '/rests/operations/data-provider:read-network-element-connection-list';
+ const body = { 'data-provider:input': { 'filter': [{ 'property': 'node-id', 'filtervalue': nodeId }], 'sortorder': [], 'pagination': { 'size': 1, 'page': 1 } } };
+ const networkElementResult = await requestRest<{ 'data-provider:output': { data: NetworkElementConnection[] } }>(path, { method: 'POST', body: JSON.stringify(body) });
+ return networkElementResult && networkElementResult['data-provider:output'] && networkElementResult['data-provider:output'].data &&
+ networkElementResult['data-provider:output'].data.map(obj => convertPropertyNames(obj, replaceHyphen))[0] || null;
}
/** Reads the config data by restconf path.
@@ -135,7 +135,7 @@
* @returns The data.
*/
public getConfigData(path: string) {
- return requestRestExt<{ [key: string]: any }>(path, { method: "GET" });
+ return requestRestExt<{ [key: string]: any }>(path, { method: 'GET' });
}
/** Updates or creates the config data by restconf path using data.
@@ -144,11 +144,11 @@
* @returns The written data.
*/
public setConfigData(path: string, data: any) {
- return requestRestExt<{ [key: string]: any }>(path, { method: "PUT", body: JSON.stringify(data) });
+ return requestRestExt<{ [key: string]: any }>(path, { method: 'PUT', body: JSON.stringify(data) });
}
public executeRpc(path: string, data: any) {
- return requestRestExt<{ [key: string]: any }>(path, { method: "POST", body: JSON.stringify(data) });
+ return requestRestExt<{ [key: string]: any }>(path, { method: 'POST', body: JSON.stringify(data) });
}
/** Removes the element by restconf path.
@@ -156,7 +156,7 @@
* @returns The restconf result.
*/
public removeConfigElement(path: string) {
- return requestRestExt<{ [key: string]: any }>(path, { method: "DELETE" });
+ return requestRestExt<{ [key: string]: any }>(path, { method: 'DELETE' });
}
}
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/services/yangService.ts b/sdnr/wt/odlux/apps/configurationApp/src/services/yangService.ts
index b81a92c..bbd051a 100644
--- a/sdnr/wt/odlux/apps/configurationApp/src/services/yangService.ts
+++ b/sdnr/wt/odlux/apps/configurationApp/src/services/yangService.ts
@@ -16,28 +16,22 @@
* ============LICENSE_END==========================================================================
*/
-type YangInfo = [string, (string | null | undefined)];
+const cache: { [path: string]: string } = { };
+const getCapability = async (capability: string, nodeId: string, version?: string) => {
+ const url = `/yang-schema/${capability}${version ? `/${version}` : ''}?node=${nodeId}`;
-const cache: { [path: string]: string } = {
+ const cacheHit = cache[url];
+ if (cacheHit) return cacheHit;
+ const res = await fetch(url);
+ const yangFile = res.ok && (await res.text());
+ if (yangFile !== false && yangFile !== null) {
+ cache[url] = yangFile;
+ }
+ return yangFile;
};
-class YangService {
-
- public async getCapability(capability: string, nodeId: string, version?: string) {
- const url = `/yang-schema/${capability}${version ? `/${version}` : ""}?node=${nodeId}`;
-
- const cacheHit = cache[url];
- if (cacheHit) return cacheHit;
-
- const res = await fetch(url);
- const yangFile = res.ok && (await res.text());
- if (yangFile !== false && yangFile !== null) {
- cache[url] = yangFile;
- }
- return yangFile;
- }
-}
-
-export const yangService = new YangService();
+export const yangService = {
+ getCapability,
+};
export default yangService;
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/utilities/verifyer.ts b/sdnr/wt/odlux/apps/configurationApp/src/utilities/verifyer.ts
new file mode 100644
index 0000000..9dd1203
--- /dev/null
+++ b/sdnr/wt/odlux/apps/configurationApp/src/utilities/verifyer.ts
@@ -0,0 +1,261 @@
+/**
+ * ============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 { YangRange, Operator, ViewElementNumber, ViewElementString, isViewElementNumber, isViewElementString } from '../models/uiModels';
+
+export type validated = { isValid: boolean; error?: string };
+
+export type validatedRange = { isValid: boolean; error?: string };
+
+const rangeErrorStartNumber = 'The entered number must be';
+const rangeErrorInnerMinTextNumber = 'greater or equals than';
+const rangeErrorInnerMaxTextNumber = 'less or equals than';
+const rangeErrorEndTextNumber = '.';
+
+const rangeErrorStartString = 'The entered text must have';
+const rangeErrorInnerMinTextString = 'no more than';
+const rangeErrorInnerMaxTextString = 'less than';
+const rangeErrorEndTextString = ' characters.';
+
+let errorMessageStart = '';
+let errorMessageMiddleMinPart = '';
+let errorMessageMiddleMaxPart = '';
+let errorMessageEnd = '';
+
+const isYangRange = (val: YangRange | Operator<YangRange>): val is YangRange => (val as YangRange).min !== undefined;
+
+const isYangOperator = (val: YangRange | Operator<YangRange>): val is Operator<YangRange> => (val as Operator<YangRange>).operation !== undefined;
+
+const isRegExp = (val: RegExp | Operator<RegExp>): val is RegExp => (val as RegExp).source !== undefined;
+
+const isRegExpOperator = (val: RegExp | Operator<RegExp>): val is Operator<RegExp> => (val as Operator<RegExp>).operation !== undefined;
+
+const getRangeErrorMessagesRecursively = (value: Operator<YangRange>, data: number): string[] => {
+ let currentIteration: string[] = [];
+
+ // iterate over all elements
+ for (let i = 0; i < value.arguments.length; i++) {
+ const element = value.arguments[i];
+
+ let min = undefined;
+ let max = undefined;
+
+ let isNumberCorrect = false;
+
+ if (isYangRange(element)) {
+
+ //check found min values
+ if (!isNaN(element.min)) {
+ if (data < element.min) {
+ min = element.min;
+ } else {
+ isNumberCorrect = true;
+ }
+ }
+
+ // check found max values
+ if (!isNaN(element.max)) {
+ if (data > element.max) {
+ max = element.max;
+ } else {
+ isNumberCorrect = true;
+ }
+ }
+
+ // construct error messages
+ if (min != undefined) {
+ currentIteration.push(`${value.operation.toLocaleLowerCase()} ${errorMessageMiddleMinPart} ${min}`);
+ } else if (max != undefined) {
+ currentIteration.push(`${value.operation.toLocaleLowerCase()} ${errorMessageMiddleMaxPart} ${max}`);
+
+ }
+
+ } else if (isYangOperator(element)) {
+
+ //get error_message from expression
+ const result = getRangeErrorMessagesRecursively(element, data);
+ if (result.length === 0) {
+ isNumberCorrect = true;
+ }
+ currentIteration = currentIteration.concat(result);
+ }
+
+ // if its an OR operation, the number has been checked and min/max are empty (thus not violated)
+ // delete everything found (because at least one found is correct, therefore all are correct) and break from loop
+ if (min === undefined && max === undefined && isNumberCorrect && value.operation === 'OR') {
+
+ currentIteration.splice(0, currentIteration.length);
+ break;
+ }
+ }
+
+ return currentIteration;
+};
+
+const createStartMessage = (element: string) => {
+ //remove leading or or and from text
+ if (element.startsWith('and')) {
+ element = element.replace('and', '');
+ } else if (element.startsWith('or')) {
+ element = element.replace('or', '');
+ }
+ return `${errorMessageStart} ${element}`;
+};
+
+const getRangeErrorMessages = (value: Operator<YangRange>, data: number): string => {
+
+ const currentIteration = getRangeErrorMessagesRecursively(value, data);
+
+ // build complete error message from found parts
+ let errorMessage = '';
+ if (currentIteration.length > 1) {
+
+ currentIteration.forEach((element, index) => {
+ if (index === 0) {
+ errorMessage = createStartMessage(element);
+ } else if (index === currentIteration.length - 1) {
+ errorMessage += ` ${element}${errorMessageEnd}`;
+ } else {
+ errorMessage += `, ${element}`;
+ }
+ });
+ } else if (currentIteration.length == 1) {
+ errorMessage = `${createStartMessage(currentIteration[0])}${errorMessageEnd}`;
+ }
+
+ return errorMessage;
+};
+
+export const checkRange = (element: ViewElementNumber | ViewElementString, data: number): string => {
+ const number = data;
+
+ let expression = undefined;
+
+ if (isViewElementString(element)) {
+ expression = element.length;
+
+ errorMessageStart = rangeErrorStartString;
+ errorMessageMiddleMaxPart = rangeErrorInnerMaxTextString;
+ errorMessageMiddleMinPart = rangeErrorInnerMinTextString;
+ errorMessageEnd = rangeErrorEndTextString;
+
+ } else if (isViewElementNumber(element)) {
+ expression = element.range;
+
+ errorMessageStart = rangeErrorStartNumber;
+ errorMessageMiddleMaxPart = rangeErrorInnerMaxTextNumber;
+ errorMessageMiddleMinPart = rangeErrorInnerMinTextNumber;
+ errorMessageEnd = rangeErrorEndTextNumber;
+ }
+
+ if (expression) {
+ if (isYangOperator(expression)) {
+
+ const errorMessage = getRangeErrorMessages(expression, data);
+ return errorMessage;
+
+ } else
+ if (isYangRange(expression)) {
+
+ if (!isNaN(expression.min)) {
+ if (number < expression.min) {
+ return `${errorMessageStart} ${errorMessageMiddleMinPart} ${expression.min}${errorMessageEnd}`;
+ }
+ }
+
+ if (!isNaN(expression.max)) {
+ if (number > expression.max) {
+ return `${errorMessageStart} ${errorMessageMiddleMaxPart} ${expression.max}${errorMessageEnd}`;
+ }
+ }
+ }
+ }
+
+ return '';
+};
+
+const getRegexRecursively = (value: Operator<RegExp>, data: string): boolean[] => {
+ let currentItteration: boolean[] = [];
+ for (let i = 0; i < value.arguments.length; i++) {
+ const element = value.arguments[i];
+ if (isRegExp(element)) {
+ // if regex is found, add it to list
+ currentItteration.push(element.test(data));
+ } else if (isRegExpOperator(element)) {
+ //if RegexExpression is found, try to get regex from it
+ currentItteration = currentItteration.concat(getRegexRecursively(element, data));
+ }
+ }
+
+ if (value.operation === 'OR') {
+ // if one is true, all are true, all found items can be discarded
+ let result = currentItteration.find(element => element);
+ if (result) {
+ return [];
+ }
+ }
+ return currentItteration;
+};
+
+const isPatternValid = (value: Operator<RegExp>, data: string): boolean => {
+ // get all regex
+ const result = getRegexRecursively(value, data);
+
+ if (value.operation === 'AND') {
+ // if AND operation is executed...
+ // no element can be false
+ const check = result.find(element => element !== true);
+ if (check)
+ return false;
+ else
+ return true;
+ } else {
+ // if OR operation is executed...
+ // ... just one element must be true
+ const check = result.find(element => element === true);
+ if (check)
+ return true;
+ else
+ return false;
+
+ }
+};
+
+export const checkPattern = (expression: RegExp | Operator<RegExp> | undefined, data: string): validated => {
+
+ if (expression) {
+ if (isRegExp(expression)) {
+ const isValid = expression.test(data);
+ if (!isValid)
+ return { isValid: isValid, error: 'The input is in a wrong format.' };
+
+ } else if (isRegExpOperator(expression)) {
+ const result = isPatternValid(expression, data);
+
+ if (!result) {
+ return { isValid: false, error: 'The input is in a wrong format.' };
+ }
+ }
+ }
+
+ return { isValid: true };
+};
+
+
+
+
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/utilities/viewEngineHelper.ts b/sdnr/wt/odlux/apps/configurationApp/src/utilities/viewEngineHelper.ts
new file mode 100644
index 0000000..ad34c83
--- /dev/null
+++ b/sdnr/wt/odlux/apps/configurationApp/src/utilities/viewEngineHelper.ts
@@ -0,0 +1,324 @@
+import { storeService } from '../../../../framework/src/services/storeService';
+import { WhenAST, WhenTokenType } from '../yang/whenParser';
+
+import {
+ ViewSpecification,
+ ViewElement,
+ isViewElementReference,
+ isViewElementList,
+ isViewElementObjectOrList,
+ isViewElementRpc,
+ isViewElementChoice,
+ ViewElementChoiceCase,
+} from '../models/uiModels';
+
+import { Module } from '../models/yang';
+
+import { restService } from '../services/restServices';
+
+export type HttpResult = {
+ status: number;
+ message?: string | undefined;
+ data: {
+ [key: string]: any;
+ } | null | undefined;
+};
+
+export const checkResponseCode = (restResult: HttpResult) =>{
+ //403 gets handled by the framework from now on
+ return restResult.status !== 403 && ( restResult.status < 200 || restResult.status > 299);
+};
+
+export const resolveVPath = (current: string, vPath: string): string => {
+ if (vPath.startsWith('/')) {
+ return vPath;
+ }
+ const parts = current.split('/');
+ const vPathParts = vPath.split('/');
+ for (const part of vPathParts) {
+ if (part === '.') {
+ continue;
+ } else if (part === '..') {
+ parts.pop();
+ } else {
+ parts.push(part);
+ }
+ }
+ return parts.join('/');
+};
+
+export const splitVPath = (vPath: string, vPathParser : RegExp): [string, string?][] => {
+ const pathParts: [string, string?][] = [];
+ let partMatch: RegExpExecArray | null;
+ if (vPath) do {
+ partMatch = vPathParser.exec(vPath);
+ if (partMatch) {
+ pathParts.push([partMatch[1], partMatch[2] || undefined]);
+ }
+ } while (partMatch);
+ return pathParts;
+};
+
+const derivedFrom = (vPath: string, when: WhenAST, viewData: any, includeSelf = false) => {
+ if (when.args?.length !== 2) {
+ throw new Error('derived-from or derived-from-or-self requires 2 arguments.');
+ }
+ const [arg1, arg2] = when.args;
+ if (arg1.type !== WhenTokenType.IDENTIFIER || arg2.type !== WhenTokenType.STRING) {
+ throw new Error('derived-from or derived-from-or-self requires first argument IDENTIFIER and second argument STRING.');
+ }
+
+ if (!storeService.applicationStore) {
+ throw new Error('storeService.applicationStore is not defined.');
+ }
+
+ const pathParts = splitVPath(arg1.value as string || '', /(?:(?:([^\/\:]+):)?([^\/]+))/g);
+ const referenceValueParts = /(?:(?:([^\/\:]+):)?([^\/]+))/g.exec(arg2.value as string || '');
+
+ if (!pathParts || !referenceValueParts || pathParts.length === 0 || referenceValueParts.length === 0) {
+ throw new Error('derived-from or derived-from-or-self requires first argument PATH and second argument IDENTITY.');
+ }
+
+ if (pathParts[0][1]?.startsWith('..') || pathParts[0][1]?.startsWith('/')) {
+ throw new Error('derived-from or derived-from-or-self currently only supports relative paths.');
+ }
+
+ const { configuration: { deviceDescription: { modules } } } = storeService.applicationStore.state;
+ const dataValue = pathParts.reduce((acc, [ns, prop]) => {
+ if (prop === '.') {
+ return acc;
+ }
+ if (acc && prop) {
+ const moduleName = ns && (Object.values(modules).find((m: Module) => m.prefix === ns) || Object.values(modules).find((m: Module) => m.name === ns))?.name;
+ return (moduleName) ? acc[`${moduleName}:${prop}`] || acc[prop] : acc[prop];
+ }
+ return undefined;
+ }, viewData);
+
+ let dataValueParts = dataValue && /(?:(?:([^\/\:]+):)?([^\/]+))/g.exec(dataValue);
+ if (!dataValueParts || dataValueParts.length < 2) {
+ throw new Error(`derived-from or derived-from-or-self value referenced by first argument [${arg1.value}] not found.`);
+ }
+ let [, dataValueNs, dataValueProp] = dataValueParts;
+ let dataValueModule: Module = dataValueNs && (Object.values(modules).find((m: Module) => m.name === dataValueNs));
+ let dataValueIdentity = dataValueModule && dataValueModule.identities && (Object.values(dataValueModule.identities).find((i) => i.label === dataValueProp));
+
+ if (!dataValueIdentity) {
+ throw new Error(`derived-from or derived-from-or-self identity [${dataValue}] referenced by first argument [${arg1.value}] not found.`);
+ }
+
+ const [, referenceValueNs, referenceValueProp] = referenceValueParts;
+ const referenceValueModule = referenceValueNs && (Object.values(modules).find((m: Module) => m.prefix === referenceValueNs));
+ const referenceValueIdentity = referenceValueModule && referenceValueModule.identities && (Object.values(referenceValueModule.identities).find((i) => i.label === referenceValueProp));
+
+ if (!referenceValueIdentity) {
+ throw new Error(`derived-from or derived-from-or-self identity [${arg2.value}] referenced by second argument not found.`);
+ }
+
+ let result = includeSelf && (referenceValueIdentity === dataValueIdentity);
+ while (dataValueIdentity && dataValueIdentity.base && !result) {
+ dataValueParts = dataValue && /(?:(?:([^\/\:]+):)?([^\/]+))/g.exec(dataValueIdentity.base);
+ const [, innerDataValueNs, innerDataValueProp] = dataValueParts;
+ dataValueModule = innerDataValueNs && (Object.values(modules).find((m: Module) => m.prefix === innerDataValueNs)) || dataValueModule;
+ dataValueIdentity = dataValueModule && dataValueModule.identities && (Object.values(dataValueModule.identities).find((i) => i.label === innerDataValueProp)) ;
+ result = (referenceValueIdentity === dataValueIdentity);
+ }
+
+ return result;
+};
+
+const evaluateWhen = async (vPath: string, when: WhenAST, viewData: any): Promise<boolean> => {
+ switch (when.type) {
+ case WhenTokenType.FUNCTION:
+ switch (when.name) {
+ case 'derived-from-or-self':
+ return derivedFrom(vPath, when, viewData, true);
+ case 'derived-from':
+ return derivedFrom(vPath, when, viewData, false);
+ default:
+ throw new Error(`Unknown function ${when.name}`);
+ }
+ case WhenTokenType.AND:
+ return !when.left || !when.right || (await evaluateWhen(vPath, when.left, viewData) && await evaluateWhen(vPath, when.right, viewData));
+ case WhenTokenType.OR:
+ return !when.left || !when.right || (await evaluateWhen(vPath, when.left, viewData) || await evaluateWhen(vPath, when.right, viewData));
+ case WhenTokenType.NOT:
+ return !when.right || ! await evaluateWhen(vPath, when.right, viewData);
+ case WhenTokenType.EXPRESSION:
+ return !(when.value && typeof when.value !== 'string') || await evaluateWhen(vPath, when.value, viewData);
+ }
+ return true;
+};
+
+export const getReferencedDataList = async (refPath: string, dataPath: string, modules: { [name: string]: Module }, views: ViewSpecification[]) => {
+ const pathParts = splitVPath(refPath, /(?:(?:([^\/\:]+):)?([^\/]+))/g); // 1 = opt: namespace / 2 = property
+ const defaultNS = pathParts[0][0];
+ let referencedModule = modules[defaultNS];
+
+ let dataMember: string;
+ let view: ViewSpecification;
+ let currentNS: string | null = null;
+ let dataUrls = [dataPath];
+ let data: any;
+
+ for (let i = 0; i < pathParts.length; ++i) {
+ const [pathPartNS, pathPart] = pathParts[i];
+ const namespace = pathPartNS != null ? (currentNS = pathPartNS) : currentNS;
+
+ const viewElement = i === 0
+ ? views[0].elements[`${referencedModule.name}:${pathPart}`]
+ : view!.elements[`${pathPart}`] || view!.elements[`${namespace}:${pathPart}`];
+
+ if (!viewElement) throw new Error(`Could not find ${pathPart} in ${refPath}`);
+ if (i < pathParts.length - 1) {
+ if (!isViewElementObjectOrList(viewElement)) {
+ throw Error(`Module: [${referencedModule.name}].[${viewElement.label}]. View element is not list or object.`);
+ }
+ view = views[+viewElement.viewId];
+ const resultingDataUrls : string[] = [];
+ if (isViewElementList(viewElement)) {
+ for (let j = 0; j < dataUrls.length; ++j) {
+ const dataUrl = dataUrls[j];
+ const restResult = (await restService.getConfigData(dataUrl));
+ if (restResult.data == null || checkResponseCode(restResult)) {
+ const message = restResult.data && restResult.data.errors && restResult.data.errors.error && restResult.data.errors.error[0] && restResult.data.errors.error[0]['error-message'] || '';
+ throw new Error(`Server Error. Status: [${restResult.status}]\n${message || restResult.message || ''}`);
+ }
+
+ let dataRaw = restResult.data[`${defaultNS}:${dataMember!}`];
+ if (dataRaw === undefined) {
+ dataRaw = restResult.data[dataMember!];
+ }
+ dataRaw = dataRaw instanceof Array
+ ? dataRaw[0]
+ : dataRaw;
+
+ data = dataRaw && dataRaw[viewElement.label] || [];
+ const keys: string[] = data.map((entry: { [key: string]: any } )=> entry[viewElement.key!]);
+ resultingDataUrls.push(...keys.map(key => `${dataUrl}/${viewElement.label.replace(/\//ig, '%2F')}=${key.replace(/\//ig, '%2F')}`));
+ }
+ dataMember = viewElement.label;
+ } else {
+ // just a member, not a list
+ const pathSegment = (i === 0
+ ? `/${referencedModule.name}:${viewElement.label.replace(/\//ig, '%2F')}`
+ : `/${viewElement.label.replace(/\//ig, '%2F')}`);
+ resultingDataUrls.push(...dataUrls.map(dataUrl => dataUrl + pathSegment));
+ dataMember = viewElement.label;
+ }
+ dataUrls = resultingDataUrls;
+ } else {
+ data = [];
+ for (let j = 0; j < dataUrls.length; ++j) {
+ const dataUrl = dataUrls[j];
+ const restResult = (await restService.getConfigData(dataUrl));
+ if (restResult.data == null || checkResponseCode(restResult)) {
+ const message = restResult.data && restResult.data.errors && restResult.data.errors.error && restResult.data.errors.error[0] && restResult.data.errors.error[0]['error-message'] || '';
+ throw new Error(`Server Error. Status: [${restResult.status}]\n${message || restResult.message || ''}`);
+ }
+ let dataRaw = restResult.data[`${defaultNS}:${dataMember!}`];
+ if (dataRaw === undefined) {
+ dataRaw = restResult.data[dataMember!];
+ }
+ dataRaw = dataRaw instanceof Array
+ ? dataRaw[0]
+ : dataRaw;
+ data.push(dataRaw);
+ }
+ // BUG UUID ist nicht in den elements enthalten !!!!!!
+ const key = viewElement && viewElement.label || pathPart;
+ return {
+ view: view!,
+ data: data,
+ key: key,
+ };
+ }
+ }
+ return null;
+};
+
+export const resolveViewDescription = (defaultNS: string | null, vPath: string, view: ViewSpecification): ViewSpecification =>{
+
+ // resolve all references.
+ view = { ...view };
+ view.elements = Object.keys(view.elements).reduce<{ [name: string]: ViewElement }>((acc, cur) => {
+ const resolveHistory : ViewElement[] = [];
+ let elm = view.elements[cur];
+ const key = defaultNS && cur.replace(new RegExp(`^${defaultNS}:`, 'i'), '') || cur;
+ while (isViewElementReference(elm)) {
+ const result = (elm.ref(vPath));
+ if (result) {
+ const [referencedElement, referencedPath] = result;
+ if (resolveHistory.some(hist => hist === referencedElement)) {
+ console.error(`Circle reference found at: ${vPath}`, resolveHistory);
+ break;
+ }
+ elm = referencedElement;
+ vPath = referencedPath;
+ resolveHistory.push(elm);
+ }
+ }
+
+ acc[key] = { ...elm, id: key };
+
+ return acc;
+ }, {});
+ return view;
+};
+
+export const flattenViewElements = (defaultNS: string | null, parentPath: string, elements: { [name: string]: ViewElement }, views: ViewSpecification[], currentPath: string ): { [name: string]: ViewElement } => {
+ if (!elements) return {};
+ return Object.keys(elements).reduce<{ [name: string]: ViewElement }>((acc, cur) => {
+ const elm = elements[cur];
+
+ // remove the default namespace, and only the default namespace, sine it seems that this is also not in the restconf response
+ const elmKey = defaultNS && elm.id.replace(new RegExp(`^${defaultNS}:`, 'i'), '') || elm.id;
+ const key = parentPath ? `${parentPath}.${elmKey}` : elmKey;
+
+ if (isViewElementRpc(elm)) {
+ console.warn(`Flatten of RFC not supported ! [${currentPath}][${elm.label}]`);
+ return acc;
+ } else if (isViewElementObjectOrList(elm)) {
+ const view = views[+elm.viewId];
+ const inner = view && flattenViewElements(defaultNS, key, view.elements, views, `${currentPath}/${view.name}`);
+ if (inner) {
+ Object.keys(inner).forEach(k => (acc[k] = inner[k]));
+ }
+ } else if (isViewElementChoice(elm)) {
+ acc[key] = {
+ ...elm,
+ id: key,
+ cases: Object.keys(elm.cases).reduce<{ [name: string]: ViewElementChoiceCase }>((accCases, curCases) => {
+ const caseElement = elm.cases[curCases];
+ accCases[curCases] = {
+ ...caseElement,
+ // Hint: do not use key it contains elmKey, which shell be omitted for cases.
+ elements: flattenViewElements(defaultNS, /*key*/ parentPath, caseElement.elements, views, `${currentPath}/${elm.label}`),
+ };
+ return accCases;
+ }, {}),
+ };
+ } else {
+ acc[key] = {
+ ...elm,
+ id: key,
+ };
+ }
+ return acc;
+ }, {});
+};
+
+export const filterViewElements = async (vPath: string, viewData: any, viewSpecification: ViewSpecification) => {
+ // filter elements of viewSpecification by evaluating when property
+ return Object.keys(viewSpecification.elements).reduce(async (accPromise, cur) => {
+ const acc = await accPromise;
+ const elm = viewSpecification.elements[cur];
+ if (!elm.when || await evaluateWhen(vPath || '', elm.when, viewData).catch((ex) => {
+ console.warn(`Error evaluating when clause at: ${viewSpecification.name} for element: ${cur}`, ex);
+ return true;
+ })) {
+ acc.elements[cur] = elm;
+ }
+ return acc;
+ }, Promise.resolve({ ...viewSpecification, elements: {} as { [key: string]: ViewElement } }));
+};
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/views/configurationApplication.tsx b/sdnr/wt/odlux/apps/configurationApp/src/views/configurationApplication.tsx
index 0e2ddb3..0f143d8 100644
--- a/sdnr/wt/odlux/apps/configurationApp/src/views/configurationApplication.tsx
+++ b/sdnr/wt/odlux/apps/configurationApp/src/views/configurationApplication.tsx
@@ -25,17 +25,41 @@
import withStyles from '@mui/styles/withStyles';
import createStyles from '@mui/styles/createStyles';
-import connect, { IDispatcher, Connect } from "../../../../framework/src/flux/connect";
-import { IApplicationStoreState } from "../../../../framework/src/store/applicationStore";
-import MaterialTable, { ColumnModel, ColumnType, MaterialTableCtorType } from "../../../../framework/src/components/material-table";
-import { Loader } from "../../../../framework/src/components/material-ui/loader";
+import { useConfirm } from 'material-ui-confirm';
+
+import { connect, IDispatcher, Connect } from '../../../../framework/src/flux/connect';
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+import MaterialTable, { ColumnModel, ColumnType, MaterialTableCtorType } from '../../../../framework/src/components/material-table';
+import { Loader } from '../../../../framework/src/components/material-ui/loader';
import { renderObject } from '../../../../framework/src/components/objectDump';
import { DisplayModeType } from '../handlers/viewDescriptionHandler';
-import { SetSelectedValue, splitVPath, updateDataActionAsyncCreator, updateViewActionAsyncCreator, removeElementActionAsyncCreator, executeRpcActionAsyncCreator } from "../actions/deviceActions";
-import { ViewSpecification, isViewElementString, isViewElementNumber, isViewElementBoolean, isViewElementObjectOrList, isViewElementSelection, isViewElementChoise, ViewElement, ViewElementChoise, isViewElementUnion, isViewElementRpc, ViewElementRpc, isViewElementEmpty, isViewElementDate } from "../models/uiModels";
+import {
+ SetSelectedValue,
+ updateDataActionAsyncCreator,
+ updateViewActionAsyncCreator,
+ removeElementActionAsyncCreator,
+ executeRpcActionAsyncCreator,
+} from '../actions/deviceActions';
-import { getAccessPolicyByUrl } from "../../../../framework/src/services/restService";
+import {
+ ViewElement,
+ ViewSpecification,
+ ViewElementChoice,
+ ViewElementRpc,
+ isViewElementString,
+ isViewElementNumber,
+ isViewElementBoolean,
+ isViewElementObjectOrList,
+ isViewElementSelection,
+ isViewElementChoice,
+ isViewElementUnion,
+ isViewElementRpc,
+ isViewElementEmpty,
+ isViewElementDate,
+} from '../models/uiModels';
+
+import { getAccessPolicyByUrl } from '../../../../framework/src/services/restService';
import Fab from '@mui/material/Fab';
import AddIcon from '@mui/icons-material/Add';
@@ -44,23 +68,22 @@
import RemoveIcon from '@mui/icons-material/RemoveCircleOutline';
import SaveIcon from '@mui/icons-material/Save';
import EditIcon from '@mui/icons-material/Edit';
-import Tooltip from "@mui/material/Tooltip";
-import FormControl from "@mui/material/FormControl";
-import IconButton from "@mui/material/IconButton";
+import Tooltip from '@mui/material/Tooltip';
+import FormControl from '@mui/material/FormControl';
+import IconButton from '@mui/material/IconButton';
-import InputLabel from "@mui/material/InputLabel";
-import Select from "@mui/material/Select";
-import MenuItem from "@mui/material/MenuItem";
-import Breadcrumbs from "@mui/material/Breadcrumbs";
+import InputLabel from '@mui/material/InputLabel';
+import Select from '@mui/material/Select';
+import MenuItem from '@mui/material/MenuItem';
+import Breadcrumbs from '@mui/material/Breadcrumbs';
import Button from '@mui/material/Button';
-import Link from "@mui/material/Link";
+import Link from '@mui/material/Link';
import Accordion from '@mui/material/Accordion';
import AccordionSummary from '@mui/material/AccordionSummary';
import AccordionDetails from '@mui/material/AccordionDetails';
import Typography from '@mui/material/Typography';
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
-
import { BaseProps } from '../components/baseProps';
import { UIElementReference } from '../components/uiElementReference';
import { UiElementNumber } from '../components/uiElementNumber';
@@ -70,44 +93,43 @@
import { UIElementUnion } from '../components/uiElementUnion';
import { UiElementLeafList } from '../components/uiElementLeafList';
-import { useConfirm } from 'material-ui-confirm';
-import restService from '../services/restServices';
+import { splitVPath } from '../utilities/viewEngineHelper';
const styles = (theme: Theme) => createStyles({
header: {
- "display": "flex",
- "justifyContent": "space-between",
+ 'display': 'flex',
+ 'justifyContent': 'space-between',
},
leftButton: {
- "justifyContent": "left"
+ 'justifyContent': 'left',
},
outer: {
- "flex": "1",
- "height": "100%",
- "display": "flex",
- "alignItems": "center",
- "justifyContent": "center",
+ 'flex': '1',
+ 'height': '100%',
+ 'display': 'flex',
+ 'alignItems': 'center',
+ 'justifyContent': 'center',
},
inner: {
},
container: {
- "height": "100%",
- "display": "flex",
- "flexDirection": "column",
+ 'height': '100%',
+ 'display': 'flex',
+ 'flexDirection': 'column',
},
- "icon": {
- "marginRight": theme.spacing(0.5),
- "width": 20,
- "height": 20,
+ 'icon': {
+ 'marginRight': theme.spacing(0.5),
+ 'width': 20,
+ 'height': 20,
},
- "fab": {
- "margin": theme.spacing(1),
+ 'fab': {
+ 'margin': theme.spacing(1),
},
button: {
margin: 0,
- padding: "6px 6px",
- minWidth: 'unset'
+ padding: '6px 6px',
+ minWidth: 'unset',
},
readOnly: {
'& label.Mui-focused': {
@@ -129,29 +151,29 @@
},
},
uiView: {
- overflowY: "auto",
+ overflowY: 'auto',
},
section: {
- padding: "15px",
+ padding: '15px',
borderBottom: `2px solid ${theme.palette.divider}`,
},
viewElements: {
- width: 485, marginLeft: 20, marginRight: 20
+ width: 485, marginLeft: 20, marginRight: 20,
},
verificationElements: {
- width: 485, marginLeft: 20, marginRight: 20
+ width: 485, marginLeft: 20, marginRight: 20,
},
heading: {
fontSize: theme.typography.pxToRem(15),
fontWeight: theme.typography.fontWeightRegular,
},
moduleCollection: {
- marginTop: "16px",
- overflow: "auto",
+ marginTop: '16px',
+ overflow: 'auto',
},
objectReult: {
- overflow: "auto"
- }
+ overflow: 'auto',
+ },
});
const mapProps = (state: IApplicationStoreState) => ({
@@ -183,10 +205,10 @@
editMode: boolean;
canEdit: boolean;
viewData: { [key: string]: any } | null;
- choises: { [path: string]: { selectedCase: string, data: { [property: string]: any } } };
-}
+ choices: { [path: string]: { selectedCase: string; data: { [property: string]: any } } };
+};
-type GetStatelessComponentProps<T> = T extends (props: infer P & { children?: React.ReactNode }) => any ? P : any
+type GetStatelessComponentProps<T> = T extends (props: infer P & { children?: React.ReactNode }) => any ? P : any;
const AccordionSummaryExt: React.FC<GetStatelessComponentProps<typeof AccordionSummary>> = (props) => {
const [disabled, setDisabled] = useState(true);
const onMouseDown = (ev: React.MouseEvent<HTMLElement>) => {
@@ -202,7 +224,7 @@
);
};
-const OldProps = Symbol("OldProps");
+const OldProps = Symbol('OldProps');
class ConfigurationApplicationComponent extends React.Component<ConfigurationApplicationComponentProps, ConfigurationApplicationComponentState> {
/**
@@ -216,17 +238,17 @@
canEdit: false,
editMode: false,
viewData: null,
- choises: {},
- }
+ choices: {},
+ };
}
- private static getChoisesFromElements = (elements: { [name: string]: ViewElement }, viewData: any) => {
+ private static getChoicesFromElements = (elements: { [name: string]: ViewElement }, viewData: any) => {
return Object.keys(elements).reduce((acc, cur) => {
const elm = elements[cur];
- if (isViewElementChoise(elm)) {
+ if (isViewElementChoice(elm)) {
const caseKeys = Object.keys(elm.cases);
- // find the right case for this choise, use the first one with data, at least use index 0
+ // find the right case for this choice, use the first one with data, at least use index 0
const selectedCase = caseKeys.find(key => {
const caseElm = elm.cases[key];
return Object.keys(caseElm.elements).some(caseElmKey => {
@@ -255,26 +277,26 @@
};
}
return acc;
- }, {} as { [path: string]: { selectedCase: string, data: { [property: string]: any } } }) || {}
- }
+ }, {} as { [path: string]: { selectedCase: string; data: { [property: string]: any } } }) || {};
+ };
static getDerivedStateFromProps(nextProps: ConfigurationApplicationComponentProps, prevState: ConfigurationApplicationComponentState & { [OldProps]: ConfigurationApplicationComponentProps }) {
if (!prevState || !prevState[OldProps] || (prevState[OldProps].viewData !== nextProps.viewData)) {
- const isNew: boolean = nextProps.vPath?.endsWith("[]") || false;
+ const isNew: boolean = nextProps.vPath?.endsWith('[]') || false;
const state = {
...prevState,
isNew: isNew,
editMode: isNew,
viewData: nextProps.viewData || null,
[OldProps]: nextProps,
- choises: nextProps.displaySpecification.displayMode === DisplayModeType.doNotDisplay
+ choices: nextProps.displaySpecification.displayMode === DisplayModeType.doNotDisplay
|| nextProps.displaySpecification.displayMode === DisplayModeType.displayAsMessage
? null
: nextProps.displaySpecification.displayMode === DisplayModeType.displayAsRPC
- ? nextProps.displaySpecification.inputViewSpecification && ConfigurationApplicationComponent.getChoisesFromElements(nextProps.displaySpecification.inputViewSpecification.elements, nextProps.viewData) || []
- : ConfigurationApplicationComponent.getChoisesFromElements(nextProps.displaySpecification.viewSpecification.elements, nextProps.viewData)
- }
+ ? nextProps.displaySpecification.inputViewSpecification && ConfigurationApplicationComponent.getChoicesFromElements(nextProps.displaySpecification.inputViewSpecification.elements, nextProps.viewData) || []
+ : ConfigurationApplicationComponent.getChoicesFromElements(nextProps.displaySpecification.viewSpecification.elements, nextProps.viewData),
+ };
return state;
}
return null;
@@ -282,24 +304,24 @@
private navigate = (path: string) => {
this.props.history.push(`${this.props.match.url}${path}`);
- }
+ };
private changeValueFor = (property: string, value: any) => {
this.setState({
viewData: {
...this.state.viewData,
- [property]: value
- }
+ [property]: value,
+ },
});
- }
+ };
private collectData = (elements: { [name: string]: ViewElement }) => {
- // ensure only active choises will be contained
+ // ensure only active choices will be contained
const viewData: { [key: string]: any } = { ...this.state.viewData };
- const choiseKeys = Object.keys(elements).filter(elmKey => isViewElementChoise(elements[elmKey]));
- const elementsToRemove = choiseKeys.reduce((acc, curChoiceKey) => {
- const currentChoice = elements[curChoiceKey] as ViewElementChoise;
- const selectedCase = this.state.choises[curChoiceKey].selectedCase;
+ const choiceKeys = Object.keys(elements).filter(elmKey => isViewElementChoice(elements[elmKey]));
+ const elementsToRemove = choiceKeys.reduce((acc, curChoiceKey) => {
+ const currentChoice = elements[curChoiceKey] as ViewElementChoice;
+ const selectedCase = this.state.choices[curChoiceKey].selectedCase;
Object.keys(currentChoice.cases).forEach(caseKey => {
const caseElements = currentChoice.cases[caseKey].elements;
if (caseKey === selectedCase) {
@@ -311,7 +333,7 @@
}
});
return;
- };
+ }
Object.keys(caseElements).forEach(caseElementKey => {
acc.push(caseElements[caseElementKey]);
});
@@ -325,17 +347,17 @@
}
return acc;
}, {} as { [key: string]: any });
- }
+ };
private isPolicyViewElementForbidden = (element: ViewElement, dataPath: string): boolean => {
const policy = getAccessPolicyByUrl(`${dataPath}/${element.id}`);
return !(policy.GET && policy.POST);
- }
+ };
private isPolicyModuleForbidden = (moduleName: string, dataPath: string): boolean => {
const policy = getAccessPolicyByUrl(`${dataPath}/${moduleName}`);
return !(policy.GET && policy.POST);
- }
+ };
private getEditorForViewElement = (uiElement: ViewElement): (null | React.ComponentType<BaseProps<any>>) => {
if (isViewElementEmpty(uiElement)) {
@@ -353,12 +375,12 @@
} else if (isViewElementUnion(uiElement)) {
return UIElementUnion;
} else {
- if (process.env.NODE_ENV !== "production") {
- console.error(`Unknown element type - ${(uiElement as any).uiType} in ${(uiElement as any).id}.`)
+ if (process.env.NODE_ENV !== 'production') {
+ console.error(`Unknown element type - ${(uiElement as any).uiType} in ${(uiElement as any).id}.`);
}
return null;
}
- }
+ };
private renderUIElement = (uiElement: ViewElement, viewData: { [key: string]: any }, keyProperty: string | undefined, editMode: boolean, isNew: boolean) => {
const isKey = (uiElement.label === keyProperty);
@@ -377,7 +399,7 @@
value={uiElement}
readOnly={!canEdit}
disabled={editMode && !canEdit}
- onChange={(e) => { this.changeValueFor(uiElement.id, e) }}
+ onChange={(e) => { this.changeValueFor(uiElement.id, e); }}
getEditorForViewElement={this.getEditorForViewElement}
/>;
} else {
@@ -391,7 +413,7 @@
value={uiElement}
readOnly={!canEdit}
disabled={editMode && !canEdit}
- onChange={(e) => { this.changeValueFor(uiElement.id, e) }}
+ onChange={(e) => { this.changeValueFor(uiElement.id, e); }}
/>)
: null;
}
@@ -418,14 +440,14 @@
// }
// };
- private renderUIChoise = (uiElement: ViewElementChoise, viewData: { [key: string]: any }, keyProperty: string | undefined, editMode: boolean, isNew: boolean) => {
+ private renderUIChoice = (uiElement: ViewElementChoice, viewData: { [key: string]: any }, keyProperty: string | undefined, editMode: boolean, isNew: boolean) => {
const isKey = (uiElement.label === keyProperty);
- const currentChoise = this.state.choises[uiElement.id];
- const currentCase = currentChoise && uiElement.cases[currentChoise.selectedCase];
+ const currentChoice = this.state.choices[uiElement.id];
+ const currentCase = currentChoice && uiElement.cases[currentChoice.selectedCase];
const canEdit = editMode && (isNew || (uiElement.config && !isKey));
- if (isViewElementChoise(uiElement)) {
+ if (isViewElementChoice(uiElement)) {
const subElements = currentCase?.elements;
return (
<>
@@ -435,14 +457,14 @@
aria-label={uiElement.label + '-selection'}
required={!!uiElement.mandatory}
onChange={(e) => {
- if (currentChoise.selectedCase === e.target.value) {
+ if (currentChoice.selectedCase === e.target.value) {
return; // nothing changed
}
- this.setState({ choises: { ...this.state.choises, [uiElement.id]: { ...this.state.choises[uiElement.id], selectedCase: e.target.value as string } } });
+ this.setState({ choices: { ...this.state.choices, [uiElement.id]: { ...this.state.choices[uiElement.id], selectedCase: e.target.value as string } } });
}}
readOnly={!canEdit}
disabled={editMode && !canEdit}
- value={this.state.choises[uiElement.id].selectedCase}
+ value={this.state.choices[uiElement.id].selectedCase}
inputProps={{
name: uiElement.id,
id: `select-${uiElement.id}`,
@@ -452,7 +474,7 @@
Object.keys(uiElement.cases).map(caseKey => {
const caseElm = uiElement.cases[caseKey];
return (
- <MenuItem key={caseElm.id} value={caseKey} aria-label={caseKey}><Tooltip title={caseElm.description || ''}><div style={{ width: "100%" }}>{caseElm.label}</div></Tooltip></MenuItem>
+ <MenuItem key={caseElm.id} value={caseKey} aria-label={caseKey}><Tooltip title={caseElm.description || ''}><div style={{ width: '100%' }}>{caseElm.label}</div></Tooltip></MenuItem>
);
})
}
@@ -463,13 +485,13 @@
const elm = subElements[elmKey];
return this.renderUIElement(elm, viewData, keyProperty, editMode, isNew);
})
- : <h3>Invalid Choise</h3>
+ : <h3>Invalid Choice</h3>
}
</>
);
} else {
- if (process.env.NODE_ENV !== "production") {
- console.error(`Unknown type - ${(uiElement as any).uiType} in ${(uiElement as any).id}.`)
+ if (process.env.NODE_ENV !== 'production') {
+ console.error(`Unknown type - ${(uiElement as any).uiType} in ${(uiElement as any).id}.`);
}
return null;
}
@@ -478,8 +500,6 @@
private renderUIView = (viewSpecification: ViewSpecification, dataPath: string, viewData: { [key: string]: any }, keyProperty: string | undefined, editMode: boolean, isNew: boolean) => {
const { classes } = this.props;
-
-
const orderFunc = (vsA: ViewElement, vsB: ViewElement) => {
if (keyProperty) {
// if (vsA.label === vsB.label) return 0;
@@ -497,15 +517,15 @@
const elm = viewSpecification.elements[cur];
if (isViewElementObjectOrList(elm)) {
acc.references.push(elm);
- } else if (isViewElementChoise(elm)) {
- acc.choises.push(elm);
+ } else if (isViewElementChoice(elm)) {
+ acc.choices.push(elm);
} else if (isViewElementRpc(elm)) {
acc.rpcs.push(elm);
} else {
acc.elements.push(elm);
}
return acc;
- }, { elements: [] as ViewElement[], references: [] as ViewElement[], choises: [] as ViewElementChoise[], rpcs: [] as ViewElementRpc[] });
+ }, { elements: [] as ViewElement[], references: [] as ViewElement[], choices: [] as ViewElementChoice[], rpcs: [] as ViewElementRpc[] });
sections.elements = sections.elements.sort(orderFunc);
@@ -523,15 +543,15 @@
? (
<div className={classes.section}>
{sections.references.map(element => (
- <UIElementReference key={element.id} element={element} disabled={editMode || this.isPolicyViewElementForbidden(element, dataPath)} onOpenReference={(elm) => { this.navigate(`/${elm.id}`) }} />
+ <UIElementReference key={element.id} element={element} disabled={editMode || this.isPolicyViewElementForbidden(element, dataPath)} onOpenReference={(elm) => { this.navigate(`/${elm.id}`); }} />
))}
</div>
) : null
}
- {sections.choises.length > 0
+ {sections.choices.length > 0
? (
<div className={classes.section}>
- {sections.choises.map(element => this.renderUIChoise(element, viewData, keyProperty, editMode, isNew))}
+ {sections.choices.map(element => this.renderUIChoice(element, viewData, keyProperty, editMode, isNew))}
</div>
) : null
}
@@ -539,7 +559,7 @@
? (
<div className={classes.section}>
{sections.rpcs.map(element => (
- <UIElementReference key={element.id} element={element} disabled={editMode || this.isPolicyViewElementForbidden(element, dataPath)} onOpenReference={(elm) => { this.navigate(`/${elm.id}`) }} />
+ <UIElementReference key={element.id} element={element} disabled={editMode || this.isPolicyViewElementForbidden(element, dataPath)} onOpenReference={(elm) => { this.navigate(`/${elm.id}`); }} />
))}
</div>
) : null
@@ -550,6 +570,7 @@
private renderUIViewSelector = (viewSpecification: ViewSpecification, dataPath: string, viewData: { [key: string]: any }, keyProperty: string | undefined, editMode: boolean, isNew: boolean) => {
const { classes } = this.props;
+
// group by module name
const modules = Object.keys(viewSpecification.elements).reduce<{ [key: string]: ViewSpecification }>((acc, cur) => {
const elm = viewSpecification.elements[cur];
@@ -565,6 +586,7 @@
{
moduleKeys.map(key => {
const moduleView = modules[key];
+
return (
<Accordion key={key} defaultExpanded={moduleKeys.length < 4} aria-label={key + '-panel'} >
<AccordionSummaryExt expandIcon={<ExpandMoreIcon />} aria-controls={`content-${key}`} id={`header-${key}`} disabled={this.isPolicyModuleForbidden(`${key}:`, dataPath)} >
@@ -584,8 +606,8 @@
private renderUIViewList(listSpecification: ViewSpecification, dataPath: string, listKeyProperty: string, apiDocPath: string, listData: { [key: string]: any }[]) {
const listElements = listSpecification.elements;
const apiDocPathCreate = apiDocPath ? `${location.origin}${apiDocPath
- .replace("$$$standard$$$", "topology-netconfnode%20resources%20-%20RestConf%20RFC%208040")
- .replace("$$$action$$$", "put")}${listKeyProperty ? `_${listKeyProperty.replace(/[\/=\-\:]/g, '_')}_` : '' }` : undefined;
+ .replace('$$$standard$$$', 'topology-netconfnode%20resources%20-%20RestConf%20RFC%208040')
+ .replace('$$$action$$$', 'put')}${listKeyProperty ? `_${listKeyProperty.replace(/[\/=\-\:]/g, '_')}_` : '' }` : undefined;
const config = listSpecification.config && listKeyProperty; // We can not configure a list with no key.
@@ -598,7 +620,7 @@
tooltip: 'Add',
ariaLabel:'add-element',
onClick: () => {
- navigate("[]"); // empty key means new element
+ navigate('[]'); // empty key means new element
},
disabled: !config,
};
@@ -615,11 +637,11 @@
const { classes, removeElement } = this.props;
- const DeleteIconWithConfirmation: React.FC<{disabled?: boolean, rowData: { [key: string]: any }, onReload: () => void }> = (props) => {
+ const DeleteIconWithConfirmation: React.FC<{ disabled?: boolean; rowData: { [key: string]: any }; onReload: () => void }> = (props) => {
const confirm = useConfirm();
return (
- <Tooltip disableInteractive title={"Remove"} >
+ <Tooltip disableInteractive title={'Remove'} >
<IconButton
disabled={props.disabled}
className={classes.button}
@@ -627,15 +649,15 @@
onClick={async (e) => {
e.stopPropagation();
e.preventDefault();
- confirm({ title: "Do you really want to delete this element ?", description: "This action is permanent!", confirmationButtonProps: { color: "secondary" }, cancellationButtonProps: { color:"inherit" } })
- .then(() => {
- let keyId = "";
- if (listKeyProperty && listKeyProperty.split(" ").length > 1) {
- keyId += listKeyProperty.split(" ").map(id => props.rowData[id]).join(",");
+ confirm({ title: 'Do you really want to delete this element ?', description: 'This action is permanent!', confirmationButtonProps: { color: 'secondary' }, cancellationButtonProps: { color:'inherit' } })
+ .then(() => {
+ let keyId = '';
+ if (listKeyProperty && listKeyProperty.split(' ').length > 1) {
+ keyId += listKeyProperty.split(' ').map(id => props.rowData[id]).join(',');
} else {
- keyId = props.rowData[listKeyProperty];
- }
- return removeElement(`${this.props.vPath}[${keyId}]`)
+ keyId = props.rowData[listKeyProperty];
+ }
+ return removeElement(`${this.props.vPath}[${keyId}]`);
}).then(props.onReload);
}}
size="large">
@@ -643,44 +665,46 @@
</IconButton>
</Tooltip>
);
- }
+ };
return (
<SelectElementTable stickyHeader idProperty={listKeyProperty} tableId={null} rows={listData} customActionButtons={apiDocPathCreate ? [addNewElementAction, addWithApiDocElementAction] : [addNewElementAction]} columns={
Object.keys(listElements).reduce<ColumnModel<{ [key: string]: any }>[]>((acc, cur) => {
const elm = listElements[cur];
- if (elm.uiType !== "object" && listData.every(entry => entry[elm.label] != null)) {
+ if (elm.uiType !== 'object' && listData.every(entry => entry[elm.label] != null)) {
if (elm.label !== listKeyProperty) {
- acc.push(elm.uiType === "boolean"
+ acc.push(elm.uiType === 'boolean'
? { property: elm.label, type: ColumnType.boolean }
- : elm.uiType === "date"
+ : elm.uiType === 'date'
? { property: elm.label, type: ColumnType.date }
- : { property: elm.label, type: elm.uiType === "number" ? ColumnType.numeric : ColumnType.text });
+ : { property: elm.label, type: elm.uiType === 'number' ? ColumnType.numeric : ColumnType.text });
} else {
- acc.unshift(elm.uiType === "boolean"
+ acc.unshift(elm.uiType === 'boolean'
? { property: elm.label, type: ColumnType.boolean }
- : elm.uiType === "date"
+ : elm.uiType === 'date'
? { property: elm.label, type: ColumnType.date }
- : { property: elm.label, type: elm.uiType === "number" ? ColumnType.numeric : ColumnType.text });
+ : { property: elm.label, type: elm.uiType === 'number' ? ColumnType.numeric : ColumnType.text });
}
}
return acc;
}, []).concat([{
- property: "Actions", disableFilter: true, disableSorting: true, type: ColumnType.custom, customControl: (({ rowData }) => {
+ property: 'Actions', disableFilter: true, disableSorting: true, type: ColumnType.custom, customControl: (({ rowData }) => {
return (
<DeleteIconWithConfirmation disabled={!config} rowData={rowData} onReload={() => this.props.vPath && this.props.reloadView(this.props.vPath)} />
);
- })
+ }),
}])
} onHandleClick={(ev, row) => {
ev.preventDefault();
- let keyId = ""
- if (listKeyProperty && listKeyProperty.split(" ").length > 1) {
- keyId += listKeyProperty.split(" ").map(id => row[id]).join(",");
+ let keyId = '';
+ if (listKeyProperty && listKeyProperty.split(' ').length > 1) {
+ keyId += listKeyProperty.split(' ').map(id => row[id]).join(',');
} else {
keyId = row[listKeyProperty];
}
- listKeyProperty && navigate(`[${encodeURIComponent(keyId)}]`); // Do not navigate without key.
+ if (listKeyProperty) {
+ navigate(`[${encodeURIComponent(keyId)}]`); // Do not navigate without key.
+ }
}} ></SelectElementTable>
);
}
@@ -704,17 +728,17 @@
const sections = inputViewSpecification && Object.keys(inputViewSpecification.elements).reduce((acc, cur) => {
const elm = inputViewSpecification.elements[cur];
if (isViewElementObjectOrList(elm)) {
- console.error("Object should not appear in RPC view !");
- } else if (isViewElementChoise(elm)) {
- acc.choises.push(elm);
+ console.error('Object should not appear in RPC view !');
+ } else if (isViewElementChoice(elm)) {
+ acc.choices.push(elm);
} else if (isViewElementRpc(elm)) {
- console.error("RPC should not appear in RPC view !");
+ console.error('RPC should not appear in RPC view !');
} else {
acc.elements.push(elm);
}
return acc;
- }, { elements: [] as ViewElement[], references: [] as ViewElement[], choises: [] as ViewElementChoise[], rpcs: [] as ViewElementRpc[] })
- || { elements: [] as ViewElement[], references: [] as ViewElement[], choises: [] as ViewElementChoise[], rpcs: [] as ViewElementRpc[] };
+ }, { elements: [] as ViewElement[], references: [] as ViewElement[], choices: [] as ViewElementChoice[], rpcs: [] as ViewElementRpc[] })
+ || { elements: [] as ViewElement[], references: [] as ViewElement[], choices: [] as ViewElementChoice[], rpcs: [] as ViewElementRpc[] };
sections.elements = sections.elements.sort(orderFunc);
@@ -728,10 +752,10 @@
</div>
) : null
}
- { sections.choises.length > 0
+ { sections.choices.length > 0
? (
<div className={classes.section}>
- {sections.choises.map(element => this.renderUIChoise(element, inputViewData, keyProperty, editMode, isNew))}
+ {sections.choices.map(element => this.renderUIChoice(element, inputViewData, keyProperty, editMode, isNew))}
</div>
) : null
}
@@ -747,13 +771,13 @@
</div>
</>
);
- };
+ }
private renderBreadCrumps() {
const { editMode } = this.state;
const { displaySpecification, vPath, nodeId } = this.props;
const pathParts = splitVPath(vPath!, /(?:([^\/\["]+)(?:\[([^\]]*)\])?)/g); // 1 = property / 2 = optional key
- let lastPath = `/configuration`;
+ let lastPath = '/configuration';
let basePath = `/configuration/${nodeId}`;
return (
<div className={this.props.classes.header}>
@@ -774,7 +798,7 @@
pathParts.map(([prop, key], ind) => {
const path = `${basePath}/${prop}`;
const keyPath = key && `${basePath}/${prop}[${key}]`;
- const propTitle = prop.replace(/^[^:]+:/, "");
+ const propTitle = prop.replace(/^[^:]+:/, '');
const ret = (
<span key={ind}>
<Link underline="hover" color="inherit" href="#"
@@ -789,8 +813,8 @@
onClick={(ev: React.MouseEvent<HTMLElement>) => {
ev.preventDefault();
this.props.history.push(keyPath);
- }}>{`[${key && key.replace(/\%2C/g, ",")}]`}</Link> || null
- }
+ }}>{`[${key && key.replace(/\%2C/g, ',')}]`}</Link> || null
+ }
</span>
);
lastPath = basePath;
@@ -802,7 +826,9 @@
</div>
{this.state.editMode && (
<Fab color="secondary" aria-label="back-button" className={this.props.classes.fab} onClick={async () => {
- this.props.vPath && (await this.props.reloadView(this.props.vPath));
+ if (this.props.vPath) {
+ await this.props.reloadView(this.props.vPath);
+ }
this.setState({ editMode: false });
}} ><ArrowBack /></Fab>
) || null}
@@ -810,7 +836,7 @@
displaySpecification.displayMode === DisplayModeType.displayAsObject && displaySpecification.viewSpecification.canEdit && (<div>
<Fab color="secondary" aria-label={editMode ? 'save-button' : 'edit-button'} className={this.props.classes.fab} onClick={() => {
if (this.state.editMode) {
- // ensure only active choises will be contained
+ // ensure only active choices will be contained
const resultingViewData = this.collectData(displaySpecification.viewSpecification.elements);
this.props.onUpdateData(this.props.vPath!, resultingViewData);
}
@@ -830,7 +856,7 @@
private renderValueSelector() {
const { listKeyProperty, listSpecification, listData, onValueSelected } = this.props;
if (!listKeyProperty || !listSpecification) {
- throw new Error("ListKex ot view not specified.");
+ throw new Error('ListKex ot view not specified.');
}
return (
@@ -838,11 +864,11 @@
<SelectElementTable stickyHeader idProperty={listKeyProperty} tableId={null} rows={listData} columns={
Object.keys(listSpecification.elements).reduce<ColumnModel<{ [key: string]: any }>[]>((acc, cur) => {
const elm = listSpecification.elements[cur];
- if (elm.uiType !== "object" && listData.every(entry => entry[elm.label] != null)) {
+ if (elm.uiType !== 'object' && listData.every(entry => entry[elm.label] != null)) {
if (elm.label !== listKeyProperty) {
- acc.push({ property: elm.label, type: elm.uiType === "number" ? ColumnType.numeric : ColumnType.text });
+ acc.push({ property: elm.label, type: elm.uiType === 'number' ? ColumnType.numeric : ColumnType.text });
} else {
- acc.unshift({ property: elm.label, type: elm.uiType === "number" ? ColumnType.numeric : ColumnType.text });
+ acc.unshift({ property: elm.label, type: elm.uiType === 'number' ? ColumnType.numeric : ColumnType.text });
}
}
return acc;
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/views/networkElementSelector.tsx b/sdnr/wt/odlux/apps/configurationApp/src/views/networkElementSelector.tsx
index 1a1008d..e96f40d 100644
--- a/sdnr/wt/odlux/apps/configurationApp/src/views/networkElementSelector.tsx
+++ b/sdnr/wt/odlux/apps/configurationApp/src/views/networkElementSelector.tsx
@@ -16,15 +16,15 @@
* ============LICENSE_END==========================================================================
*/
-import * as React from 'react';
+import React from 'react';
import { RouteComponentProps, withRouter } from 'react-router-dom';
-import connect, { IDispatcher, Connect } from "../../../../framework/src/flux/connect";
-import { IApplicationStoreState } from "../../../../framework/src/store/applicationStore";
-import { MaterialTable, MaterialTableCtorType, ColumnType } from "../../../../framework/src/components/material-table";
-import { createConnectedNetworkElementsProperties, createConnectedNetworkElementsActions } from "../../../configurationApp/src/handlers/connectedNetworkElementsHandler";
+import { connect, IDispatcher, Connect } from '../../../../framework/src/flux/connect';
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+import { MaterialTable, MaterialTableCtorType, ColumnType } from '../../../../framework/src/components/material-table';
-import { NetworkElementConnection } from "../models/networkElementConnection";
+import { NetworkElementConnection } from '../models/networkElementConnection';
+import { createConnectedNetworkElementsProperties, createConnectedNetworkElementsActions } from '../../../configurationApp/src/handlers/connectedNetworkElementsHandler';
const mapProps = (state: IApplicationStoreState) => ({
@@ -47,20 +47,20 @@
if (!initialSorted) {
initialSorted = true;
- this.props.connectedNetworkElementsActions.onHandleRequestSort("node-id");
+ this.props.connectedNetworkElementsActions.onHandleRequestSort('node-id');
} else
this.props.connectedNetworkElementsActions.onRefresh();
}
render() {
return (
- <ConnectedElementTable stickyHeader tableId="configurable-elements-table" onHandleClick={(e, row) => { this.props.history.push(`${this.props.match.path}/${row.nodeId}`) }} columns={[
- { property: "nodeId", title: "Node Name", type: ColumnType.text },
- { property: "isRequired", title: "Required", type: ColumnType.boolean },
- { property: "host", title: "Host", type: ColumnType.text },
- { property: "port", title: "Port", type: ColumnType.numeric },
- { property: "coreModelCapability", title: "Core Model", type: ColumnType.text },
- { property: "deviceType", title: "Type", type: ColumnType.text },
+ <ConnectedElementTable stickyHeader tableId="configurable-elements-table" onHandleClick={(e, row) => { this.props.history.push(`${this.props.match.path}/${row.nodeId}`); }} columns={[
+ { property: 'nodeId', title: 'Node Name', type: ColumnType.text },
+ { property: 'isRequired', title: 'Required', type: ColumnType.boolean },
+ { property: 'host', title: 'Host', type: ColumnType.text },
+ { property: 'port', title: 'Port', type: ColumnType.numeric },
+ { property: 'coreModelCapability', title: 'Core Model', type: ColumnType.text },
+ { property: 'deviceType', title: 'Type', type: ColumnType.text },
]} idProperty="id" {...this.props.connectedNetworkElementsActions} {...this.props.connectedNetworkElementsProperties} asynchronus >
</ConnectedElementTable>
);
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/yang/whenParser.ts b/sdnr/wt/odlux/apps/configurationApp/src/yang/whenParser.ts
new file mode 100644
index 0000000..fa2968c
--- /dev/null
+++ b/sdnr/wt/odlux/apps/configurationApp/src/yang/whenParser.ts
@@ -0,0 +1,235 @@
+enum WhenTokenType {
+ AND = 'AND',
+ OR = 'OR',
+ NOT = 'NOT',
+ EQUALS = 'EQUALS',
+ COMMA = 'COMMA',
+ STRING = 'STRING',
+ FUNCTION = 'FUNCTION',
+ IDENTIFIER = 'IDENTIFIER',
+ OPEN_PAREN = 'OPEN_PAREN',
+ CLOSE_PAREN = 'CLOSE_PAREN',
+ EXPRESSION = 'EXPRESSION',
+}
+
+type Token = {
+ type: WhenTokenType;
+ value: string;
+};
+
+const isAlpha = (char: string) => /[a-z]/i.test(char);
+
+const isAlphaNumeric = (char: string) => /[A-Za-z0-9_\-/:\.]/i.test(char);
+
+const lex = (input: string) : Token[] => {
+ let tokens = [] as any[];
+ let current = 0;
+
+ while (current < input.length) {
+ let char = input[current];
+
+ if (char === ' ') {
+ current++;
+ continue;
+ }
+
+ if (char === '(') {
+ tokens.push({ type: WhenTokenType.OPEN_PAREN, value: char });
+ current++;
+ continue;
+ }
+
+ if (char === ')') {
+ tokens.push({ type: WhenTokenType.CLOSE_PAREN, value: char });
+ current++;
+ continue;
+ }
+
+ if (char === '=') {
+ tokens.push({ type: WhenTokenType.EQUALS, value: char });
+ current++;
+ continue;
+ }
+
+ if (char === ',') {
+ tokens.push({ type: WhenTokenType.COMMA, value: char });
+ current++;
+ continue;
+ }
+
+ if (char === '\"' || char === '\'') {
+ let value = '';
+ let start = current;
+ current++;
+
+ while (current < input.length) {
+ let innerChar = input[current];
+ if (innerChar === '\\') {
+ value += input[current] + input[current + 1];
+ current += 2;
+ } else if (innerChar === input[start]) {
+ current++;
+ break;
+ } else {
+ value += innerChar;
+ current++;
+ }
+ }
+
+ tokens.push({ type: WhenTokenType.STRING, value });
+ continue;
+ }
+
+ if (isAlpha(char)) {
+ let value = '';
+ while (isAlpha(char)) {
+ value += char;
+ char = input[++current];
+ }
+
+ switch (value) {
+ case 'and':
+ tokens.push({ type: WhenTokenType.AND });
+ break;
+ case 'or':
+ tokens.push({ type: WhenTokenType.OR });
+ break;
+ case 'not':
+ tokens.push({ type: WhenTokenType.NOT });
+ break;
+ case 'eq':
+ tokens.push({ type: WhenTokenType.EQUALS });
+ break;
+ default:
+ while (isAlphaNumeric(char)) {
+ value += char;
+ char = input[++current];
+ }
+ tokens.push({ type: WhenTokenType.IDENTIFIER, value });
+ }
+
+ continue;
+ }
+ if (isAlphaNumeric(char)) {
+ let value = '';
+ while (isAlphaNumeric(char)) {
+ value += char;
+ char = input[++current];
+ }
+
+ tokens.push({ type: WhenTokenType.IDENTIFIER, value });
+ continue;
+ }
+ throw new TypeError(`I don't know what this character is: ${char}`);
+ }
+ return tokens;
+};
+
+type WhenAST = {
+ type: WhenTokenType;
+ left?: WhenAST;
+ right?: WhenAST;
+ value?: string | WhenAST;
+ name?: string;
+ args?: WhenAST[];
+};
+
+const precedence : { [index: string] : number } = {
+ 'EQUALS': 4,
+ 'NOT': 3,
+ 'AND': 2,
+ 'OR': 1,
+};
+
+const parseWhen = (whenExpression: string) => {
+ const tokens = lex(whenExpression);
+ let current = 0;
+
+ const walk = (precedenceLevel = 0) : WhenAST => {
+ let token = tokens[current];
+ let node: WhenAST | null = null;
+
+ if (token.type === WhenTokenType.OPEN_PAREN) {
+ token = tokens[++current];
+ let innerNode: WhenAST = { type: WhenTokenType.EXPRESSION, value: walk() };
+ token = tokens[current];
+
+ while (token.type !== WhenTokenType.CLOSE_PAREN) {
+ innerNode = {
+ type: token.type,
+ value: token.value,
+ left: innerNode,
+ right: walk(),
+ };
+ token = tokens[current];
+ }
+ current++;
+ return innerNode;
+ }
+
+ if (token.type === WhenTokenType.STRING ) {
+ current++;
+ node = { type: token.type, value: token.value };
+ }
+
+ if (token.type === WhenTokenType.NOT) {
+ token = tokens[++current];
+ node = { type: WhenTokenType.NOT, value: token.value, right: walk() };
+ }
+
+ if (token.type === WhenTokenType.IDENTIFIER) {
+ const nextToken = tokens[current + 1];
+ if (nextToken.type === WhenTokenType.OPEN_PAREN) {
+ let name = token.value;
+ token = tokens[++current];
+
+ let args = [];
+ token = tokens[++current];
+
+ while (token.type !== WhenTokenType.CLOSE_PAREN) {
+ if (token.type === WhenTokenType.COMMA) {
+ current++;
+ } else {
+ args.push(walk());
+ }
+ token = tokens[current];
+ }
+
+ current++;
+ node = { type: WhenTokenType.FUNCTION, name, args };
+ } else {
+ current++;
+ node = { type: WhenTokenType.IDENTIFIER, value: token.value };
+ }
+ }
+
+ if (!node) throw new TypeError('Unexpected token: ' + token.type);
+
+ token = tokens[current];
+ while (current < tokens.length && precedence[token.type] >= precedenceLevel) {
+ console.log(current, tokens[current], tokens[current].type, precedenceLevel, precedence[token.type]);
+ token = tokens[current];
+ if (token.type === WhenTokenType.EQUALS || token.type === WhenTokenType.AND || token.type === WhenTokenType.OR) {
+ current++;
+ node = {
+ type: token.type,
+ left: node,
+ right: walk(precedence[token.type]),
+ };
+ } else {
+ break;
+ }
+ }
+
+ return node;
+
+ };
+
+ return walk();
+};
+
+export {
+ parseWhen,
+ WhenAST,
+ WhenTokenType,
+};
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/yang/yangParser.ts b/sdnr/wt/odlux/apps/configurationApp/src/yang/yangParser.ts
index e8e636f..cc25201 100644
--- a/sdnr/wt/odlux/apps/configurationApp/src/yang/yangParser.ts
+++ b/sdnr/wt/odlux/apps/configurationApp/src/yang/yangParser.ts
@@ -1,3 +1,6 @@
+/* eslint-disable @typescript-eslint/no-loss-of-precision */
+/* eslint-disable @typescript-eslint/no-unused-expressions */
+/* eslint-disable @typescript-eslint/naming-convention */
/**
* ============LICENSE_START========================================================================
* ONAP : ccsdk feature sdnr wt odlux
@@ -15,14 +18,30 @@
* the License.
* ============LICENSE_END==========================================================================
*/
-import { Token, Statement, Module, Identity, ModuleState } from "../models/yang";
+import { Token, Statement, Module, Identity, ModuleState } from '../models/yang';
import {
- ViewSpecification, ViewElement, isViewElementObjectOrList, ViewElementBase,
- isViewElementReference, ViewElementChoise, ViewElementBinary, ViewElementString, isViewElementString,
- isViewElementNumber, ViewElementNumber, Expression, YangRange, ViewElementUnion, ViewElementRpc, isViewElementRpc, ResolveFunction, ViewElementDate
-} from "../models/uiModels";
-import { yangService } from "../services/yangService";
+ Expression,
+ ViewElement,
+ ViewElementBase,
+ ViewSpecification,
+ ViewElementNumber,
+ ViewElementString,
+ ViewElementChoice,
+ ViewElementUnion,
+ ViewElementRpc,
+ isViewElementObjectOrList,
+ isViewElementNumber,
+ isViewElementString,
+ isViewElementRpc,
+ ResolveFunction,
+ YangRange,
+} from '../models/uiModels';
+import { yangService } from '../services/yangService';
+const LOGLEVEL = +(localStorage.getItem('log.odlux.app.configuration.yang.yangParser') || 0);
+
+import { LogLevel } from '../../../../framework/src/utilities/logLevel';
+import { parseWhen, WhenAST, WhenTokenType } from './whenParser';
export const splitVPath = (vPath: string, vPathParser: RegExp): RegExpMatchArray[] => {
const pathParts: RegExpMatchArray[] = [];
@@ -32,21 +51,22 @@
if (partMatch) {
pathParts.push(partMatch);
}
- } while (partMatch)
+ } while (partMatch);
return pathParts;
-}
+};
class YangLexer {
private pos: number = 0;
- private buf: string = "";
+
+ private buf: string = '';
constructor(input: string) {
this.pos = 0;
this.buf = input;
}
- private _optable: { [key: string]: string } = {
+ private _opTable: { [key: string]: string } = {
';': 'SEMI',
'{': 'L_BRACE',
'}': 'R_BRACE',
@@ -66,7 +86,7 @@
private _isAlpha(char: string): boolean {
return (char >= 'a' && char <= 'z') ||
- (char >= 'A' && char <= 'Z')
+ (char >= 'A' && char <= 'Z');
}
private _isAlphanum(char: string): boolean {
@@ -74,7 +94,7 @@
char === '_' || char === '-' || char === '.';
}
- private _skipNontokens() {
+ private _skipNonTokens() {
while (this.pos < this.buf.length) {
const char = this.buf.charAt(this.pos);
if (this._isWhitespace(char)) {
@@ -90,11 +110,11 @@
let end_index = this.pos + 1;
while (end_index < this.buf.length) {
const char = this.buf.charAt(end_index);
- if (char === "\\") {
+ if (char === '\\') {
end_index += 2;
continue;
- };
- if (terminator === null && (this._isWhitespace(char) || this._optable[char] !== undefined) || char === terminator) {
+ }
+ if (terminator === null && (this._isWhitespace(char) || this._opTable[char] !== undefined) || char === terminator) {
break;
}
end_index++;
@@ -109,7 +129,7 @@
name: 'STRING',
value: this.buf.substring(start, end),
start,
- end
+ end,
};
this.pos = terminator ? end + 1 : end;
return tok;
@@ -122,8 +142,8 @@
++endpos;
}
- let name = 'IDENTIFIER'
- if (this.buf.charAt(endpos) === ":") {
+ let name = 'IDENTIFIER';
+ if (this.buf.charAt(endpos) === ':') {
name = 'IDENTIFIERREF';
++endpos;
while (endpos < this.buf.length && this._isAlphanum(this.buf.charAt(endpos))) {
@@ -135,7 +155,7 @@
name: name,
value: this.buf.substring(this.pos, endpos),
start: this.pos,
- end: endpos
+ end: endpos,
};
this.pos = endpos;
@@ -153,7 +173,7 @@
name: 'NUMBER',
value: this.buf.substring(this.pos, endpos),
start: this.pos,
- end: endpos
+ end: endpos,
};
this.pos = endpos;
return tok;
@@ -171,7 +191,7 @@
private _processBlockComment() {
var endpos = this.pos + 2;
// Skip until the end of the line
- while (endpos < this.buf.length && !((this.buf.charAt(endpos) === "/" && this.buf.charAt(endpos - 1) === "*"))) {
+ while (endpos < this.buf.length && !((this.buf.charAt(endpos) === '/' && this.buf.charAt(endpos - 1) === '*'))) {
endpos++;
}
this.pos = endpos + 1;
@@ -179,87 +199,87 @@
public tokenize(): Token[] {
const result: Token[] = [];
- this._skipNontokens();
+ this._skipNonTokens();
while (this.pos < this.buf.length) {
const char = this.buf.charAt(this.pos);
- const op = this._optable[char];
+ const op = this._opTable[char];
if (op !== undefined) {
result.push({ name: op, value: char, start: this.pos, end: ++this.pos });
} else if (this._isAlpha(char)) {
result.push(this._processIdentifier());
- this._skipNontokens();
+ this._skipNonTokens();
const peekChar = this.buf.charAt(this.pos);
- if (this._optable[peekChar] === undefined) {
- result.push((peekChar !== "'" && peekChar !== '"')
+ if (this._opTable[peekChar] === undefined) {
+ result.push((peekChar !== '\'' && peekChar !== '"')
? this._processString(null)
: this._processString(peekChar));
}
- } else if (char === '/' && this.buf.charAt(this.pos + 1) === "/") {
+ } else if (char === '/' && this.buf.charAt(this.pos + 1) === '/') {
this._processLineComment();
- } else if (char === '/' && this.buf.charAt(this.pos + 1) === "*") {
+ } else if (char === '/' && this.buf.charAt(this.pos + 1) === '*') {
this._processBlockComment();
} else {
- throw Error('Token error at ' + this.pos + " " + this.buf[this.pos]);
+ throw Error('Token error at ' + this.pos + ' ' + this.buf[this.pos]);
}
- this._skipNontokens();
+ this._skipNonTokens();
}
return result;
}
public tokenize2(): Statement {
- let stack: Statement[] = [{ key: "ROOT", sub: [] }];
+ let stack: Statement[] = [{ key: 'ROOT', sub: [] }];
let current: Statement | null = null;
- this._skipNontokens();
+ this._skipNonTokens();
while (this.pos < this.buf.length) {
const char = this.buf.charAt(this.pos);
- const op = this._optable[char];
+ const op = this._opTable[char];
if (op !== undefined) {
- if (op === "L_BRACE") {
+ if (op === 'L_BRACE') {
current && stack.unshift(current);
current = null;
- } else if (op === "R_BRACE") {
+ } else if (op === 'R_BRACE') {
current = stack.shift() || null;
}
this.pos++;
- } else if (this._isAlpha(char) || char === "_") {
+ } else if (this._isAlpha(char) || char === '_') {
const key = this._processIdentifier().value;
- this._skipNontokens();
+ this._skipNonTokens();
let peekChar = this.buf.charAt(this.pos);
let arg = undefined;
- if (this._optable[peekChar] === undefined) {
- arg = (peekChar === '"' || peekChar === "'")
+ if (this._opTable[peekChar] === undefined) {
+ arg = (peekChar === '"' || peekChar === '\'')
? this._processString(peekChar).value
: this._processString(null).value;
}
do {
- this._skipNontokens();
+ this._skipNonTokens();
peekChar = this.buf.charAt(this.pos);
- if (peekChar !== "+") break;
+ if (peekChar !== '+') break;
this.pos++;
- this._skipNontokens();
+ this._skipNonTokens();
peekChar = this.buf.charAt(this.pos);
- arg += (peekChar === '"' || peekChar === "'")
+ arg += (peekChar === '"' || peekChar === '\'')
? this._processString(peekChar).value
: this._processString(null).value;
} while (true);
current = { key, arg, sub: [] };
stack[0].sub!.push(current);
- } else if (char === '/' && this.buf.charAt(this.pos + 1) === "/") {
+ } else if (char === '/' && this.buf.charAt(this.pos + 1) === '/') {
this._processLineComment();
- } else if (char === '/' && this.buf.charAt(this.pos + 1) === "*") {
+ } else if (char === '/' && this.buf.charAt(this.pos + 1) === '*') {
this._processBlockComment();
} else {
- throw Error('Token error at ' + this.pos + " " + this.buf.slice(this.pos - 10, this.pos + 10));
+ throw Error('Token error at ' + this.pos + ' ' + this.buf.slice(this.pos - 10, this.pos + 10));
}
- this._skipNontokens();
+ this._skipNonTokens();
}
- if (stack[0].key !== "ROOT" || !stack[0].sub![0]) {
- throw new Error("Internal Perser Error");
+ if (stack[0].key !== 'ROOT' || !stack[0].sub![0]) {
+ throw new Error('Internal Perser Error');
}
return stack[0].sub![0];
}
@@ -269,25 +289,33 @@
private _groupingsToResolve: ViewSpecification[] = [];
private _identityToResolve: (() => void)[] = [];
+
private _unionsToResolve: (() => void)[] = [];
+
private _modulesToResolve: (() => void)[] = [];
private _modules: { [name: string]: Module } = {};
+
private _views: ViewSpecification[] = [{
- id: "0",
- name: "root",
- language: "en-US",
+ id: '0',
+ name: 'root',
+ language: 'en-US',
canEdit: false,
config: true,
- parentView: "0",
- title: "root",
+ parentView: '0',
+ title: 'root',
elements: {},
}];
- public static ResolveStack = Symbol("ResolveStack");
+ public static ResolveStack = Symbol('ResolveStack');
- constructor(private _unavailableCapabilities: { failureReason: string; capability: string; }[] = [], private _importOnlyModules: { name: string; revision: string; }[] = [], private nodeId: string) {
-
+ constructor(
+ private nodeId: string,
+ private _capabilityRevisionMap: { [capability: string]: string } = {},
+ private _unavailableCapabilities: { failureReason: string; capability: string }[] = [],
+ private _importOnlyModules: { name: string; revision: string }[] = [],
+ ) {
+
}
public get modules() {
@@ -300,8 +328,12 @@
public async addCapability(capability: string, version?: string, parentImportOnlyModule?: boolean) {
// do not add twice
- if (this._modules[capability]) {
- // console.warn(`Skipped capability: ${capability} since already contained.` );
+ const existingCapability = this._modules[capability];
+ const latestVersionExisting = existingCapability && Object.keys(existingCapability.revisions).sort().reverse()[0];
+ if ((latestVersionExisting && version) && (version <= latestVersionExisting)) {
+ if (LOGLEVEL == LogLevel.Warning) {
+ console.warn(`Skipped capability: ${capability}:${version || ''} since already contained.`);
+ }
return;
}
@@ -310,14 +342,15 @@
// // console.warn(`Skipped capability: ${capability} since it is marked as unavailable.` );
// return;
// }
+
const data = await yangService.getCapability(capability, this.nodeId, version);
if (!data) {
- throw new Error(`Could not load yang file for ${capability}.`);
+ throw new Error(`Could not load yang file for ${capability}:${version || ''}.`);
}
const rootStatement = new YangLexer(data).tokenize2();
- if (rootStatement.key !== "module") {
+ if (rootStatement.key !== 'module') {
throw new Error(`Root element of ${capability} is not a module.`);
}
if (rootStatement.arg !== capability) {
@@ -326,10 +359,32 @@
const isUnavailable = this._unavailableCapabilities.some(c => c.capability === capability);
const isImportOnly = parentImportOnlyModule === true || this._importOnlyModules.some(c => c.name === capability);
+
+ // extract revisions
+ const revisions = this.extractNodes(rootStatement, 'revision').reduce<{ [version: string]: {} }>((acc, revision) => {
+ if (!revision.arg) {
+ throw new Error(`Module [${rootStatement.arg}] has a version w/o version number.`);
+ }
+ const description = this.extractValue(revision, 'description');
+ const reference = this.extractValue(revision, 'reference');
+ acc[revision.arg] = {
+ description,
+ reference,
+ };
+ return acc;
+ }, {});
+
+ const latestVersionLoaded = Object.keys(revisions).sort().reverse()[0];
+ if (existingCapability && latestVersionExisting >= latestVersionLoaded) {
+ if (LOGLEVEL == LogLevel.Warning) {
+ console.warn(`Skipped capability: ${capability}:${latestVersionLoaded} since ${capability}:${latestVersionExisting} already contained.`);
+ }
+ return;
+ }
const module = this._modules[capability] = {
name: rootStatement.arg,
- revisions: {},
+ revisions,
imports: {},
features: {},
identities: {},
@@ -339,10 +394,10 @@
views: {},
elements: {},
state: isUnavailable
- ? ModuleState.unavailable
- : isImportOnly
- ? ModuleState.importOnly
- : ModuleState.stable,
+ ? ModuleState.unavailable
+ : isImportOnly
+ ? ModuleState.importOnly
+ : ModuleState.stable,
};
await this.handleModule(module, rootStatement, capability);
@@ -351,84 +406,66 @@
private async handleModule(module: Module, rootStatement: Statement, capability: string) {
// extract namespace && prefix
- module.namespace = this.extractValue(rootStatement, "namespace");
- module.prefix = this.extractValue(rootStatement, "prefix");
+ module.namespace = this.extractValue(rootStatement, 'namespace');
+ module.prefix = this.extractValue(rootStatement, 'prefix');
if (module.prefix) {
module.imports[module.prefix] = capability;
}
- // extract revisions
- const revisions = this.extractNodes(rootStatement, "revision");
- module.revisions = {
- ...module.revisions,
- ...revisions.reduce<{ [version: string]: {} }>((acc, version) => {
- if (!version.arg) {
- throw new Error(`Module [${module.name}] has a version w/o version number.`);
- }
- const description = this.extractValue(version, "description");
- const reference = this.extractValue(version, "reference");
- acc[version.arg] = {
- description,
- reference,
- };
- return acc;
- }, {})
- };
-
// extract features
- const features = this.extractNodes(rootStatement, "feature");
+ const features = this.extractNodes(rootStatement, 'feature');
module.features = {
...module.features,
...features.reduce<{ [version: string]: {} }>((acc, feature) => {
if (!feature.arg) {
throw new Error(`Module [${module.name}] has a feature w/o name.`);
}
- const description = this.extractValue(feature, "description");
+ const description = this.extractValue(feature, 'description');
acc[feature.arg] = {
description,
};
return acc;
- }, {})
+ }, {}),
};
// extract imports
- const imports = this.extractNodes(rootStatement, "import");
+ const imports = this.extractNodes(rootStatement, 'import');
module.imports = {
...module.imports,
...imports.reduce<{ [key: string]: string }>((acc, imp) => {
- const prefix = imp.sub && imp.sub.filter(s => s.key === "prefix");
+ const prefix = imp.sub && imp.sub.filter(s => s.key === 'prefix');
if (!imp.arg) {
throw new Error(`Module [${module.name}] has an import with neither name nor prefix.`);
}
acc[prefix && prefix.length === 1 && prefix[0].arg || imp.arg] = imp.arg;
return acc;
- }, {})
+ }, {}),
};
// import all required files and set module state
if (imports) for (let ind = 0; ind < imports.length; ++ind) {
- const moduleName = imports[ind].arg!;
+ const moduleName = imports[ind].arg!;
- //TODO: Fix imports getting loaded without revision
- await this.addCapability(moduleName, undefined, module.state === ModuleState.importOnly);
+ const revision = this._capabilityRevisionMap[moduleName] || undefined;
+ await this.addCapability(moduleName, revision, module.state === ModuleState.importOnly);
const importedModule = this._modules[imports[ind].arg!];
if (importedModule && importedModule.state > ModuleState.stable) {
- module.state = Math.max(module.state, ModuleState.instable);
+ module.state = Math.max(module.state, ModuleState.instable);
}
}
- this.extractTypeDefinitions(rootStatement, module, "");
+ this.extractTypeDefinitions(rootStatement, module, '');
- this.extractIdentities(rootStatement, 0, module, "");
+ this.extractIdentities(rootStatement, 0, module, '');
- const groupings = this.extractGroupings(rootStatement, 0, module, "");
+ const groupings = this.extractGroupings(rootStatement, 0, module, '');
this._views.push(...groupings);
- const augments = this.extractAugments(rootStatement, 0, module, "");
+ const augments = this.extractAugments(rootStatement, 0, module, '');
this._views.push(...augments);
// the default for config on module level is config = true;
- const [currentView, subViews] = this.extractSubViews(rootStatement, 0, module, "");
+ const [currentView, subViews] = this.extractSubViews(rootStatement, 0, module, '');
this._views.push(currentView, ...subViews);
// create the root elements for this module
@@ -443,7 +480,7 @@
const viewIdIndex = Number(viewElement.viewId);
module.views[key] = this._views[viewIdIndex];
}
-
+
// add only the UI View if the module is available
if (module.state === ModuleState.stable || module.state === ModuleState.instable) this._views[0].elements[key] = module.elements[key];
});
@@ -462,7 +499,7 @@
// process all groupings
this._groupingsToResolve.filter(vs => vs.uses && vs.uses[ResolveFunction]).forEach(vs => {
- try { vs.uses![ResolveFunction] !== undefined && vs.uses![ResolveFunction]!("|"); } catch (error) {
+ try { vs.uses![ResolveFunction] !== undefined && vs.uses![ResolveFunction]!('|'); } catch (error) {
console.warn(`Error resolving: [${vs.name}] [${error.message}]`);
}
});
@@ -471,16 +508,16 @@
* This is to fix the issue for sequential execution of modules based on their child and parent relationship
* We are sorting the module object based on their augment status
*/
- Object.keys(this.modules)
+ Object.keys(this.modules)
.map(elem => {
- if(this.modules[elem].augments && Object.keys(this.modules[elem].augments).length > 0) {
- const {augments, ...rest} = this.modules[elem];
- const partsOfKeys = Object.keys(augments).map((key) => (key.split("/").length - 1))
- this.modules[elem].executionOrder= Math.max(...partsOfKeys)
- } else {
- this.modules[elem].executionOrder=0;
- }
- })
+ if (this.modules[elem].augments && Object.keys(this.modules[elem].augments).length > 0) {
+ const { augments, ..._rest } = this.modules[elem];
+ const partsOfKeys = Object.keys(augments).map((key) => (key.split('/').length - 1));
+ this.modules[elem].executionOrder = Math.max(...partsOfKeys);
+ } else {
+ this.modules[elem].executionOrder = 0;
+ }
+ });
// process all augmentations / sort by namespace changes to ensure proper order
Object.keys(this.modules).sort((a, b) => this.modules[a].executionOrder! - this.modules[b].executionOrder!).forEach(modKey => {
@@ -489,8 +526,8 @@
const pathParts = splitVPath(key, /(?:(?:([^\/\:]+):)?([^\/]+))/g); // 1 = opt: namespace / 2 = property
let nameSpaceChangeCounter = 0;
let currentNS = module.name; // init namespace
- pathParts.forEach(([ns, _])=> {
- if (ns === currentNS){
+ pathParts.forEach(([ns, _]) => {
+ if (ns === currentNS) {
currentNS = ns;
nameSpaceChangeCounter++;
}
@@ -498,11 +535,11 @@
return {
key,
nameSpaceChangeCounter,
- }
+ };
});
-
+
const augmentKeys = augmentKeysWithCounter
- .sort((a,b) => a.nameSpaceChangeCounter > b.nameSpaceChangeCounter ? 1 : a.nameSpaceChangeCounter === b.nameSpaceChangeCounter ? 0 : -1 )
+ .sort((a, b) => a.nameSpaceChangeCounter > b.nameSpaceChangeCounter ? 1 : a.nameSpaceChangeCounter === b.nameSpaceChangeCounter ? 0 : -1)
.map((a) => a.key);
augmentKeys.forEach(augKey => {
@@ -512,11 +549,23 @@
if (augments && viewSpec) {
augments.forEach(augment => Object.keys(augment.elements).forEach(key => {
const elm = augment.elements[key];
+
+ const when = elm.when && augment.when
+ ? {
+ type: WhenTokenType.AND,
+ left: elm.when,
+ right: augment.when,
+ }
+ : elm.when || augment.when;
+
+ const ifFeature = elm.ifFeature
+ ? `(${augment.ifFeature}) and (${elm.ifFeature})`
+ : augment.ifFeature;
+
viewSpec.elements[key] = {
...augment.elements[key],
-
- when: elm.when ? `(${augment.when}) and (${elm.when})` : augment.when,
- ifFeature: elm.ifFeature ? `(${augment.ifFeature}) and (${elm.ifFeature})` : augment.ifFeature,
+ when,
+ ifFeature,
};
}));
}
@@ -534,7 +583,7 @@
}
}
return result;
- }
+ };
const baseIdentities: Identity[] = [];
Object.keys(this.modules).forEach(modKey => {
@@ -565,30 +614,31 @@
}
});
- // resolve readOnly
- const resolveReadOnly = (view: ViewSpecification, parentConfig: boolean) => {
-
- // update view config
- view.config = view.config && parentConfig;
-
- Object.keys(view.elements).forEach((key) => {
- const elm = view.elements[key];
+ // // resolve readOnly
+ // const resolveReadOnly = (view: ViewSpecification, parentConfig: boolean) => {
- // update element config
- elm.config = elm.config && view.config;
-
- // update all sub-elements of objects
- if (elm.uiType === "object") {
- resolveReadOnly(this.views[+elm.viewId], elm.config);
- }
+ // // update view config
+ // view.config = view.config && parentConfig;
- })
- }
+ // Object.keys(view.elements).forEach((key) => {
+ // const elm = view.elements[key];
- const dump = resolveReadOnly(this.views[0], true);
- };
+ // // update element config
+ // elm.config = elm.config && view.config;
+
+ // // update all sub-elements of objects
+ // if (elm.uiType === 'object') {
+ // resolveReadOnly(this.views[+elm.viewId], elm.config);
+ // }
+
+ // });
+ // };
+
+ // const dump = resolveReadOnly(this.views[0], true);
+ }
private _nextId = 1;
+
private get nextId() {
return this._nextId++;
}
@@ -608,7 +658,7 @@
}
private extractTypeDefinitions(statement: Statement, module: Module, currentPath: string): void {
- const typedefs = this.extractNodes(statement, "typedef");
+ const typedefs = this.extractNodes(statement, 'typedef');
typedefs && typedefs.forEach(def => {
if (!def.arg) {
throw new Error(`Module: [${module.name}]. Found typefed without name.`);
@@ -620,7 +670,7 @@
/** Handles groupings like named Container */
private extractGroupings(statement: Statement, parentId: number, module: Module, currentPath: string): ViewSpecification[] {
const subViews: ViewSpecification[] = [];
- const groupings = this.extractNodes(statement, "grouping");
+ const groupings = this.extractNodes(statement, 'grouping');
if (groupings && groupings.length > 0) {
subViews.push(...groupings.reduce<ViewSpecification[]>((acc, cur) => {
if (!cur.arg) {
@@ -629,9 +679,9 @@
const grouping = cur.arg;
// the default for config on module level is config = true;
- const [currentView, subViews] = this.extractSubViews(cur, /* parentId */ -1, module, currentPath);
+ const [currentView, currentSubViews] = this.extractSubViews(cur, /* parentId */ -1, module, currentPath);
grouping && (module.groupings[grouping] = currentView);
- acc.push(currentView, ...subViews);
+ acc.push(currentView, ...currentSubViews);
return acc;
}, []));
}
@@ -642,7 +692,7 @@
/** Handles augments also like named container */
private extractAugments(statement: Statement, parentId: number, module: Module, currentPath: string): ViewSpecification[] {
const subViews: ViewSpecification[] = [];
- const augments = this.extractNodes(statement, "augment");
+ const augments = this.extractNodes(statement, 'augment');
if (augments && augments.length > 0) {
subViews.push(...augments.reduce<ViewSpecification[]>((acc, cur) => {
if (!cur.arg) {
@@ -651,12 +701,12 @@
const augment = this.resolveReferencePath(cur.arg, module);
// the default for config on module level is config = true;
- const [currentView, subViews] = this.extractSubViews(cur, parentId, module, currentPath);
+ const [currentView, currentSubViews] = this.extractSubViews(cur, parentId, module, currentPath);
if (augment) {
module.augments[augment] = module.augments[augment] || [];
module.augments[augment].push(currentView);
}
- acc.push(currentView, ...subViews);
+ acc.push(currentView, ...currentSubViews);
return acc;
}, []));
}
@@ -666,109 +716,109 @@
/** Handles identities */
private extractIdentities(statement: Statement, parentId: number, module: Module, currentPath: string) {
- const identities = this.extractNodes(statement, "identity");
+ const identities = this.extractNodes(statement, 'identity');
module.identities = identities.reduce<{ [name: string]: Identity }>((acc, cur) => {
if (!cur.arg) {
- throw new Error(`Module: [${module.name}][${currentPath}]. Found identiy without name.`);
+ throw new Error(`Module: [${module.name}][${currentPath}]. Found identity without name.`);
}
acc[cur.arg] = {
id: `${module.name}:${cur.arg}`,
label: cur.arg,
- base: this.extractValue(cur, "base"),
- description: this.extractValue(cur, "description"),
- reference: this.extractValue(cur, "reference"),
- children: []
- }
+ base: this.extractValue(cur, 'base'),
+ description: this.extractValue(cur, 'description'),
+ reference: this.extractValue(cur, 'reference'),
+ children: [],
+ };
return acc;
}, {});
}
- // Hint: use 0 as parentId for rootElements and -1 for rootGroupings.
+ // Hint: use 0 as parentId for rootElements and -1 for rootGroupings.
private extractSubViews(statement: Statement, parentId: number, module: Module, currentPath: string): [ViewSpecification, ViewSpecification[]] {
// used for scoped definitions
const context: Module = {
...module,
typedefs: {
- ...module.typedefs
- }
+ ...module.typedefs,
+ },
};
const currentId = this.nextId;
const subViews: ViewSpecification[] = [];
let elements: ViewElement[] = [];
- const configValue = this.extractValue(statement, "config");
- const config = configValue == null ? true : configValue.toLocaleLowerCase() !== "false";
+ const configValue = this.extractValue(statement, 'config');
+ const config = configValue == null ? true : configValue.toLocaleLowerCase() !== 'false';
// extract conditions
- const ifFeature = this.extractValue(statement, "if-feature");
- const whenCondition = this.extractValue(statement, "when");
- if (whenCondition) console.warn("Found in [" + context.name + "]" + currentPath + " when: " + whenCondition);
+ const ifFeature = this.extractValue(statement, 'if-feature');
+ const whenCondition = this.extractValue(statement, 'when');
+ if (whenCondition) console.warn('Found in [' + context.name + ']' + currentPath + ' when: ' + whenCondition);
// extract all scoped typedefs
this.extractTypeDefinitions(statement, context, currentPath);
// extract all scoped groupings
subViews.push(
- ...this.extractGroupings(statement, parentId, context, currentPath)
+ ...this.extractGroupings(statement, parentId, context, currentPath),
);
// extract all container
- const container = this.extractNodes(statement, "container");
+ const container = this.extractNodes(statement, 'container');
if (container && container.length > 0) {
subViews.push(...container.reduce<ViewSpecification[]>((acc, cur) => {
if (!cur.arg) {
throw new Error(`Module: [${context.name}]${currentPath}. Found container without name.`);
}
- const [currentView, subViews] = this.extractSubViews(cur, currentId, context, `${currentPath}/${context.name}:${cur.arg}`);
+ const [currentView, currentSubViews] = this.extractSubViews(cur, currentId, context, `${currentPath}/${context.name}:${cur.arg}`);
elements.push({
id: parentId === 0 ? `${context.name}:${cur.arg}` : cur.arg,
label: cur.arg,
path: currentPath,
module: context.name || module.name || '',
- uiType: "object",
+ uiType: 'object',
viewId: currentView.id,
config: currentView.config,
});
- acc.push(currentView, ...subViews);
+ acc.push(currentView, ...currentSubViews);
return acc;
}, []));
}
// process all lists
// a list is a list of containers with the leafs contained in the list
- const lists = this.extractNodes(statement, "list");
+ const lists = this.extractNodes(statement, 'list');
if (lists && lists.length > 0) {
subViews.push(...lists.reduce<ViewSpecification[]>((acc, cur) => {
let elmConfig = config;
if (!cur.arg) {
throw new Error(`Module: [${context.name}]${currentPath}. Found list without name.`);
}
- const key = this.extractValue(cur, "key") || undefined;
+ const key = this.extractValue(cur, 'key') || undefined;
if (elmConfig && !key) {
console.warn(`Module: [${context.name}]${currentPath}. Found configurable list without key. Assume config shell be false.`);
elmConfig = false;
}
- const [currentView, subViews] = this.extractSubViews(cur, currentId, context, `${currentPath}/${context.name}:${cur.arg}`);
+ const [currentView, currentSubViews] = this.extractSubViews(cur, currentId, context, `${currentPath}/${context.name}:${cur.arg}`);
elements.push({
id: parentId === 0 ? `${context.name}:${cur.arg}` : cur.arg,
label: cur.arg,
path: currentPath,
module: context.name || module.name || '',
isList: true,
- uiType: "object",
+ uiType: 'object',
viewId: currentView.id,
key: key,
config: elmConfig && currentView.config,
});
- acc.push(currentView, ...subViews);
+ acc.push(currentView, ...currentSubViews);
return acc;
}, []));
}
// process all leaf-lists
// a leaf-list is a list of some type
- const leafLists = this.extractNodes(statement, "leaf-list");
+ const leafLists = this.extractNodes(statement, 'leaf-list');
if (leafLists && leafLists.length > 0) {
elements.push(...leafLists.reduce<ViewElement[]>((acc, cur) => {
const element = this.getViewElement(cur, context, parentId, currentPath, true);
@@ -779,7 +829,7 @@
// process all leafs
// a leaf is mainly a property of an object
- const leafs = this.extractNodes(statement, "leaf");
+ const leafs = this.extractNodes(statement, 'leaf');
if (leafs && leafs.length > 0) {
elements.push(...leafs.reduce<ViewElement[]>((acc, cur) => {
const element = this.getViewElement(cur, context, parentId, currentPath, false);
@@ -789,92 +839,92 @@
}
- const choiceStms = this.extractNodes(statement, "choice");
+ const choiceStms = this.extractNodes(statement, 'choice');
if (choiceStms && choiceStms.length > 0) {
- elements.push(...choiceStms.reduce<ViewElementChoise[]>((accChoise, curChoise) => {
- if (!curChoise.arg) {
+ elements.push(...choiceStms.reduce<ViewElementChoice[]>((accChoice, curChoice) => {
+ if (!curChoice.arg) {
throw new Error(`Module: [${context.name}]${currentPath}. Found choise without name.`);
}
// extract all cases like containers
- const cases: { id: string, label: string, description?: string, elements: { [name: string]: ViewElement } }[] = [];
- const caseStms = this.extractNodes(curChoise, "case");
+ const cases: { id: string; label: string; description?: string; elements: { [name: string]: ViewElement } }[] = [];
+ const caseStms = this.extractNodes(curChoice, 'case');
if (caseStms && caseStms.length > 0) {
cases.push(...caseStms.reduce((accCase, curCase) => {
if (!curCase.arg) {
- throw new Error(`Module: [${context.name}]${currentPath}/${curChoise.arg}. Found case without name.`);
+ throw new Error(`Module: [${context.name}]${currentPath}/${curChoice.arg}. Found case without name.`);
}
- const description = this.extractValue(curCase, "description") || undefined;
- const [caseView, caseSubViews] = this.extractSubViews(curCase, parentId, context, `${currentPath}/${context.name}:${curChoise.arg}`);
+ const description = this.extractValue(curCase, 'description') || undefined;
+ const [caseView, caseSubViews] = this.extractSubViews(curCase, parentId, context, `${currentPath}/${context.name}:${curChoice.arg}`);
subViews.push(caseView, ...caseSubViews);
- const caseDef: { id: string, label: string, description?: string, elements: { [name: string]: ViewElement } } = {
+ const caseDef: { id: string; label: string; description?: string; elements: { [name: string]: ViewElement } } = {
id: parentId === 0 ? `${context.name}:${curCase.arg}` : curCase.arg,
label: curCase.arg,
description: description,
- elements: caseView.elements
+ elements: caseView.elements,
};
accCase.push(caseDef);
return accCase;
- }, [] as { id: string, label: string, description?: string, elements: { [name: string]: ViewElement } }[]));
+ }, [] as { id: string; label: string; description?: string; elements: { [name: string]: ViewElement } }[]));
}
// extract all simple cases (one case per leaf, container, etc.)
- const [choiseView, choiseSubViews] = this.extractSubViews(curChoise, parentId, context, `${currentPath}/${context.name}:${curChoise.arg}`);
- subViews.push(choiseView, ...choiseSubViews);
- cases.push(...Object.keys(choiseView.elements).reduce((accElm, curElm) => {
- const elm = choiseView.elements[curElm];
- const caseDef: { id: string, label: string, description?: string, elements: { [name: string]: ViewElement } } = {
+ const [choiceView, choiceSubViews] = this.extractSubViews(curChoice, parentId, context, `${currentPath}/${context.name}:${curChoice.arg}`);
+ subViews.push(choiceView, ...choiceSubViews);
+ cases.push(...Object.keys(choiceView.elements).reduce((accElm, curElm) => {
+ const elm = choiceView.elements[curElm];
+ const caseDef: { id: string; label: string; description?: string; elements: { [name: string]: ViewElement } } = {
id: elm.id,
label: elm.label,
description: elm.description,
- elements: { [elm.id]: elm }
+ elements: { [elm.id]: elm },
};
accElm.push(caseDef);
return accElm;
- }, [] as { id: string, label: string, description?: string, elements: { [name: string]: ViewElement } }[]));
+ }, [] as { id: string; label: string; description?: string; elements: { [name: string]: ViewElement } }[]));
- const description = this.extractValue(curChoise, "description") || undefined;
- const configValue = this.extractValue(curChoise, "config");
- const config = configValue == null ? true : configValue.toLocaleLowerCase() !== "false";
+ const choiceDescription = this.extractValue(curChoice, 'description') || undefined;
+ const choiceConfigValue = this.extractValue(curChoice, 'config');
+ const choiceConfig = choiceConfigValue == null ? true : choiceConfigValue.toLocaleLowerCase() !== 'false';
- const mandatory = this.extractValue(curChoise, "mandatory") === "true" || false;
+ const mandatory = this.extractValue(curChoice, 'mandatory') === 'true' || false;
- const element: ViewElementChoise = {
- uiType: "choise",
- id: parentId === 0 ? `${context.name}:${curChoise.arg}` : curChoise.arg,
- label: curChoise.arg,
+ const element: ViewElementChoice = {
+ uiType: 'choice',
+ id: parentId === 0 ? `${context.name}:${curChoice.arg}` : curChoice.arg,
+ label: curChoice.arg,
path: currentPath,
module: context.name || module.name || '',
- config: config,
+ config: choiceConfig,
mandatory: mandatory,
- description: description,
+ description: choiceDescription,
cases: cases.reduce((acc, cur) => {
acc[cur.id] = cur;
return acc;
- }, {} as { [name: string]: { id: string, label: string, description?: string, elements: { [name: string]: ViewElement } } })
+ }, {} as { [name: string]: { id: string; label: string; description?: string; elements: { [name: string]: ViewElement } } }),
};
- accChoise.push(element);
- return accChoise;
+ accChoice.push(element);
+ return accChoice;
}, []));
}
- const rpcStms = this.extractNodes(statement, "rpc");
+ const rpcStms = this.extractNodes(statement, 'rpc');
if (rpcStms && rpcStms.length > 0) {
elements.push(...rpcStms.reduce<ViewElementRpc[]>((accRpc, curRpc) => {
if (!curRpc.arg) {
throw new Error(`Module: [${context.name}]${currentPath}. Found rpc without name.`);
}
- const description = this.extractValue(curRpc, "description") || undefined;
- const configValue = this.extractValue(curRpc, "config");
- const config = configValue == null ? true : configValue.toLocaleLowerCase() !== "false";
+ const rpcDescription = this.extractValue(curRpc, 'description') || undefined;
+ const rpcConfigValue = this.extractValue(curRpc, 'config');
+ const rpcConfig = rpcConfigValue == null ? true : rpcConfigValue.toLocaleLowerCase() !== 'false';
let inputViewId: string | undefined = undefined;
let outputViewId: string | undefined = undefined;
- const input = this.extractNodes(curRpc, "input") || undefined;
- const output = this.extractNodes(curRpc, "output") || undefined;
+ const input = this.extractNodes(curRpc, 'input') || undefined;
+ const output = this.extractNodes(curRpc, 'output') || undefined;
if (input && input.length > 0) {
const [inputView, inputSubViews] = this.extractSubViews(input[0], parentId, context, `${currentPath}/${context.name}:${curRpc.arg}`);
@@ -889,13 +939,13 @@
}
const element: ViewElementRpc = {
- uiType: "rpc",
+ uiType: 'rpc',
id: parentId === 0 ? `${context.name}:${curRpc.arg}` : curRpc.arg,
label: curRpc.arg,
path: currentPath,
module: context.name || module.name || '',
- config: config,
- description: description,
+ config: rpcConfig,
+ description: rpcDescription,
inputViewId: inputViewId,
outputViewId: outputViewId,
};
@@ -906,9 +956,16 @@
}, []));
}
- // if (!statement.arg) {
- // throw new Error(`Module: [${context.name}]. Found statement without name.`);
- // }
+ if (!statement.arg) {
+ console.error(new Error(`Module: [${context.name}]. Found statement without name.`));
+ }
+
+ let whenParsed: WhenAST | undefined = undefined;
+ try {
+ whenParsed = whenCondition && parseWhen(whenCondition) || undefined;
+ } catch (e) {
+ console.error(new Error(`Module: [${context.name}]. Found invalid when condition: ${whenCondition}`));
+ }
const viewSpec: ViewSpecification = {
id: String(currentId),
@@ -916,11 +973,11 @@
ns: context.name,
name: statement.arg != null ? statement.arg : undefined,
title: statement.arg != null ? statement.arg : undefined,
- language: "en-us",
+ language: 'en-us',
canEdit: false,
config: config,
ifFeature: ifFeature,
- when: whenCondition,
+ when: whenParsed,
elements: elements.reduce<{ [name: string]: ViewElement }>((acc, cur) => {
acc[cur.id] = cur;
return acc;
@@ -928,21 +985,21 @@
};
// evaluate canEdit depending on all conditions
- Object.defineProperty(viewSpec, "canEdit", {
+ Object.defineProperty(viewSpec, 'canEdit', {
get: () => {
return Object.keys(viewSpec.elements).some(key => {
const elm = viewSpec.elements[key];
return (!isViewElementObjectOrList(elm) && elm.config);
});
- }
+ },
});
// merge in all uses references and resolve groupings
- const usesRefs = this.extractNodes(statement, "uses");
+ const usesRefs = this.extractNodes(statement, 'uses');
if (usesRefs && usesRefs.length > 0) {
viewSpec.uses = (viewSpec.uses || []);
- const resolveFunctions : ((parentElementPath: string)=>void)[] = [];
+ const resolveFunctions: ((parentElementPath: string) => void)[] = [];
for (let i = 0; i < usesRefs.length; ++i) {
const groupingName = usesRefs[i].arg;
@@ -951,7 +1008,7 @@
}
viewSpec.uses.push(this.resolveReferencePath(groupingName, context));
-
+
resolveFunctions.push((parentElementPath: string) => {
const groupingViewSpec = this.resolveGrouping(groupingName, context);
if (groupingViewSpec) {
@@ -963,10 +1020,22 @@
Object.keys(groupingViewSpec.elements).forEach(key => {
const elm = groupingViewSpec.elements[key];
// a useRef on root level need a namespace
+ const resolvedWhen = elm.when && groupingViewSpec.when
+ ? {
+ type: WhenTokenType.AND,
+ left: elm.when,
+ right: groupingViewSpec.when,
+ }
+ : elm.when || groupingViewSpec.when;
+
+ const resolvedIfFeature = elm.ifFeature
+ ? `(${groupingViewSpec.ifFeature}) and (${elm.ifFeature})`
+ : groupingViewSpec.ifFeature;
+
viewSpec.elements[parentId === 0 ? `${module.name}:${key}` : key] = {
...elm,
- when: elm.when ? `(${groupingViewSpec.when}) and (${elm.when})` : groupingViewSpec.when,
- ifFeature: elm.ifFeature ? `(${groupingViewSpec.ifFeature}) and (${elm.ifFeature})` : groupingViewSpec.ifFeature,
+ when: resolvedWhen,
+ ifFeature: resolvedIfFeature,
};
});
}
@@ -974,19 +1043,19 @@
}
viewSpec.uses[ResolveFunction] = (parentElementPath: string) => {
- const currentElementPath = `${parentElementPath} -> ${viewSpec.ns}:${viewSpec.name}`;
+ const currentElementPath = `${parentElementPath} -> ${viewSpec.ns}:${viewSpec.name}`;
resolveFunctions.forEach(resolve => {
- try {
- resolve(currentElementPath);
- } catch (error) {
- console.error(error);
- }
+ try {
+ resolve(currentElementPath);
+ } catch (error) {
+ console.error(error);
+ }
});
// console.log("Resolved "+currentElementPath, viewSpec);
if (viewSpec?.uses) {
viewSpec.uses[ResolveFunction] = undefined;
}
- }
+ };
this._groupingsToResolve.push(viewSpec);
}
@@ -1020,28 +1089,28 @@
/** Extracts the UI View from the type in the cur statement. */
private getViewElement(cur: Statement, module: Module, parentId: number, currentPath: string, isList: boolean): ViewElement {
- const type = this.extractValue(cur, "type");
- const defaultVal = this.extractValue(cur, "default") || undefined;
- const description = this.extractValue(cur, "description") || undefined;
+ const type = this.extractValue(cur, 'type');
+ const defaultVal = this.extractValue(cur, 'default') || undefined;
+ const description = this.extractValue(cur, 'description') || undefined;
- const configValue = this.extractValue(cur, "config");
- const config = configValue == null ? true : configValue.toLocaleLowerCase() !== "false";
+ const configValue = this.extractValue(cur, 'config');
+ const config = configValue == null ? true : configValue.toLocaleLowerCase() !== 'false';
- const extractRange = (min: number, max: number, property: string = "range"): { expression: Expression<YangRange> | undefined, min: number, max: number } => {
- const ranges = this.extractValue(this.extractNodes(cur, "type")[0]!, property) || undefined;
- const range = ranges ?.replace(/min/i, String(min)).replace(/max/i, String(max)).split("|").map(r => {
+ const extractRange = (min: number, max: number, property: string = 'range'): { expression: Expression<YangRange> | undefined; min: number; max: number } => {
+ const ranges = this.extractValue(this.extractNodes(cur, 'type')[0]!, property) || undefined;
+ const range = ranges?.replace(/min/i, String(min)).replace(/max/i, String(max)).split('|').map(r => {
let minValue: number;
let maxValue: number;
-
+
if (r.indexOf('..') > -1) {
- const [minStr, maxStr] = r.split('..');
- minValue = Number(minStr);
- maxValue = Number(maxStr);
- } else if (!isNaN(maxValue = Number(r && r.trim() )) ) {
- minValue = maxValue;
+ const [minStr, maxStr] = r.split('..');
+ minValue = Number(minStr);
+ maxValue = Number(maxStr);
+ } else if (!isNaN(maxValue = Number(r && r.trim()))) {
+ minValue = maxValue;
} else {
- minValue = min,
- maxValue = max;
+ minValue = min,
+ maxValue = max;
}
if (minValue > min) min = minValue;
@@ -1049,7 +1118,7 @@
return {
min: minValue,
- max: maxValue
+ max: maxValue,
};
});
return {
@@ -1058,21 +1127,22 @@
expression: range && range.length === 1
? range[0]
: range && range.length > 1
- ? { operation: "OR", arguments: range }
- : undefined
- }
+ ? { operation: 'OR', arguments: range }
+ : undefined,
+ };
};
const extractPattern = (): Expression<RegExp> | undefined => {
- const pattern = this.extractNodes(this.extractNodes(cur, "type")[0]!, "pattern").map(p => p.arg!).filter(p => !!p).map(p => `^${p.replace(/(?:\\(.))/g, '$1')}$`);
+ // 2023.01.26 decision MF & SKO: we will no longer remove the backslashes from the pattern, seems to be a bug in the original code
+ const pattern = this.extractNodes(this.extractNodes(cur, 'type')[0]!, 'pattern').map(p => p.arg!).filter(p => !!p).map(p => `^${p/*.replace(/(?:\\(.))/g, '$1')*/}$`);
return pattern && pattern.length == 1
? new RegExp(pattern[0])
: pattern && pattern.length > 1
- ? { operation: "AND", arguments: pattern.map(p => new RegExp(p)) }
+ ? { operation: 'AND', arguments: pattern.map(p => new RegExp(p)) }
: undefined;
- }
+ };
- const mandatory = this.extractValue(cur, "mandatory") === "true" || false;
+ const mandatory = this.extractValue(cur, 'mandatory') === 'true' || false;
if (!cur.arg) {
throw new Error(`Module: [${module.name}]. Found element without name.`);
@@ -1084,159 +1154,159 @@
const element: ViewElementBase = {
id: parentId === 0 ? `${module.name}:${cur.arg}` : cur.arg,
- label: cur.arg,
+ label: cur.arg,
path: currentPath,
- module: module.name || "",
+ module: module.name || '',
config: config,
mandatory: mandatory,
isList: isList,
default: defaultVal,
- description: description
+ description: description,
};
- if (type === "string") {
- const length = extractRange(0, +18446744073709551615, "length");
+ if (type === 'string') {
+ const length = extractRange(0, +18446744073709551615, 'length');
return ({
...element,
- uiType: "string",
+ uiType: 'string',
length: length.expression,
pattern: extractPattern(),
});
- } else if (type === "boolean") {
+ } else if (type === 'boolean') {
return ({
...element,
- uiType: "boolean"
+ uiType: 'boolean',
});
- } else if (type === "uint8") {
+ } else if (type === 'uint8') {
const range = extractRange(0, +255);
return ({
...element,
- uiType: "number",
+ uiType: 'number',
range: range.expression,
min: range.min,
max: range.max,
- units: this.extractValue(cur, "units") || undefined,
- format: this.extractValue(cur, "format") || undefined,
+ units: this.extractValue(cur, 'units') || undefined,
+ format: this.extractValue(cur, 'format') || undefined,
});
- } else if (type === "uint16") {
+ } else if (type === 'uint16') {
const range = extractRange(0, +65535);
return ({
...element,
- uiType: "number",
+ uiType: 'number',
range: range.expression,
min: range.min,
max: range.max,
- units: this.extractValue(cur, "units") || undefined,
- format: this.extractValue(cur, "format") || undefined,
+ units: this.extractValue(cur, 'units') || undefined,
+ format: this.extractValue(cur, 'format') || undefined,
});
- } else if (type === "uint32") {
+ } else if (type === 'uint32') {
const range = extractRange(0, +4294967295);
return ({
...element,
- uiType: "number",
+ uiType: 'number',
range: range.expression,
min: range.min,
max: range.max,
- units: this.extractValue(cur, "units") || undefined,
- format: this.extractValue(cur, "format") || undefined,
+ units: this.extractValue(cur, 'units') || undefined,
+ format: this.extractValue(cur, 'format') || undefined,
});
- } else if (type === "uint64") {
+ } else if (type === 'uint64') {
const range = extractRange(0, +18446744073709551615);
return ({
...element,
- uiType: "number",
+ uiType: 'number',
range: range.expression,
min: range.min,
max: range.max,
- units: this.extractValue(cur, "units") || undefined,
- format: this.extractValue(cur, "format") || undefined,
+ units: this.extractValue(cur, 'units') || undefined,
+ format: this.extractValue(cur, 'format') || undefined,
});
- } else if (type === "int8") {
+ } else if (type === 'int8') {
const range = extractRange(-128, +127);
return ({
...element,
- uiType: "number",
+ uiType: 'number',
range: range.expression,
min: range.min,
max: range.max,
- units: this.extractValue(cur, "units") || undefined,
- format: this.extractValue(cur, "format") || undefined,
+ units: this.extractValue(cur, 'units') || undefined,
+ format: this.extractValue(cur, 'format') || undefined,
});
- } else if (type === "int16") {
+ } else if (type === 'int16') {
const range = extractRange(-32768, +32767);
return ({
...element,
- uiType: "number",
+ uiType: 'number',
range: range.expression,
min: range.min,
max: range.max,
- units: this.extractValue(cur, "units") || undefined,
- format: this.extractValue(cur, "format") || undefined,
+ units: this.extractValue(cur, 'units') || undefined,
+ format: this.extractValue(cur, 'format') || undefined,
});
- } else if (type === "int32") {
+ } else if (type === 'int32') {
const range = extractRange(-2147483648, +2147483647);
return ({
...element,
- uiType: "number",
+ uiType: 'number',
range: range.expression,
min: range.min,
max: range.max,
- units: this.extractValue(cur, "units") || undefined,
- format: this.extractValue(cur, "format") || undefined,
+ units: this.extractValue(cur, 'units') || undefined,
+ format: this.extractValue(cur, 'format') || undefined,
});
- } else if (type === "int64") {
+ } else if (type === 'int64') {
const range = extractRange(-9223372036854775808, +9223372036854775807);
return ({
...element,
- uiType: "number",
+ uiType: 'number',
range: range.expression,
min: range.min,
max: range.max,
- units: this.extractValue(cur, "units") || undefined,
- format: this.extractValue(cur, "format") || undefined,
+ units: this.extractValue(cur, 'units') || undefined,
+ format: this.extractValue(cur, 'format') || undefined,
});
- } else if (type === "decimal64") {
+ } else if (type === 'decimal64') {
// decimalRange
- const fDigits = Number(this.extractValue(this.extractNodes(cur, "type")[0]!, "fraction-digits")) || -1;
+ const fDigits = Number(this.extractValue(this.extractNodes(cur, 'type')[0]!, 'fraction-digits')) || -1;
if (fDigits === -1) {
throw new Error(`Module: [${module.name}][${currentPath}][${cur.arg}]. Found decimal64 with invalid fraction-digits.`);
}
const range = extractRange(YangParser.decimalRange[fDigits].min, YangParser.decimalRange[fDigits].max);
return ({
...element,
- uiType: "number",
+ uiType: 'number',
fDigits: fDigits,
range: range.expression,
min: range.min,
max: range.max,
- units: this.extractValue(cur, "units") || undefined,
- format: this.extractValue(cur, "format") || undefined,
+ units: this.extractValue(cur, 'units') || undefined,
+ format: this.extractValue(cur, 'format') || undefined,
});
- } else if (type === "enumeration") {
- const typeNode = this.extractNodes(cur, "type")[0]!;
- const enumNodes = this.extractNodes(typeNode, "enum");
+ } else if (type === 'enumeration') {
+ const typeNode = this.extractNodes(cur, 'type')[0]!;
+ const enumNodes = this.extractNodes(typeNode, 'enum');
return ({
...element,
- uiType: "selection",
+ uiType: 'selection',
options: enumNodes.reduce<{ key: string; value: string; description?: string }[]>((acc, enumNode) => {
if (!enumNode.arg) {
throw new Error(`Module: [${module.name}][${currentPath}][${cur.arg}]. Found option without name.`);
}
- const ifClause = this.extractValue(enumNode, "if-feature");
- const value = this.extractValue(enumNode, "value");
+ // const ifClause = this.extractValue(enumNode, 'if-feature');
+ const value = this.extractValue(enumNode, 'value');
const enumOption = {
key: enumNode.arg,
value: value != null ? value : enumNode.arg,
- description: this.extractValue(enumNode, "description") || undefined
+ description: this.extractValue(enumNode, 'description') || undefined,
};
// todo: ❗ handle the if clause ⚡
acc.push(enumOption);
return acc;
- }, [])
+ }, []),
});
- } else if (type === "leafref") {
- const typeNode = this.extractNodes(cur, "type")[0]!;
- const vPath = this.extractValue(typeNode, "path");
+ } else if (type === 'leafref') {
+ const typeNode = this.extractNodes(cur, 'type')[0]!;
+ const vPath = this.extractValue(typeNode, 'path');
if (!vPath) {
throw new Error(`Module: [${module.name}][${currentPath}][${cur.arg}]. Found leafref without path.`);
}
@@ -1244,11 +1314,11 @@
const resolve = this.resolveReference.bind(this);
const res: ViewElement = {
...element,
- uiType: "reference",
+ uiType: 'reference',
referencePath: refPath,
- ref(this: ViewElement, currentPath: string) {
- const elementPath = `${currentPath}/${cur.arg}`;
-
+ ref(this: ViewElement, basePath: string) {
+ const elementPath = `${basePath}/${cur.arg}`;
+
const result = resolve(refPath, elementPath);
if (!result) return undefined;
@@ -1262,20 +1332,20 @@
isList: this.isList,
default: this.default,
description: this.description,
- } as ViewElement , resolvedPath] || undefined;
- }
+ } as ViewElement, resolvedPath] || undefined;
+ },
};
return res;
- } else if (type === "identityref") {
- const typeNode = this.extractNodes(cur, "type")[0]!;
- const base = this.extractValue(typeNode, "base");
+ } else if (type === 'identityref') {
+ const typeNode = this.extractNodes(cur, 'type')[0]!;
+ const base = this.extractValue(typeNode, 'base');
if (!base) {
throw new Error(`Module: [${module.name}][${currentPath}][${cur.arg}]. Found identityref without base.`);
}
const res: ViewElement = {
...element,
- uiType: "selection",
- options: []
+ uiType: 'selection',
+ options: [],
};
this._identityToResolve.push(() => {
const identity: Identity = this.resolveIdentity(base, module);
@@ -1288,29 +1358,29 @@
res.options = identity.values.map(val => ({
key: val.id,
value: val.id,
- description: val.description
+ description: val.description,
}));
});
return res;
- } else if (type === "empty") {
+ } else if (type === 'empty') {
// todo: ❗ handle empty ⚡
/* 9.11. The empty Built-In Type
The empty built-in type represents a leaf that does not have any
value, it conveys information by its presence or absence. */
return {
...element,
- uiType: "empty",
+ uiType: 'empty',
};
- } else if (type === "union") {
+ } else if (type === 'union') {
// todo: ❗ handle union ⚡
/* 9.12. The union Built-In Type */
- const typeNode = this.extractNodes(cur, "type")[0]!;
- const typeNodes = this.extractNodes(typeNode, "type");
+ const typeNode = this.extractNodes(cur, 'type')[0]!;
+ const typeNodes = this.extractNodes(typeNode, 'type');
const resultingElement = {
...element,
- uiType: "union",
- elements: []
+ uiType: 'union',
+ elements: [],
} as ViewElementUnion;
const resolveUnion = () => {
@@ -1318,13 +1388,13 @@
const stm: Statement = {
...cur,
sub: [
- ...(cur.sub ?.filter(s => s.key !== "type") || []),
- node
- ]
+ ...(cur.sub?.filter(s => s.key !== 'type') || []),
+ node,
+ ],
};
return {
...this.getViewElement(stm, module, parentId, currentPath, isList),
- id: node.arg!
+ id: node.arg!,
};
}));
};
@@ -1332,34 +1402,34 @@
this._unionsToResolve.push(resolveUnion);
return resultingElement;
- } else if (type === "bits") {
- const typeNode = this.extractNodes(cur, "type")[0]!;
- const bitNodes = this.extractNodes(typeNode, "bit");
+ } else if (type === 'bits') {
+ const typeNode = this.extractNodes(cur, 'type')[0]!;
+ const bitNodes = this.extractNodes(typeNode, 'bit');
return {
...element,
- uiType: "bits",
- flags: bitNodes.reduce<{ [name: string]: number | undefined; }>((acc, bitNode) => {
+ uiType: 'bits',
+ flags: bitNodes.reduce<{ [name: string]: number | undefined }>((acc, bitNode) => {
if (!bitNode.arg) {
throw new Error(`Module: [${module.name}][${currentPath}][${cur.arg}]. Found bit without name.`);
}
- const ifClause = this.extractValue(bitNode, "if-feature");
- const pos = Number(this.extractValue(bitNode, "position"));
+ // const ifClause = this.extractValue(bitNode, 'if-feature');
+ const pos = Number(this.extractValue(bitNode, 'position'));
acc[bitNode.arg] = pos === pos ? pos : undefined;
return acc;
- }, {})
+ }, {}),
};
- } else if (type === "binary") {
+ } else if (type === 'binary') {
return {
...element,
- uiType: "binary",
- length: extractRange(0, +18446744073709551615, "length"),
+ uiType: 'binary',
+ length: extractRange(0, +18446744073709551615, 'length'),
};
- } else if (type === "instance-identifier") {
+ } else if (type === 'instance-identifier') {
// https://tools.ietf.org/html/rfc7950#page-168
return {
...element,
- uiType: "string",
- length: extractRange(0, +18446744073709551615, "length"),
+ uiType: 'string',
+ length: extractRange(0, +18446744073709551615, 'length'),
};
} else {
// not a build in type, need to resolve type
@@ -1374,13 +1444,13 @@
}
// spoof date type here from special string type
- if ((type === 'date-and-time' || type.endsWith(':date-and-time') ) && typeRef.module === "ietf-yang-types") {
- return {
- ...typeRef,
- ...element,
- description: description,
- uiType: "date",
- };
+ if ((type === 'date-and-time' || type.endsWith(':date-and-time')) && typeRef.module === 'ietf-yang-types') {
+ return {
+ ...typeRef,
+ ...element,
+ description: description,
+ uiType: 'date',
+ };
}
return ({
@@ -1391,27 +1461,27 @@
}
}
- private resolveStringType(parentElement: ViewElementString, pattern: Expression<RegExp> | undefined, length: { expression: Expression<YangRange> | undefined, min: number, max: number }) {
+ private resolveStringType(parentElement: ViewElementString, pattern: Expression<RegExp> | undefined, length: { expression: Expression<YangRange> | undefined; min: number; max: number }) {
return {
...parentElement,
pattern: pattern != null && parentElement.pattern
- ? { operation: "AND", arguments: [pattern, parentElement.pattern] }
+ ? { operation: 'AND', arguments: [pattern, parentElement.pattern] }
: parentElement.pattern
? parentElement.pattern
: pattern,
length: length.expression != null && parentElement.length
- ? { operation: "AND", arguments: [length.expression, parentElement.length] }
+ ? { operation: 'AND', arguments: [length.expression, parentElement.length] }
: parentElement.length
? parentElement.length
- : length ?.expression,
+ : length?.expression,
} as ViewElementString;
}
- private resolveNumberType(parentElement: ViewElementNumber, range: { expression: Expression<YangRange> | undefined, min: number, max: number }) {
+ private resolveNumberType(parentElement: ViewElementNumber, range: { expression: Expression<YangRange> | undefined; min: number; max: number }) {
return {
...parentElement,
range: range.expression != null && parentElement.range
- ? { operation: "AND", arguments: [range.expression, parentElement.range] }
+ ? { operation: 'AND', arguments: [range.expression, parentElement.range] }
: parentElement.range
? parentElement.range
: range,
@@ -1421,7 +1491,7 @@
}
private resolveReferencePath(vPath: string, module: Module) {
- const vPathParser = /(?:(?:([^\/\:]+):)?([^\/]+))/g // 1 = opt: namespace / 2 = property
+ const vPathParser = /(?:(?:([^\/\:]+):)?([^\/]+))/g; // 1 = opt: namespace / 2 = property
return vPath.replace(vPathParser, (_, ns, property) => {
const nameSpace = ns && module.imports[ns] || module.name;
return `${nameSpace}:${property}`;
@@ -1429,20 +1499,20 @@
}
private resolveReference(vPath: string, currentPath: string) {
- const vPathParser = /(?:(?:([^\/\[\]\:]+):)?([^\/\[\]]+)(\[[^\]]+\])?)/g // 1 = opt: namespace / 2 = property / 3 = opt: indexPath
+ const vPathParser = /(?:(?:([^\/\[\]\:]+):)?([^\/\[\]]+)(\[[^\]]+\])?)/g; // 1 = opt: namespace / 2 = property / 3 = opt: indexPath
let element: ViewElement | null = null;
- let moduleName = "";
+ let moduleName = '';
const vPathParts = splitVPath(vPath, vPathParser).map(p => ({ ns: p[1], property: p[2], ind: p[3] }));
- const resultPathParts = !vPath.startsWith("/")
- ? splitVPath(currentPath, vPathParser).map(p => { moduleName = p[1] || moduleName ; return { ns: moduleName, property: p[2], ind: p[3] } })
+ const resultPathParts = !vPath.startsWith('/')
+ ? splitVPath(currentPath, vPathParser).map(p => { moduleName = p[1] || moduleName; return { ns: moduleName, property: p[2], ind: p[3] }; })
: [];
for (let i = 0; i < vPathParts.length; ++i) {
const vPathPart = vPathParts[i];
- if (vPathPart.property === "..") {
+ if (vPathPart.property === '..') {
resultPathParts.pop();
- } else if (vPathPart.property !== ".") {
+ } else if (vPathPart.property !== '.') {
resultPathParts.push(vPathPart);
}
}
@@ -1453,30 +1523,30 @@
if (j === 0) {
moduleName = pathPart.ns;
const rootModule = this._modules[moduleName];
- if (!rootModule) throw new Error("Could not resolve module [" + moduleName + "].\r\n" + vPath);
+ if (!rootModule) throw new Error('Could not resolve module [' + moduleName + '].\r\n' + vPath);
element = rootModule.elements[`${pathPart.ns}:${pathPart.property}`];
} else if (element && isViewElementObjectOrList(element)) {
const view: ViewSpecification = this._views[+element.viewId];
if (moduleName !== pathPart.ns) {
moduleName = pathPart.ns;
- }
+ }
element = view.elements[pathPart.property] || view.elements[`${moduleName}:${pathPart.property}`];
} else {
- throw new Error("Could not resolve reference.\r\n" + vPath);
+ throw new Error('Could not resolve reference.\r\n' + vPath);
}
- if (!element) throw new Error("Could not resolve path [" + pathPart.property + "] in [" + currentPath + "] \r\n" + vPath);
+ if (!element) throw new Error('Could not resolve path [' + pathPart.property + '] in [' + currentPath + '] \r\n' + vPath);
}
- moduleName = ""; // create the vPath for the resolved element, do not add the element itself this will be done later in the res(...) function
- return [element, resultPathParts.slice(0,-1).map(p => `${moduleName !== p.ns ? `${moduleName=p.ns}:` : ""}${p.property}${p.ind || ''}`).join("/")];
+ moduleName = ''; // create the vPath for the resolved element, do not add the element itself this will be done later in the res(...) function
+ return [element, resultPathParts.slice(0, -1).map(p => `${moduleName !== p.ns ? `${moduleName = p.ns}:` : ''}${p.property}${p.ind || ''}`).join('/')];
}
private resolveView(vPath: string) {
- const vPathParser = /(?:(?:([^\/\[\]\:]+):)?([^\/\[\]]+)(\[[^\]]+\])?)/g // 1 = opt: namespace / 2 = property / 3 = opt: indexPath
+ const vPathParser = /(?:(?:([^\/\[\]\:]+):)?([^\/\[\]]+)(\[[^\]]+\])?)/g; // 1 = opt: namespace / 2 = property / 3 = opt: indexPath
let element: ViewElement | null = null;
let partMatch: RegExpExecArray | null;
let view: ViewSpecification | null = null;
- let moduleName = "";
+ let moduleName = '';
if (vPath) do {
partMatch = vPathParser.exec(vPath);
if (partMatch) {
@@ -1498,13 +1568,13 @@
}
if (!element) return null;
}
- } while (partMatch)
+ } while (partMatch);
return element && isViewElementObjectOrList(element) && this._views[+element.viewId] || null;
}
private resolveType(type: string, module: Module) {
- const collonInd = type.indexOf(":");
- const preFix = collonInd > -1 ? type.slice(0, collonInd) : "";
+ const collonInd = type.indexOf(':');
+ const preFix = collonInd > -1 ? type.slice(0, collonInd) : '';
const typeName = collonInd > -1 ? type.slice(collonInd + 1) : type;
const res = preFix
@@ -1514,8 +1584,8 @@
}
private resolveGrouping(grouping: string, module: Module) {
- const collonInd = grouping.indexOf(":");
- const preFix = collonInd > -1 ? grouping.slice(0, collonInd) : "";
+ const collonInd = grouping.indexOf(':');
+ const preFix = collonInd > -1 ? grouping.slice(0, collonInd) : '';
const groupingName = collonInd > -1 ? grouping.slice(collonInd + 1) : grouping;
return preFix
@@ -1525,8 +1595,8 @@
}
private resolveIdentity(identity: string, module: Module) {
- const collonInd = identity.indexOf(":");
- const preFix = collonInd > -1 ? identity.slice(0, collonInd) : "";
+ const collonInd = identity.indexOf(':');
+ const preFix = collonInd > -1 ? identity.slice(0, collonInd) : '';
const identityName = collonInd > -1 ? identity.slice(collonInd + 1) : identity;
return preFix
diff --git a/sdnr/wt/odlux/apps/configurationApp/webpack.config.js b/sdnr/wt/odlux/apps/configurationApp/webpack.config.js
index 57caf07..0d37c7d 100644
--- a/sdnr/wt/odlux/apps/configurationApp/webpack.config.js
+++ b/sdnr/wt/odlux/apps/configurationApp/webpack.config.js
@@ -10,6 +10,7 @@
const webpack = require("webpack");
const CopyWebpackPlugin = require("copy-webpack-plugin");
const TerserPlugin = require('terser-webpack-plugin');
+const proxyConf = require('../../proxy.conf');
const policies = require('./policies.json');
@@ -59,6 +60,16 @@
use: [{
loader: "babel-loader"
}]
+ },{
+ //don't minify images
+ test: /\.(png|gif|jpg|svg)$/,
+ use: [{
+ loader: 'url-loader',
+ options: {
+ limit: 10,
+ name: './images/[name].[ext]'
+ }
+ }]
}]
},
@@ -133,56 +144,7 @@
before: function(app, server, compiler) {
app.get('/oauth/policies',(_, res) => res.json(policies));
},
- proxy: {
- "/about": {
- target: "http://sdnr:8181",
- secure: false
- },
- "/yang-schema/": {
- target: "http://sdnr:8181",
- secure: false
- },
- "/oauth/": {
- target: "http://sdnr:8181",
- secure: false
- },
- "/database/": {
- target: "http://sdnr:8181",
- secure: false
- },
- "/restconf/": {
- target: "http://sdnr:8181",
- secure: false
- },
- "/rests/": {
- target: "http://sdnr:8181",
- secure: false
- },
- "/help/": {
- target: "http://sdnr:8181",
- secure: false
- },
- "/about/": {
- target: "http://sdnr:8181",
- secure: false
- },
- "/tree/": {
- target: "http://sdnr:8181",
- secure: false
- },
- "/websocket": {
- target: "http://sdnr:8181",
- ws: true,
- changeOrigin: true,
- secure: false
- },
- "/apidoc": {
- target: "http://sdnr:8181",
- ws: true,
- changeOrigin: true,
- secure: false
- }
- }
+ proxy: proxyConf,
}
}];
}
diff --git a/sdnr/wt/odlux/apps/connectApp/package.json b/sdnr/wt/odlux/apps/connectApp/package.json
index a31824a..9a3c35b 100644
--- a/sdnr/wt/odlux/apps/connectApp/package.json
+++ b/sdnr/wt/odlux/apps/connectApp/package.json
@@ -29,6 +29,7 @@
"@odlux/framework": "*"
},
"peerDependencies": {
+ "@fortawesome/free-solid-svg-icons": "5.6.3",
"@types/classnames": "2.2.6",
"@types/flux": "3.1.8",
"@types/jquery": "3.3.10",
diff --git a/sdnr/wt/odlux/apps/connectApp/pom.xml b/sdnr/wt/odlux/apps/connectApp/pom.xml
index c12048e..c9509c7 100644
--- a/sdnr/wt/odlux/apps/connectApp/pom.xml
+++ b/sdnr/wt/odlux/apps/connectApp/pom.xml
@@ -19,6 +19,7 @@
~ ============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>
@@ -139,7 +140,7 @@
<!-- optional: default phase is "generate-resources" -->
<phase>initialize</phase>
<configuration>
- <nodeVersion>v12.13.0</nodeVersion>
+ <nodeVersion>v12.22.0</nodeVersion>
<yarnVersion>v1.22.10</yarnVersion>
</configuration>
</execution>
diff --git a/sdnr/wt/odlux/apps/connectApp/src/actions/commonNetworkElementsActions.ts b/sdnr/wt/odlux/apps/connectApp/src/actions/commonNetworkElementsActions.ts
index 26aa8d2..948f2aa 100644
--- a/sdnr/wt/odlux/apps/connectApp/src/actions/commonNetworkElementsActions.ts
+++ b/sdnr/wt/odlux/apps/connectApp/src/actions/commonNetworkElementsActions.ts
@@ -1,5 +1,3 @@
-// update action erstellen, die unterscheiden kann, ob die eine oder die andere Ansicht gerade aktive ist und diese katualisiert.
-// Diese action wird dann bei jeder aktualisierung in den anderen Actions und bei eintreffen von notifikationen verwendet.
/**
* ============LICENSE_START========================================================================
@@ -19,16 +17,22 @@
* ============LICENSE_END==========================================================================
*/
+/**
+ * Create an update action that can distinguish whether one or the other view is currently active and update it.
+ * This action is then used for each update in the other actions and when notifications arrive.
+ * create an update action that can distinguish whether one or the other view is currently active and update it.
+ * This action is then used for each update in the other actions and when notifications arrive.
+ */
+
import { Action } from '../../../../framework/src/flux/action';
import { Dispatch } from '../../../../framework/src/flux/store';
import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
-import { networkElementsReloadAction } from '../handlers/networkElementsHandler';
import { connectionStatusLogReloadAction } from '../handlers/connectionStatusLogHandler';
-
-import { PanelId } from '../models/panelId';
+import { networkElementsReloadAction } from '../handlers/networkElementsHandler';
import { guiCutThrough } from '../models/guiCutTrough';
-import { connectService} from '../services/connectService';
+import { PanelId } from '../models/panelId';
+import { connectService } from '../services/connectService';
export class SetPanelAction extends Action {
@@ -51,7 +55,7 @@
export const removeWebUriAction = (nodeId: string) => {
return new RemoveWebUri(nodeId);
-}
+};
export class SetWeburiSearchBusy extends Action {
constructor(public isbusy: boolean) {
@@ -68,7 +72,7 @@
return;
isBusy = true;
- const { connect: { guiCutThrough, networkElements } } = getState();
+ const { connect: { guiCutThrough: guiCutThrough2, networkElements } } = getState();
let notConnectedElements: string[] = [];
let elementsToSearch: string[] = [];
@@ -78,16 +82,16 @@
networkElementIds.forEach(id => {
const item = networkElements.rows.find((ne) => ne.id === id);
if (item) {
- if (item.status === "Connected") {
+ if (item.status === 'Connected') {
// if (item.coreModelCapability !== "Unsupported") {
// element is connected and is added to search list, if it doesn't exist already
- const exists = guiCutThrough.searchedElements.filter(element => element.id === id).length > 0;
+ const exists = guiCutThrough2.searchedElements.filter(element => element.id === id).length > 0;
if (!exists) {
elementsToSearch.push(id);
//element was found previously, but wasn't connected
- if (guiCutThrough.notSearchedElements.length > 0 && guiCutThrough.notSearchedElements.includes(id)) {
+ if (guiCutThrough2.notSearchedElements.length > 0 && guiCutThrough2.notSearchedElements.includes(id)) {
prevFoundElements.push(id);
}
}
@@ -104,10 +108,9 @@
// }
// }
// }
- }
- else {
+ } else {
// element isn't connected and cannot be searched for a weburi
- if (!guiCutThrough.notSearchedElements.includes(id)) {
+ if (!guiCutThrough2.notSearchedElements.includes(id)) {
notConnectedElements.push(item.id as string);
}
}
@@ -121,18 +124,17 @@
}
isBusy = false;
-}
+};
export const setPanelAction = (panelId: PanelId) => {
return new SetPanelAction(panelId);
-}
+};
export const updateCurrentViewAsyncAction = () => (dispatch: Dispatch, getState: () => IApplicationStoreState) => {
const { connect: { currentOpenPanel } } = getState();
- if (currentOpenPanel === "NetworkElements") {
+ if (currentOpenPanel === 'NetworkElements') {
return dispatch(networkElementsReloadAction);
- }
- else {
+ } else {
return dispatch(connectionStatusLogReloadAction);
}
};
diff --git a/sdnr/wt/odlux/apps/connectApp/src/actions/infoNetworkElementActions.ts b/sdnr/wt/odlux/apps/connectApp/src/actions/infoNetworkElementActions.ts
index bb744e2..120f991 100644
--- a/sdnr/wt/odlux/apps/connectApp/src/actions/infoNetworkElementActions.ts
+++ b/sdnr/wt/odlux/apps/connectApp/src/actions/infoNetworkElementActions.ts
@@ -15,68 +15,68 @@
* the License.
* ============LICENSE_END==========================================================================
*/
- import { Action } from '../../../../framework/src/flux/action';
- import { Dispatch } from '../../../../framework/src/flux/store';
+import { Action } from '../../../../framework/src/flux/action';
+import { Dispatch } from '../../../../framework/src/flux/store';
- import { Module, TopologyNode } from '../models/topologyNetconf';
- import { connectService } from '../services/connectService';
+import { Module, TopologyNode } from '../models/topologyNetconf';
+import { connectService } from '../services/connectService';
- /**
+/**
* Represents the base action.
*/
- export class BaseAction extends Action { }
+export class BaseAction extends Action { }
- /**
+/**
* Represents an action causing the store to load all element Yang capabilities.
*/
- export class LoadAllElementInfoAction extends BaseAction { }
+export class LoadAllElementInfoAction extends BaseAction { }
- /**
+/**
* Represents an action causing the store to update element Yang capabilities.
*/
- export class AllElementInfoLoadedAction extends BaseAction {
- /**
+export class AllElementInfoLoadedAction extends BaseAction {
+ /**
* Initialize this instance.
* @param elementInfo The information of the element which is returned.
*/
- constructor(public elementInfo: TopologyNode | null, public error?: string) {
- super();
- }
- }
+ constructor(public elementInfo: TopologyNode | null, public error?: string) {
+ super();
+ }
+}
- /**
+/**
* Represents an action causing the store to update element Yang capabilities Module Features.
*/
- export class AllElementInfoFeatureLoadedAction extends BaseAction {
- /**
+export class AllElementInfoFeatureLoadedAction extends BaseAction {
+ /**
* Initialize this instance.
* @param elementFeatureInfo The information of the element which is returned.
*/
- constructor(public elementFeatureInfo: Module[] | null | undefined, public error?: string) {
- super();
- }
- }
+ constructor(public elementFeatureInfo: Module[] | null | undefined, public error?: string) {
+ super();
+ }
+}
- /**
+/**
* Represents an asynchronous thunk action to load all yang capabilities.
*/
- export const loadAllInfoElementAsync = (nodeId: string) => (dispatch: Dispatch) => {
- dispatch(new LoadAllElementInfoAction());
- connectService.infoNetworkElement(nodeId).then(info => {
- dispatch(new AllElementInfoLoadedAction(info));
- }, error => {
- dispatch(new AllElementInfoLoadedAction(null, error));
- });
- }
+export const loadAllInfoElementAsync = (nodeId: string) => (dispatch: Dispatch) => {
+ dispatch(new LoadAllElementInfoAction());
+ connectService.infoNetworkElement(nodeId).then(info => {
+ dispatch(new AllElementInfoLoadedAction(info));
+ }, error => {
+ dispatch(new AllElementInfoLoadedAction(null, error));
+ });
+};
- /**
+/**
* Represents an asynchronous thunk action to load all yang features.
*/
- export const loadAllInfoElementFeaturesAsync = (nodeId: string) => (dispatch: Dispatch) => {
- dispatch(new LoadAllElementInfoAction());
- connectService.infoNetworkElementFeatures(nodeId).then(infoFeatures => {
- dispatch(new AllElementInfoFeatureLoadedAction(infoFeatures));
- }, error => {
- dispatch(new AllElementInfoFeatureLoadedAction(null, error));
- });
- }
\ No newline at end of file
+export const loadAllInfoElementFeaturesAsync = (nodeId: string) => (dispatch: Dispatch) => {
+ dispatch(new LoadAllElementInfoAction());
+ connectService.infoNetworkElementFeatures(nodeId).then(infoFeatures => {
+ dispatch(new AllElementInfoFeatureLoadedAction(infoFeatures));
+ }, error => {
+ dispatch(new AllElementInfoFeatureLoadedAction(null, error));
+ });
+};
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/connectApp/src/actions/mountedNetworkElementsActions.ts b/sdnr/wt/odlux/apps/connectApp/src/actions/mountedNetworkElementsActions.ts
index 26ee767..11bac10 100644
--- a/sdnr/wt/odlux/apps/connectApp/src/actions/mountedNetworkElementsActions.ts
+++ b/sdnr/wt/odlux/apps/connectApp/src/actions/mountedNetworkElementsActions.ts
@@ -32,7 +32,7 @@
return connectService.mountNetworkElement(networkElement).then((success) => {
if (success) {
dispatch(updateCurrentViewAsyncAction());
- dispatch(new AddSnackbarNotification({ message: `Requesting mount [${networkElement.nodeId}]`, options: { variant: 'info' } }))
+ dispatch(new AddSnackbarNotification({ message: `Requesting mount [${networkElement.nodeId}]`, options: { variant: 'info' } }));
} else {
dispatch(new AddSnackbarNotification({ message: `Failed to mount [${networkElement.nodeId}]`, options: { variant: 'warning' } }));
}
diff --git a/sdnr/wt/odlux/apps/connectApp/src/actions/networkElementsActions.ts b/sdnr/wt/odlux/apps/connectApp/src/actions/networkElementsActions.ts
index 57f036e..d22a6c6 100644
--- a/sdnr/wt/odlux/apps/connectApp/src/actions/networkElementsActions.ts
+++ b/sdnr/wt/odlux/apps/connectApp/src/actions/networkElementsActions.ts
@@ -30,7 +30,7 @@
/** Represents an async thunk action creator to add an element to the network elements/nodes. */
export const addNewNetworkElementAsyncActionCreator = (element: NetworkElementConnection) => async (dispatch: Dispatch) => {
- const res = await connectService.createNetworkElement({ ...element });
+ await connectService.createNetworkElement({ ...element });
dispatch(updateCurrentViewAsyncAction());
dispatch(new AddSnackbarNotification({ message: `Successfully added [${element.nodeId}]`, options: { variant: 'success' } }));
};
@@ -39,11 +39,10 @@
export const editNetworkElementAsyncActionCreator = (element: UpdateNetworkElement) => async (dispatch: Dispatch) => {
const connectionStatus: ConnectionStatus[] = (await connectService.getNetworkElementConnectionStatus(element.id).then(ne => (ne))) || [];
const currentConnectionStatus = connectionStatus[0].status;
- if (currentConnectionStatus === "Disconnected") {
- const res = await connectService.deleteNetworkElement(element);
- }
- else {
- const res = await connectService.updateNetworkElement(element);
+ if (currentConnectionStatus === 'Disconnected') {
+ await connectService.deleteNetworkElement(element);
+ } else {
+ await connectService.updateNetworkElement(element);
}
dispatch(updateCurrentViewAsyncAction());
dispatch(new AddSnackbarNotification({ message: `Successfully modified [${element.id}]`, options: { variant: 'success' } }));
@@ -52,7 +51,7 @@
/** Represents an async thunk action creator to delete an element from network elements/nodes. */
export const removeNetworkElementAsyncActionCreator = (element: UpdateNetworkElement) => async (dispatch: Dispatch) => {
- const res = await connectService.deleteNetworkElement(element);
+ await connectService.deleteNetworkElement(element);
await dispatch(unmountNetworkElementAsyncActionCreator(element && element.id));
await dispatch(updateCurrentViewAsyncAction());
};
diff --git a/sdnr/wt/odlux/apps/connectApp/src/actions/tlsKeyActions.ts b/sdnr/wt/odlux/apps/connectApp/src/actions/tlsKeyActions.ts
index 1da16d9..65d23c4 100644
--- a/sdnr/wt/odlux/apps/connectApp/src/actions/tlsKeyActions.ts
+++ b/sdnr/wt/odlux/apps/connectApp/src/actions/tlsKeyActions.ts
@@ -17,7 +17,6 @@
*/
import { Action } from '../../../../framework/src/flux/action';
import { Dispatch } from '../../../../framework/src/flux/store';
-import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
import { TlsKeys } from '../models/networkElementConnection';
import { connectService } from '../services/connectService';
@@ -36,14 +35,14 @@
* Represents an action causing the store to get all TLS Keys.
*/
export class AllTlsKeyListLoadedAction extends BaseAction {
- /**
+ /**
* Initialize this instance.
*
* @param gets all the tlsKey list from the database.
*/
- constructor(public tlsList: TlsKeys[] | null, public error?: string) {
- super();
- }
+ constructor(public tlsList: TlsKeys[] | null, public error?: string) {
+ super();
+ }
}
/**
@@ -51,10 +50,10 @@
*/
export const loadAllTlsKeyListAsync = () => async (dispatch: Dispatch) => {
- dispatch(new LoadAllTlsKeyListAction());
- connectService.getTlsKeys().then(TlsKeyList => {
- dispatch(new AllTlsKeyListLoadedAction(TlsKeyList));
- }).catch(error => {
- dispatch(new AllTlsKeyListLoadedAction(null, error));
- });
+ dispatch(new LoadAllTlsKeyListAction());
+ connectService.getTlsKeys().then(TlsKeyList => {
+ dispatch(new AllTlsKeyListLoadedAction(TlsKeyList));
+ }).catch(error => {
+ dispatch(new AllTlsKeyListLoadedAction(null, error));
+ });
};
diff --git a/sdnr/wt/odlux/apps/connectApp/src/assets/icons/connectAppIcon.svg b/sdnr/wt/odlux/apps/connectApp/src/assets/icons/connectAppIcon.svg
new file mode 100644
index 0000000..5aca4fa
--- /dev/null
+++ b/sdnr/wt/odlux/apps/connectApp/src/assets/icons/connectAppIcon.svg
@@ -0,0 +1,22 @@
+<!-- highstreet technologies GmbH colour scheme
+ Grey #565656
+ LBlue #36A9E1
+ DBlue #246DA2
+ Green #003F2C / #006C4B
+ Yellw #C8D400
+ Red #D81036
+-->
+
+<svg version="1.0" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 650 650">
+
+<g transform="translate(20,0) scale(1,1)">
+
+<path fill="#C8D400" d="M 121.5 10 c -11.5 4.1 -19.6 12.1 -23.6 23.5 c -1.8 5 -1.9 9.2 -1.9 73.9 l 0 48.5 l 37.5 0 l 37.5 0 l 0 -45.9 c 0 -40.3 -0.4 -67.9 -1 -71.2 c -2.3 -11.9 -10.6 -22.5 -21.6 -27.6 c -7.9 -3.6 -18.8 -4.1 -26.9 -1.2 z"/>
+
+<path fill="#C8D400" d="M 347.9 10 c -11.5 4.1 -19.6 12.1 -23.6 23.5 c -1.8 5 -1.9 9.2 -1.9 73.9 l 0 48.5 l 37.5 0 l 37.5 0 l 0 -45.9 c 0 -40.3 -0.4 -67.9 -1 -71.2 c -2.3 -11.9 -10.6 -22.5 -21.6 -27.6 c -7.9 -3.6 -18.8 -4.1 -26.9 -1.2 z"/>
+
+<path fill="#565656" d="m 32.5 190 c -4.9 2.2 -9.1 6.9 -10.5 11.9 c -0.7 2.4 -1 11.9 -0.8 26.3 l 0.3 22.6 l 2.9 4.1 c 4.5 6.5 9.1 8.2 22.4 8.2 l 11.2 0 l 0 17.7 c 0 35.3 3.1 59 10.5 80.3 c 21.5 61.6 70.5 105.9 135.3 122 l 4.2 1.1 l 0 57.9 c 1 27.9 4 72.9 75 75 c 177 -5.1 344 -100.1 345 -204.1 l 1 -75 c -49 124 -165 214 -337 217.1 c -5 -0.1 -7 -3.1 -7 -7.1 l 0 -63.8 l 4.2 -1.1 c 17.1 -4.4 26.1 -7.6 39.6 -14 c 51.7 -24.6 90.3 -74.2 101.7 -130.5 c 3 -14.6 4.5 -33.9 4.5 -57.7 l 0 -17.6 l 12.3 -0.4 c 11.1 -0.3 12.7 -0.5 15.9 -2.7 c 1.9 -1.3 4.6 -4 5.9 -5.9 c 2.3 -3.5 2.4 -4.2 2.7 -26.1 c 0.2 -14.4 -0.1 -23.9 -0.8 -26.3 c -1.4 -5 -5.6 -9.7 -10.5 -11.9 c -3.8 -1.8 -12.4 -1.9 -213 -1.9 c -200.6 0 -209.2 0.1 -213 1.9 z"/>
+
+
+</g>
+</svg>
diff --git a/sdnr/wt/odlux/apps/connectApp/src/components/connectionStatusLog.tsx b/sdnr/wt/odlux/apps/connectApp/src/components/connectionStatusLog.tsx
index b240b24..6a8c924 100644
--- a/sdnr/wt/odlux/apps/connectApp/src/components/connectionStatusLog.tsx
+++ b/sdnr/wt/odlux/apps/connectApp/src/components/connectionStatusLog.tsx
@@ -15,11 +15,13 @@
* the License.
* ============LICENSE_END==========================================================================
*/
-import * as React from 'react';
-import connect, { IDispatcher, Connect } from '../../../../framework/src/flux/connect';
+import React from 'react';
+
+import Refresh from '@mui/icons-material/Refresh';
+
+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 { MaterialTable, ColumnType, MaterialTableCtorType } from '../../../../framework/src/components/material-table';
-import Refresh from '@mui/icons-material/Refresh';
import { createConnectionStatusLogActions, createConnectionStatusLogProperties } from '../handlers/connectionStatusLogHandler';
import { NetworkElementConnectionLog } from '../models/networkElementConnectionLog';
@@ -37,36 +39,36 @@
type ConnectionStatusLogComponentProps = Connect<typeof mapProps, typeof mapDispatch>;
type ConnectionStatusLogComponentState = {
- refreshConnectionStatusLogEditorMode: RefreshConnectionStatusLogDialogMode
-}
+ refreshConnectionStatusLogEditorMode: RefreshConnectionStatusLogDialogMode;
+};
let initialSorted = false;
-class ConnectionStatusLogComponent extends React.Component<ConnectionStatusLogComponentProps,ConnectionStatusLogComponentState > {
+class ConnectionStatusLogComponent extends React.Component<ConnectionStatusLogComponentProps, ConnectionStatusLogComponentState > {
constructor(props: ConnectionStatusLogComponentProps) {
super(props);
this.state = {
- refreshConnectionStatusLogEditorMode: RefreshConnectionStatusLogDialogMode.None
+ refreshConnectionStatusLogEditorMode: RefreshConnectionStatusLogDialogMode.None,
};
}
render(): JSX.Element {
const refreshConnectionStatusLogAction = {
- icon: Refresh, tooltip: 'Refresh Connection Status Log Table',ariaLabel:'refresh', onClick: () => {
+ icon: Refresh, tooltip: 'Refresh Connection Status Log Table', ariaLabel:'refresh', onClick: () => {
this.setState({
- refreshConnectionStatusLogEditorMode: RefreshConnectionStatusLogDialogMode.RefreshConnectionStatusLogTable
+ refreshConnectionStatusLogEditorMode: RefreshConnectionStatusLogDialogMode.RefreshConnectionStatusLogTable,
});
- }
+ },
};
return (
<>
<ConnectionStatusTable stickyHeader tableId="connection-status-table" customActionButtons={[refreshConnectionStatusLogAction]} columns={[
- { property: "timestamp", title: "Timestamp", type: ColumnType.text },
- { property: "nodeId", title: "Node ID", type: ColumnType.text },
- { property: "status", title: "Connection Status", type: ColumnType.text },
+ { property: 'timestamp', title: 'Timestamp', type: ColumnType.text },
+ { property: 'nodeId', title: 'Node ID', type: ColumnType.text },
+ { property: 'status', title: 'Connection Status', type: ColumnType.text },
]} idProperty="id" {...this.props.connectionStatusLogActions} {...this.props.connectionStatusLogProperties} >
</ConnectionStatusTable>
<RefreshConnectionStatusLogDialog
@@ -75,17 +77,18 @@
/>
</>
);
- };
+ }
private onCloseRefreshConnectionStatusLogDialog = () => {
this.setState({
- refreshConnectionStatusLogEditorMode: RefreshConnectionStatusLogDialogMode.None
+ refreshConnectionStatusLogEditorMode: RefreshConnectionStatusLogDialogMode.None,
});
- }
+ };
+
componentDidMount() {
if (!initialSorted) {
initialSorted = true;
- this.props.connectionStatusLogActions.onHandleExplicitRequestSort("timestamp", "desc");
+ this.props.connectionStatusLogActions.onHandleExplicitRequestSort('timestamp', 'desc');
} else {
this.props.connectionStatusLogActions.onRefresh();
}
diff --git a/sdnr/wt/odlux/apps/connectApp/src/components/editNetworkElementDialog.tsx b/sdnr/wt/odlux/apps/connectApp/src/components/editNetworkElementDialog.tsx
index 5740ebd..b0db634 100644
--- a/sdnr/wt/odlux/apps/connectApp/src/components/editNetworkElementDialog.tsx
+++ b/sdnr/wt/odlux/apps/connectApp/src/components/editNetworkElementDialog.tsx
@@ -15,42 +15,43 @@
* the License.
* ============LICENSE_END==========================================================================
*/
-import * as React from 'react';
+import React from 'react';
import Button from '@mui/material/Button';
-import TextField from '@mui/material/TextField';
import Dialog from '@mui/material/Dialog';
import DialogActions from '@mui/material/DialogActions';
import DialogContent from '@mui/material/DialogContent';
import DialogContentText from '@mui/material/DialogContentText';
import DialogTitle from '@mui/material/DialogTitle';
-import { FormControl, InputLabel, Select, MenuItem, Typography, Radio, RadioGroup, Options, FormLabel, FormControlLabel } from '@mui/material';
-import { loadAllTlsKeyListAsync } from '../actions/tlsKeyActions';
-import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+import FormControl from '@mui/material/FormControl';
+import FormControlLabel from '@mui/material/FormControlLabel';
+import InputLabel from '@mui/material/InputLabel';
+import MenuItem from '@mui/material/MenuItem';
+import Radio from '@mui/material/Radio';
+import RadioGroup from '@mui/material/RadioGroup';
+import Select from '@mui/material/Select';
+import TextField from '@mui/material/TextField';
+import Typography from '@mui/material/Typography';
-import { IDispatcher, connect, Connect } from '../../../../framework/src/flux/connect';
+import { connect, Connect, IDispatcher } from '../../../../framework/src/flux/connect';
-import {
- editNetworkElementAsyncActionCreator,
- addNewNetworkElementAsyncActionCreator,
- removeNetworkElementAsyncActionCreator
-} from '../actions/networkElementsActions';
-
-import { unmountNetworkElementAsyncActionCreator, mountNetworkElementAsyncActionCreator } from '../actions/mountedNetworkElementsActions';
-import { NetworkElementConnection, UpdateNetworkElement, propertyOf } from '../models/networkElementConnection';
import { removeWebUriAction } from '../actions/commonNetworkElementsActions';
+import { mountNetworkElementAsyncActionCreator, unmountNetworkElementAsyncActionCreator } from '../actions/mountedNetworkElementsActions';
+import {
+ addNewNetworkElementAsyncActionCreator, editNetworkElementAsyncActionCreator, removeNetworkElementAsyncActionCreator,
+} from '../actions/networkElementsActions';
+import { loadAllTlsKeyListAsync } from '../actions/tlsKeyActions';
+import { NetworkElementConnection, propertyOf, UpdateNetworkElement } from '../models/networkElementConnection';
export enum EditNetworkElementDialogMode {
- None = "none",
- EditNetworkElement = "editNetworkElement",
- RemoveNetworkElement = "removeNetworkElement",
- AddNewNetworkElement = "addNewNetworkElement",
- MountNetworkElement = "mountNetworkElement",
- UnmountNetworkElement = "unmountNetworkElement",
+ None = 'none',
+ EditNetworkElement = 'editNetworkElement',
+ RemoveNetworkElement = 'removeNetworkElement',
+ AddNewNetworkElement = 'addNewNetworkElement',
+ MountNetworkElement = 'mountNetworkElement',
+ UnmountNetworkElement = 'unmountNetworkElement',
}
-
-
const mapDispatch = (dispatcher: IDispatcher) => ({
addNewNetworkElement: async (element: NetworkElementConnection) => {
await dispatcher.dispatch(addNewNetworkElementAsyncActionCreator(element));
@@ -63,12 +64,12 @@
editNetworkElement: async (element: UpdateNetworkElement, mountElement: NetworkElementConnection) => {
const values = Object.keys(element);
- console.log("edit element");
+ console.log('edit element');
console.log(values);
//make sure properties are there in case they get renamed
- const idProperty = propertyOf<UpdateNetworkElement>("id");
- const isRequiredProperty = propertyOf<UpdateNetworkElement>("isRequired");
+ const idProperty = propertyOf<UpdateNetworkElement>('id');
+ const isRequiredProperty = propertyOf<UpdateNetworkElement>('isRequired');
if (values.length === 2 && values.includes(idProperty as string) && values.includes(isRequiredProperty as string)) {
@@ -84,92 +85,92 @@
await dispatcher.dispatch(removeNetworkElementAsyncActionCreator(element));
dispatcher.dispatch(removeWebUriAction(element.id));
},
- getAvailableTlsKeys: async () => await dispatcher.dispatch(loadAllTlsKeyListAsync()),
+ getAvailableTlsKeys: async () => dispatcher.dispatch(loadAllTlsKeyListAsync()),
});
type DialogSettings = {
- dialogTitle: string,
- dialogDescription: string,
- applyButtonText: string,
- cancelButtonText: string,
- enableMountIdEditor: boolean,
- enableUsernameEditor: boolean,
- enableExtendedEditor: boolean,
-}
+ dialogTitle: string;
+ dialogDescription: string;
+ applyButtonText: string;
+ cancelButtonText: string;
+ enableMountIdEditor: boolean;
+ enableUsernameEditor: boolean;
+ enableExtendedEditor: boolean;
+};
const settings: { [key: string]: DialogSettings } = {
[EditNetworkElementDialogMode.None]: {
- dialogTitle: "",
- dialogDescription: "",
- applyButtonText: "",
- cancelButtonText: "",
+ dialogTitle: '',
+ dialogDescription: '',
+ applyButtonText: '',
+ cancelButtonText: '',
enableMountIdEditor: false,
enableUsernameEditor: false,
enableExtendedEditor: false,
},
[EditNetworkElementDialogMode.AddNewNetworkElement]: {
- dialogTitle: "Add New Node",
- dialogDescription: "Add this new node:",
- applyButtonText: "Add node",
- cancelButtonText: "Cancel",
+ dialogTitle: 'Add New Node',
+ dialogDescription: 'Add this new node:',
+ applyButtonText: 'Add node',
+ cancelButtonText: 'Cancel',
enableMountIdEditor: true,
enableUsernameEditor: true,
enableExtendedEditor: true,
},
[EditNetworkElementDialogMode.MountNetworkElement]: {
- dialogTitle: "Mount Node",
- dialogDescription: "Mount this node:",
- applyButtonText: "Mount node",
- cancelButtonText: "Cancel",
+ dialogTitle: 'Mount Node',
+ dialogDescription: 'Mount this node:',
+ applyButtonText: 'Mount node',
+ cancelButtonText: 'Cancel',
enableMountIdEditor: false,
enableUsernameEditor: false,
enableExtendedEditor: false,
},
[EditNetworkElementDialogMode.UnmountNetworkElement]: {
- dialogTitle: "Unmount Node",
- dialogDescription: "Unmount this node:",
- applyButtonText: "Unmount node",
- cancelButtonText: "Cancel",
+ dialogTitle: 'Unmount Node',
+ dialogDescription: 'Unmount this node:',
+ applyButtonText: 'Unmount node',
+ cancelButtonText: 'Cancel',
enableMountIdEditor: false,
enableUsernameEditor: false,
enableExtendedEditor: false,
},
[EditNetworkElementDialogMode.EditNetworkElement]: {
- dialogTitle: "Modify Node",
- dialogDescription: "Modify this node",
- applyButtonText: "Modify",
- cancelButtonText: "Cancel",
+ dialogTitle: 'Modify Node',
+ dialogDescription: 'Modify this node',
+ applyButtonText: 'Modify',
+ cancelButtonText: 'Cancel',
enableMountIdEditor: false,
enableUsernameEditor: true,
enableExtendedEditor: false,
},
[EditNetworkElementDialogMode.RemoveNetworkElement]: {
- dialogTitle: "Remove Node",
- dialogDescription: "Do you really want to remove this node?",
- applyButtonText: "Remove node",
- cancelButtonText: "Cancel",
+ dialogTitle: 'Remove Node',
+ dialogDescription: 'Do you really want to remove this node?',
+ applyButtonText: 'Remove node',
+ cancelButtonText: 'Cancel',
enableMountIdEditor: false,
enableUsernameEditor: false,
enableExtendedEditor: false,
- }
-}
+ },
+};
type EditNetworkElementDialogComponentProps = Connect<undefined, typeof mapDispatch> & {
mode: EditNetworkElementDialogMode;
initialNetworkElement: NetworkElementConnection;
onClose: () => void;
- radioChecked: string
+ radioChecked: string;
};
type EditNetworkElementDialogComponentState = NetworkElementConnection & {
- isNameValid: boolean,
- isHostSet: boolean,
- isPasswordSelected: boolean,
- isTlsSelected: boolean,
- radioSelected: string,
- showPasswordTextField: boolean,
- showTlsDropdown: boolean
+ isNameValid: boolean;
+ isHostSet: boolean;
+ isPasswordSelected: boolean;
+ isTlsSelected: boolean;
+ radioSelected: string;
+ showPasswordTextField: boolean;
+ showTlsDropdown: boolean;
};
class EditNetworkElementDialogComponent extends React.Component<EditNetworkElementDialogComponentProps, EditNetworkElementDialogComponentState> {
@@ -189,16 +190,17 @@
isTlsSelected: false,
radioSelected: '',
showPasswordTextField: true,
- showTlsDropdown: false
+ showTlsDropdown: false,
};
}
+
public handleRadioChange = (event: any) => {
this.setState({
radioSelected: event.target.value,
showPasswordTextField: event.target.value === 'password',
- showTlsDropdown: event.target.value === 'tlsKey'
+ showTlsDropdown: event.target.value === 'tlsKey',
});
- }
+ };
render(): JSX.Element {
const setting = settings[this.props.mode];
@@ -215,22 +217,27 @@
showTlsDropdown = true;
}
- let tlsKeysList = this.props.state.connect.availableTlsKeys ? this.props.state.connect.availableTlsKeys.tlsKeysList ? this.props.state.connect.availableTlsKeys.tlsKeysList : [] : []
+ let tlsKeysList = this.props.state.connect.availableTlsKeys ? this.props.state.connect.availableTlsKeys.tlsKeysList ? this.props.state.connect.availableTlsKeys.tlsKeysList : [] : [];
return (
<Dialog open={this.props.mode !== EditNetworkElementDialogMode.None}>
- <DialogTitle id="form-dialog-title" aria-label={`${setting.dialogTitle.replace(/ /g, "-").toLowerCase()}-dialog`}>{setting.dialogTitle}</DialogTitle>
+ <DialogTitle id="form-dialog-title" aria-label={`${setting.dialogTitle.replace(/ /g, '-').toLowerCase()}-dialog`}>{setting.dialogTitle}</DialogTitle>
<DialogContent>
<DialogContentText>
{setting.dialogDescription}
</DialogContentText>
- <TextField variant="standard" disabled={!setting.enableMountIdEditor} spellCheck={false} autoFocus margin="dense" id="name" label="Node ID" aria-label="name" type="text" fullWidth value={this.state.nodeId} onChange={(event) => { this.setState({ nodeId: event.target.value }); }} />
+ <TextField variant="standard" disabled={!setting.enableMountIdEditor} spellCheck={false} autoFocus margin="dense"
+ id="name" label="Node ID" aria-label="name" type="text" fullWidth value={this.state.nodeId} onChange={(event) => { this.setState({ nodeId: event.target.value }); }} />
{!this.state.isNameValid && <Typography variant="body1" color="error">Node ID cannot be empty.</Typography>}
- <TextField variant="standard" disabled={!setting.enableMountIdEditor} spellCheck={false} margin="dense" id="ipaddress" label="Host/IP address" aria-label="ip adress" type="text" fullWidth value={this.state.host} onChange={(event) => { this.setState({ host: event.target.value }); }} />
+ <TextField variant="standard" disabled={!setting.enableMountIdEditor} spellCheck={false} margin="dense"
+ id="ipaddress" label="Host/IP address" aria-label="ip adress" type="text" fullWidth value={this.state.host} onChange={(event) => { this.setState({ host: event.target.value }); }} />
{!this.state.isHostSet && <Typography variant="body1" color="error">Host/IP address cannot be empty.</Typography>}
- <TextField variant="standard" disabled={!setting.enableMountIdEditor} spellCheck={false} margin="dense" id="netconfport" label="NETCONF port" aria-label="netconf port" type="number" fullWidth value={this.state.port.toString()} onChange={(event) => { this.setState({ port: +event.target.value }); }} />
- {setting.enableUsernameEditor && <TextField variant="standard" disabled={!setting.enableUsernameEditor} spellCheck={false} margin="dense" id="username" label="Username" aria-label="username" type="text" fullWidth value={this.state.username} onChange={(event) => { this.setState({ username: event.target.value }); }} /> || null}
+ <TextField variant="standard" disabled={!setting.enableMountIdEditor} spellCheck={false} margin="dense"
+ id="netconfport" label="NETCONF port" aria-label="netconf port" type="number" fullWidth value={this.state.port.toString()}
+ onChange={(event) => { this.setState({ port: +event.target.value }); }} />
+ {setting.enableUsernameEditor && <TextField variant="standard" disabled={!setting.enableUsernameEditor} spellCheck={false} margin="dense"
+ id="username" label="Username" aria-label="username" type="text" fullWidth value={this.state.username} onChange={(event) => { this.setState({ username: event.target.value }); }} /> || null}
{setting.enableUsernameEditor &&
<RadioGroup row aria-label="password-tls-key" name="password-tls-key" value={radioSelected}
@@ -253,7 +260,7 @@
id="tlsKey" aria-label="tlsKey" value={this.state.tlsKey} fullWidth // displayEmpty
onChange={(event) => { this.setState({ tlsKey: event.target.value as any }); }}
inputProps={{ name: 'tlsKey', id: 'tlsKey' }} >
- <MenuItem value={""} disabled >--Select tls-key--</MenuItem>
+ <MenuItem value={''} disabled >--Select tls-key--</MenuItem>
{tlsKeysList.map(tlsKey =>
(<MenuItem value={tlsKey.key} key={tlsKey.key} aria-label={tlsKey.key} >{tlsKey.key}</MenuItem>))}
</Select>
@@ -283,7 +290,7 @@
port: this.state.port,
username: this.state.username,
password: this.state.password,
- tlsKey: this.state.tlsKey
+ tlsKey: this.state.tlsKey,
});
}
event.preventDefault();
@@ -305,7 +312,7 @@
} catch (err) {
console.log(err);
}
- }
+ };
public componentDidMount() {
this.renderTlsKeys();
@@ -313,37 +320,36 @@
public onRadioSelect = (e: any) => {
if (e.target.value == 'password') {
- this.setState({ isPasswordSelected: true, isTlsSelected: false })
+ this.setState({ isPasswordSelected: true, isTlsSelected: false });
} else if (e.target.value == 'tlsKey') {
- this.setState({ isPasswordSelected: false, isTlsSelected: true })
+ this.setState({ isPasswordSelected: false, isTlsSelected: true });
}
};
private onApply = (element: NetworkElementConnection) => {
- this.props.onClose && this.props.onClose();
+ if (this.props.onClose) this.props.onClose();
let updateElement: UpdateNetworkElement = {
- id: this.state.nodeId
- }
+ id: this.state.nodeId,
+ };
if (this.state.isPasswordSelected) {
- element.tlsKey = ''
- }
- else if (this.state.isTlsSelected) { //check here
- element.password = ''
+ element.tlsKey = '';
+ } else if (this.state.isTlsSelected) { //check here
+ element.password = '';
}
switch (this.props.mode) {
case EditNetworkElementDialogMode.AddNewNetworkElement:
- element && this.props.addNewNetworkElement(element);
+ if (element) this.props.addNewNetworkElement(element);
this.setState({
radioSelected: '',
isPasswordSelected: true,
});
break;
case EditNetworkElementDialogMode.MountNetworkElement:
- element && this.props.mountNetworkElement(element);
+ if (element) this.props.mountNetworkElement(element);
break;
case EditNetworkElementDialogMode.UnmountNetworkElement:
- element && this.props.unmountNetworkElement(element);
+ if (element) this.props.unmountNetworkElement(element);
break;
case EditNetworkElementDialogMode.EditNetworkElement:
if (this.props.initialNetworkElement.isRequired !== this.state.isRequired)
@@ -358,13 +364,13 @@
updateElement.tlsKey = this.state.tlsKey;
updateElement.password = '';
}
- element && this.props.editNetworkElement(updateElement, element);
+ if (element) this.props.editNetworkElement(updateElement, element);
this.setState({
- radioSelected: ''
+ radioSelected: '',
});
break;
case EditNetworkElementDialogMode.RemoveNetworkElement:
- element && this.props.removeNetworkElement(updateElement);
+ if (element) this.props.removeNetworkElement(updateElement);
break;
}
@@ -373,10 +379,10 @@
};
private onCancel = () => {
- this.props.onClose && this.props.onClose();
+ if (this.props.onClose) this.props.onClose();
this.setState({ password: '', username: '', tlsKey: '', radioSelected: '' });
this.resetRequieredFields();
- }
+ };
private resetRequieredFields() {
this.setState({ isNameValid: true, isHostSet: true });
@@ -402,15 +408,16 @@
return areFieldsValid;
}
- static getDerivedStateFromProps(props: EditNetworkElementDialogComponentProps, state: EditNetworkElementDialogComponentState & { _initialNetworkElement: NetworkElementConnection }): EditNetworkElementDialogComponentState & { _initialNetworkElement: NetworkElementConnection } {
- if (props.initialNetworkElement !== state._initialNetworkElement) {
- state = {
+ static getDerivedStateFromProps(props: EditNetworkElementDialogComponentProps, state: EditNetworkElementDialogComponentState & { initialNetworkElement: NetworkElementConnection }): EditNetworkElementDialogComponentState & { initialNetworkElement: NetworkElementConnection } {
+ let returnState = state;
+ if (props.initialNetworkElement !== state.initialNetworkElement) {
+ returnState = {
...state,
...props.initialNetworkElement,
- _initialNetworkElement: props.initialNetworkElement,
+ initialNetworkElement: props.initialNetworkElement,
};
}
- return state;
+ return returnState;
}
}
diff --git a/sdnr/wt/odlux/apps/connectApp/src/components/infoNetworkElementDialog.tsx b/sdnr/wt/odlux/apps/connectApp/src/components/infoNetworkElementDialog.tsx
index b0c7840..4841b93 100644
--- a/sdnr/wt/odlux/apps/connectApp/src/components/infoNetworkElementDialog.tsx
+++ b/sdnr/wt/odlux/apps/connectApp/src/components/infoNetworkElementDialog.tsx
@@ -15,145 +15,146 @@
* the License.
* ============LICENSE_END==========================================================================
*/
- import * as React from 'react';
+import * as React from 'react';
- import Button from '@mui/material/Button';
- import Dialog from '@mui/material/Dialog';
- import DialogActions from '@mui/material/DialogActions';
- import DialogTitle from '@mui/material/DialogTitle';
- import { MaterialTable, ColumnType, MaterialTableCtorType } from '../../../../framework/src/components/material-table';
- import { IDispatcher, connect, Connect } from '../../../../framework/src/flux/connect';
-
- import { NetworkElementConnection } from '../models/networkElementConnection';
- import { AvailableCapabilities } from '../models/yangCapabilitiesType'
-
- export enum InfoNetworkElementDialogMode {
- None = "none",
- InfoNetworkElement = "infoNetworkElement"
- }
-
- const mapDispatch = (dispatcher: IDispatcher) => ({
- });
-
-
- const InfoElementTable = MaterialTable as MaterialTableCtorType<AvailableCapabilities>;
-
- type DialogSettings = {
- dialogTitle: string,
- dialogDescription: string,
- cancelButtonText: string,
- }
-
- const settings: { [key: string]: DialogSettings } = {
- [InfoNetworkElementDialogMode.None]: {
- dialogTitle: "",
- dialogDescription: "",
- cancelButtonText: "",
- },
- [InfoNetworkElementDialogMode.InfoNetworkElement]: {
- dialogTitle: "YANG Capabilities of the Node",
- dialogDescription: "",
- cancelButtonText: "OK",
- }
- }
-
- type InfoNetworkElementDialogComponentProps = Connect<undefined, typeof mapDispatch> & {
- mode: InfoNetworkElementDialogMode;
- initialNetworkElement: NetworkElementConnection;
- onClose: () => void;
- };
-
- type InfoNetworkElementDialogComponentState = NetworkElementConnection;
-
- class InfoNetworkElementDialogComponent extends React.Component<InfoNetworkElementDialogComponentProps, InfoNetworkElementDialogComponentState> {
- constructor(props: InfoNetworkElementDialogComponentProps) {
- super(props);
-
- this.state = {
- nodeId: this.props.initialNetworkElement.nodeId,
- isRequired: false,
- host: this.props.initialNetworkElement.host,
- port: this.props.initialNetworkElement.port,
- };
- }
-
- render(): JSX.Element {
- const setting = settings[this.props.mode];
- const availableCapabilities = this.props.state.connect.elementInfo.elementInfo["netconf-node-topology:available-capabilities"]["available-capability"];
- let yangFeatures = this.props.state.connect.elementFeatureInfo.elementFeatureInfo;
- let yangCapabilities: AvailableCapabilities[] = [];
-
- availableCapabilities.forEach(value => {
- const capabilty = value.capability;
- const indexRevision = capabilty.indexOf("revision=");
- const indexModule = capabilty.indexOf(")", indexRevision);
- if (indexRevision > 0 && indexModule > 0) {
- let moduleName = capabilty.substring(indexModule + 1);
- let ModuleFeaturesList;
- for(let index = 0; index < yangFeatures.length; index++) {
- if(yangFeatures[index].name == moduleName) {
- ModuleFeaturesList = yangFeatures[index].feature? yangFeatures[index].feature : null;
- break;
- }
- }
- const featuresListCommaSeparated= ModuleFeaturesList? ModuleFeaturesList.toString() : ""
- let featuresList = featuresListCommaSeparated.replace(',',', ');
-
- yangCapabilities.push({
- module: moduleName,
- revision: capabilty.substring(indexRevision + 9, indexRevision + 19),
- features: featuresList
- });
- }
- });
-
- yangCapabilities = yangCapabilities.sort((a,b) => a.module === b.module ? 0 : a.module > b.module ? 1 : -1);
-
- return (
- <>
- <Dialog open={this.props.mode !== InfoNetworkElementDialogMode.None} >
- <DialogTitle id="form-dialog-title">{`${setting.dialogTitle}: "${this.state.nodeId}"`}</DialogTitle>
- <InfoElementTable stickyHeader isPopup tableId="info-element-table" asynchronus columns={[
- { property: "module", title: "YANG Capability", type: ColumnType.text, width:900 },
- {
- property: "revision", title: "Revision", type: ColumnType.custom, customControl: ({ rowData }) => {
- return (
- <div>
- <a href={`/yang-schema/${rowData.module}/${rowData.revision}`} target="_blank" > {rowData.revision} </a>
- </div>
- )
- }
- },
- { property: "features", title: "Features", type: ColumnType.text, width:500 },
- ]} idProperty="id" rows={yangCapabilities} >
- </InfoElementTable>
- <DialogActions>
- <Button aria-label="ok-button" onClick={(event) => {
- this.onCancel();
- event.preventDefault();
- event.stopPropagation();
- }} color="secondary"> {setting.cancelButtonText} </Button>
- </DialogActions>
- </Dialog>
- </>
- )
- }
-
- private onCancel = () => {
- this.props.onClose();
- }
-
- static getDerivedStateFromProps(props: InfoNetworkElementDialogComponentProps, state: InfoNetworkElementDialogComponentState & { _initialNetworkElement: NetworkElementConnection }): InfoNetworkElementDialogComponentState & { _initialNetworkElement: NetworkElementConnection } {
- if (props.initialNetworkElement !== state._initialNetworkElement) {
- state = {
- ...state,
- ...props.initialNetworkElement,
- _initialNetworkElement: props.initialNetworkElement,
- };
- }
- return state;
- }
- }
-
- export const InfoNetworkElementDialog = connect(undefined, mapDispatch)(InfoNetworkElementDialogComponent);
- export default InfoNetworkElementDialog;
\ No newline at end of file
+import Button from '@mui/material/Button';
+import Dialog from '@mui/material/Dialog';
+import DialogActions from '@mui/material/DialogActions';
+import DialogTitle from '@mui/material/DialogTitle';
+
+import { ColumnType, MaterialTable, MaterialTableCtorType } from '../../../../framework/src/components/material-table';
+import { connect, Connect } from '../../../../framework/src/flux/connect';
+
+import { NetworkElementConnection } from '../models/networkElementConnection';
+import { AvailableCapabilities } from '../models/yangCapabilitiesType';
+
+export enum InfoNetworkElementDialogMode {
+ None = 'none',
+ InfoNetworkElement = 'infoNetworkElement',
+}
+
+const mapDispatch = () => ({
+});
+
+const InfoElementTable = MaterialTable as MaterialTableCtorType<AvailableCapabilities>;
+
+type DialogSettings = {
+ dialogTitle: string;
+ dialogDescription: string;
+ cancelButtonText: string;
+};
+
+const settings: { [key: string]: DialogSettings } = {
+ [InfoNetworkElementDialogMode.None]: {
+ dialogTitle: '',
+ dialogDescription: '',
+ cancelButtonText: '',
+ },
+ [InfoNetworkElementDialogMode.InfoNetworkElement]: {
+ dialogTitle: 'YANG Capabilities of the Node',
+ dialogDescription: '',
+ cancelButtonText: 'OK',
+ },
+};
+
+type InfoNetworkElementDialogComponentProps = Connect<undefined, typeof mapDispatch> & {
+ mode: InfoNetworkElementDialogMode;
+ initialNetworkElement: NetworkElementConnection;
+ onClose: () => void;
+};
+
+type InfoNetworkElementDialogComponentState = NetworkElementConnection;
+
+class InfoNetworkElementDialogComponent extends React.Component<InfoNetworkElementDialogComponentProps, InfoNetworkElementDialogComponentState> {
+ constructor(props: InfoNetworkElementDialogComponentProps) {
+ super(props);
+
+ this.state = {
+ nodeId: this.props.initialNetworkElement.nodeId,
+ isRequired: false,
+ host: this.props.initialNetworkElement.host,
+ port: this.props.initialNetworkElement.port,
+ };
+ }
+
+ render(): JSX.Element {
+ const setting = settings[this.props.mode];
+ const availableCapabilities = this.props.state.connect.elementInfo.elementInfo['netconf-node-topology:available-capabilities']['available-capability'];
+ let yangFeatures = this.props.state.connect.elementFeatureInfo.elementFeatureInfo;
+ let yangCapabilities: AvailableCapabilities[] = [];
+
+ availableCapabilities.forEach(value => {
+ const capabilty = value.capability;
+ const indexRevision = capabilty.indexOf('revision=');
+ const indexModule = capabilty.indexOf(')', indexRevision);
+ if (indexRevision > 0 && indexModule > 0) {
+ let moduleName = capabilty.substring(indexModule + 1);
+ let ModuleFeaturesList;
+ for (let index = 0; index < yangFeatures.length; index++) {
+ if (yangFeatures[index].name == moduleName) {
+ ModuleFeaturesList = yangFeatures[index].feature ? yangFeatures[index].feature : null;
+ break;
+ }
+ }
+ const featuresListCommaSeparated = ModuleFeaturesList ? ModuleFeaturesList.toString() : '';
+ let featuresList = featuresListCommaSeparated.replace(',', ', ');
+
+ yangCapabilities.push({
+ module: moduleName,
+ revision: capabilty.substring(indexRevision + 9, indexRevision + 19),
+ features: featuresList,
+ });
+ }
+ });
+
+ yangCapabilities = yangCapabilities.sort((a, b) => a.module === b.module ? 0 : a.module > b.module ? 1 : -1);
+
+ return (
+ <>
+ <Dialog open={this.props.mode !== InfoNetworkElementDialogMode.None} >
+ <DialogTitle id="form-dialog-title">{`${setting.dialogTitle}: "${this.state.nodeId}"`}</DialogTitle>
+ <InfoElementTable stickyHeader isPopup tableId="info-element-table" asynchronus columns={[
+ { property: 'module', title: 'YANG Capability', type: ColumnType.text, width: 900 },
+ {
+ property: 'revision', title: 'Revision', type: ColumnType.custom, customControl: ({ rowData }) => {
+ return (
+ <div>
+ <a href={`/yang-schema/${rowData.module}/${rowData.revision}`} target="_blank" > {rowData.revision} </a>
+ </div>
+ );
+ },
+ },
+ { property: 'features', title: 'Features', type: ColumnType.text, width: 500 },
+ ]} idProperty="id" rows={yangCapabilities} >
+ </InfoElementTable>
+ <DialogActions>
+ <Button aria-label="ok-button" onClick={(event) => {
+ this.onCancel();
+ event.preventDefault();
+ event.stopPropagation();
+ }} color="secondary"> {setting.cancelButtonText} </Button>
+ </DialogActions>
+ </Dialog>
+ </>
+ );
+ }
+
+ private onCancel = () => {
+ this.props.onClose();
+ };
+
+ static getDerivedStateFromProps(props: InfoNetworkElementDialogComponentProps, state: InfoNetworkElementDialogComponentState & { initialNetworkElement: NetworkElementConnection }): InfoNetworkElementDialogComponentState & { initialNetworkElement: NetworkElementConnection } {
+ let returnState = state;
+ if (props.initialNetworkElement !== state.initialNetworkElement) {
+ returnState = {
+ ...state,
+ ...props.initialNetworkElement,
+ initialNetworkElement: props.initialNetworkElement,
+ };
+ }
+ return returnState;
+ }
+}
+
+export const InfoNetworkElementDialog = connect(undefined, mapDispatch)(InfoNetworkElementDialogComponent);
+export default InfoNetworkElementDialog;
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/connectApp/src/components/networkElements.tsx b/sdnr/wt/odlux/apps/connectApp/src/components/networkElements.tsx
index 67fdef6..1ce8f0c 100644
--- a/sdnr/wt/odlux/apps/connectApp/src/components/networkElements.tsx
+++ b/sdnr/wt/odlux/apps/connectApp/src/components/networkElements.tsx
@@ -15,39 +15,37 @@
* the License.
* ============LICENSE_END==========================================================================
*/
-import * as React from 'react';
-import { Theme } from '@mui/material/styles';
+import React from 'react';
+import AddIcon from '@mui/icons-material/Add';
+import ComputerIcon from '@mui/icons-material/Computer';
+import EditIcon from '@mui/icons-material/Edit';
+import Info from '@mui/icons-material/Info';
+import LinkIcon from '@mui/icons-material/Link';
+import LinkOffIcon from '@mui/icons-material/LinkOff';
+import Refresh from '@mui/icons-material/Refresh';
+import RemoveIcon from '@mui/icons-material/RemoveCircleOutline';
+import { Divider, MenuItem, Typography } from '@mui/material';
+import { Theme } from '@mui/material/styles';
import { WithStyles } from '@mui/styles';
import createStyles from '@mui/styles/createStyles';
import withStyles from '@mui/styles/withStyles';
-import AddIcon from '@mui/icons-material/Add';
-import Refresh from '@mui/icons-material/Refresh';
-import LinkIcon from '@mui/icons-material/Link';
-import LinkOffIcon from '@mui/icons-material/LinkOff';
-import RemoveIcon from '@mui/icons-material/RemoveCircleOutline';
-import EditIcon from '@mui/icons-material/Edit';
-import Info from '@mui/icons-material/Info';
-import ComputerIcon from '@mui/icons-material/Computer';
-import { MenuItem, Divider, Typography } from '@mui/material';
-
-import { MaterialTable, ColumnType, MaterialTableCtorType } from '../../../../framework/src/components/material-table';
-import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
-import { connect, Connect, IDispatcher } from '../../../../framework/src/flux/connect';
import { NavigateToApplication } from '../../../../framework/src/actions/navigationActions';
+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 { getAccessPolicyByUrl } from '../../../../framework/src/services/restService';
+import { loadAllInfoElementAsync, loadAllInfoElementFeaturesAsync } from '../actions/infoNetworkElementActions';
import { createNetworkElementsActions, createNetworkElementsProperties } from '../handlers/networkElementsHandler';
-
import { NetworkElementConnection } from '../models/networkElementConnection';
import { ModuleSet, TopologyNode } from '../models/topologyNetconf';
-import EditNetworkElementDialog, { EditNetworkElementDialogMode } from './editNetworkElementDialog';
-import RefreshNetworkElementsDialog, { RefreshNetworkElementsDialogMode } from './refreshNetworkElementsDialog';
-
-import InfoNetworkElementDialog, { InfoNetworkElementDialogMode } from './infoNetworkElementDialog';
-import { loadAllInfoElementAsync, loadAllInfoElementFeaturesAsync } from '../actions/infoNetworkElementActions';
import { connectService } from '../services/connectService';
-import { getAccessPolicyByUrl } from '../../../../framework/src/services/restService';
+
+import EditNetworkElementDialog, { EditNetworkElementDialogMode } from './editNetworkElementDialog';
+import InfoNetworkElementDialog, { InfoNetworkElementDialogMode } from './infoNetworkElementDialog';
+import RefreshNetworkElementsDialog, { RefreshNetworkElementsDialogMode } from './refreshNetworkElementsDialog';
const styles = (theme: Theme) => createStyles({
connectionStatusConnected: {
@@ -61,17 +59,17 @@
},
button: {
margin: 0,
- padding: "6px 6px",
- minWidth: 'unset'
+ padding: '6px 6px',
+ minWidth: 'unset',
},
spacer: {
marginLeft: theme.spacing(1),
marginRight: theme.spacing(1),
- display: "inline"
- }
+ display: 'inline',
+ },
});
-type GetStatelessComponentProps<T> = T extends (props: infer P & { children?: React.ReactNode }) => any ? P : any
+type GetStatelessComponentProps<T> = T extends (props: infer P & { children?: React.ReactNode }) => any ? P : any;
const MenuItemExt: React.FC<GetStatelessComponentProps<typeof MenuItem>> = (props) => {
const [disabled, setDisabled] = React.useState(true);
const onMouseDown = (ev: React.MouseEvent<HTMLElement>) => {
@@ -95,21 +93,21 @@
const mapDispatch = (dispatcher: IDispatcher) => ({
networkElementsActions: createNetworkElementsActions(dispatcher.dispatch),
navigateToApplication: (applicationName: string, path?: string) => dispatcher.dispatch(new NavigateToApplication(applicationName, path)),
- networkElementInfo: async (nodeId: string) => await dispatcher.dispatch(loadAllInfoElementAsync(nodeId)),
- networkElementFeaturesInfo: async (nodeId: string) => await dispatcher.dispatch(loadAllInfoElementFeaturesAsync(nodeId))
+ networkElementInfo: async (nodeId: string) => dispatcher.dispatch(loadAllInfoElementAsync(nodeId)),
+ networkElementFeaturesInfo: async (nodeId: string) => dispatcher.dispatch(loadAllInfoElementFeaturesAsync(nodeId)),
});
type NetworkElementsListComponentProps = WithStyles<typeof styles> & Connect<typeof mapProps, typeof mapDispatch>;
type NetworkElementsListComponentState = {
- networkElementToEdit: NetworkElementConnection,
- networkElementEditorMode: EditNetworkElementDialogMode,
- refreshNetworkElementsEditorMode: RefreshNetworkElementsDialogMode,
- infoNetworkElementEditorMode: InfoNetworkElementDialogMode,
- elementInfo: TopologyNode | null,
- elementInfoFeature: ModuleSet | null
-}
+ networkElementToEdit: NetworkElementConnection;
+ networkElementEditorMode: EditNetworkElementDialogMode;
+ refreshNetworkElementsEditorMode: RefreshNetworkElementsDialogMode;
+ infoNetworkElementEditorMode: InfoNetworkElementDialogMode;
+ elementInfo: TopologyNode | null;
+ elementInfoFeature: ModuleSet | null;
+};
-const emptyRequireNetworkElement: NetworkElementConnection = { id: "", nodeId: "", host: "", port: 830, status: "Disconnected", isRequired: true };
+const emptyRequireNetworkElement: NetworkElementConnection = { id: '', nodeId: '', host: '', port: 830, status: 'Disconnected', isRequired: true };
let initialSorted = false;
const NetworkElementTable = MaterialTable as MaterialTableCtorType<NetworkElementConnection>;
@@ -124,7 +122,7 @@
refreshNetworkElementsEditorMode: RefreshNetworkElementsDialogMode.None,
elementInfo: null,
elementInfoFeature: null,
- infoNetworkElementEditorMode: InfoNetworkElementDialogMode.None
+ infoNetworkElementEditorMode: InfoNetworkElementDialogMode.None,
};
}
@@ -135,25 +133,25 @@
const { configuration } = this.props.applicationState as any;
const buttonArray = [
- <MenuItemExt aria-label={"mount-button"} onClick={event => this.onOpenMountdNetworkElementsDialog(event, rowData)} disabled={!canMount} ><LinkIcon /><Typography>Mount</Typography></MenuItemExt>,
- <MenuItemExt aria-label={"unmount-button"} onClick={event => this.onOpenUnmountdNetworkElementsDialog(event, rowData)} disabled={!canMount} ><LinkOffIcon /><Typography>Unmount</Typography></MenuItemExt>,
+ <MenuItemExt aria-label={'mount-button'} onClick={event => this.onOpenMountdNetworkElementsDialog(event, rowData)} disabled={!canMount} ><LinkIcon /><Typography>Mount</Typography></MenuItemExt>,
+ <MenuItemExt aria-label={'unmount-button'} onClick={event => this.onOpenUnmountdNetworkElementsDialog(event, rowData)} disabled={!canMount} ><LinkOffIcon /><Typography>Unmount</Typography></MenuItemExt>,
<Divider />,
- <MenuItem aria-label={"info-button"} onClick={event => this.onOpenInfoNetworkElementDialog(event, rowData)} disabled={rowData.status !== "Connected"} ><Info /><Typography>Info</Typography></MenuItem>,
- <MenuItem aria-label={"edit-button"} onClick={event => this.onOpenEditNetworkElementDialog(event, rowData)}><EditIcon /><Typography>Edit</Typography></MenuItem>,
- <MenuItem aria-label={"remove-button"} onClick={event => this.onOpenRemoveNetworkElementDialog(event, rowData)} ><RemoveIcon /><Typography>Remove</Typography></MenuItem>,
+ <MenuItem aria-label={'info-button'} onClick={event => this.onOpenInfoNetworkElementDialog(event, rowData)} disabled={rowData.status !== 'Connected'} ><Info /><Typography>Info</Typography></MenuItem>,
+ <MenuItem aria-label={'edit-button'} onClick={event => this.onOpenEditNetworkElementDialog(event, rowData)}><EditIcon /><Typography>Edit</Typography></MenuItem>,
+ <MenuItem aria-label={'remove-button'} onClick={event => this.onOpenRemoveNetworkElementDialog(event, rowData)} ><RemoveIcon /><Typography>Remove</Typography></MenuItem>,
<Divider />,
- <MenuItem aria-label={"inventory-button"} onClick={event => this.props.navigateToApplication("inventory", rowData.nodeId)}><Typography>Inventory</Typography></MenuItem>,
+ <MenuItem aria-label={'inventory-button'} onClick={() => this.props.navigateToApplication('inventory', rowData.nodeId)}><Typography>Inventory</Typography></MenuItem>,
<Divider />,
- <MenuItem aria-label={"fault-button"} onClick={event => this.props.navigateToApplication("fault", rowData.nodeId)} ><Typography>Fault</Typography></MenuItem>,
- <MenuItem aria-label={"configure-button"} onClick={event => this.props.navigateToApplication("configuration", rowData.nodeId)} disabled={rowData.status === "Connecting" || rowData.status === "Disconnected" || !configuration}><Typography>Configure</Typography></MenuItem>,
- <MenuItem onClick={event => this.props.navigateToApplication("accounting", rowData.nodeId)} disabled={true}><Typography>Accounting</Typography></MenuItem>,
- <MenuItem aria-label={"performance-button"} onClick={event => this.props.navigateToApplication("performanceHistory", rowData.nodeId)}><Typography>Performance</Typography></MenuItem>,
- <MenuItem onClick={event => this.props.navigateToApplication("security", rowData.nodeId)} disabled={true} ><Typography>Security</Typography></MenuItem>,
+ <MenuItem aria-label={'fault-button'} onClick={() => this.props.navigateToApplication('fault', rowData.nodeId)} ><Typography>Fault</Typography></MenuItem>,
+ <MenuItem aria-label={'configure-button'} onClick={() => this.props.navigateToApplication('configuration', rowData.nodeId)} disabled={rowData.status === 'Connecting' || rowData.status === 'Disconnected' || !configuration}><Typography>Configure</Typography></MenuItem>,
+ <MenuItem onClick={() => this.props.navigateToApplication('accounting', rowData.nodeId)} disabled={true}><Typography>Accounting</Typography></MenuItem>,
+ <MenuItem aria-label={'performance-button'} onClick={() => this.props.navigateToApplication('performanceHistory', rowData.nodeId)}><Typography>Performance</Typography></MenuItem>,
+ <MenuItem onClick={() => this.props.navigateToApplication('security', rowData.nodeId)} disabled={true} ><Typography>Security</Typography></MenuItem>,
];
if (rowData.weburi) {
// add an icon for gui cuttrough, if weburi is available
- return [<MenuItem aria-label={"web-client-button"} onClick={event => window.open(rowData.weburi, "_blank")} ><ComputerIcon /><Typography>Web Client</Typography></MenuItem>].concat(buttonArray)
+ return [<MenuItem aria-label={'web-client-button'} onClick={() => window.open(rowData.weburi, '_blank')} ><ComputerIcon /><Typography>Web Client</Typography></MenuItem>].concat(buttonArray);
} else {
return buttonArray;
}
@@ -162,13 +160,13 @@
// private navigationCreator
render(): JSX.Element {
- const { classes } = this.props;
+ //const { classes } = this.props;
const { networkElementToEdit } = this.state;
- let savedRadio = "password";
+ let savedRadio = 'password';
if (this.state.networkElementToEdit.password && this.state.networkElementToEdit.password.length > 0) {
- savedRadio = 'password'
+ savedRadio = 'password';
} else if (this.state.networkElementToEdit.tlsKey && this.state.networkElementToEdit.tlsKey.length > 0) {
- savedRadio = 'tlsKey'
+ savedRadio = 'tlsKey';
}
// const mountUri = rowData.id && connectService.getNetworkElementUri(rowData.id);
@@ -177,32 +175,32 @@
const canAdd = true;
const addRequireNetworkElementAction = {
- icon: AddIcon, tooltip: 'Add node', ariaLabel: "add-element", onClick: () => {
+ icon: AddIcon, tooltip: 'Add node', ariaLabel: 'add-element', onClick: () => {
this.setState({
networkElementEditorMode: EditNetworkElementDialogMode.AddNewNetworkElement,
networkElementToEdit: emptyRequireNetworkElement,
});
- }
+ },
};
const refreshNetworkElementsAction = {
icon: Refresh, tooltip: 'Refresh table', ariaLabel: 'refresh', onClick: () => {
this.setState({
- refreshNetworkElementsEditorMode: RefreshNetworkElementsDialogMode.RefreshNetworkElementsTable
+ refreshNetworkElementsEditorMode: RefreshNetworkElementsDialogMode.RefreshNetworkElementsTable,
});
- }
+ },
};
return <>
<NetworkElementTable stickyHeader tableId="network-element-table" customActionButtons={[refreshNetworkElementsAction, ...(canAdd ? [addRequireNetworkElementAction] : [])]} columns={[
- { property: "nodeId", title: "Node ID", type: ColumnType.text },
- { property: "status", title: "Connection Status", type: ColumnType.text, width:'15%' },
- { property: "host", title: "Host", type: ColumnType.text },
- { property: "port", title: "Port", type: ColumnType.numeric },
- { property: "isRequired", title: "Required", type: ColumnType.boolean },
- { property: "deviceType", title: "Type", type: ColumnType.text },
- // { property: "coreModelCapability", title: "Core Model", type: ColumnType.text },
- { property: "deviceFunction", title: "Function", type: ColumnType.text, width: '25%' }
+ { property: 'nodeId', title: 'Node ID', type: ColumnType.text },
+ { property: 'status', title: 'Connection Status', type: ColumnType.text, width:'15%' },
+ { property: 'host', title: 'Host', type: ColumnType.text },
+ { property: 'port', title: 'Port', type: ColumnType.numeric },
+ { property: 'isRequired', title: 'Required', type: ColumnType.boolean },
+ { property: 'deviceType', title: 'Type', type: ColumnType.text },
+ // { property: "coreModelCapability", title: "Core Model", type: ColumnType.text },
+ { property: 'deviceFunction', title: 'Function', type: ColumnType.text, width: '25%' },
]} idProperty="id" {...this.props.networkElementsActions} {...this.props.networkElementsProperties} asynchronus createContextMenu={rowData => {
return this.getContextMenu(rowData);
@@ -224,12 +222,12 @@
onClose={this.onCloseInfoNetworkElementDialog}
/>
</>;
- };
+ }
public componentDidMount() {
if (!initialSorted) {
initialSorted = true;
- this.props.networkElementsActions.onHandleRequestSort("node-id");
+ this.props.networkElementsActions.onHandleRequestSort('node-id');
} else {
this.props.networkElementsActions.onRefresh();
}
@@ -238,23 +236,23 @@
private onOpenAddNetworkElementDialog = (event: React.MouseEvent<HTMLElement>, element: NetworkElementConnection) => {
this.setState({
networkElementToEdit: element,
- networkElementEditorMode: EditNetworkElementDialogMode.AddNewNetworkElement
+ networkElementEditorMode: EditNetworkElementDialogMode.AddNewNetworkElement,
});
- }
+ };
private onOpenRemoveNetworkElementDialog = (event: React.MouseEvent<HTMLElement>, element: NetworkElementConnection) => {
this.setState({
networkElementToEdit: element,
- networkElementEditorMode: EditNetworkElementDialogMode.RemoveNetworkElement
+ networkElementEditorMode: EditNetworkElementDialogMode.RemoveNetworkElement,
});
- }
+ };
private onOpenEditNetworkElementDialog = (event: React.MouseEvent<HTMLElement>, element: NetworkElementConnection) => {
- let radioSaved;
- if (element.password && element.password.length > 0)
- radioSaved = 'password'
- else if (element.tlsKey && element.tlsKey.length > 0)
- radioSaved = 'tlsKey'
+ //let radioSaved;
+ //if (element.password && element.password.length > 0)
+ // radioSaved = 'password';
+ //else if (element.tlsKey && element.tlsKey.length > 0)
+ // radioSaved = 'tlsKey';
this.setState({
networkElementToEdit: {
nodeId: element.nodeId,
@@ -263,25 +261,25 @@
port: element.port,
username: element.username,
password: element.password,
- tlsKey: element.tlsKey
+ tlsKey: element.tlsKey,
},
- networkElementEditorMode: EditNetworkElementDialogMode.EditNetworkElement
+ networkElementEditorMode: EditNetworkElementDialogMode.EditNetworkElement,
});
- }
+ };
private onOpenUnmountdNetworkElementsDialog = (event: React.MouseEvent<HTMLElement>, element: NetworkElementConnection) => {
this.setState({
networkElementToEdit: element,
- networkElementEditorMode: EditNetworkElementDialogMode.UnmountNetworkElement
+ networkElementEditorMode: EditNetworkElementDialogMode.UnmountNetworkElement,
});
- }
+ };
private onOpenMountdNetworkElementsDialog = (event: React.MouseEvent<HTMLElement>, element: NetworkElementConnection) => {
this.setState({
networkElementToEdit: element,
- networkElementEditorMode: EditNetworkElementDialogMode.MountNetworkElement
+ networkElementEditorMode: EditNetworkElementDialogMode.MountNetworkElement,
});
- }
+ };
private onOpenInfoNetworkElementDialog = (event: React.MouseEvent<HTMLElement>, element: NetworkElementConnection) => {
this.props.networkElementInfo(element.nodeId);
@@ -290,25 +288,27 @@
networkElementToEdit: element,
infoNetworkElementEditorMode: InfoNetworkElementDialogMode.InfoNetworkElement,
});
- }
+ };
private onCloseEditNetworkElementDialog = () => {
this.setState({
networkElementEditorMode: EditNetworkElementDialogMode.None,
networkElementToEdit: emptyRequireNetworkElement,
});
- }
+ };
+
private onCloseInfoNetworkElementDialog = () => {
this.setState({
infoNetworkElementEditorMode: InfoNetworkElementDialogMode.None,
networkElementToEdit: emptyRequireNetworkElement,
});
- }
+ };
+
private onCloseRefreshNetworkElementsDialog = () => {
this.setState({
- refreshNetworkElementsEditorMode: RefreshNetworkElementsDialogMode.None
+ refreshNetworkElementsEditorMode: RefreshNetworkElementsDialogMode.None,
});
- }
+ };
}
export const NetworkElementsList = withStyles(styles)(connect(mapProps, mapDispatch)(NetworkElementsListComponent));
diff --git a/sdnr/wt/odlux/apps/connectApp/src/components/refreshConnectionStatusLogDialog.tsx b/sdnr/wt/odlux/apps/connectApp/src/components/refreshConnectionStatusLogDialog.tsx
index c09f59b..a4aea7f 100644
--- a/sdnr/wt/odlux/apps/connectApp/src/components/refreshConnectionStatusLogDialog.tsx
+++ b/sdnr/wt/odlux/apps/connectApp/src/components/refreshConnectionStatusLogDialog.tsx
@@ -15,7 +15,7 @@
* the License.
* ============LICENSE_END==========================================================================
*/
-import * as React from 'react';
+import React from 'react';
import Button from '@mui/material/Button';
import Dialog from '@mui/material/Dialog';
@@ -24,78 +24,75 @@
import DialogContentText from '@mui/material/DialogContentText';
import DialogTitle from '@mui/material/DialogTitle';
-import { connectionStatusLogReloadAction } from '../handlers/connectionStatusLogHandler';
-import { IDispatcher, connect, Connect } from '../../../../framework/src/flux/connect';
+import { connect, Connect, IDispatcher } from '../../../../framework/src/flux/connect';
+import { connectionStatusLogReloadAction } from '../handlers/connectionStatusLogHandler';
import { ConnectionStatusLogType } from '../models/connectionStatusLog';
export enum RefreshConnectionStatusLogDialogMode {
- None = "none",
- RefreshConnectionStatusLogTable = "RefreshConnectionStatusLogTable",
+ None = 'none',
+ RefreshConnectionStatusLogTable = 'RefreshConnectionStatusLogTable',
}
const mapDispatch = (dispatcher: IDispatcher) => ({
- refreshConnectionStatusLog: () => dispatcher.dispatch(connectionStatusLogReloadAction)
+ refreshConnectionStatusLog: () => dispatcher.dispatch(connectionStatusLogReloadAction),
});
type DialogSettings = {
- dialogTitle: string,
- dialogDescription: string,
- applyButtonText: string,
- cancelButtonText: string,
- enableMountIdEditor: boolean,
- enableUsernameEditor: boolean,
- enableExtendedEditor: boolean,
-}
+ dialogTitle: string;
+ dialogDescription: string;
+ applyButtonText: string;
+ cancelButtonText: string;
+ enableMountIdEditor: boolean;
+ enableUsernameEditor: boolean;
+ enableExtendedEditor: boolean;
+};
const settings: { [key: string]: DialogSettings } = {
[RefreshConnectionStatusLogDialogMode.None]: {
- dialogTitle: "",
- dialogDescription: "",
- applyButtonText: "",
- cancelButtonText: "",
+ dialogTitle: '',
+ dialogDescription: '',
+ applyButtonText: '',
+ cancelButtonText: '',
enableMountIdEditor: false,
enableUsernameEditor: false,
enableExtendedEditor: false,
},
[RefreshConnectionStatusLogDialogMode.RefreshConnectionStatusLogTable]: {
- dialogTitle: "Do you want to refresh the Connection Status Log table?",
- dialogDescription: "",
- applyButtonText: "Yes",
- cancelButtonText: "Cancel",
+ dialogTitle: 'Do you want to refresh the Connection Status Log table?',
+ dialogDescription: '',
+ applyButtonText: 'Yes',
+ cancelButtonText: 'Cancel',
enableMountIdEditor: true,
enableUsernameEditor: true,
enableExtendedEditor: true,
- }
-}
+ },
+};
type RefreshConnectionStatusLogDialogComponentProps = Connect<undefined, typeof mapDispatch> & {
mode: RefreshConnectionStatusLogDialogMode;
onClose: () => void;
};
-type RefreshConnectionStatusLogDialogComponentState = ConnectionStatusLogType & { isNameValid: boolean, isHostSet: boolean };
+type RefreshConnectionStatusLogDialogComponentState = ConnectionStatusLogType & { isNameValid: boolean; isHostSet: boolean };
class RefreshConnectionStatusLogDialogComponent extends React.Component<RefreshConnectionStatusLogDialogComponentProps, RefreshConnectionStatusLogDialogComponentState> {
- constructor(props: RefreshConnectionStatusLogDialogComponentProps) {
- super(props);
- }
render(): JSX.Element {
const setting = settings[this.props.mode];
return (
<Dialog open={this.props.mode !== RefreshConnectionStatusLogDialogMode.None}>
- <DialogTitle id="form-dialog-title" aria-label={`${setting.dialogTitle.replace(/ /g, "-").toLowerCase()}-dialog`}>{setting.dialogTitle}</DialogTitle>
+ <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={(event) => {
+ <Button aria-label="dialog-confirm-button" onClick={() => {
this.onRefresh();
}} color="inherit" > {setting.applyButtonText} </Button>
- <Button aria-label="dialog-cancel-button" onClick={(event) => {
+ <Button aria-label="dialog-cancel-button" onClick={() => {
this.onCancel();
}} color="secondary"> {setting.cancelButtonText} </Button>
</DialogActions>
@@ -110,7 +107,7 @@
private onCancel = () => {
this.props.onClose();
- }
+ };
}
export const RefreshConnectionStatusLogDialog = connect(undefined, mapDispatch)(RefreshConnectionStatusLogDialogComponent);
diff --git a/sdnr/wt/odlux/apps/connectApp/src/components/refreshNetworkElementsDialog.tsx b/sdnr/wt/odlux/apps/connectApp/src/components/refreshNetworkElementsDialog.tsx
index abf5938..e41fd27 100644
--- a/sdnr/wt/odlux/apps/connectApp/src/components/refreshNetworkElementsDialog.tsx
+++ b/sdnr/wt/odlux/apps/connectApp/src/components/refreshNetworkElementsDialog.tsx
@@ -15,7 +15,7 @@
* the License.
* ============LICENSE_END==========================================================================
*/
-import * as React from 'react';
+import React from 'react';
import Button from '@mui/material/Button';
import Dialog from '@mui/material/Dialog';
@@ -24,78 +24,75 @@
import DialogContentText from '@mui/material/DialogContentText';
import DialogTitle from '@mui/material/DialogTitle';
-import { networkElementsReloadAction } from '../handlers/networkElementsHandler';
-import { IDispatcher, connect, Connect } from '../../../../framework/src/flux/connect';
+import { connect, Connect, IDispatcher } from '../../../../framework/src/flux/connect';
+import { networkElementsReloadAction } from '../handlers/networkElementsHandler';
import { NetworkElementConnection } from '../models/networkElementConnection';
export enum RefreshNetworkElementsDialogMode {
- None = "none",
- RefreshNetworkElementsTable = "RefreshNetworkElementsTable",
+ None = 'none',
+ RefreshNetworkElementsTable = 'RefreshNetworkElementsTable',
}
const mapDispatch = (dispatcher: IDispatcher) => ({
- refreshNetworkElement: () => dispatcher.dispatch(networkElementsReloadAction)
+ refreshNetworkElement: () => dispatcher.dispatch(networkElementsReloadAction),
});
type DialogSettings = {
- dialogTitle: string,
- dialogDescription: string,
- applyButtonText: string,
- cancelButtonText: string,
- enableMountIdEditor: boolean,
- enableUsernameEditor: boolean,
- enableExtendedEditor: boolean,
-}
+ dialogTitle: string;
+ dialogDescription: string;
+ applyButtonText: string;
+ cancelButtonText: string;
+ enableMountIdEditor: boolean;
+ enableUsernameEditor: boolean;
+ enableExtendedEditor: boolean;
+};
const settings: { [key: string]: DialogSettings } = {
[RefreshNetworkElementsDialogMode.None]: {
- dialogTitle: "",
- dialogDescription: "",
- applyButtonText: "",
- cancelButtonText: "",
+ dialogTitle: '',
+ dialogDescription: '',
+ applyButtonText: '',
+ cancelButtonText: '',
enableMountIdEditor: false,
enableUsernameEditor: false,
enableExtendedEditor: false,
},
[RefreshNetworkElementsDialogMode.RefreshNetworkElementsTable]: {
- dialogTitle: "Do you want to refresh the nodes table?",
- dialogDescription: "",
- applyButtonText: "Yes",
- cancelButtonText: "Cancel",
+ dialogTitle: 'Do you want to refresh the nodes table?',
+ dialogDescription: '',
+ applyButtonText: 'Yes',
+ cancelButtonText: 'Cancel',
enableMountIdEditor: true,
enableUsernameEditor: true,
enableExtendedEditor: true,
- }
-}
+ },
+};
type RefreshNetworkElementsDialogComponentProps = Connect<undefined, typeof mapDispatch> & {
mode: RefreshNetworkElementsDialogMode;
onClose: () => void;
};
-type RefreshNetworkElementsDialogComponentState = NetworkElementConnection & { isNameValid: boolean, isHostSet: boolean };
+type RefreshNetworkElementsDialogComponentState = NetworkElementConnection & { isNameValid: boolean; isHostSet: boolean };
class RefreshNetworkElementsDialogComponent extends React.Component<RefreshNetworkElementsDialogComponentProps, RefreshNetworkElementsDialogComponentState> {
- constructor(props: RefreshNetworkElementsDialogComponentProps) {
- super(props);
- }
render(): JSX.Element {
const setting = settings[this.props.mode];
return (
<Dialog open={this.props.mode !== RefreshNetworkElementsDialogMode.None}>
- <DialogTitle id="form-dialog-title" aria-label={`${setting.dialogTitle.replace(/ /g, "-").toLowerCase()}-dialog`}>{setting.dialogTitle}</DialogTitle>
+ <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={(event) => {
+ <Button aria-label="dialog-confirm-button" onClick={() => {
this.onRefresh();
}} color="inherit" > {setting.applyButtonText} </Button>
- <Button aria-label="dialog-cancel-button" onClick={(event) => {
+ <Button aria-label="dialog-cancel-button" onClick={() => {
this.onCancel();
}} color="secondary"> {setting.cancelButtonText} </Button>
</DialogActions>
@@ -110,7 +107,7 @@
private onCancel = () => {
this.props.onClose();
- }
+ };
}
export const RefreshNetworkElementsDialog = connect(undefined, mapDispatch)(RefreshNetworkElementsDialogComponent);
diff --git a/sdnr/wt/odlux/apps/connectApp/src/handlers/connectAppRootHandler.ts b/sdnr/wt/odlux/apps/connectApp/src/handlers/connectAppRootHandler.ts
index 6a18252..b386dcd 100644
--- a/sdnr/wt/odlux/apps/connectApp/src/handlers/connectAppRootHandler.ts
+++ b/sdnr/wt/odlux/apps/connectApp/src/handlers/connectAppRootHandler.ts
@@ -18,12 +18,13 @@
import { IActionHandler } from '../../../../framework/src/flux/action';
import { combineActionHandler } from '../../../../framework/src/flux/middleware';
-import { INetworkElementsState, networkElementsActionHandler } from './networkElementsHandler';
-import { IConnectionStatusLogState, connectionStatusLogActionHandler } from './connectionStatusLogHandler';
-import { IInfoNetworkElementsState, infoNetworkElementsActionHandler, IInfoNetworkElementFeaturesState, infoNetworkElementFeaturesActionHandler } from './infoNetworkElementHandler';
-import { SetPanelAction, AddWebUriList, RemoveWebUri, SetWeburiSearchBusy } from '../actions/commonNetworkElementsActions';
-import { PanelId } from '../models/panelId';
+
+import { AddWebUriList, RemoveWebUri, SetPanelAction } from '../actions/commonNetworkElementsActions';
import { guiCutThrough } from '../models/guiCutTrough';
+import { PanelId } from '../models/panelId';
+import { connectionStatusLogActionHandler, IConnectionStatusLogState } from './connectionStatusLogHandler';
+import { IInfoNetworkElementFeaturesState, IInfoNetworkElementsState, infoNetworkElementFeaturesActionHandler, infoNetworkElementsActionHandler } from './infoNetworkElementHandler';
+import { INetworkElementsState, networkElementsActionHandler } from './networkElementsHandler';
import { availableTlsKeysActionHandler, IAvailableTlsKeysState } from './tlsKeyHandler';
export interface IConnectAppStoreState {
@@ -33,7 +34,7 @@
elementInfo: IInfoNetworkElementsState;
elementFeatureInfo: IInfoNetworkElementFeaturesState;
guiCutThrough: guiCutThroughState;
- availableTlsKeys: IAvailableTlsKeysState
+ availableTlsKeys: IAvailableTlsKeysState;
}
const currentOpenPanelHandler: IActionHandler<PanelId> = (state = null, action) => {
@@ -41,7 +42,7 @@
state = action.panelId;
}
return state;
-}
+};
interface guiCutThroughState {
searchedElements: guiCutThrough[];
@@ -62,12 +63,12 @@
if (action.newlySearchedElements) {
action.newlySearchedElements.forEach(item => {
notSearchedElements = notSearchedElements.filter(id => id !== item);
- })
+ });
}
searchedElements = state.searchedElements.concat(action.searchedElements);
- state = { searchedElements: searchedElements, notSearchedElements: notSearchedElements, unsupportedElements: unsupportedElements }
+ state = { searchedElements: searchedElements, notSearchedElements: notSearchedElements, unsupportedElements: unsupportedElements };
} else if (action instanceof RemoveWebUri) {
const nodeId = action.element;
@@ -77,11 +78,11 @@
state = { notSearchedElements: knownElements, searchedElements: webUris, unsupportedElements: unsupportedElement };
}
return state;
-}
+};
declare module '../../../../framework/src/store/applicationStore' {
interface IApplicationStoreState {
- connect: IConnectAppStoreState
+ connect: IConnectAppStoreState;
}
}
@@ -92,7 +93,7 @@
elementInfo: infoNetworkElementsActionHandler,
elementFeatureInfo: infoNetworkElementFeaturesActionHandler,
guiCutThrough: guiCutThroughHandler,
- availableTlsKeys: availableTlsKeysActionHandler
+ availableTlsKeys: availableTlsKeysActionHandler,
};
export const connectAppRootHandler = combineActionHandler<IConnectAppStoreState>(actionHandlers);
diff --git a/sdnr/wt/odlux/apps/connectApp/src/handlers/connectionStatusLogHandler.ts b/sdnr/wt/odlux/apps/connectApp/src/handlers/connectionStatusLogHandler.ts
index 6863ec3..264b6c1 100644
--- a/sdnr/wt/odlux/apps/connectApp/src/handlers/connectionStatusLogHandler.ts
+++ b/sdnr/wt/odlux/apps/connectApp/src/handlers/connectionStatusLogHandler.ts
@@ -15,10 +15,11 @@
* the License.
* ============LICENSE_END==========================================================================
*/
-import { createExternal,IExternalTableState } from '../../../../framework/src/components/material-table/utilities';
+import { createExternal, IExternalTableState } from '../../../../framework/src/components/material-table/utilities';
import { createSearchDataHandler } from '../../../../framework/src/utilities/elasticSearch';
import { NetworkElementConnectionLog } from '../models/networkElementConnectionLog';
+
export interface IConnectionStatusLogState extends IExternalTableState<NetworkElementConnectionLog> { }
// create eleactic search material data fetch handler
diff --git a/sdnr/wt/odlux/apps/connectApp/src/handlers/infoNetworkElementHandler.ts b/sdnr/wt/odlux/apps/connectApp/src/handlers/infoNetworkElementHandler.ts
index 3e2d1ce..692e63a 100644
--- a/sdnr/wt/odlux/apps/connectApp/src/handlers/infoNetworkElementHandler.ts
+++ b/sdnr/wt/odlux/apps/connectApp/src/handlers/infoNetworkElementHandler.ts
@@ -15,79 +15,78 @@
* the License.
* ============LICENSE_END==========================================================================
*/
- import { IActionHandler } from '../../../../framework/src/flux/action';
+import { IActionHandler } from '../../../../framework/src/flux/action';
- import { AllElementInfoLoadedAction, AllElementInfoFeatureLoadedAction, LoadAllElementInfoAction } from '../actions/infoNetworkElementActions';
+import { AllElementInfoFeatureLoadedAction, AllElementInfoLoadedAction, LoadAllElementInfoAction } from '../actions/infoNetworkElementActions';
+import { Module, TopologyNode } from '../models/topologyNetconf';
- import { Module, TopologyNode } from '../models/topologyNetconf';
+export interface IInfoNetworkElementsState {
+ elementInfo: TopologyNode;
+ busy: boolean;
+}
- export interface IInfoNetworkElementsState {
- elementInfo: TopologyNode;
- busy: boolean;
- }
+export interface IInfoNetworkElementFeaturesState {
+ elementFeatureInfo: Module[];
+ busy: boolean;
+}
- export interface IInfoNetworkElementFeaturesState {
- elementFeatureInfo: Module[];
- busy: boolean;
- }
+const infoNetworkElementsStateInit: IInfoNetworkElementsState = {
+ elementInfo: {
+ 'node-id': '',
+ 'netconf-node-topology:available-capabilities': {
+ 'available-capability': [],
+ },
+ },
+ busy: false,
+};
- const infoNetworkElementsStateInit: IInfoNetworkElementsState = {
- elementInfo: {
- "node-id": "",
- "netconf-node-topology:available-capabilities": {
- "available-capability": []
- }
- },
- busy: false
- };
+const infoNetworkElementFeaturesStateInit: IInfoNetworkElementFeaturesState = {
+ elementFeatureInfo: [],
+ busy: false,
+};
- const infoNetworkElementFeaturesStateInit: IInfoNetworkElementFeaturesState = {
- elementFeatureInfo: [],
- busy: false
- };
+export const infoNetworkElementsActionHandler: IActionHandler<IInfoNetworkElementsState> = (state = infoNetworkElementsStateInit, action) => {
+ if (action instanceof LoadAllElementInfoAction) {
+ state = {
+ ...state,
+ busy: true,
+ };
+ } else if (action instanceof AllElementInfoLoadedAction) {
+ if (!action.error && action.elementInfo) {
+ state = {
+ ...state,
+ elementInfo: action.elementInfo,
+ busy: false,
+ };
+ } else {
+ state = {
+ ...state,
+ busy: false,
+ };
+ }
+ }
+ return state;
+};
- export const infoNetworkElementsActionHandler: IActionHandler<IInfoNetworkElementsState> = (state = infoNetworkElementsStateInit, action) => {
- if (action instanceof LoadAllElementInfoAction) {
- state = {
- ...state,
- busy: true
- };
- } else if (action instanceof AllElementInfoLoadedAction) {
- if (!action.error && action.elementInfo) {
- state = {
- ...state,
- elementInfo: action.elementInfo,
- busy: false
- };
- } else {
- state = {
- ...state,
- busy: false
- };
- }
- }
- return state;
- };
-
- export const infoNetworkElementFeaturesActionHandler: IActionHandler<IInfoNetworkElementFeaturesState> = (state = infoNetworkElementFeaturesStateInit, action) => {
- if (action instanceof LoadAllElementInfoAction) {
- state = {
- ...state,
- busy: true
- };
- } else if (action instanceof AllElementInfoFeatureLoadedAction) {
- if (!action.error && action.elementFeatureInfo) {
- state = {
- ...state,
- elementFeatureInfo: action.elementFeatureInfo,
- busy: false
- };
- } else {
- state = {
- ...state,
- busy: false
- };
- }
- }
- return state;
- };
\ No newline at end of file
+export const infoNetworkElementFeaturesActionHandler: IActionHandler<IInfoNetworkElementFeaturesState> = (state = infoNetworkElementFeaturesStateInit, action) => {
+ if (action instanceof LoadAllElementInfoAction) {
+ state = {
+ ...state,
+ busy: true,
+ };
+ } else if (action instanceof AllElementInfoFeatureLoadedAction) {
+ if (!action.error && action.elementFeatureInfo) {
+ state = {
+ ...state,
+ elementFeatureInfo: action.elementFeatureInfo,
+ busy: false,
+ };
+ } else {
+ state = {
+ ...state,
+ busy: false,
+ };
+ }
+ }
+ return state;
+};
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/connectApp/src/handlers/networkElementsHandler.ts b/sdnr/wt/odlux/apps/connectApp/src/handlers/networkElementsHandler.ts
index b74a394..42d2824 100644
--- a/sdnr/wt/odlux/apps/connectApp/src/handlers/networkElementsHandler.ts
+++ b/sdnr/wt/odlux/apps/connectApp/src/handlers/networkElementsHandler.ts
@@ -16,8 +16,8 @@
* ============LICENSE_END==========================================================================
*/
import { createExternal, IExternalTableState } from '../../../../framework/src/components/material-table/utilities';
-import { createSearchDataHandler } from '../../../../framework/src/utilities/elasticSearch';
import { getAccessPolicyByUrl } from '../../../../framework/src/services/restService';
+import { createSearchDataHandler } from '../../../../framework/src/utilities/elasticSearch';
import { NetworkElementConnection } from '../models/networkElementConnection';
import { connectService } from '../services/connectService';
@@ -32,7 +32,7 @@
createActions: createNetworkElementsActions,
createProperties: createNetworkElementsProperties,
reloadAction: networkElementsReloadAction,
-
+
// set value action, to change a value
} = createExternal<NetworkElementConnection>(networkElementsSearchHandler, appState => {
@@ -42,20 +42,19 @@
appState.connect.networkElements.rows.forEach(element => {
- if (element.status === "Connected") {
+ if (element.status === 'Connected') {
const webUri = webUris.find(item => item.id === element.id as string);
if (webUri) {
element.weburi = webUri.weburi;
element.isWebUriUnreachable = false;
- }
- else {
- element.isWebUriUnreachable = true
+ } else {
+ element.isWebUriUnreachable = true;
}
}
});
}
- return appState.connect.networkElements
+ return appState.connect.networkElements;
}, (ne) => {
if (!ne || !ne.id) return true;
const neUrl = connectService.getNetworkElementUri(ne.id);
diff --git a/sdnr/wt/odlux/apps/connectApp/src/handlers/tlsKeyHandler.ts b/sdnr/wt/odlux/apps/connectApp/src/handlers/tlsKeyHandler.ts
index 326b3cc..20badcb 100644
--- a/sdnr/wt/odlux/apps/connectApp/src/handlers/tlsKeyHandler.ts
+++ b/sdnr/wt/odlux/apps/connectApp/src/handlers/tlsKeyHandler.ts
@@ -34,7 +34,7 @@
if (action instanceof LoadAllTlsKeyListAction) {
state = {
...state,
- busy: true
+ busy: true,
};
} else if (action instanceof AllTlsKeyListLoadedAction) {
@@ -47,7 +47,7 @@
} else {
state = {
...state,
- busy: false
+ busy: false,
};
}
}
diff --git a/sdnr/wt/odlux/apps/connectApp/src/models/connectionStatusLog.ts b/sdnr/wt/odlux/apps/connectApp/src/models/connectionStatusLog.ts
index df43c21..82b49a0 100644
--- a/sdnr/wt/odlux/apps/connectApp/src/models/connectionStatusLog.ts
+++ b/sdnr/wt/odlux/apps/connectApp/src/models/connectionStatusLog.ts
@@ -23,5 +23,5 @@
objectId: string;
type: string;
newValue: string;
-}
+};
diff --git a/sdnr/wt/odlux/apps/connectApp/src/models/guiCutTrough.ts b/sdnr/wt/odlux/apps/connectApp/src/models/guiCutTrough.ts
index b9f515d..0fd46a8 100644
--- a/sdnr/wt/odlux/apps/connectApp/src/models/guiCutTrough.ts
+++ b/sdnr/wt/odlux/apps/connectApp/src/models/guiCutTrough.ts
@@ -17,6 +17,6 @@
*/
export type guiCutThrough = {
- id: string,
- weburi?: string
-}
\ No newline at end of file
+ id: string;
+ weburi?: string;
+};
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/connectApp/src/models/networkElementBase.ts b/sdnr/wt/odlux/apps/connectApp/src/models/networkElementBase.ts
index 39278a8..a46a30e 100644
--- a/sdnr/wt/odlux/apps/connectApp/src/models/networkElementBase.ts
+++ b/sdnr/wt/odlux/apps/connectApp/src/models/networkElementBase.ts
@@ -16,7 +16,7 @@
* ============LICENSE_END==========================================================================
*/
export type NetworkElementBaseType = {
- mountId: string,
- host: string,
- port: number,
-}
\ No newline at end of file
+ mountId: string;
+ host: string;
+ port: number;
+};
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/connectApp/src/models/networkElementConnection.ts b/sdnr/wt/odlux/apps/connectApp/src/models/networkElementConnection.ts
index bc15afb..bb076c7 100644
--- a/sdnr/wt/odlux/apps/connectApp/src/models/networkElementConnection.ts
+++ b/sdnr/wt/odlux/apps/connectApp/src/models/networkElementConnection.ts
@@ -27,7 +27,7 @@
tlsKey?: string;
weburi?: string;
isWebUriUnreachable?: boolean;
- status?: "Connected" | "mounted" | "unmounted" | "Connecting" | "Disconnected" | "idle";
+ status?: 'Connected' | 'mounted' | 'unmounted' | 'Connecting' | 'Disconnected' | 'idle';
coreModelCapability?: string;
deviceType?: string;
deviceFunction?: string;
@@ -40,8 +40,8 @@
failureReason: string;
capability: string;
}[];
- }
-}
+ };
+};
export type UpdateNetworkElement = {
@@ -50,15 +50,15 @@
username?: string;
password?: string;
tlsKey?: string;
-}
+};
export type ConnectionStatus = {
- status: string
-}
+ status: string;
+};
export type TlsKeys = {
- key: string
-}
+ key: string;
+};
/**
diff --git a/sdnr/wt/odlux/apps/connectApp/src/models/networkElementConnectionLog.ts b/sdnr/wt/odlux/apps/connectApp/src/models/networkElementConnectionLog.ts
index a1535cb..4b4e283 100644
--- a/sdnr/wt/odlux/apps/connectApp/src/models/networkElementConnectionLog.ts
+++ b/sdnr/wt/odlux/apps/connectApp/src/models/networkElementConnectionLog.ts
@@ -19,7 +19,7 @@
export type NetworkElementConnectionLog = {
id: string;
nodeId: string;
- status: "connected" | "mounted" | "unmounted" | "connecting" | "disconnected" | "idle";
+ status: 'connected' | 'mounted' | 'unmounted' | 'connecting' | 'disconnected' | 'idle';
timestamp: string;
-}
+};
diff --git a/sdnr/wt/odlux/apps/connectApp/src/models/panelId.ts b/sdnr/wt/odlux/apps/connectApp/src/models/panelId.ts
index 2000d94..2861f10 100644
--- a/sdnr/wt/odlux/apps/connectApp/src/models/panelId.ts
+++ b/sdnr/wt/odlux/apps/connectApp/src/models/panelId.ts
@@ -16,4 +16,4 @@
* ============LICENSE_END==========================================================================
*/
-export type PanelId = null | "NetworkElements" | "ConnectionStatusLog";
\ No newline at end of file
+export type PanelId = null | 'NetworkElements' | 'ConnectionStatusLog';
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/connectApp/src/models/topologyNetconf.ts b/sdnr/wt/odlux/apps/connectApp/src/models/topologyNetconf.ts
index 936e20b..85a1a71 100644
--- a/sdnr/wt/odlux/apps/connectApp/src/models/topologyNetconf.ts
+++ b/sdnr/wt/odlux/apps/connectApp/src/models/topologyNetconf.ts
@@ -16,23 +16,23 @@
* ============LICENSE_END==========================================================================
*/
- export interface AvailableCapability {
- "capability-origin": string;
+export interface AvailableCapability {
+ 'capability-origin': string;
capability: string;
}
export interface NetconfNodeTopologyAvailableCapabilities {
- "available-capability": AvailableCapability[];
+ 'available-capability': AvailableCapability[];
}
export interface TopologyNode {
- "node-id": string;
- "netconf-node-topology:available-capabilities": NetconfNodeTopologyAvailableCapabilities;
+ 'node-id': string;
+ 'netconf-node-topology:available-capabilities': NetconfNodeTopologyAvailableCapabilities;
}
export interface Topology {
- "topology-id": string;
- "network-topology:node": TopologyNode[];
+ 'topology-id': string;
+ 'network-topology:node': TopologyNode[];
}
/**
@@ -47,13 +47,13 @@
}
export interface ModuleFeatures {
- module: Module[];
+ module: Module[];
}
export interface ModuleSet {
- "module-set": ModuleFeatures[];
+ 'module-set': ModuleFeatures[];
}
export interface FeatureTopology {
- "ietf-yang-library:yang-library" : ModuleSet
+ 'ietf-yang-library:yang-library' : ModuleSet;
}
diff --git a/sdnr/wt/odlux/apps/connectApp/src/models/yangCapabilitiesType.ts b/sdnr/wt/odlux/apps/connectApp/src/models/yangCapabilitiesType.ts
index c8cf704..b69993f 100644
--- a/sdnr/wt/odlux/apps/connectApp/src/models/yangCapabilitiesType.ts
+++ b/sdnr/wt/odlux/apps/connectApp/src/models/yangCapabilitiesType.ts
@@ -16,9 +16,9 @@
* ============LICENSE_END==========================================================================
*/
- export type AvailableCapabilities = {
- id?: string,
- module: string,
- revision: string,
- features: string
-}
\ No newline at end of file
+export type AvailableCapabilities = {
+ id?: string;
+ module: string;
+ revision: string;
+ features: string;
+};
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/connectApp/src/pluginConnect.tsx b/sdnr/wt/odlux/apps/connectApp/src/pluginConnect.tsx
index 2a9a46d..c290716 100644
--- a/sdnr/wt/odlux/apps/connectApp/src/pluginConnect.tsx
+++ b/sdnr/wt/odlux/apps/connectApp/src/pluginConnect.tsx
@@ -16,27 +16,25 @@
* ============LICENSE_END==========================================================================
*/
-import * as React from "react";
-import { withRouter, RouteComponentProps, Route, Switch, Redirect } from 'react-router-dom';
-import { faPlug } from '@fortawesome/free-solid-svg-icons';
+import React from 'react';
+import { Redirect, Route, RouteComponentProps, Switch, withRouter } from 'react-router-dom';
-import applicationManager from '../../../framework/src/services/applicationManager';
-import { subscribe, IFormatedMessage } from '../../../framework/src/services/notificationService';
import { AddSnackbarNotification } from '../../../framework/src/actions/snackbarActions';
-import { IApplicationStoreState } from "../../../framework/src/store/applicationStore";
-import connect, { Connect, IDispatcher } from '../../../framework/src/flux/connect';
+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 { findWebUrisForGuiCutThroughAsyncAction, updateCurrentViewAsyncAction, SetPanelAction } from './actions/commonNetworkElementsActions';
-import { createNetworkElementsActions, createNetworkElementsProperties, networkElementsReloadAction } from './handlers/networkElementsHandler';
-import connectAppRootHandler from './handlers/connectAppRootHandler';
-import ConnectApplication from './views/connectView';
-import { PanelId } from "./models/panelId";
+import { findWebUrisForGuiCutThroughAsyncAction, SetPanelAction, updateCurrentViewAsyncAction } from './actions/commonNetworkElementsActions';
import { NetworkElementsList } from './components/networkElements';
+import connectAppRootHandler from './handlers/connectAppRootHandler';
+import { createNetworkElementsActions, createNetworkElementsProperties, networkElementsReloadAction } from './handlers/networkElementsHandler';
+import { PanelId } from './models/panelId';
+import ConnectApplication from './views/connectView';
+const appIcon = require('./assets/icons/connectAppIcon.svg'); // select app icon
let currentStatus: string | undefined = undefined;
-let refreshInterval: ReturnType<typeof window.setInterval> | null = null;
-
const mapProps = (state: IApplicationStoreState) => ({
networkElementDashboardProperties: createNetworkElementsProperties(state),
@@ -48,24 +46,25 @@
});
const ConnectApplicationRouteAdapter = connect(mapProps, mapDisp)((props: RouteComponentProps<{ status?: string }> & Connect<typeof mapProps, typeof mapDisp>) => {
+
+ // TODO: move into useEffect!
if (currentStatus !== props.match.params.status) {
currentStatus = props.match.params.status || undefined;
window.setTimeout(() => {
if (currentStatus) {
- props.setCurrentPanel("NetworkElements");
- props.networkElementsDashboardActions.onFilterChanged("status", currentStatus);
+ props.setCurrentPanel('NetworkElements');
+ props.networkElementsDashboardActions.onFilterChanged('status', currentStatus);
if (!props.networkElementDashboardProperties.showFilter) {
props.networkElementsDashboardActions.onToggleFilter(false);
props.networkElementsDashboardActions.onRefresh();
- }
- else
+ } else
props.networkElementsDashboardActions.onRefresh();
}
});
}
return (
<NetworkElementsList />
- )
+ );
});
@@ -79,19 +78,19 @@
export function register() {
const applicationApi = applicationManager.registerApplication({
- name: "connect",
- icon: faPlug,
+ name: 'connect',
+ icon: appIcon,
rootComponent: App,
rootActionHandler: connectAppRootHandler,
- menuEntry: "Connect"
+ menuEntry: 'Connect',
});
// subscribe to the websocket notifications
- subscribe<IFormatedMessage>(["object-creation-notification", "object-deletion-notification", "attribute-value-changed-notification"], (msg => {
+ subscribe<IFormatedMessage>(['object-creation-notification', 'object-deletion-notification', 'attribute-value-changed-notification'], (msg => {
const store = applicationApi.applicationStore;
- if (msg && msg.type.type === "object-creation-notification" && store) {
+ if (msg && msg.type.type === 'object-creation-notification' && store) {
store.dispatch(new AddSnackbarNotification({ message: `Adding node [${msg.data['object-id-ref']}]`, options: { variant: 'info' } }));
- } else if (msg && (msg.type.type === "object-deletion-notification" || msg.type.type === "attribute-value-changed-notification") && store) {
+ } else if (msg && (msg.type.type === 'object-deletion-notification' || msg.type.type === 'attribute-value-changed-notification') && store) {
store.dispatch(new AddSnackbarNotification({ message: `Updating node [${msg.data['object-id-ref']}]`, options: { variant: 'info' } }));
}
if (store) {
diff --git a/sdnr/wt/odlux/apps/connectApp/src/services/connectService.ts b/sdnr/wt/odlux/apps/connectApp/src/services/connectService.ts
index 08cc580..1d74f85 100644
--- a/sdnr/wt/odlux/apps/connectApp/src/services/connectService.ts
+++ b/sdnr/wt/odlux/apps/connectApp/src/services/connectService.ts
@@ -18,7 +18,7 @@
import { requestRest } from '../../../../framework/src/services/restService';
import { NetworkElementConnection, ConnectionStatus, UpdateNetworkElement } from '../models/networkElementConnection';
-import { TlsKeys } from '../models/networkElementConnection'
+import { TlsKeys } from '../models/networkElementConnection';
import { convertPropertyNames, replaceUpperCase } from '../../../../framework/src/utilities/yangHelper';
import { Result } from '../../../../framework/src/models/elasticSearch';
@@ -30,17 +30,20 @@
*/
class ConnectService {
public getNetworkElementUri = (nodeId: string) => '/rests/data/network-topology:network-topology/topology=topology-netconf/node=' + nodeId;
- public getNetworkElementConnectDataProviderUri = (operation: "create" | "update" | "delete") => `/rests/operations/data-provider:${operation}-network-element-connection`;
+
+ public getNetworkElementConnectDataProviderUri = (operation: 'create' | 'update' | 'delete') => `/rests/operations/data-provider:${operation}-network-element-connection`;
+
public getAllWebUriExtensionsForNetworkElementListUri = (nodeId: string) => this.getNetworkElementUri(nodeId) + '/yang-ext:mount/core-model:network-element';
- public getNetworkElementYangLibraryFeature = (nodeId: string) => '/rests/data/network-topology:network-topology/topology=topology-netconf/node=' + nodeId + '/yang-ext:mount/ietf-yang-library:yang-library?content=nonconfig'
+
+ public getNetworkElementYangLibraryFeature = (nodeId: string) => '/rests/data/network-topology:network-topology/topology=topology-netconf/node=' + nodeId + '/yang-ext:mount/ietf-yang-library:yang-library?content=nonconfig';
/**
* Inserts a network element/node.
*/
public async createNetworkElement(element: NetworkElementConnection): Promise<NetworkElementConnection | null> {
- const path = this.getNetworkElementConnectDataProviderUri("create");
+ const path = this.getNetworkElementConnectDataProviderUri('create');
const result = await requestRest<NetworkElementConnection>(path, {
- method: "POST", body: JSON.stringify(convertPropertyNames({ "data-provider:input": element }, replaceUpperCase))
+ method: 'POST', body: JSON.stringify(convertPropertyNames({ 'data-provider:input': element }, replaceUpperCase)),
});
return result || null;
}
@@ -49,9 +52,9 @@
* Updates a network element/node.
*/
public async updateNetworkElement(element: UpdateNetworkElement): Promise<NetworkElementConnection | null> {
- const path = this.getNetworkElementConnectDataProviderUri("update");
+ const path = this.getNetworkElementConnectDataProviderUri('update');
const result = await requestRest<NetworkElementConnection>(path, {
- method: "POST", body: JSON.stringify(convertPropertyNames({ "data-provider:input": element }, replaceUpperCase))
+ method: 'POST', body: JSON.stringify(convertPropertyNames({ 'data-provider:input': element }, replaceUpperCase)),
});
return result || null;
}
@@ -61,11 +64,11 @@
*/
public async deleteNetworkElement(element: UpdateNetworkElement): Promise<NetworkElementConnection | null> {
const query = {
- "id": element.id
+ 'id': element.id,
};
- const path = this.getNetworkElementConnectDataProviderUri("delete");
+ const path = this.getNetworkElementConnectDataProviderUri('delete');
const result = await requestRest<NetworkElementConnection>(path, {
- method: "POST", body: JSON.stringify(convertPropertyNames({ "data-provider:input": query }, replaceUpperCase))
+ method: 'POST', body: JSON.stringify(convertPropertyNames({ 'data-provider:input': query }, replaceUpperCase)),
});
return result || null;
}
@@ -107,13 +110,12 @@
'<name xmlns="urn:opendaylight:netconf-node-topology">TLS</name>',
' </protocol>',
'<max-connection-attempts xmlns="urn:opendaylight:netconf-node-topology">2</max-connection-attempts>',
- '</node>'].join('')
+ '</node>'].join('');
let bodyXml;
if (networkElement.password) {
- bodyXml = mountXml
- }
- else {
- bodyXml = tlsXml
+ bodyXml = mountXml;
+ } else {
+ bodyXml = tlsXml;
}
try {
@@ -121,16 +123,16 @@
method: 'PUT',
headers: {
'Content-Type': 'application/xml',
- 'Accept': 'application/xml'
+ 'Accept': 'application/xml',
},
- body: bodyXml
+ body: bodyXml,
});
// expect an empty answer
return result !== null;
} catch {
return false;
}
- };
+ }
/** Unmounts a network element by its id. */
public async unmountNetworkElement(nodeId: string): Promise<boolean> {
@@ -141,7 +143,7 @@
method: 'DELETE',
headers: {
'Content-Type': 'application/xml',
- 'Accept': 'application/xml'
+ 'Accept': 'application/xml',
},
});
// expect an empty answer
@@ -150,15 +152,15 @@
} catch {
return false;
}
- };
+ }
/** Yang capabilities of the selected network element/node */
public async infoNetworkElement(nodeId: string): Promise<TopologyNode | null> {
const path = this.getNetworkElementUri(nodeId);
- const topologyRequestPomise = requestRest<Topology>(path, { method: "GET" });
+ const topologyRequestPomise = requestRest<Topology>(path, { method: 'GET' });
return topologyRequestPomise && topologyRequestPomise.then(result => {
- return result && result["network-topology:node"] && result["network-topology:node"][0] || null;
+ return result && result['network-topology:node'] && result['network-topology:node'][0] || null;
});
}
@@ -166,13 +168,13 @@
/** Yang features of the selected network element/node module */
public async infoNetworkElementFeatures(nodeId: string): Promise<Module[] | null | undefined> {
const path = this.getNetworkElementYangLibraryFeature(nodeId);
- const topologyRequestPomise = requestRest<FeatureTopology>(path, { method: "GET" });
+ const topologyRequestPomise = requestRest<FeatureTopology>(path, { method: 'GET' });
return topologyRequestPomise && topologyRequestPomise.then(result => {
const resultFinal = result && result['ietf-yang-library:yang-library']
- && result["ietf-yang-library:yang-library"]["module-set"] &&
- result["ietf-yang-library:yang-library"]["module-set"][0] &&
- result["ietf-yang-library:yang-library"]["module-set"][0]['module'] || null;
+ && result['ietf-yang-library:yang-library']['module-set'] &&
+ result['ietf-yang-library:yang-library']['module-set'][0] &&
+ result['ietf-yang-library:yang-library']['module-set'][0].module || null;
return resultFinal;
});
}
@@ -183,22 +185,22 @@
* Get the connection state of the network element/ node
*/
public async getNetworkElementConnectionStatus(element: string): Promise<(ConnectionStatus)[] | null> {
- const path = `/rests/operations/data-provider:read-network-element-connection-list`;
+ const path = '/rests/operations/data-provider:read-network-element-connection-list';
const query = {
- "data-provider:input": {
- "filter": [{
- "property": "node-id",
- "filtervalue": element
+ 'data-provider:input': {
+ 'filter': [{
+ 'property': 'node-id',
+ 'filtervalue': element,
}],
- "pagination": {
- "size": 20,
- "page": 1
- }
- }
- }
- const result = await requestRest<Result<ConnectionStatus>>(path, { method: "POST", body: JSON.stringify(query) });
- return result && result["data-provider:output"] && result["data-provider:output"].data && result["data-provider:output"].data.map(ne => ({
- status: ne.status
+ 'pagination': {
+ 'size': 20,
+ 'page': 1,
+ },
+ },
+ };
+ const result = await requestRest<Result<ConnectionStatus>>(path, { method: 'POST', body: JSON.stringify(query) });
+ return result && result['data-provider:output'] && result['data-provider:output'].data && result['data-provider:output'].data.map(ne => ({
+ status: ne.status,
})) || null;
}
@@ -209,44 +211,43 @@
public async getTlsKeys(): Promise<(TlsKeys)[] | null> {
const path = '/rests/operations/data-provider:read-tls-key-entry';
const query = {
- "data-provider:input": {
- "filter": [],
- "sortorder": [],
- "pagination": {
- "size": 20,
- "page": 1
- }
- }
+ 'data-provider:input': {
+ 'filter': [],
+ 'sortorder': [],
+ 'pagination': {
+ 'size': 20,
+ 'page': 1,
+ },
+ },
};
- const result = await requestRest<Result<string>>(path, { method: "POST", body: JSON.stringify(query) });
- return result && result["data-provider:output"] && result["data-provider:output"].data && result["data-provider:output"].data.map(ne => ({
- key: ne
+ const result = await requestRest<Result<string>>(path, { method: 'POST', body: JSON.stringify(query) });
+ return result && result['data-provider:output'] && result['data-provider:output'].data && result['data-provider:output'].data.map(ne => ({
+ key: ne,
})) || null;
}
public async getAllWebUriExtensionsForNetworkElementListAsync(neList: string[]): Promise<(guiCutThrough)[]> {
- const path = `/rests/operations/data-provider:read-gui-cut-through-entry`;
- let webUriList: guiCutThrough[] = []
+ const path = '/rests/operations/data-provider:read-gui-cut-through-entry';
+ let webUriList: guiCutThrough[] = [];
const query = {
- "data-provider:input": {
- "filter": [{
- "property": "id",
- "filtervalues": neList
+ 'data-provider:input': {
+ 'filter': [{
+ 'property': 'id',
+ 'filtervalues': neList,
}],
- "pagination": {
- "size": 20,
- "page": 1
- }
- }
- }
+ 'pagination': {
+ 'size': 20,
+ 'page': 1,
+ },
+ },
+ };
- const result = await requestRest<Result<guiCutThrough>>(path, { method: "POST", body: JSON.stringify(query) });
- const resultData = result && result["data-provider:output"] && result["data-provider:output"].data;
+ const result = await requestRest<Result<guiCutThrough>>(path, { method: 'POST', body: JSON.stringify(query) });
+ const resultData = result && result['data-provider:output'] && result['data-provider:output'].data;
neList.forEach(nodeId => {
let entryNotFound = true;
if (resultData) {
- const BreakException = {};
try {
resultData.forEach(entry => {
if (entry.id == nodeId) {
@@ -256,7 +257,7 @@
} else {
webUriList.push({ id: nodeId, weburi: undefined });
}
- throw BreakException;
+ throw new Error();
}
});
} catch (e) { }
diff --git a/sdnr/wt/odlux/apps/connectApp/src/views/connectView.tsx b/sdnr/wt/odlux/apps/connectApp/src/views/connectView.tsx
index 0828397..a6fcb7c 100644
--- a/sdnr/wt/odlux/apps/connectApp/src/views/connectView.tsx
+++ b/sdnr/wt/odlux/apps/connectApp/src/views/connectView.tsx
@@ -15,113 +15,88 @@
* the License.
* ============LICENSE_END==========================================================================
*/
-import * as React from 'react';
+import React from 'react';
-import connect, { IDispatcher, Connect } from '../../../../framework/src/flux/connect';
-import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
-import { Panel } from '../../../../framework/src/components/material-ui';
-import { networkElementsReloadAction, createNetworkElementsActions } from '../handlers/networkElementsHandler';
-import { connectionStatusLogReloadAction, createConnectionStatusLogActions } from '../handlers/connectionStatusLogHandler';
+import { AppBar, Tab, Tabs } from '@mui/material';
-import { NetworkElementsList } from '../components/networkElements';
+import { useApplicationDispatch, useSelectApplicationState } from '../../../../framework/src/flux/connect';
+
+import { findWebUrisForGuiCutThroughAsyncAction, setPanelAction } from '../actions/commonNetworkElementsActions';
import { ConnectionStatusLog } from '../components/connectionStatusLog';
-import { setPanelAction, findWebUrisForGuiCutThroughAsyncAction, SetWeburiSearchBusy } from '../actions/commonNetworkElementsActions';
+import { NetworkElementsList } from '../components/networkElements';
+import { connectionStatusLogReloadAction } from '../handlers/connectionStatusLogHandler';
+import { networkElementsReloadAction } from '../handlers/networkElementsHandler';
+import { NetworkElementConnection } from '../models/networkElementConnection';
import { PanelId } from '../models/panelId';
-import { NetworkElementConnection } from 'models/networkElementConnection';
-import { AppBar, Tabs, Tab } from '@mui/material';
-const mapProps = (state: IApplicationStoreState) => ({
- panelId: state.connect.currentOpenPanel,
- user: state.framework.authenticationState.user,
- netWorkElements: state.connect.networkElements,
- availableGuiCutroughs: state.connect.guiCutThrough
-});
+const ConnectApplicationComponent: React.FC<{}> = () => {
-const mapDispatcher = (dispatcher: IDispatcher) => ({
- networkElementsActions: createNetworkElementsActions(dispatcher.dispatch),
- connectionStatusLogActions: createConnectionStatusLogActions(dispatcher.dispatch),
- onLoadNetworkElements: () => dispatcher.dispatch(networkElementsReloadAction),
- loadWebUris: (networkElements: NetworkElementConnection[]) =>
- dispatcher.dispatch(findWebUrisForGuiCutThroughAsyncAction(networkElements.map((ne) => ne.id!))),
- isBusy: (busy: boolean) => dispatcher.dispatch(new SetWeburiSearchBusy(busy)),
- onLoadConnectionStatusLog: () => {
- dispatcher.dispatch(connectionStatusLogReloadAction);
- },
- switchActivePanel: (panelId: PanelId) => {
- dispatcher.dispatch(setPanelAction(panelId));
- }
-});
+ const panelId = useSelectApplicationState(state => state.connect.currentOpenPanel);
+ const netWorkElements = useSelectApplicationState(state => state.connect.networkElements);
-type ConnectApplicationComponentProps = Connect<typeof mapProps, typeof mapDispatcher>;
+ const dispatch = useApplicationDispatch();
+ const onLoadNetworkElements = () => dispatch(networkElementsReloadAction);
+ const loadWebUris = (networkElements: NetworkElementConnection[]) => dispatch(findWebUrisForGuiCutThroughAsyncAction(networkElements.map((ne) => ne.id!)));
+ const onLoadConnectionStatusLog = () => dispatch(connectionStatusLogReloadAction);
+ const switchActivePanel = (panelId2: PanelId) => dispatch(setPanelAction(panelId2));
-class ConnectApplicationComponent extends React.Component<ConnectApplicationComponentProps>{
-
- public componentDidMount() {
- if (this.props.panelId === null) { //don't change tabs, if one is selected already
- this.onTogglePanel("NetworkElements");
- }
- //this.props.networkElementsActions.onToggleFilter();
- //this.props.connectionStatusLogActions.onToggleFilter();
- }
-
- public componentDidUpdate = () => {
-
- const networkElements = this.props.netWorkElements;
-
- if (networkElements.rows.length > 0) {
- // Update all netWorkElements for propper WebUriClient settings in case of table data changes.
- // e.G: Pagination of the table data (there is no event)
- this.props.loadWebUris(networkElements.rows);
- }
- }
-
- private onTogglePanel = (panelId: PanelId) => {
- const nextActivePanel = panelId;
- this.props.switchActivePanel(nextActivePanel);
+ const onTogglePanel = (panelId2: PanelId) => {
+ const nextActivePanel = panelId2;
+ switchActivePanel(nextActivePanel);
switch (nextActivePanel) {
case 'NetworkElements':
- this.props.onLoadNetworkElements();
+ onLoadNetworkElements();
break;
case 'ConnectionStatusLog':
- this.props.onLoadConnectionStatusLog();
+ onLoadConnectionStatusLog();
break;
case null:
// do nothing if all panels are closed
break;
default:
- console.warn("Unknown nextActivePanel [" + nextActivePanel + "] in connectView");
+ console.warn('Unknown nextActivePanel [' + nextActivePanel + '] in connectView');
break;
}
-
};
- private onHandleTabChange = (event: React.SyntheticEvent, newValue: PanelId) => {
- this.props.switchActivePanel(newValue);
- }
-
- render(): JSX.Element {
- const { panelId: activePanelId } = this.props;
-
- return (
- <>
- <AppBar enableColorOnDark position="static">
- <Tabs indicatorColor="secondary" textColor="inherit" value={activePanelId} onChange={this.onHandleTabChange} aria-label="connect-app-tabs">
- <Tab aria-label="network-elements-list-tab" label="NODES" value="NetworkElements" />
- <Tab aria-label="connection-status-log-tab" label="Connection Status Log" value="ConnectionStatusLog" />
- </Tabs>
- </AppBar>
- {activePanelId === 'NetworkElements'
- ? <NetworkElementsList />
- : activePanelId === 'ConnectionStatusLog'
- ? <ConnectionStatusLog />
- : null}
- </>
- );
+ const onHandleTabChange = (event: React.SyntheticEvent, newValue: PanelId) => {
+ switchActivePanel(newValue);
};
+ React.useEffect(()=>{
+ if (panelId === null) { //don't change tabs, if one is selected already
+ onTogglePanel('NetworkElements');
+ }
+ }, []);
-}
+ React.useEffect(()=>{
+ const networkElements = netWorkElements;
-export const ConnectApplication = (connect(mapProps, mapDispatcher)(ConnectApplicationComponent));
+ if (networkElements.rows.length > 0) {
+ // Search for weburi client for all netWorkElements in case of table data changes.
+ // e.G: Pagination of the table data (there is no event)
+ loadWebUris(networkElements.rows);
+ }
+ }, [netWorkElements]);
+
+ return (
+ <>
+ <AppBar enableColorOnDark position="static">
+ <Tabs indicatorColor="secondary" textColor="inherit" value={panelId} onChange={onHandleTabChange} aria-label="connect-app-tabs">
+ <Tab aria-label="network-elements-list-tab" label="NODES" value="NetworkElements" />
+ <Tab aria-label="connection-status-log-tab" label="Connection Status Log" value="ConnectionStatusLog" />
+ </Tabs>
+ </AppBar>
+ {panelId === 'NetworkElements'
+ ? <NetworkElementsList />
+ : panelId === 'ConnectionStatusLog'
+ ? <ConnectionStatusLog />
+ : null
+ }
+ </>
+ );
+};
+
+export const ConnectApplication = ConnectApplicationComponent;
export default ConnectApplication;
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/connectApp/tsconfig.json b/sdnr/wt/odlux/apps/connectApp/tsconfig.json
index a66b5d8..ca65092 100644
--- a/sdnr/wt/odlux/apps/connectApp/tsconfig.json
+++ b/sdnr/wt/odlux/apps/connectApp/tsconfig.json
@@ -4,7 +4,7 @@
"outDir": "./dist",
"sourceMap": true,
"forceConsistentCasingInFileNames": true,
- "allowSyntheticDefaultImports": false,
+ "allowSyntheticDefaultImports": true,
"allowUnreachableCode": false,
"allowUnusedLabels": false,
"noFallthroughCasesInSwitch": true,
diff --git a/sdnr/wt/odlux/apps/connectApp/webpack.config.js b/sdnr/wt/odlux/apps/connectApp/webpack.config.js
index ff76904..b7aebb9 100644
--- a/sdnr/wt/odlux/apps/connectApp/webpack.config.js
+++ b/sdnr/wt/odlux/apps/connectApp/webpack.config.js
@@ -59,6 +59,16 @@
use: [{
loader: "babel-loader"
}]
+ },{
+ //don't minify images
+ test: /\.(png|gif|jpg|svg)$/,
+ use: [{
+ loader: 'url-loader',
+ options: {
+ limit: 10,
+ name: './images/[name].[ext]'
+ }
+ }]
}]
},
diff --git a/sdnr/wt/odlux/apps/demoApp/package.json b/sdnr/wt/odlux/apps/demoApp/package.json
index 951332a..6a31bc3 100644
--- a/sdnr/wt/odlux/apps/demoApp/package.json
+++ b/sdnr/wt/odlux/apps/demoApp/package.json
@@ -21,6 +21,9 @@
"author": "Matthias Fischer",
"license": "Apache-2.0",
"dependencies": {
+ "@fortawesome/fontawesome-svg-core": "1.2.35",
+ "@fortawesome/free-solid-svg-icons": "5.6.3",
+ "@fortawesome/react-fontawesome": "0.1.14",
"@emotion/react": "^11.7.0",
"@emotion/styled": "^11.6.0",
"@mui/icons-material": "^5.2.0",
diff --git a/sdnr/wt/odlux/apps/demoApp/pom.xml b/sdnr/wt/odlux/apps/demoApp/pom.xml
index 07f990b..172a435 100644
--- a/sdnr/wt/odlux/apps/demoApp/pom.xml
+++ b/sdnr/wt/odlux/apps/demoApp/pom.xml
@@ -19,6 +19,7 @@
~ ============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>
@@ -139,7 +140,7 @@
<!-- optional: default phase is "generate-resources" -->
<phase>initialize</phase>
<configuration>
- <nodeVersion>v12.13.0</nodeVersion>
+ <nodeVersion>v12.22.0</nodeVersion>
<yarnVersion>v1.22.10</yarnVersion>
</configuration>
</execution>
diff --git a/sdnr/wt/odlux/apps/demoApp/src/actions/authorActions.ts b/sdnr/wt/odlux/apps/demoApp/src/actions/authorActions.ts
index f750751..f22d1e0 100644
--- a/sdnr/wt/odlux/apps/demoApp/src/actions/authorActions.ts
+++ b/sdnr/wt/odlux/apps/demoApp/src/actions/authorActions.ts
@@ -26,16 +26,13 @@
export class LoadAllAuthorsAction extends ApplicationBaseAction {
- constructor() {
- super();
- }
+
}
// in React Action is most times a Message
export class AllAuthorsLoadedAction extends ApplicationBaseAction {
constructor(public authors: IAuthor[] | null, public error?: string) {
super();
-
}
}
@@ -47,5 +44,5 @@
dispatch(new AllAuthorsLoadedAction(null, error));
dispatch(new AddErrorInfoAction(error));
});
-}
+};
diff --git a/sdnr/wt/odlux/apps/demoApp/src/components/counter.tsx b/sdnr/wt/odlux/apps/demoApp/src/components/counter.tsx
index 6b960cd..1aad974 100644
--- a/sdnr/wt/odlux/apps/demoApp/src/components/counter.tsx
+++ b/sdnr/wt/odlux/apps/demoApp/src/components/counter.tsx
@@ -15,20 +15,15 @@
* the License.
* ============LICENSE_END==========================================================================
*/
-import * as React from 'react';
+import React, { FC, useState } from 'react';
-export class Counter extends React.Component<{}, { counter: number }> {
- constructor(props: {}) {
- super(props);
+const Counter: FC = () => {
+ const [counter, setCounter] = useState(0);
+ return (
+ <button onClick={() => setCounter(counter + 1 )} color="inherit">{counter}</button>
+ );
+};
- this.state = {
- counter: 0
- };
- }
-
- render() {
- return (
- <button onClick={ () => this.setState({ counter: this.state.counter + 1 }) } color="inherit">{ this.state.counter }</button>
- )
- }
-}
\ No newline at end of file
+Counter.displayName = 'Counter';
+
+export { Counter };
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/demoApp/src/handlers/demoAppRootHandler.ts b/sdnr/wt/odlux/apps/demoApp/src/handlers/demoAppRootHandler.ts
index 9ff8450..1f920f2 100644
--- a/sdnr/wt/odlux/apps/demoApp/src/handlers/demoAppRootHandler.ts
+++ b/sdnr/wt/odlux/apps/demoApp/src/handlers/demoAppRootHandler.ts
@@ -18,6 +18,7 @@
import { combineActionHandler } from '../../../../framework/src/flux/middleware';
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
import { listAuthorsHandler, IListAuthors } from './listAuthorsHandler';
@@ -30,7 +31,7 @@
declare module '../../../../framework/src/store/applicationStore' {
interface IApplicationStoreState {
- demo: IDemoAppStoreState
+ demo: IDemoAppStoreState;
}
}
diff --git a/sdnr/wt/odlux/apps/demoApp/src/handlers/editAuthorHandler.ts b/sdnr/wt/odlux/apps/demoApp/src/handlers/editAuthorHandler.ts
index 34b533c..1d37a36 100644
--- a/sdnr/wt/odlux/apps/demoApp/src/handlers/editAuthorHandler.ts
+++ b/sdnr/wt/odlux/apps/demoApp/src/handlers/editAuthorHandler.ts
@@ -25,9 +25,9 @@
const editAuthorInit: IEditAuthor = {
author: null,
- isDirty: false
+ isDirty: false,
};
-export const editAuthorHandler: IActionHandler<IEditAuthor> = (state = editAuthorInit, action) => {
+export const editAuthorHandler: IActionHandler<IEditAuthor> = (state = editAuthorInit, _action) => {
return state;
};
diff --git a/sdnr/wt/odlux/apps/demoApp/src/handlers/listAuthorsHandler.ts b/sdnr/wt/odlux/apps/demoApp/src/handlers/listAuthorsHandler.ts
index ca2b6d3..c85eaff 100644
--- a/sdnr/wt/odlux/apps/demoApp/src/handlers/listAuthorsHandler.ts
+++ b/sdnr/wt/odlux/apps/demoApp/src/handlers/listAuthorsHandler.ts
@@ -27,7 +27,7 @@
const listAuthorsInit: IListAuthors = {
authors: [],
- busy: false
+ busy: false,
};
export const listAuthorsHandler: IActionHandler<IListAuthors> = (state = listAuthorsInit, action) => {
@@ -35,7 +35,7 @@
state = {
...state,
- busy: true
+ busy: true,
};
} else if (action instanceof AllAuthorsLoadedAction) {
@@ -43,12 +43,12 @@
state = {
...state,
authors: action.authors,
- busy: false
+ busy: false,
};
} else {
state = {
...state,
- busy: false
+ busy: false,
};
}
}
diff --git a/sdnr/wt/odlux/apps/demoApp/src/models/author.ts b/sdnr/wt/odlux/apps/demoApp/src/models/author.ts
index 0aaa308..bdd414c 100644
--- a/sdnr/wt/odlux/apps/demoApp/src/models/author.ts
+++ b/sdnr/wt/odlux/apps/demoApp/src/models/author.ts
@@ -21,7 +21,7 @@
*/
export interface IAuthor {
/**
- * Defines the unique id of the autor.
+ * Defines the unique id of the author.
*/
id: number;
diff --git a/sdnr/wt/odlux/apps/demoApp/src/plugin.tsx b/sdnr/wt/odlux/apps/demoApp/src/plugin.tsx
index 4d67c28..7b29b40 100644
--- a/sdnr/wt/odlux/apps/demoApp/src/plugin.tsx
+++ b/sdnr/wt/odlux/apps/demoApp/src/plugin.tsx
@@ -15,13 +15,13 @@
* the License.
* ============LICENSE_END==========================================================================
*/
-import * as React from "react";
+import React from 'react';
import { withRouter, RouteComponentProps, Route, Switch, Redirect } from 'react-router-dom';
-import { faAddressBook, faRegistered } from '@fortawesome/free-solid-svg-icons';
+import { faAddressBook } from '@fortawesome/free-solid-svg-icons/faAddressBook';
import applicationManager from '../../../framework/src/services/applicationManager';
-import connect, { Connect } from '../../../framework/src/flux/connect';
+import { connect, Connect } from '../../../framework/src/flux/connect';
import { demoAppRootHandler } from './handlers/demoAppRootHandler';
@@ -43,12 +43,12 @@
const FinalApp = withRouter(connect()(App));
export function register() {
- const applicationApi = applicationManager.registerApplication({
- name: "demo",
+ applicationManager.registerApplication({
+ name: 'demo',
icon: faAddressBook,
rootComponent: FinalApp,
rootActionHandler: demoAppRootHandler,
exportedComponents: { counter: Counter },
- menuEntry: "Demo"
+ menuEntry: 'Demo',
});
}
diff --git a/sdnr/wt/odlux/apps/demoApp/src/services/authorService.ts b/sdnr/wt/odlux/apps/demoApp/src/services/authorService.ts
index 13e4b31..deaa2ff 100644
--- a/sdnr/wt/odlux/apps/demoApp/src/services/authorService.ts
+++ b/sdnr/wt/odlux/apps/demoApp/src/services/authorService.ts
@@ -26,39 +26,39 @@
*/
class AuthorService {
- /**
+ /**
* Gets all known authors from the backend.
* @returns A promise of the type array of @see {@link IAuthor} containing all known authors.
*/
public getAllAuthors(): Promise<IAuthor[]> {
return new Promise((resolve: (value: IAuthor[]) => void, reject: (err: any) => void) => {
- $.ajax({ method: "GET", url: base_url })
- .then((data) => { resolve(data); }, (err) => { reject(err) });
+ $.ajax({ method: 'GET', url: base_url })
+ .then((data) => { resolve(data); }, (err) => { reject(err); });
});
}
- /**
+ /**
* Gets an author by its id from the backend.
* @returns A promise of the type @see {@link IAuthor} containing the author to get.
*/
public getAuthorById(id: string | number): Promise<IAuthor> {
return new Promise((resolve: (value: IAuthor) => void, reject: (err: any) => void) => {
- $.ajax({ method: "GET", url: base_url + "/" + id })
- .then((data) => { resolve(data); }, (err) => { reject(err) });
+ $.ajax({ method: 'GET', url: base_url + '/' + id })
+ .then((data) => { resolve(data); }, (err) => { reject(err); });
});
}
-/**
+ /**
* Saves the given author to the backend api.
* @returns A promise of the type @see {@link IAuthor} containing the autor returned by the backend api.
*/
public saveAuthor(author: IAuthor): Promise<IAuthor> {
return new Promise((resolve: (value: IAuthor) => void, reject: (err: any) => void) => {
- // simulate server save
+ // simulate server save
window.setTimeout(() => {
if (Math.random() > 0.8) {
- reject("Could not save author.");
+ reject('Could not save author.');
} else {
resolve(author);
}
diff --git a/sdnr/wt/odlux/apps/demoApp/src/views/authorsList.tsx b/sdnr/wt/odlux/apps/demoApp/src/views/authorsList.tsx
index b56058d..5d9f13a 100644
--- a/sdnr/wt/odlux/apps/demoApp/src/views/authorsList.tsx
+++ b/sdnr/wt/odlux/apps/demoApp/src/views/authorsList.tsx
@@ -15,7 +15,7 @@
* the License.
* ============LICENSE_END==========================================================================
*/
-import * as React from 'react';
+import React from 'react';
import { withRouter, RouteComponentProps } from 'react-router-dom';
import Table from '@mui/material/Table';
@@ -25,22 +25,28 @@
import TableRow from '@mui/material/TableRow';
import Paper from '@mui/material/Paper'; // means border
-import connect from '../../../../framework/src/flux/connect';
+import { connect } from '../../../../framework/src/flux/connect';
import { loadAllAuthorsAsync } from '../actions/authorActions';
import { IAuthor } from '../models/author';
interface IAuthorsListProps {
- authors: IAuthor[],
- busy: boolean,
- onLoadAllAuthors: () => void
+ authors: IAuthor[];
+ busy: boolean;
+ onLoadAllAuthors: () => void;
}
class AuthorsListComponent extends React.Component<RouteComponentProps & IAuthorsListProps> {
render(): JSX.Element {
const { authors, busy } = this.props;
- return (
+ return busy
+ ? (
+ <Paper>
+ Loading
+ </Paper>
+ )
+ : (
<Paper>
<Table padding="normal" >
<TableHead>
@@ -52,7 +58,7 @@
</TableHead>
<TableBody>
{authors.map(author => (
- <TableRow key={author.id} onClick={(e) => this.editAuthor(author)}>
+ <TableRow key={author.id} onClick={(_e) => this.editAuthor(author)}>
<TableCell>{author.id}</TableCell>
<TableCell>{author.firstName}</TableCell>
<TableCell>{author.lastName}</TableCell>
@@ -61,15 +67,15 @@
</TableBody>
</Table>
</Paper>
- );
- };
+ );
+ }
public componentDidMount() {
this.props.onLoadAllAuthors();
}
private editAuthor = (author: IAuthor) => {
- author && this.props.history.push(this.props.match.path + '/' + author.id);
+ if (author) this.props.history.push(this.props.match.path + '/' + author.id);
};
}
@@ -77,11 +83,11 @@
connect(
({ demo: state }) => ({
authors: state.listAuthors.authors,
- busy: state.listAuthors.busy
+ busy: state.listAuthors.busy,
}),
(dispatcher) => ({
onLoadAllAuthors: () => {
- dispatcher.dispatch(loadAllAuthorsAsync)
- }
+ dispatcher.dispatch(loadAllAuthorsAsync);
+ },
}))(AuthorsListComponent));
export default AuthorsList;
diff --git a/sdnr/wt/odlux/apps/demoApp/src/views/editAuthor.tsx b/sdnr/wt/odlux/apps/demoApp/src/views/editAuthor.tsx
index 92f6712..0da619b 100644
--- a/sdnr/wt/odlux/apps/demoApp/src/views/editAuthor.tsx
+++ b/sdnr/wt/odlux/apps/demoApp/src/views/editAuthor.tsx
@@ -15,10 +15,10 @@
* the License.
* ============LICENSE_END==========================================================================
*/
-import * as React from 'react';
+import React from 'react';
import { withRouter, RouteComponentProps } from 'react-router-dom';
-type EditAuthorProps = RouteComponentProps<{ authorId: string}>;
+type EditAuthorProps = RouteComponentProps<{ authorId: string }>;
class EditAuthorComponent extends React.Component<EditAuthorProps> {
render(): JSX.Element {
@@ -26,7 +26,7 @@
<div>
<h2>Edit Author { this.props.match.params.authorId }</h2>
</div>
- )
+ );
}
}
diff --git a/sdnr/wt/odlux/apps/demoApp/tsconfig.json b/sdnr/wt/odlux/apps/demoApp/tsconfig.json
index a66b5d8..ca65092 100644
--- a/sdnr/wt/odlux/apps/demoApp/tsconfig.json
+++ b/sdnr/wt/odlux/apps/demoApp/tsconfig.json
@@ -4,7 +4,7 @@
"outDir": "./dist",
"sourceMap": true,
"forceConsistentCasingInFileNames": true,
- "allowSyntheticDefaultImports": false,
+ "allowSyntheticDefaultImports": true,
"allowUnreachableCode": false,
"allowUnusedLabels": false,
"noFallthroughCasesInSwitch": true,
diff --git a/sdnr/wt/odlux/apps/eventLogApp/pom.xml b/sdnr/wt/odlux/apps/eventLogApp/pom.xml
index 19d9ad0..9e4ed5f 100644
--- a/sdnr/wt/odlux/apps/eventLogApp/pom.xml
+++ b/sdnr/wt/odlux/apps/eventLogApp/pom.xml
@@ -19,6 +19,7 @@
~ ============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>
@@ -139,7 +140,7 @@
<!-- optional: default phase is "generate-resources" -->
<phase>initialize</phase>
<configuration>
- <nodeVersion>v12.13.0</nodeVersion>
+ <nodeVersion>v12.22.0</nodeVersion>
<yarnVersion>v1.22.10</yarnVersion>
</configuration>
</execution>
diff --git a/sdnr/wt/odlux/apps/eventLogApp/src/assets/icons/eventLogAppIcon.svg b/sdnr/wt/odlux/apps/eventLogApp/src/assets/icons/eventLogAppIcon.svg
new file mode 100644
index 0000000..743167d
--- /dev/null
+++ b/sdnr/wt/odlux/apps/eventLogApp/src/assets/icons/eventLogAppIcon.svg
@@ -0,0 +1,21 @@
+<!-- highstreet technologies GmbH colour scheme
+ Grey #565656
+ LBlue #36A9E1
+ DBlue #246DA2
+ Green #003F2C / #006C4B
+ Yellw #C8D400
+ Red #D81036
+-->
+
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 512 512">
+
+<g>
+<path fill="#C8D400" d="M192,224c-17.672,0-32,14.328-32,32s14.328,32,32,32h128c17.672,0,32-14.328,32-32s-14.328-32-32-32H192z"/>
+
+<path fill="#C8D400" d="M256,320h-64c-17.672,0-32,14.328-32,32s14.328,32,32,32h64c17.672,0,32-14.328,32-32S273.672,320,256,320z"/>
+
+<path fill="#565656" d="M416,32h-80c0-17.674-11.938-32-26.668-32H202.668C187.938,0,176,14.326,176,32H96c-17.672,0-32,14.328-32,32v416
+ c0,17.672,14.328,32,32,32h320c17.672,0,32-14.328,32-32V64C448,46.328,433.672,32,416,32z M256,32c17.672,0,32,14.326,32,32
+ c0,17.673-14.328,32-32,32s-32-14.327-32-32C224,46.326,238.328,32,256,32z M384,448H128V96h48v32h160V96h48V448z"/>
+</g>
+</svg>
diff --git a/sdnr/wt/odlux/apps/eventLogApp/src/pluginEventLog.tsx b/sdnr/wt/odlux/apps/eventLogApp/src/pluginEventLog.tsx
index a2edb43..8ee322a 100644
--- a/sdnr/wt/odlux/apps/eventLogApp/src/pluginEventLog.tsx
+++ b/sdnr/wt/odlux/apps/eventLogApp/src/pluginEventLog.tsx
@@ -17,24 +17,26 @@
*/
// app configuration and main entry point for the app
-import * as React from "react";
-import { faBookOpen } from '@fortawesome/free-solid-svg-icons'; // select app icon
+import React, { FC } from 'react';
+
import applicationManager from '../../../framework/src/services/applicationManager';
import { EventLog } from './views/eventLog';
import eventLogAppRootHandler from './handlers/eventLogAppRootHandler';
-const App : React.SFC = (props) => {
- return <EventLog />
+const appIcon = require('./assets/icons/eventLogAppIcon.svg'); // select app icon
+
+const App : FC = () => {
+ return <EventLog />;
};
export function register() {
applicationManager.registerApplication({
- name: "eventLog",
- icon: faBookOpen,
+ name: 'eventLog',
+ icon: appIcon,
rootActionHandler: eventLogAppRootHandler,
rootComponent: App,
- menuEntry: "EventLog"
+ menuEntry: 'EventLog',
});
}
diff --git a/sdnr/wt/odlux/apps/eventLogApp/tsconfig.json b/sdnr/wt/odlux/apps/eventLogApp/tsconfig.json
index a66b5d8..ca65092 100644
--- a/sdnr/wt/odlux/apps/eventLogApp/tsconfig.json
+++ b/sdnr/wt/odlux/apps/eventLogApp/tsconfig.json
@@ -4,7 +4,7 @@
"outDir": "./dist",
"sourceMap": true,
"forceConsistentCasingInFileNames": true,
- "allowSyntheticDefaultImports": false,
+ "allowSyntheticDefaultImports": true,
"allowUnreachableCode": false,
"allowUnusedLabels": false,
"noFallthroughCasesInSwitch": true,
diff --git a/sdnr/wt/odlux/apps/eventLogApp/webpack.config.js b/sdnr/wt/odlux/apps/eventLogApp/webpack.config.js
index de309c1..3d056ec 100644
--- a/sdnr/wt/odlux/apps/eventLogApp/webpack.config.js
+++ b/sdnr/wt/odlux/apps/eventLogApp/webpack.config.js
@@ -57,6 +57,16 @@
use: [{
loader: "babel-loader"
}]
+ }, {
+ //don't minify images
+ test: /\.(png|gif|jpg|svg)$/,
+ use: [{
+ loader: 'url-loader',
+ options: {
+ limit: 10,
+ name: './images/[name].[ext]'
+ }
+ }]
}]
},
diff --git a/sdnr/wt/odlux/apps/faultApp/package.json b/sdnr/wt/odlux/apps/faultApp/package.json
index a5958d8..9531055 100644
--- a/sdnr/wt/odlux/apps/faultApp/package.json
+++ b/sdnr/wt/odlux/apps/faultApp/package.json
@@ -26,7 +26,9 @@
"@mui/icons-material": "^5.2.0",
"@mui/material": "^5.2.2",
"@mui/styles": "^5.2.2",
- "@odlux/framework": "*"
+ "@odlux/framework": "*",
+ "@fortawesome/free-solid-svg-icons": "5.6.3",
+ "@fortawesome/react-fontawesome": "0.1.14"
},
"peerDependencies": {
"@types/classnames": "2.2.6",
@@ -38,6 +40,7 @@
"jquery": "3.3.1",
"react": "17.0.2",
"react-dom": "17.0.2",
- "react-router-dom": "5.2.0"
+ "react-router-dom": "5.2.0",
+ "react-chartjs-2": "^3.0.3"
}
}
diff --git a/sdnr/wt/odlux/apps/faultApp/pom.xml b/sdnr/wt/odlux/apps/faultApp/pom.xml
index 31a3760..ba4df50 100644
--- a/sdnr/wt/odlux/apps/faultApp/pom.xml
+++ b/sdnr/wt/odlux/apps/faultApp/pom.xml
@@ -19,6 +19,7 @@
~ ============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>
@@ -139,7 +140,7 @@
<!-- optional: default phase is "generate-resources" -->
<phase>initialize</phase>
<configuration>
- <nodeVersion>v12.13.0</nodeVersion>
+ <nodeVersion>v12.22.0</nodeVersion>
<yarnVersion>v1.22.10</yarnVersion>
</configuration>
</execution>
diff --git a/sdnr/wt/odlux/apps/faultApp/src/actions/clearStuckAlarmsAction.ts b/sdnr/wt/odlux/apps/faultApp/src/actions/clearStuckAlarmsAction.ts
index cdcbf64..7aac8ba 100644
--- a/sdnr/wt/odlux/apps/faultApp/src/actions/clearStuckAlarmsAction.ts
+++ b/sdnr/wt/odlux/apps/faultApp/src/actions/clearStuckAlarmsAction.ts
@@ -17,20 +17,21 @@
*/
-import { clearStuckAlarms } from "../services/faultStatusService"
-import { Dispatch } from "../../../../framework/src/flux/store";
-import { FaultApplicationBaseAction } from "./notificationActions";
+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();
- }
+ 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
+ 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/apps/faultApp/src/actions/panelChangeActions.ts b/sdnr/wt/odlux/apps/faultApp/src/actions/panelChangeActions.ts
index 7cf02ac..fb29e9c 100644
--- a/sdnr/wt/odlux/apps/faultApp/src/actions/panelChangeActions.ts
+++ b/sdnr/wt/odlux/apps/faultApp/src/actions/panelChangeActions.ts
@@ -16,6 +16,7 @@
* ============LICENSE_END==========================================================================
*/
import { Action } from '../../../../framework/src/flux/action';
+
import { PanelId } from '../models/panelId';
export class SetPanelAction extends Action {
@@ -32,5 +33,5 @@
export const setPanelAction = (panelId: PanelId) => {
return new SetPanelAction(panelId);
-}
+};
diff --git a/sdnr/wt/odlux/apps/faultApp/src/actions/statusActions.ts b/sdnr/wt/odlux/apps/faultApp/src/actions/statusActions.ts
index 54fea6a..8b631b9 100644
--- a/sdnr/wt/odlux/apps/faultApp/src/actions/statusActions.ts
+++ b/sdnr/wt/odlux/apps/faultApp/src/actions/statusActions.ts
@@ -15,10 +15,11 @@
* the License.
* ============LICENSE_END==========================================================================
*/
-import { FaultApplicationBaseAction } from './notificationActions';
-import { getFaultStateFromDatabase } from '../services/faultStatusService';
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,
@@ -32,29 +33,28 @@
export const refreshFaultStatusAsyncAction = async (dispatch: Dispatch) => {
- dispatch(new SetFaultStatusAction(0, 0, 0, 0, true, 0, 0, 0, 0, 0, 0, 0, 0, true));
+ // 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,
+ 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
+ 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 {
+ } else {
dispatch(new SetFaultStatusAction(0, 0, 0, 0, false, 0, 0, 0, 0, 0, 0, 0, 0, false));
}
-}
+};
diff --git a/sdnr/wt/odlux/apps/faultApp/src/assets/icons/faultAppIcon.svg b/sdnr/wt/odlux/apps/faultApp/src/assets/icons/faultAppIcon.svg
new file mode 100644
index 0000000..aabbf4c
--- /dev/null
+++ b/sdnr/wt/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/apps/faultApp/src/components/clearStuckAlarmsDialog.tsx b/sdnr/wt/odlux/apps/faultApp/src/components/clearStuckAlarmsDialog.tsx
index 463c207..e86b756 100644
--- a/sdnr/wt/odlux/apps/faultApp/src/components/clearStuckAlarmsDialog.tsx
+++ b/sdnr/wt/odlux/apps/faultApp/src/components/clearStuckAlarmsDialog.tsx
@@ -16,119 +16,122 @@
* ============LICENSE_END==========================================================================
*/
-import * as React from 'react'
-import { DialogContent, DialogActions, Button, Dialog, DialogTitle, DialogContentText } from '@mui/material';
-import { currentProblemsReloadAction } from '../handlers/currentProblemsHandler';
+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 connect, { IDispatcher, Connect } from '../../../../framework/src/flux/connect';
+import { currentAlarmsReloadAction } from '../handlers/currentAlarmsHandler';
export enum ClearStuckAlarmsDialogMode {
- None = "none",
- Show = "show"
+ None = 'none',
+ Show = 'show',
}
const mapDispatch = (dispatcher: IDispatcher) => ({
- clearStuckAlarmsAsync: clearStuckAlarmAsyncAction(dispatcher.dispatch),
- reloadCurrentProblemsAction: () => dispatcher.dispatch(currentProblemsReloadAction)
+ clearStuckAlarmsAsync: clearStuckAlarmAsyncAction(dispatcher.dispatch),
+ reloadCurrentAlarmsAction: () => dispatcher.dispatch(currentAlarmsReloadAction),
});
type clearStuckAlarmsProps = Connect<typeof undefined, typeof mapDispatch> & {
- numberDevices: Number;
- mode: ClearStuckAlarmsDialogMode;
- stuckAlarms: string[];
- onClose: () => void;
-}
+ numberDevices: Number;
+ mode: ClearStuckAlarmsDialogMode;
+ stuckAlarms: string[];
+ onClose: () => void;
+};
type ClearStuckAlarmsState = {
- clearAlarmsSuccessful: boolean;
- errormessage: string;
- unclearedAlarms: string[];
-}
+ clearAlarmsSuccessful: boolean;
+ errormessage: string;
+ unclearedAlarms: string[];
+};
-class ClearStuckAlarmsDialogComponent extends React.Component<clearStuckAlarmsProps, ClearStuckAlarmsState>{
- constructor(props: clearStuckAlarmsProps) {
- super(props);
- this.state = {
- clearAlarmsSuccessful: true,
- errormessage: '',
- unclearedAlarms: []
- };
+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: [] });
}
- onClose = (event: React.MouseEvent) => {
- event.stopPropagation();
- event.preventDefault();
- this.props.onClose();
- }
+ this.props.reloadCurrentAlarmsAction();
+ this.props.onClose();
+ };
- onRefresh = async (event: React.MouseEvent) => {
- event.stopPropagation();
- event.preventDefault();
- const result = await this.props.clearStuckAlarmsAsync(this.props.stuckAlarms);
+ onOk = (event: React.MouseEvent) => {
- 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;
+ event.stopPropagation();
+ event.preventDefault();
+ if (this.state.unclearedAlarms.length > 0)
+ this.props.reloadCurrentAlarmsAction();
+ this.props.onClose();
+ };
- } else { //show errormessage if no devices were cleared
- this.setState({ clearAlarmsSuccessful: false, errormessage: "Alarms couldn't be refreshed.", unclearedAlarms: [] });
- }
+ 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;
- this.props.reloadCurrentProblemsAction();
- this.props.onClose();
- }
+ const defaultTitle = 'Refresh Confirmation';
+ const title = this.state.clearAlarmsSuccessful ? defaultTitle : 'Refresh Result';
- onOk = (event: React.MouseEvent) => {
+ 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>
+ </>
+ }
- event.stopPropagation();
- event.preventDefault();
- if (this.state.unclearedAlarms.length > 0)
- this.props.reloadCurrentProblemsAction();
- this.props.onClose();
- }
-
- render() {
- console.log(this.props.stuckAlarms);
- const device = this.props.numberDevices > 1 ? 'devices' : 'device'
- const defaultMessage = "Are you sure you want to refresh all alarms for " + this.props.numberDevices + " " + device + "?"
- const message = this.state.clearAlarmsSuccessful ? defaultMessage : this.state.errormessage;
-
- const defaultTitle = "Refresh Confirmation"
- const title = this.state.clearAlarmsSuccessful ? defaultTitle : 'Refresh Result';
-
- return (
- <Dialog open={this.props.mode !== ClearStuckAlarmsDialogMode.None}>
- <DialogTitle>{title}</DialogTitle>
- <DialogContent>
- <DialogContentText>
- {message}
- </DialogContentText>
- {
- this.state.unclearedAlarms.map(item =>
- <DialogContentText>
- {item}
- </DialogContentText>
- )
- }
- </DialogContent>
- <DialogActions>
- {
- this.state.clearAlarmsSuccessful &&
- <>
- <Button 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>
- )
- }
+ {
+ !this.state.clearAlarmsSuccessful && <Button color="inherit" onClick={this.onOk}>Ok</Button>
+ }
+ </DialogActions>
+ </Dialog>
+ );
+ }
}
const ClearStuckAlarmsDialog = connect(undefined, mapDispatch)(ClearStuckAlarmsDialogComponent);
diff --git a/sdnr/wt/odlux/apps/faultApp/src/components/dashboardHome.tsx b/sdnr/wt/odlux/apps/faultApp/src/components/dashboardHome.tsx
index a817059..a3e32c4 100644
--- a/sdnr/wt/odlux/apps/faultApp/src/components/dashboardHome.tsx
+++ b/sdnr/wt/odlux/apps/faultApp/src/components/dashboardHome.tsx
@@ -15,26 +15,25 @@
* the License.
* ============LICENSE_END==========================================================================
*/
-import * as React from 'react';
+import React from 'react';
+import { RouteComponentProps, withRouter } from 'react-router-dom';
-import { withRouter, RouteComponentProps } from 'react-router-dom';
-import connect, { Connect, IDispatcher } from '../../../../framework/src/flux/connect';;
-import { Theme } from '@mui/material';
import { WithStyles } from '@mui/styles';
import createStyles from '@mui/styles/createStyles';
-import withStyles from '@mui/styles/withStyles';
import { Doughnut } from 'react-chartjs-2';
-import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
-import { NavigateToApplication } from '../../../../framework/src/actions/navigationActions';
+import { connect, Connect, IDispatcher } from '../../../../framework/src/flux/connect';
-const styles = (theme: Theme) => createStyles({
+import { NavigateToApplication } from '../../../../framework/src/actions/navigationActions';
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+
+const styles = () => createStyles({
pageWidthSettings: {
width: '50%',
- float: 'left'
+ float: 'left',
},
-})
+});
-const scrollbar = { overflow: "auto", paddingRight: "20px" }
+const scrollbar = { overflow: 'auto', paddingRight: '20px' };
let connectionStatusinitialLoad = true;
let connectionStatusinitialStateChanged = false;
@@ -47,7 +46,7 @@
let alarmTotalCount = 0;
const mapProps = (state: IApplicationStoreState) => ({
- alarmStatus: state.fault.faultStatus
+ alarmStatus: state.fault.faultStatus,
});
const mapDispatch = (dispatcher: IDispatcher) => ({
@@ -60,11 +59,10 @@
constructor(props: HomeComponentProps) {
super(props);
this.state = {
- }
+ };
}
render(): JSX.Element {
- const { classes } = this.props;
if (!this.props.alarmStatus.isLoadingConnectionStatusChart) {
connectionStatusDataLoad = [
@@ -72,7 +70,7 @@
this.props.alarmStatus.Connecting,
this.props.alarmStatus.Disconnected,
this.props.alarmStatus.UnableToConnect,
- this.props.alarmStatus.Undefined
+ 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;
@@ -84,7 +82,7 @@
this.props.alarmStatus.critical,
this.props.alarmStatus.major,
this.props.alarmStatus.minor,
- this.props.alarmStatus.warning
+ this.props.alarmStatus.warning,
];
alarmTotalCount = this.props.alarmStatus.critical + this.props.alarmStatus.major
+ this.props.alarmStatus.minor + this.props.alarmStatus.warning;
@@ -97,7 +95,7 @@
'Connecting: ' + this.props.alarmStatus.Connecting,
'Disconnected: ' + this.props.alarmStatus.Disconnected,
'UnableToConnect: ' + this.props.alarmStatus.UnableToConnect,
- 'Undefined: ' + this.props.alarmStatus.Undefined
+ 'Undefined: ' + this.props.alarmStatus.Undefined,
],
datasets: [{
labels: ['Connected', 'Connecting', 'Disconnected', 'UnableToConnect', 'Undefined'],
@@ -107,9 +105,9 @@
'rgb(255, 102, 0)',
'rgb(191, 191, 191)',
'rgb(191, 191, 191)',
- 'rgb(242, 240, 240)'
- ]
- }]
+ 'rgb(242, 240, 240)',
+ ],
+ }],
};
@@ -119,9 +117,9 @@
datasets: [{
data: [1],
backgroundColor: [
- 'rgb(255, 255, 255)'
- ]
- }]
+ 'rgb(255, 255, 255)',
+ ],
+ }],
};
/** Loading Connection Status chart */
@@ -130,9 +128,9 @@
datasets: [{
data: [1],
backgroundColor: [
- 'rgb(255, 255, 255)'
- ]
- }]
+ 'rgb(255, 255, 255)',
+ ],
+ }],
};
/** Loading Alarm Status chart */
@@ -141,9 +139,9 @@
datasets: [{
data: [1],
backgroundColor: [
- 'rgb(255, 255, 255)'
- ]
- }]
+ 'rgb(255, 255, 255)',
+ ],
+ }],
};
/** Connection status options */
@@ -155,57 +153,57 @@
let label =
(data.datasets[tooltipItem.datasetIndex].labels &&
data.datasets[tooltipItem.datasetIndex].labels[
- tooltipItem.index
+ tooltipItem.index
]) ||
data.labels[tooltipItem.index] ||
- "";
+ '';
if (label) {
- label += ": ";
+ label += ': ';
}
label +=
data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index] +
- (data.datasets[tooltipItem.datasetIndex].labelSuffix || "");
+ (data.datasets[tooltipItem.datasetIndex].labelSuffix || '');
return label;
- }
- }
+ },
+ },
},
responsive: true,
maintainAspectRatio: false,
animation: {
- duration: 0
+ duration: 0,
},
plugins: {
legend: {
display: true,
- position: 'top'
- }
+ position: 'top',
+ },
},
onClick: (event: MouseEvent, item: any) => {
if (item[0]) {
let connectionStatus = labels[item[0]._index] + '';
- this.props.navigateToApplication("connect", '/connectionStatus/' + connectionStatus);
+ this.props.navigateToApplication('connect', '/connectionStatus/' + connectionStatus);
}
- }
- }
+ },
+ };
/** Connection status unavailable options */
const connectionStatusUnavailableOptions = {
responsive: true,
maintainAspectRatio: false,
animation: {
- duration: 0
+ duration: 0,
},
plugins: {
legend: {
display: true,
- position: 'top'
+ position: 'top',
},
tooltip: {
- enabled: false
- }
- }
- }
+ enabled: false,
+ },
+ },
+ };
/** Add text inside the doughnut chart for Connection Status */
const connectionStatusPlugins = [{
@@ -215,15 +213,15 @@
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",
+ 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 = {
@@ -231,7 +229,7 @@
'Critical : ' + this.props.alarmStatus.critical,
'Major : ' + this.props.alarmStatus.major,
'Minor : ' + this.props.alarmStatus.minor,
- 'Warning : ' + this.props.alarmStatus.warning
+ 'Warning : ' + this.props.alarmStatus.warning,
],
datasets: [{
labels: ['Critical', 'Major', 'Minor', 'Warning'],
@@ -240,10 +238,10 @@
'rgb(240, 25, 10)',
'rgb(240, 133, 10)',
'rgb(240, 240, 10)',
- 'rgb(46, 115, 176)'
+ 'rgb(46, 115, 176)',
],
- }]
- }
+ }],
+ };
/** No Alarm status available */
const alarmStatusUnavailableData = {
@@ -251,9 +249,9 @@
datasets: [{
data: [1],
backgroundColor: [
- 'rgb(0, 153, 51)'
- ]
- }]
+ 'rgb(0, 153, 51)',
+ ],
+ }],
};
/** Alarm status Options */
@@ -265,36 +263,36 @@
let label =
(data.datasets[tooltipItem.datasetIndex].labels &&
data.datasets[tooltipItem.datasetIndex].labels[
- tooltipItem.index
+ tooltipItem.index
]) ||
data.labels[tooltipItem.index] ||
- "";
+ '';
if (label) {
- label += ": ";
+ label += ': ';
}
label +=
data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index] +
- (data.datasets[tooltipItem.datasetIndex].labelSuffix || "");
+ (data.datasets[tooltipItem.datasetIndex].labelSuffix || '');
return label;
- }
- }
+ },
+ },
},
responsive: true,
maintainAspectRatio: false,
animation: {
- duration: 0
+ duration: 0,
},
plugins: {
legend: {
display: true,
- position: 'top'
- }
+ position: 'top',
+ },
},
onClick: (event: MouseEvent, item: any) => {
if (item[0]) {
let severity = alarmLabels[item[0]._index] + '';
- this.props.navigateToApplication("fault", '/alarmStatus/' + severity);
+ this.props.navigateToApplication('fault', '/alarmStatus/' + severity);
}
},
};
@@ -304,18 +302,18 @@
responsive: true,
maintainAspectRatio: false,
animation: {
- duration: 0
+ duration: 0,
},
plugins: {
legend: {
display: true,
- position: 'top'
+ position: 'top',
},
tooltip: {
- enabled: false
- }
- }
- }
+ enabled: false,
+ },
+ },
+ };
/** Add text inside the doughnut chart for Alarm Status */
const alarmStatusPlugins = [{
beforeDraw: function (chart: any) {
@@ -324,15 +322,15 @@
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",
+ 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 (
<>
@@ -397,7 +395,7 @@
</div>
</div>
</>
- )
+ );
}
/** Check if connection status data available */
@@ -412,7 +410,7 @@
} else {
return true;
}
- }
+ };
/** Check if connection status chart data is loaded */
public checkElementsAreLoaded = () => {
@@ -434,7 +432,7 @@
return !isLoadingCheck.isLoadingConnectionStatusChart;
}
return true;
- }
+ };
/** Check if alarms data available */
public checkAlarmStatus = () => {
@@ -444,11 +442,10 @@
}
if (alarmCount.critical == 0 && alarmCount.major == 0 && alarmCount.minor == 0 && alarmCount.warning == 0) {
return false;
- }
- else {
+ } else {
return true;
}
- }
+ };
/** Check if alarm status chart data is loaded */
public checkAlarmsAreLoaded = () => {
@@ -470,7 +467,7 @@
return !isLoadingCheck.isLoadingAlarmStatusChart;
}
return true;
- }
+ };
}
export default (withRouter(connect(mapProps, mapDispatch)(DashboardHome)));
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/faultApp/src/components/faultStatus.tsx b/sdnr/wt/odlux/apps/faultApp/src/components/faultStatus.tsx
index 7820dfd..c2ca4a5 100644
--- a/sdnr/wt/odlux/apps/faultApp/src/components/faultStatus.tsx
+++ b/sdnr/wt/odlux/apps/faultApp/src/components/faultStatus.tsx
@@ -15,37 +15,36 @@
* the License.
* ============LICENSE_END==========================================================================
*/
-import * as React from 'react';
+import React from 'react';
-import { Theme } from '@mui/material/styles';
+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 withStyles from '@mui/styles/withStyles';
import createStyles from '@mui/styles/createStyles';
-import { faExclamationTriangle } from '@fortawesome/free-solid-svg-icons'; // select app icon
+import withStyles from '@mui/styles/withStyles';
-import connect, { Connect } from '../../../../framework/src/flux/connect';
+import { connect, Connect } from '../../../../framework/src/flux/connect';
import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
-import Typography from '@mui/material/Typography';
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-const styles = (theme: Theme) => createStyles({
+const styles = () => createStyles({
icon: {
marginLeft: 8,
- marginRight: 8
+ marginRight: 8,
},
critical: {
- color: "red"
+ color: 'red',
},
major: {
- color: "orange"
+ color: 'orange',
},
minor: {
- color: "#f7f700"
+ color: '#f7f700',
},
warning: {
- color: "#428bca"
- }
+ color: '#428bca',
+ },
});
const mapProps = (state: IApplicationStoreState) => ({
@@ -75,7 +74,7 @@
</Typography>
</>
);
- };
+ }
}
export const FaultStatus = withStyles(styles)(connect(mapProps)(FaultStatusComponent));
diff --git a/sdnr/wt/odlux/apps/faultApp/src/components/refreshAlarmLogDialog.tsx b/sdnr/wt/odlux/apps/faultApp/src/components/refreshAlarmLogDialog.tsx
index 8c639ee..59657d8 100644
--- a/sdnr/wt/odlux/apps/faultApp/src/components/refreshAlarmLogDialog.tsx
+++ b/sdnr/wt/odlux/apps/faultApp/src/components/refreshAlarmLogDialog.tsx
@@ -24,78 +24,73 @@
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 { IDispatcher, connect, Connect } from '../../../../framework/src/flux/connect';
-
import { Fault } from '../models/fault';
export enum RefreshAlarmLogDialogMode {
- None = "none",
- RefreshAlarmLogTable = "RefreshAlarmLogTable",
+ None = 'none',
+ RefreshAlarmLogTable = 'RefreshAlarmLogTable',
}
const mapDispatch = (dispatcher: IDispatcher) => ({
- refreshAlarmLog: () => dispatcher.dispatch(alarmLogEntriesReloadAction)
+ refreshAlarmLog: () => dispatcher.dispatch(alarmLogEntriesReloadAction),
});
type DialogSettings = {
- dialogTitle: string,
- dialogDescription: string,
- applyButtonText: string,
- cancelButtonText: string,
- enableMountIdEditor: boolean,
- enableUsernameEditor: boolean,
- enableExtendedEditor: boolean,
-}
+ 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: "",
+ 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",
+ 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 };
+type RefreshAlarmLogDialogComponentState = Fault & { isNameValid: boolean; isHostSet: boolean };
class RefreshAlarmLogDialogComponent extends React.Component<RefreshAlarmLogDialogComponentProps, RefreshAlarmLogDialogComponentState> {
- constructor(props: RefreshAlarmLogDialogComponentProps) {
- super(props);
- }
-
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>
+ <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={(event) => {
+ <Button aria-label="dialog-confirm-button" onClick={() => {
this.onRefresh();
}} color="inherit" > {setting.applyButtonText} </Button>
- <Button aria-label="dialog-cancel-button" onClick={(event) => {
+ <Button aria-label="dialog-cancel-button" onClick={() => {
this.onCancel();
}} color="secondary"> {setting.cancelButtonText} </Button>
</DialogActions>
@@ -110,7 +105,7 @@
private onCancel = () => {
this.props.onClose();
- }
+ };
}
export const RefreshAlarmLogDialog = connect(undefined, mapDispatch)(RefreshAlarmLogDialogComponent);
diff --git a/sdnr/wt/odlux/apps/faultApp/src/components/refreshCurrentAlarmsDialog.tsx b/sdnr/wt/odlux/apps/faultApp/src/components/refreshCurrentAlarmsDialog.tsx
new file mode 100644
index 0000000..20cd514
--- /dev/null
+++ b/sdnr/wt/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/apps/faultApp/src/components/refreshCurrentProblemsDialog.tsx b/sdnr/wt/odlux/apps/faultApp/src/components/refreshCurrentProblemsDialog.tsx
deleted file mode 100644
index e501ec0..0000000
--- a/sdnr/wt/odlux/apps/faultApp/src/components/refreshCurrentProblemsDialog.tsx
+++ /dev/null
@@ -1,117 +0,0 @@
-/**
- * ============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 { currentProblemsReloadAction } from '../handlers/currentProblemsHandler';
-import { IDispatcher, connect, Connect } from '../../../../framework/src/flux/connect';
-
-import { Fault } from '../models/fault';
-
-export enum RefreshCurrentProblemsDialogMode {
- None = "none",
- RefreshCurrentProblemsTable = "RefreshCurrentProblemsTable",
-}
-
-const mapDispatch = (dispatcher: IDispatcher) => ({
- refreshCurrentProblems: () => dispatcher.dispatch(currentProblemsReloadAction)
-});
-
-type DialogSettings = {
- dialogTitle: string,
- dialogDescription: string,
- applyButtonText: string,
- cancelButtonText: string,
- enableMountIdEditor: boolean,
- enableUsernameEditor: boolean,
- enableExtendedEditor: boolean,
-}
-
-const settings: { [key: string]: DialogSettings } = {
- [RefreshCurrentProblemsDialogMode.None]: {
- dialogTitle: "",
- dialogDescription: "",
- applyButtonText: "",
- cancelButtonText: "",
- enableMountIdEditor: false,
- enableUsernameEditor: false,
- enableExtendedEditor: false,
- },
- [RefreshCurrentProblemsDialogMode.RefreshCurrentProblemsTable]: {
- dialogTitle: "Do you want to refresh the Current Problems List?",
- dialogDescription: "",
- applyButtonText: "Yes",
- cancelButtonText: "Cancel",
- enableMountIdEditor: true,
- enableUsernameEditor: true,
- enableExtendedEditor: true,
- }
-}
-
-type RefreshCurrentProblemsDialogComponentProps = Connect<undefined, typeof mapDispatch> & {
- mode: RefreshCurrentProblemsDialogMode;
- onClose: () => void;
-};
-
-type RefreshCurrentProblemsDialogComponentState = Fault & { isNameValid: boolean, isHostSet: boolean };
-
-class RefreshCurrentProblemsDialogComponent extends React.Component<RefreshCurrentProblemsDialogComponentProps, RefreshCurrentProblemsDialogComponentState> {
- constructor(props: RefreshCurrentProblemsDialogComponentProps) {
- super(props);
- }
-
- render(): JSX.Element {
- const setting = settings[this.props.mode];
- return (
- <Dialog open={this.props.mode !== RefreshCurrentProblemsDialogMode.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={(event) => {
- this.onRefresh();
- }} color="inherit" > {setting.applyButtonText} </Button>
- <Button aria-label="dialog-cancel-button" onClick={(event) => {
- this.onCancel();
- }} color="secondary"> {setting.cancelButtonText} </Button>
- </DialogActions>
- </Dialog>
- );
- }
-
- private onRefresh = () => {
- this.props.refreshCurrentProblems();
- this.props.onClose();
- };
-
- private onCancel = () => {
- this.props.onClose();
- }
-}
-
-export const RefreshCurrentProblemsDialog = connect(undefined, mapDispatch)(RefreshCurrentProblemsDialogComponent);
-export default RefreshCurrentProblemsDialog;
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/faultApp/src/handlers/alarmLogEntriesHandler.ts b/sdnr/wt/odlux/apps/faultApp/src/handlers/alarmLogEntriesHandler.ts
index 31b8259..bdd4596 100644
--- a/sdnr/wt/odlux/apps/faultApp/src/handlers/alarmLogEntriesHandler.ts
+++ b/sdnr/wt/odlux/apps/faultApp/src/handlers/alarmLogEntriesHandler.ts
@@ -15,7 +15,7 @@
* the License.
* ============LICENSE_END==========================================================================
*/
-import { createExternal,IExternalTableState } from '../../../../framework/src/components/material-table/utilities';
+import { createExternal, IExternalTableState } from '../../../../framework/src/components/material-table/utilities';
import { createSearchDataHandler } from '../../../../framework/src/utilities/elasticSearch';
import { Fault } from '../models/fault';
diff --git a/sdnr/wt/odlux/apps/faultApp/src/handlers/clearStuckAlarmsHandler.ts b/sdnr/wt/odlux/apps/faultApp/src/handlers/clearStuckAlarmsHandler.ts
index 14634b4..0d5a8c7 100644
--- a/sdnr/wt/odlux/apps/faultApp/src/handlers/clearStuckAlarmsHandler.ts
+++ b/sdnr/wt/odlux/apps/faultApp/src/handlers/clearStuckAlarmsHandler.ts
@@ -16,21 +16,22 @@
* ============LICENSE_END==========================================================================
*/
-import { IActionHandler } from "../../../../framework/src/flux/action"
-import { AreStuckAlarmsCleared } from "../actions/clearStuckAlarmsAction";
+import { IActionHandler } from '../../../../framework/src/flux/action';
+
+import { AreStuckAlarmsCleared } from '../actions/clearStuckAlarmsAction';
export interface IStuckAlarms {
- areAlarmsCleared: boolean
+ areAlarmsCleared: boolean;
}
const initialState: IStuckAlarms = {
- areAlarmsCleared: false
-}
+ areAlarmsCleared: false,
+};
export const stuckAlarmHandler: IActionHandler<IStuckAlarms> = (state = initialState, action) => {
- if (action instanceof AreStuckAlarmsCleared) {
- state = { ...state, areAlarmsCleared: action.isBusy }
- }
+ if (action instanceof AreStuckAlarmsCleared) {
+ state = { ...state, areAlarmsCleared: action.isBusy };
+ }
- return state;
-}
\ No newline at end of file
+ return state;
+};
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/faultApp/src/handlers/currentProblemsHandler.ts b/sdnr/wt/odlux/apps/faultApp/src/handlers/currentAlarmsHandler.ts
similarity index 69%
rename from sdnr/wt/odlux/apps/faultApp/src/handlers/currentProblemsHandler.ts
rename to sdnr/wt/odlux/apps/faultApp/src/handlers/currentAlarmsHandler.ts
index 3698a27..70aa1c2 100644
--- a/sdnr/wt/odlux/apps/faultApp/src/handlers/currentProblemsHandler.ts
+++ b/sdnr/wt/odlux/apps/faultApp/src/handlers/currentAlarmsHandler.ts
@@ -15,22 +15,22 @@
* the License.
* ============LICENSE_END==========================================================================
*/
-import { createExternal,IExternalTableState } from '../../../../framework/src/components/material-table/utilities';
+import { createExternal, IExternalTableState } from '../../../../framework/src/components/material-table/utilities';
import { createSearchDataHandler } from '../../../../framework/src/utilities/elasticSearch';
import { Fault } from '../models/fault';
-export interface ICurrentProblemsState extends IExternalTableState<Fault> { }
+export interface ICurrentAlarmsState extends IExternalTableState<Fault> { }
// create eleactic search data fetch handler
-const currentProblemsSearchHandler = createSearchDataHandler<Fault>('faultcurrent');
+const currentAlarmsSearchHandler = createSearchDataHandler<Fault>('faultcurrent');
export const {
- actionHandler: currentProblemsActionHandler,
- createActions: createCurrentProblemsActions,
- createProperties: createCurrentProblemsProperties,
- reloadAction: currentProblemsReloadAction,
+ actionHandler: currentAlarmsActionHandler,
+ createActions: createCurrentAlarmsActions,
+ createProperties: createCurrentAlarmsProperties,
+ reloadAction: currentAlarmsReloadAction,
// set value action, to change a value
-} = createExternal<Fault>(currentProblemsSearchHandler, appState => appState.fault.currentProblems);
+} = createExternal<Fault>(currentAlarmsSearchHandler, appState => appState.fault.currentAlarms);
diff --git a/sdnr/wt/odlux/apps/faultApp/src/handlers/faultAppRootHandler.ts b/sdnr/wt/odlux/apps/faultApp/src/handlers/faultAppRootHandler.ts
index 2ab1da2..e4a19ae 100644
--- a/sdnr/wt/odlux/apps/faultApp/src/handlers/faultAppRootHandler.ts
+++ b/sdnr/wt/odlux/apps/faultApp/src/handlers/faultAppRootHandler.ts
@@ -17,22 +17,21 @@
*/
// main state handler
-import { combineActionHandler } from '../../../../framework/src/flux/middleware';
-
-// ** do not remove **
-import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
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 { IFaultNotifications, faultNotificationsHandler } from './notificationsHandler';
-import { ICurrentProblemsState, currentProblemsActionHandler } from './currentProblemsHandler';
-import { IAlarmLogEntriesState, alarmLogEntriesActionHandler } from './alarmLogEntriesHandler';
import { SetPanelAction } from '../actions/panelChangeActions';
-import { IFaultStatus, faultStatusHandler } from './faultStatusHandler';
-import { stuckAlarmHandler } from './clearStuckAlarmsHandler';
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 {
- currentProblems: ICurrentProblemsState;
+ currentAlarms: ICurrentAlarmsState;
faultNotifications: IFaultNotifications;
alarmLogEntries: IAlarmLogEntriesState;
currentOpenPanel: PanelId | null;
@@ -44,7 +43,7 @@
state = action.panelId;
}
return state;
-}
+};
declare module '../../../../framework/src/store/applicationStore' {
interface IApplicationStoreState {
@@ -53,7 +52,7 @@
}
const actionHandlers = {
- currentProblems: currentProblemsActionHandler,
+ currentAlarms: currentAlarmsActionHandler,
faultNotifications: faultNotificationsHandler,
alarmLogEntries: alarmLogEntriesActionHandler,
currentOpenPanel: currentOpenPanelHandler,
diff --git a/sdnr/wt/odlux/apps/faultApp/src/handlers/faultStatusHandler.ts b/sdnr/wt/odlux/apps/faultApp/src/handlers/faultStatusHandler.ts
index 6fa95b6..21b033e 100644
--- a/sdnr/wt/odlux/apps/faultApp/src/handlers/faultStatusHandler.ts
+++ b/sdnr/wt/odlux/apps/faultApp/src/handlers/faultStatusHandler.ts
@@ -15,24 +15,25 @@
* the License.
* ============LICENSE_END==========================================================================
*/
-import { IActionHandler } from "../../../../framework/src/flux/action";
-import { SetFaultStatusAction } from "../actions/statusActions";
+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
+ 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 = {
@@ -49,7 +50,7 @@
Undefined: 0,
Unmounted: 0,
total: 0,
- isLoadingConnectionStatusChart: false
+ isLoadingConnectionStatusChart: false,
};
export const faultStatusHandler: IActionHandler<IFaultStatus> = (state = faultStatusInit, action) => {
@@ -68,9 +69,9 @@
Undefined: action.UndefinedCount,
Unmounted: action.UnmountedCount,
total: action.totalCount,
- isLoadingConnectionStatusChart: action.isLoadingConnectionStatusChart
- }
+ isLoadingConnectionStatusChart: action.isLoadingConnectionStatusChart,
+ };
}
return state;
-}
\ No newline at end of file
+};
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/faultApp/src/handlers/notificationsHandler.ts b/sdnr/wt/odlux/apps/faultApp/src/handlers/notificationsHandler.ts
index aa92d2a..3d960bf 100644
--- a/sdnr/wt/odlux/apps/faultApp/src/handlers/notificationsHandler.ts
+++ b/sdnr/wt/odlux/apps/faultApp/src/handlers/notificationsHandler.ts
@@ -16,6 +16,7 @@
* ============LICENSE_END==========================================================================
*/
import { IActionHandler } from '../../../../framework/src/flux/action';
+
import { AddFaultNotificationAction, ResetFaultNotificationsAction } from '../actions/notificationActions';
import { FaultAlarmNotification } from '../models/fault';
@@ -26,22 +27,22 @@
const faultNotoficationsInit: IFaultNotifications = {
faults: [],
- since: new Date()
+ since: new Date(),
};
export const faultNotificationsHandler: IActionHandler<IFaultNotifications> = (state = faultNotoficationsInit, action) => {
if (action instanceof AddFaultNotificationAction) {
state = {
...state,
- faults: [...state.faults, action.fault]
+ faults: [...state.faults, action.fault],
};
- } else if (action instanceof ResetFaultNotificationsAction){
+ } else if (action instanceof ResetFaultNotificationsAction) {
state = {
...state,
faults: [],
- since: new Date()
+ since: new Date(),
};
}
return state;
-}
\ No newline at end of file
+};
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/faultApp/src/models/fault.ts b/sdnr/wt/odlux/apps/faultApp/src/models/fault.ts
index 5f38e5f..c70253e 100644
--- a/sdnr/wt/odlux/apps/faultApp/src/models/fault.ts
+++ b/sdnr/wt/odlux/apps/faultApp/src/models/fault.ts
@@ -25,7 +25,7 @@
severity: null | 'Warning' | 'Minor' | 'Major' | 'Critical' | 'NonAlarmed';
type: string;
sourceType?: string;
-}
+};
export type FaultAlarmNotification = {
id: string;
@@ -35,63 +35,63 @@
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';
+ '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;
+ 'type': {
+ 'namespace': string;
+ 'revision': string;
+ 'type': string;
};
- "event-time": 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
+ 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
+ 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
+ faults: FaultsReturnType;
+ 'network-element-connections': FaultsReturnType;
};
export type DeletedStuckAlarms = {
- nodenames: string[]
-}
\ No newline at end of file
+ nodenames: string[];
+};
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/faultApp/src/models/panelId.ts b/sdnr/wt/odlux/apps/faultApp/src/models/panelId.ts
index 186aa53..daebad0 100644
--- a/sdnr/wt/odlux/apps/faultApp/src/models/panelId.ts
+++ b/sdnr/wt/odlux/apps/faultApp/src/models/panelId.ts
@@ -15,4 +15,4 @@
* the License.
* ============LICENSE_END==========================================================================
*/
-export type PanelId = null | "CurrentProblem" | "AlarmNotifications" | "AlarmLog";
\ No newline at end of file
+export type PanelId = null | 'CurrentAlarms' | 'AlarmNotifications' | 'AlarmLog';
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/faultApp/src/pluginFault.tsx b/sdnr/wt/odlux/apps/faultApp/src/pluginFault.tsx
index ff901b0..ca1cfc1 100644
--- a/sdnr/wt/odlux/apps/faultApp/src/pluginFault.tsx
+++ b/sdnr/wt/odlux/apps/faultApp/src/pluginFault.tsx
@@ -17,92 +17,85 @@
*/
// app configuration and main entry point for the app
+import React from 'react';
+import { Redirect, Route, RouteComponentProps, Switch, withRouter } from 'react-router-dom';
-import * as React from "react";
-import { withRouter, RouteComponentProps, Route, Switch, Redirect } from 'react-router-dom';
-
-import connect, { Connect, IDispatcher } from '../../../framework/src/flux/connect';
-
-import { faBell } from '@fortawesome/free-solid-svg-icons'; // select app icon
+import { connect, Connect, IDispatcher } from '../../../framework/src/flux/connect';
import applicationManager from '../../../framework/src/services/applicationManager';
-import { subscribe, IFormatedMessage } from '../../../framework/src/services/notificationService';
-import { IApplicationStoreState } from "../../../framework/src/store/applicationStore";
+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 { FaultApplication } from "./views/faultApplication";
+import { FaultAlarmNotificationWS } from './models/fault';
+import { PanelId } from './models/panelId';
+import { FaultApplication } from './views/faultApplication';
-import { FaultAlarmNotificationWS } from "./models/fault";
-import { PanelId } from "./models/panelId";
-
-import { SetPanelAction } from "./actions/panelChangeActions";
-import { AddFaultNotificationAction } from "./actions/notificationActions";
-
-import { createCurrentProblemsProperties, createCurrentProblemsActions, currentProblemsReloadAction } from "./handlers/currentProblemsHandler";
-import { FaultStatus } from "./components/faultStatus";
-import { refreshFaultStatusAsyncAction, SetFaultStatusAction } from "./actions/statusActions";
-
-import DashboardHome from "./components/dashboardHome";
+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) => ({
- currentProblemsProperties: createCurrentProblemsProperties(state),
+ currentAlarmsProperties: createCurrentAlarmsProperties(state),
});
-const mapDisp = (dispatcher: IDispatcher) => ({
- currentProblemsActions: createCurrentProblemsActions(dispatcher.dispatch, true),
+const mapDispatch = (dispatcher: IDispatcher) => ({
+ currentAlarmsActions: createCurrentAlarmsActions(dispatcher.dispatch, true),
setCurrentPanel: (panelId: PanelId) => dispatcher.dispatch(new SetPanelAction(panelId)),
});
-const FaultApplicationRouteAdapter = connect(mapProps, mapDisp)((props: RouteComponentProps<{ mountId?: string }> & Connect<typeof mapProps, typeof mapDisp>) => {
+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("CurrentProblem");
- props.currentProblemsActions.onFilterChanged("nodeId", currentMountId);
- if (!props.currentProblemsProperties.showFilter) {
- props.currentProblemsActions.onToggleFilter(false);
- props.currentProblemsActions.onRefresh();
- }
- else
- props.currentProblemsActions.onRefresh();
+ 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 FaulttApplicationAlarmStatusRouteAdapter = connect(mapProps, mapDisp)((props: RouteComponentProps<{ severity?: string }> & Connect<typeof mapProps, typeof mapDisp>) => {
+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("CurrentProblem");
- props.currentProblemsActions.onFilterChanged("severity", currentSeverity);
- if (!props.currentProblemsProperties.showFilter) {
- props.currentProblemsActions.onToggleFilter(false);
- props.currentProblemsActions.onRefresh();
- }
- else
- props.currentProblemsActions.onRefresh();
+ 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={FaulttApplicationAlarmStatusRouteAdapter} />
+ <Route path={`${props.match.path}/alarmStatus/:severity?`} component={FaultApplicationAlarmStatusRouteAdapter} />
<Route path={`${props.match.path}/:mountId?`} component={FaultApplicationRouteAdapter} />
<Redirect to={`${props.match.path}`} />
</Switch>
@@ -110,54 +103,48 @@
export function register() {
const applicationApi = applicationManager.registerApplication({
- name: "fault",
- icon: faBell,
+ name: 'fault',
+ icon: appIcon,
rootComponent: App,
rootActionHandler: faultAppRootHandler,
statusBarElement: FaultStatus,
dashbaordElement: DashboardHome,
- menuEntry: "Fault"
+ menuEntry: 'Fault',
});
let counter = 0;
// subscribe to the websocket notifications
- subscribe<FaultAlarmNotificationWS & IFormatedMessage>("problem-notification", (fault => {
+ 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"],
+ nodeName: fault['node-id'],
counter: +fault.data.counter,
- objectId: fault.data["object-id-ref"],
+ objectId: fault.data['object-id-ref'],
problem: fault.data.problem,
severity: fault.data.severity || '',
- timeStamp: fault.data["time-stamp"],
+ timeStamp: fault.data['time-stamp'],
}));
}
}));
applicationApi.applicationStoreInitialized.then(store => {
- store.dispatch(currentProblemsReloadAction);
+ store.dispatch(currentAlarmsReloadAction);
});
applicationApi.applicationStoreInitialized.then(store => {
store.dispatch(refreshFaultStatusAsyncAction);
});
- applicationApi.loginEvent.addHandler(e=>{
- refreshInterval = startRefreshInterval() as any;
- })
-
- applicationApi.logoutEvent.addHandler(e=>{
+ 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(() => {
@@ -170,4 +157,7 @@
return refreshFaultStatus;
}
+ applicationApi.loginEvent.addHandler(()=>{
+ refreshInterval = startRefreshInterval() as any;
+ });
}
diff --git a/sdnr/wt/odlux/apps/faultApp/src/services/faultStatusService.ts b/sdnr/wt/odlux/apps/faultApp/src/services/faultStatusService.ts
index 880ed77..0c7a215 100644
--- a/sdnr/wt/odlux/apps/faultApp/src/services/faultStatusService.ts
+++ b/sdnr/wt/odlux/apps/faultApp/src/services/faultStatusService.ts
@@ -15,14 +15,15 @@
* the License.
* ============LICENSE_END==========================================================================
*/
-import { requestRest } from "../../../../framework/src/services/restService";
-import { Result, SingeResult } from "../../../../framework/src/models/elasticSearch";
-import { FaultType, Faults, DeletedStuckAlarms } from "../models/fault";
+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" });
+ const result = await requestRest<Result<Faults>>(path, { method: 'POST' });
let faultType: FaultType = {
Critical: 0,
@@ -36,34 +37,33 @@
UnableToConnect: 0,
Undefined: 0,
Unmounted: 0,
- total: 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;
+ 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,
- }
+ 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 } }) })
+ 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
+};
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/faultApp/src/views/faultApplication.tsx b/sdnr/wt/odlux/apps/faultApp/src/views/faultApplication.tsx
index b9cd5e4..b9f115e 100644
--- a/sdnr/wt/odlux/apps/faultApp/src/views/faultApplication.tsx
+++ b/sdnr/wt/odlux/apps/faultApp/src/views/faultApplication.tsx
@@ -15,44 +15,37 @@
* the License.
* ============LICENSE_END==========================================================================
*/
-import * as React from 'react';
+import React from 'react';
+import { RouteComponentProps, withRouter } from 'react-router-dom';
-import { withRouter, RouteComponentProps } 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 { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { faExclamationTriangle } from '@fortawesome/free-solid-svg-icons';
-
-import { MaterialTable, ColumnType, MaterialTableCtorType } from '../../../../framework/src/components/material-table';
-import { Panel } from '../../../../framework/src/components/material-ui';
-
+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 connect, { Connect, IDispatcher } from '../../../../framework/src/flux/connect';
+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';
-import { createCurrentProblemsProperties, createCurrentProblemsActions, currentProblemsReloadAction } from '../handlers/currentProblemsHandler';
-import { createAlarmLogEntriesProperties, createAlarmLogEntriesActions, alarmLogEntriesReloadAction } from '../handlers/alarmLogEntriesHandler';
-import { setPanelAction } from '../actions/panelChangeActions';
-import { Tooltip, IconButton, AppBar, Tabs, Tab } from '@mui/material';
-import Sync from '@mui/icons-material/Sync';
-import Refresh from '@mui/icons-material/Refresh';
-
-import ClearStuckAlarmsDialog, { ClearStuckAlarmsDialogMode } from '../components/clearStuckAlarmsDialog';
-import RefreshAlarmLogDialog, { RefreshAlarmLogDialogMode } from '../components/refreshAlarmLogDialog';
-import RefreshCurrentProblemsDialog, { RefreshCurrentProblemsDialogMode } from '../components/refreshCurrentProblemsDialog';
-
const mapProps = (state: IApplicationStoreState) => ({
panelId: state.fault.currentOpenPanel,
- currentProblemsProperties: createCurrentProblemsProperties(state),
+ currentAlarmsProperties: createCurrentAlarmsProperties(state),
faultNotifications: state.fault.faultNotifications,
- alarmLogEntriesProperties: createAlarmLogEntriesProperties(state)
+ alarmLogEntriesProperties: createAlarmLogEntriesProperties(state),
});
const mapDisp = (dispatcher: IDispatcher) => ({
- currentProblemsActions: createCurrentProblemsActions(dispatcher.dispatch),
+ currentAlarmsActions: createCurrentAlarmsActions(dispatcher.dispatch),
alarmLogEntriesActions: createAlarmLogEntriesActions(dispatcher.dispatch),
- reloadCurrentProblems: () => dispatcher.dispatch(currentProblemsReloadAction),
+ reloadCurrentAlarms: () => dispatcher.dispatch(currentAlarmsReloadAction),
reloadAlarmLogEntries: () => dispatcher.dispatch(alarmLogEntriesReloadAction),
switchActivePanel: (panelId: PanelId) => {
dispatcher.dispatch(setPanelAction(panelId));
@@ -62,63 +55,59 @@
type FaultApplicationComponentProps = RouteComponentProps & Connect<typeof mapProps, typeof mapDisp>;
type FaultApplicationState = {
- clearAlarmDialogMode: ClearStuckAlarmsDialogMode,
- stuckAlarms: string[],
- refreshAlarmLogEditorMode: RefreshAlarmLogDialogMode,
- refreshCurrentProblemsEditorMode: RefreshCurrentProblemsDialogMode
-}
+ clearAlarmDialogMode: ClearStuckAlarmsDialogMode;
+ stuckAlarms: string[];
+ refreshAlarmLogEditorMode: RefreshAlarmLogDialogMode;
+ refreshCurrentAlarmsEditorMode: RefreshCurrentAlarmsDialogMode;
+};
const FaultTable = MaterialTable as MaterialTableCtorType<Fault>;
const FaultAlarmNotificationTable = MaterialTable as MaterialTableCtorType<FaultAlarmNotification>;
-let currentProblemsInitalSorted = false;
+let currentAlarmsInitalSorted = false;
let alarmLogInitialSorted = false;
-class FaultApplicationComponent extends React.Component<FaultApplicationComponentProps, FaultApplicationState>{
-
- /**
- *
- */
+class FaultApplicationComponent extends React.Component<FaultApplicationComponentProps, FaultApplicationState> {
constructor(props: FaultApplicationComponentProps) {
super(props);
this.state = {
clearAlarmDialogMode: ClearStuckAlarmsDialogMode.None,
stuckAlarms: [],
refreshAlarmLogEditorMode: RefreshAlarmLogDialogMode.None,
- refreshCurrentProblemsEditorMode: RefreshCurrentProblemsDialogMode.None
- }
+ refreshCurrentAlarmsEditorMode: RefreshCurrentAlarmsDialogMode.None,
+ };
}
onDialogClose = () => {
- this.setState({ clearAlarmDialogMode: ClearStuckAlarmsDialogMode.None, stuckAlarms: [] })
- }
+ this.setState({ clearAlarmDialogMode: ClearStuckAlarmsDialogMode.None, stuckAlarms: [] });
+ };
onDialogOpen = () => {
- const stuckAlarms = [...new Set(this.props.currentProblemsProperties.rows.map(item => item.nodeId))];
- this.setState({ clearAlarmDialogMode: ClearStuckAlarmsDialogMode.Show, stuckAlarms: stuckAlarms })
- }
+ 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 'CurrentProblem':
- if (!currentProblemsInitalSorted) {
- currentProblemsInitalSorted = true;
- this.props.currentProblemsActions.onHandleExplicitRequestSort("timestamp", "desc");
+ case 'CurrentAlarms':
+ if (!currentAlarmsInitalSorted) {
+ currentAlarmsInitalSorted = true;
+ this.props.currentAlarmsActions.onHandleExplicitRequestSort('timestamp', 'desc');
} else {
- this.props.reloadCurrentProblems();
+ this.props.reloadCurrentAlarms();
}
break;
case 'AlarmLog':
if (!alarmLogInitialSorted) {
alarmLogInitialSorted = true;
- this.props.alarmLogEntriesActions.onHandleExplicitRequestSort("timestamp", "desc");
+ this.props.alarmLogEntriesActions.onHandleExplicitRequestSort('timestamp', 'desc');
} else {
this.props.reloadAlarmLogEntries();
}
@@ -136,27 +125,27 @@
render(): JSX.Element {
const clearAlarmsAction = {
- icon: Sync, tooltip: 'Clear stuck alarms', ariaLabel:'clear-stuck-alarms', onClick: this.onDialogOpen
+ icon: Sync, tooltip: 'Clear stuck alarms', ariaLabel:'clear-stuck-alarms', onClick: this.onDialogOpen,
};
- const refreshCurrentProblemsAction = {
- icon: Refresh, tooltip: 'Refresh Current Problems List', ariaLabel:'refresh', onClick: () => {
+ const refreshCurrentAlarmsAction = {
+ icon: Refresh, tooltip: 'Refresh Current Alarms List', ariaLabel:'refresh', onClick: () => {
this.setState({
- refreshCurrentProblemsEditorMode: RefreshCurrentProblemsDialogMode.RefreshCurrentProblemsTable
+ refreshCurrentAlarmsEditorMode: RefreshCurrentAlarmsDialogMode.RefreshCurrentAlarmsTable,
});
- }
+ },
};
const refreshAlarmLogAction = {
icon: Refresh, tooltip: 'Refresh Alarm log table', ariaLabel:'refresh', onClick: () => {
this.setState({
- refreshAlarmLogEditorMode: RefreshAlarmLogDialogMode.RefreshAlarmLogTable
+ refreshAlarmLogEditorMode: RefreshAlarmLogDialogMode.RefreshAlarmLogTable,
});
- }
+ },
};
- const areFaultsAvailable = this.props.currentProblemsProperties.rows && this.props.currentProblemsProperties.rows.length > 0
- const customActions = areFaultsAvailable ? [clearAlarmsAction, refreshCurrentProblemsAction] : [refreshCurrentProblemsAction];
+ const areFaultsAvailable = this.props.currentAlarmsProperties.rows && this.props.currentAlarmsProperties.rows.length > 0;
+ const customActions = areFaultsAvailable ? [clearAlarmsAction, refreshCurrentAlarmsAction] : [refreshCurrentAlarmsAction];
const { panelId: activePanelId } = this.props;
@@ -164,26 +153,26 @@
<>
<AppBar enableColorOnDark position="static" >
<Tabs indicatorColor="secondary" textColor="inherit" value={activePanelId} onChange={this.onHandleTabChange} aria-label="fault-tabs">
- <Tab aria-label="current-problem-list-tab" label="Current Problem List" value="CurrentProblem" />
+ <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 === 'CurrentProblem' &&
+ activePanelId === 'CurrentAlarms' &&
<>
- <FaultTable stickyHeader tableId="current-problems-table" idProperty="id" customActionButtons={customActions} columns={[
+ <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.currentProblemsProperties} {...this.props.currentProblemsActions} />
- <RefreshCurrentProblemsDialog
- mode={this.state.refreshCurrentProblemsEditorMode}
- onClose={this.onCloseRefreshCurrentProblemsDialog}
+ { 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}
/>
</>
}
@@ -191,12 +180,12 @@
<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" },
- { property: "timeStamp", title: "Timestamp" },
- { property: "nodeName", title: "Node Name" },
- { property: "counter", title: "Count", width: "100px", type: ColumnType.numeric },
- { property: "objectId", title: "Object Id" },
- { property: "problem", title: "Alarm Type" },
+ { 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 },
]} />
}
@@ -205,13 +194,13 @@
<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" },
+ { 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}
@@ -224,34 +213,34 @@
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("CurrentProblem");
- }else{
+ this.onToggleTabs('CurrentAlarms');
+ } else {
this.onToggleTabs(this.props.panelId);
}
}
- private renderIcon = (props: { rowData: Fault | FaultAlarmNotification }) => {
- return (
- <FontAwesomeIcon icon={faExclamationTriangle} />
- );
- };
+ // private renderIcon = (props: { rowData: Fault | FaultAlarmNotification }) => {
+ // return (
+ // <FontAwesomeIcon icon={faExclamationTriangle} />
+ // );
+ // };
private onCloseRefreshAlarmLogDialog = () => {
this.setState({
- refreshAlarmLogEditorMode: RefreshAlarmLogDialogMode.None
+ refreshAlarmLogEditorMode: RefreshAlarmLogDialogMode.None,
});
- }
- private onCloseRefreshCurrentProblemsDialog = () => {
+ };
+
+ private onCloseRefreshCurrentAlarmsDialog = () => {
this.setState({
- refreshCurrentProblemsEditorMode: RefreshCurrentProblemsDialogMode.None
+ refreshCurrentAlarmsEditorMode: RefreshCurrentAlarmsDialogMode.None,
});
- }
+ };
}
export const FaultApplication = withRouter(connect(mapProps, mapDisp)(FaultApplicationComponent));
diff --git a/sdnr/wt/odlux/apps/faultApp/tsconfig.json b/sdnr/wt/odlux/apps/faultApp/tsconfig.json
index a66b5d8..ca65092 100644
--- a/sdnr/wt/odlux/apps/faultApp/tsconfig.json
+++ b/sdnr/wt/odlux/apps/faultApp/tsconfig.json
@@ -4,7 +4,7 @@
"outDir": "./dist",
"sourceMap": true,
"forceConsistentCasingInFileNames": true,
- "allowSyntheticDefaultImports": false,
+ "allowSyntheticDefaultImports": true,
"allowUnreachableCode": false,
"allowUnusedLabels": false,
"noFallthroughCasesInSwitch": true,
diff --git a/sdnr/wt/odlux/apps/faultApp/webpack.config.js b/sdnr/wt/odlux/apps/faultApp/webpack.config.js
index d34d31c..bc26de1 100644
--- a/sdnr/wt/odlux/apps/faultApp/webpack.config.js
+++ b/sdnr/wt/odlux/apps/faultApp/webpack.config.js
@@ -57,6 +57,16 @@
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: {
@@ -125,27 +135,27 @@
},
proxy: {
"/oauth2/": {
- target: "http://sdnr:8181",
+ target: "http://sdnc-web:8080",
secure: false
},
"/database/": {
- target: "http://sdnr:8181",
+ target: "http://sdnc-web:8080",
secure: false
},
"/restconf/": {
- target: "http://sdnr:8181",
+ target: "http://sdnc-web:8080",
secure: false
},
"/rests/": {
- target: "http://sdnr:8181",
+ target: "http://sdnc-web:8080",
secure: false
},
"/help/": {
- target: "http://sdnr:8181",
+ target: "http://sdnc-web:8080",
secure: false
},
"/websocket": {
- target: "http://sdnr:8181",
+ target: "http://sdnc-web:8080",
ws: true,
changeOrigin: true,
secure: false
diff --git a/sdnr/wt/odlux/apps/helpApp/pom.xml b/sdnr/wt/odlux/apps/helpApp/pom.xml
index 9da0309..07ac091 100644
--- a/sdnr/wt/odlux/apps/helpApp/pom.xml
+++ b/sdnr/wt/odlux/apps/helpApp/pom.xml
@@ -19,6 +19,7 @@
~ ============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>
@@ -139,7 +140,7 @@
<!-- optional: default phase is "generate-resources" -->
<phase>initialize</phase>
<configuration>
- <nodeVersion>v12.13.0</nodeVersion>
+ <nodeVersion>v12.22.0</nodeVersion>
<yarnVersion>v1.22.10</yarnVersion>
</configuration>
</execution>
diff --git a/sdnr/wt/odlux/apps/helpApp/src/assets/icons/helpAppIcon.svg b/sdnr/wt/odlux/apps/helpApp/src/assets/icons/helpAppIcon.svg
new file mode 100644
index 0000000..298eaa1
--- /dev/null
+++ b/sdnr/wt/odlux/apps/helpApp/src/assets/icons/helpAppIcon.svg
@@ -0,0 +1,27 @@
+<!-- highstreet technologies GmbH colour scheme
+ Grey #565656
+ LBlue #36A9E1
+ DBlue #246DA2
+ Green #003F2C / #006C4B
+ Yellw #C8D400
+ Red #D81036
+-->
+
+<svg version="1.0" xmlns="http://www.w3.org/2000/svg" viewBox="310 250 400 400">
+
+<g transform="translate(0,1024) scale(0.1,-0.1)">
+
+<path fill="#565656" d="M4926 7634 c-126 -17 -209 -38 -318 -79 -79 -31 -195 -89 -208 -104
+-10 -12 -69 -51 -77 -51 -4 0 -42 -28 -83 -63 -227 -190 -375 -475 -375 -722
+0 -81 3 -95 30 -143 111 -201 365 -252 514 -103 46 46 88 124 121 226 28 87
+109 255 153 315 67 95 172 168 275 192 86 20 268 21 346 2 113 -28 152 -50
+240 -137 64 -63 88 -95 104 -137 49 -125 52 -225 12 -332 -38 -102 -132 -209
+-360 -409 -153 -134 -329 -309 -375 -374 -97 -136 -148 -274 -166 -448 -19
+-192 12 -305 104 -379 64 -50 141 -72 228 -65 82 7 125 24 177 71 49 45 73
+100 105 241 59 258 63 263 528 687 218 198 295 284 374 419 134 230 138 543 9
+803 -101 202 -252 349 -474 461 -246 124 -573 172 -884 129z"/>
+
+<path fill="#36A9E1" d="M 5098 4587 C 4582 4587 4582 3845 5098 3845 C 5614 3847 5614 4585 5098 4587 Z"/>
+
+</g>
+</svg>
diff --git a/sdnr/wt/odlux/apps/helpApp/src/components/helpStatus.tsx b/sdnr/wt/odlux/apps/helpApp/src/components/helpStatus.tsx
index fd4cd3f..985b404 100644
--- a/sdnr/wt/odlux/apps/helpApp/src/components/helpStatus.tsx
+++ b/sdnr/wt/odlux/apps/helpApp/src/components/helpStatus.tsx
@@ -15,7 +15,8 @@
* the License.
* ============LICENSE_END==========================================================================
*/
-import * as React from 'react';
+import React from 'react';
+import { withRouter, RouteComponentProps } from 'react-router';
import { Theme } from '@mui/material/styles';
import { WithStyles } from '@mui/styles';
@@ -23,13 +24,12 @@
import createStyles from '@mui/styles/createStyles';
import { faExclamationTriangle } from '@fortawesome/free-solid-svg-icons'; // select app icon
-import connect, { Connect } from '../../../../framework/src/flux/connect';
-import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
-
import Typography from '@mui/material/Typography';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faQuestionCircle } from '@fortawesome/free-solid-svg-icons';
-import { withRouter, RouteComponentProps } from 'react-router';
+
+import { connect, Connect } from '../../../../framework/src/flux/connect';
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
const styles = (theme: Theme) => createStyles({
icon: {
diff --git a/sdnr/wt/odlux/apps/helpApp/src/handlers/helpAppRootHandler.ts b/sdnr/wt/odlux/apps/helpApp/src/handlers/helpAppRootHandler.ts
index cc6a984..29e0795 100644
--- a/sdnr/wt/odlux/apps/helpApp/src/handlers/helpAppRootHandler.ts
+++ b/sdnr/wt/odlux/apps/helpApp/src/handlers/helpAppRootHandler.ts
@@ -18,9 +18,10 @@
// main state handler
import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
-import { TocTreeNode } from 'models/tocNode';
import { IActionHandler } from '../../../../framework/src/flux/action';
+
import { LoadTocAction, TocLoadedAction, LoadDocumentAction, DocumentLoadedAction } from '../actions/helpActions';
+import { TocTreeNode } from '../models/tocNode';
export interface IHelpAppStoreState {
busy: boolean;
diff --git a/sdnr/wt/odlux/apps/helpApp/src/plugin.tsx b/sdnr/wt/odlux/apps/helpApp/src/plugin.tsx
index 50a264b..5d860e5 100644
--- a/sdnr/wt/odlux/apps/helpApp/src/plugin.tsx
+++ b/sdnr/wt/odlux/apps/helpApp/src/plugin.tsx
@@ -17,14 +17,12 @@
*/
// app configuration and main entry point for the app
-import * as React from "react";
+import React from "react";
import { withRouter, RouteComponentProps, Route, Switch, Redirect } from 'react-router-dom';
-import { faFirstAid } from '@fortawesome/free-solid-svg-icons'; // select app icon
-
import applicationManager from '../../../framework/src/services/applicationManager';
import { IApplicationStoreState } from "../../../framework/src/store/applicationStore";
-import connect, { Connect, IDispatcher } from '../../../framework/src/flux/connect';
+import { connect, Connect, IDispatcher } from '../../../framework/src/flux/connect';
import { requestTocAsyncAction, requestDocumentAsyncActionCreator } from "./actions/helpActions";
import { helpAppRootHandler } from './handlers/helpAppRootHandler';
@@ -35,11 +33,13 @@
import '!style-loader!css-loader!highlight.js/styles/default.css';
import HelpTocApp from "./views/helpTocApp";
+const appIcon = require('./assets/icons/helpAppIcon.svg'); // select app icon
+
const mapProps = (state: IApplicationStoreState) => ({
});
-const mapDisp = (dispatcher: IDispatcher) => ({
+const mapDispatch = (dispatcher: IDispatcher) => ({
requestDocument: (path: string) => {
dispatcher.dispatch(requestDocumentAsyncActionCreator(path));
}
@@ -47,7 +47,7 @@
let currentHelpPath: string | undefined = undefined;
-const HelpApplicationRouteAdapter = connect(mapProps, mapDisp)((props: RouteComponentProps<{ '0'?: string }> & Connect<typeof mapProps, typeof mapDisp>) => {
+const HelpApplicationRouteAdapter = connect(mapProps, mapDispatch)((props: RouteComponentProps<{ '0'?: string }> & Connect<typeof mapProps, typeof mapDispatch>) => {
if (currentHelpPath !== props.match.params["0"]) {
// route parameter has changed
@@ -76,7 +76,7 @@
export async function register() {
const applicationApi = applicationManager.registerApplication({
name: "help",
- icon: faFirstAid,
+ icon: appIcon,
rootComponent: App,
rootActionHandler: helpAppRootHandler,
statusBarElement: HelpStatus,
@@ -84,7 +84,7 @@
//subMenuEntry: SubMenuEntry
});
- // start the initial toc request after the application store is initalized
+ // start the initial toc request after the application store is initialized
const store = await applicationApi.applicationStoreInitialized;
store.dispatch(requestTocAsyncAction);
diff --git a/sdnr/wt/odlux/apps/helpApp/src/views/helpApplication.tsx b/sdnr/wt/odlux/apps/helpApp/src/views/helpApplication.tsx
index eab44b4..5940517 100644
--- a/sdnr/wt/odlux/apps/helpApp/src/views/helpApplication.tsx
+++ b/sdnr/wt/odlux/apps/helpApp/src/views/helpApplication.tsx
@@ -15,13 +15,13 @@
* the License.
* ============LICENSE_END==========================================================================
*/
-import * as React from 'react';
+import React from 'react';
import * as marked from 'marked';
import { resolvePath } from '../utilities/path';
import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
-import connect, { Connect } from '../../../../framework/src/flux/connect';
+import { connect, Connect } from '../../../../framework/src/flux/connect';
import { Markdown } from "../components/markdown";
diff --git a/sdnr/wt/odlux/apps/helpApp/src/views/helpTocApp.tsx b/sdnr/wt/odlux/apps/helpApp/src/views/helpTocApp.tsx
index e1de4d0..6a6a891 100644
--- a/sdnr/wt/odlux/apps/helpApp/src/views/helpTocApp.tsx
+++ b/sdnr/wt/odlux/apps/helpApp/src/views/helpTocApp.tsx
@@ -16,10 +16,10 @@
* ============LICENSE_END==========================================================================
*/
-import connect, { Connect, IDispatcher } from "../../../../framework/src/flux/connect";
+import React from 'react'
+import {connect, Connect, IDispatcher } from "../../../../framework/src/flux/connect";
import { NavigateToApplication } from "../../../../framework/src/actions/navigationActions";
-import * as React from 'react'
import { FunctionComponent } from "react";
import { IApplicationStoreState } from "../../../../framework/src/store/applicationStore";
import TocEntry from "../components/tocEntry";
diff --git a/sdnr/wt/odlux/apps/helpApp/tsconfig.json b/sdnr/wt/odlux/apps/helpApp/tsconfig.json
index a66b5d8..ca65092 100644
--- a/sdnr/wt/odlux/apps/helpApp/tsconfig.json
+++ b/sdnr/wt/odlux/apps/helpApp/tsconfig.json
@@ -4,7 +4,7 @@
"outDir": "./dist",
"sourceMap": true,
"forceConsistentCasingInFileNames": true,
- "allowSyntheticDefaultImports": false,
+ "allowSyntheticDefaultImports": true,
"allowUnreachableCode": false,
"allowUnusedLabels": false,
"noFallthroughCasesInSwitch": true,
diff --git a/sdnr/wt/odlux/apps/helpApp/webpack.config.js b/sdnr/wt/odlux/apps/helpApp/webpack.config.js
index b069c2a..a48f7b9 100644
--- a/sdnr/wt/odlux/apps/helpApp/webpack.config.js
+++ b/sdnr/wt/odlux/apps/helpApp/webpack.config.js
@@ -74,6 +74,16 @@
plugins: () => [autoprefixer]
}
}]
+ }, {
+ //don't minify images
+ test: /\.(png|gif|jpg|svg)$/,
+ use: [{
+ loader: 'url-loader',
+ options: {
+ limit: 10,
+ name: './images/[name].[ext]'
+ }
+ }]
}]
},
diff --git a/sdnr/wt/odlux/apps/inventoryApp/pom.xml b/sdnr/wt/odlux/apps/inventoryApp/pom.xml
index e39e267..c6ec595c 100644
--- a/sdnr/wt/odlux/apps/inventoryApp/pom.xml
+++ b/sdnr/wt/odlux/apps/inventoryApp/pom.xml
@@ -19,6 +19,7 @@
~ ============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>
@@ -139,7 +140,7 @@
<!-- optional: default phase is "generate-resources" -->
<phase>initialize</phase>
<configuration>
- <nodeVersion>v12.13.0</nodeVersion>
+ <nodeVersion>v12.22.0</nodeVersion>
<yarnVersion>v1.22.10</yarnVersion>
</configuration>
</execution>
diff --git a/sdnr/wt/odlux/apps/inventoryApp/src/actions/inventoryDeviceListActions.ts b/sdnr/wt/odlux/apps/inventoryApp/src/actions/inventoryDeviceListActions.ts
new file mode 100644
index 0000000..710959a
--- /dev/null
+++ b/sdnr/wt/odlux/apps/inventoryApp/src/actions/inventoryDeviceListActions.ts
@@ -0,0 +1,59 @@
+/**
+ * ============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 { Dispatch } from '../../../../framework/src/flux/store';
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+
+import { InventoryDeviceListType } from '../models/inventoryDeviceListType';
+import { inventoryService } from '../services/inventoryService';
+
+/**
+ * Represents the base action.
+ */
+export class BaseAction extends Action { }
+
+/**
+ * Represents an action causing the store to load all nodes.
+ */
+export class LoadAllInventoryDeviceListAction extends BaseAction { }
+
+/**
+ * Represents an action causing the store to update all nodes.
+ */
+export class AllInventoryDeviceListLoadedAction extends BaseAction {
+ /**
+ * Initialize this instance.
+ *
+ * @param inventoryDeviceList All the distinct nodes from the Inventory database.
+ */
+ constructor(public inventoryDeviceList: InventoryDeviceListType[] | null, public error?: string) {
+ super();
+ }
+}
+
+/**
+ * Represents an asynchronous thunk action to load all nodes.
+ */
+export const loadAllInventoryDeviceListAsync = async (dispatch: Dispatch) => {
+ dispatch(new LoadAllInventoryDeviceListAction());
+ const inventoryDeviceList: InventoryDeviceListType[] = (await inventoryService.getInventoryDeviceList().then(ne =>
+ (ne))) || [];
+ return inventoryDeviceList && dispatch(new AllInventoryDeviceListLoadedAction(inventoryDeviceList));
+};
+
diff --git a/sdnr/wt/odlux/apps/inventoryApp/src/actions/inventoryTreeActions.ts b/sdnr/wt/odlux/apps/inventoryApp/src/actions/inventoryTreeActions.ts
index c09b669..2c6a0ed 100644
--- a/sdnr/wt/odlux/apps/inventoryApp/src/actions/inventoryTreeActions.ts
+++ b/sdnr/wt/odlux/apps/inventoryApp/src/actions/inventoryTreeActions.ts
@@ -16,14 +16,13 @@
* ============LICENSE_END==========================================================================
*/
-import { Action } from '../../../../framework/src/flux/action';
-import { Dispatch } from '../../../../framework/src/flux/store';
-import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
-
-import { InventoryType, InventoryTreeNode, TreeDemoItem } from '../models/inventory';
-import { inventoryService } from '../services/inventoryService';
import { AddErrorInfoAction } from '../../../../framework/src/actions/errorActions';
import { NavigateToApplication } from '../../../../framework/src/actions/navigationActions';
+import { Action } from '../../../../framework/src/flux/action';
+import { Dispatch } from '../../../../framework/src/flux/store';
+
+import { InventoryTreeNode, InventoryType, TreeDemoItem } from '../models/inventory';
+import { inventoryService } from '../services/inventoryService';
/**
* Represents the base action.
@@ -38,7 +37,7 @@
}
export class SetSearchTextAction extends BaseAction {
- constructor(public searchTerm: string = "") {
+ constructor(public searchTerm: string = '') {
super();
}
@@ -65,40 +64,38 @@
}
}
-export const setSearchTermAction = (searchTerm: string) => (dispatch: Dispatch, getState: () => IApplicationStoreState) =>{
+export const setSearchTermAction = (searchTerm: string) => (dispatch: Dispatch) =>{
dispatch(new SetSearchTextAction(searchTerm));
-}
+};
-export const updateInventoryTreeAsyncAction = (mountId: string, searchTerm?: string) => async (dispatch: Dispatch, getState: () => IApplicationStoreState) => {
+export const updateInventoryTreeAsyncAction = (mountId: string, searchTerm?: string) => async (dispatch: Dispatch) => {
dispatch(new SetBusyAction(true));
dispatch(new SetSearchTextAction(searchTerm));
try {
const result = await inventoryService.getInventoryTree(mountId, searchTerm);
if (!result) {
- dispatch(new AddErrorInfoAction({ title: "Error", message: `Could not load inventory tree for [${mountId}]. Please check you connection to the server and try later.` }));
- dispatch(new NavigateToApplication("inventory"));
+ dispatch(new AddErrorInfoAction({ title: 'Error', message: `Could not load inventory tree for [${mountId}]. Please check you connection to the server and try later.` }));
+ dispatch(new NavigateToApplication('inventory'));
} else {
dispatch(new UpdateInventoryTreeAction(result));
}
} catch (err) {
- throw new Error("Could not load inventory tree from server.");
- }
- finally {
+ throw new Error('Could not load inventory tree from server.');
+ } finally {
dispatch(new SetBusyAction(false));
}
};
-export const selectInventoryNodeAsyncAction = (nodeId: string) => async (dispatch: Dispatch, getState: () => IApplicationStoreState) => {
+export const selectInventoryNodeAsyncAction = (nodeId: string) => async (dispatch: Dispatch) => {
dispatch(new SetBusyAction(true));
try {
const result = await inventoryService.getInventoryEntry(nodeId);
- if (!result) throw new Error("Could not load inventory tree from server.");
+ if (!result) throw new Error('Could not load inventory tree from server.');
dispatch(new UpdateSelectedNodeAction(result));
} catch (err) {
- throw new Error("Could not load inventory tree from server.");
- }
- finally {
+ throw new Error('Could not load inventory tree from server.');
+ } finally {
dispatch(new SetBusyAction(false));
}
};
diff --git a/sdnr/wt/odlux/apps/inventoryApp/src/actions/panelActions.ts b/sdnr/wt/odlux/apps/inventoryApp/src/actions/panelActions.ts
index 10fde8c..d666082 100644
--- a/sdnr/wt/odlux/apps/inventoryApp/src/actions/panelActions.ts
+++ b/sdnr/wt/odlux/apps/inventoryApp/src/actions/panelActions.ts
@@ -16,16 +16,16 @@
* ============LICENSE_END==========================================================================
*/
-import { Action } from "../../../../framework/src/flux/action";
-import { PanelId } from "models/panelId";
+import { Action } from '../../../../framework/src/flux/action';
+import { PanelId } from '../models/panelId';
export class SetPanelAction extends Action {
- constructor(public panelId: PanelId) {
- super();
- }
+ constructor(public panelId: PanelId) {
+ super();
}
+}
export const setPanelAction = (panelId: PanelId) => {
- return new SetPanelAction(panelId);
- }
\ No newline at end of file
+ return new SetPanelAction(panelId);
+};
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/inventoryApp/src/assets/icons/inventoryAppIcon.svg b/sdnr/wt/odlux/apps/inventoryApp/src/assets/icons/inventoryAppIcon.svg
new file mode 100644
index 0000000..507a835
--- /dev/null
+++ b/sdnr/wt/odlux/apps/inventoryApp/src/assets/icons/inventoryAppIcon.svg
@@ -0,0 +1,23 @@
+<!-- highstreet technologies GmbH colour scheme
+ Grey #565656
+ LBlue #36A9E1
+ DBlue #246DA2
+ Green #003F2C / #006C4B
+ Yellw #C8D400
+ Red #D81036
+-->
+
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="-224 -202 882 882">
+
+<path fill="#565656" d="M 576 544 H -64 V -160 C -64 -177.673 -49.673 -192 -32 -192 H 544 C 561.673 -192 576 -177.673 576 -160 V 544 Z "/>
+
+<path fill="#ffffff" d="M 480 0 H 32 C 14.327 0 0 -14.327 0 -32 V -96 C 0 -113.673 14.327 -128 32 -128 H 480 C 497.673 -128 512 -113.673 512 -96 V -32 C 512 -14.327 497.673 0 480 0 Z M 432 -88 C 418.745 -88 408 -77.255 408 -64 S 418.745 -40 432 -40 S 456 -50.745 456 -64 S 445.255 -88 432 -88 Z M 368 -88 C 354.745 -88 344 -77.255 344 -64 S 354.745 -40 368 -40 S 392 -50.745 392 -64 S 381.255 -88 368 -88 Z "/>
+
+<path fill="#ffffff" d="M 480 160 H 32 C 14.327 160 0 145.673 0 128 V 64 C 0 46.327 14.327 32 32 32 H 480 C 497.673 32 512 46.327 512 64 V 128 C 512 145.673 497.673 160 480 160 Z M 432 72 C 418.745 72 408 82.745 408 96 S 418.745 120 432 120 S 456 109.255 456 96 S 445.255 72 432 72 Z M 368 72 C 354.745 72 344 82.745 344 96 S 354.745 120 368 120 S 392 109.255 392 96 S 381.255 72 368 72 Z "/>
+
+<path fill="#ffffff" d="M 480 320 H 32 C 14.327 320 0 305.673 0 288 V 224 C 0 206.327 14.327 192 32 192 H 480 C 497.673 192 512 206.327 512 224 V 288 C 512 305.673 497.673 320 480 320 Z M 432 232 C 418.745 232 408 242.745 408 256 S 418.745 280 432 280 S 456 269.255 456 256 S 445.255 232 432 232 Z M 368 232 C 354.745 232 344 242.745 344 256 S 354.745 280 368 280 S 392 269.255 392 256 S 381.255 232 368 232 Z "/>
+
+<path fill="#ffffff" d="M 480 480 H 32 C 14.327 480 0 465.673 0 448 V 384 C 0 366.327 14.327 352 32 352 H 480 C 497.673 352 512 366.327 512 384 V 448 C 512 465.673 497.673 480 480 480 Z M 432 392 C 418.745 392 408 402.745 408 416 S 418.745 440 432 440 S 456 429.255 456 416 S 445.255 392 432 392 Z M 368 392 C 354.745 392 344 402.745 344 416 S 354.745 440 368 440 S 392 429.255 392 416 S 381.255 392 368 392 Z"/>
+
+<path fill="#C8D400" d="M 480 670 H -96 C -155 670 -190 631 -192 574 H 576 C 575 622 543 670 480 670 Z"/>
+</svg>
diff --git a/sdnr/wt/odlux/apps/inventoryApp/src/components/refreshInventoryDialog.tsx b/sdnr/wt/odlux/apps/inventoryApp/src/components/refreshInventoryDialog.tsx
index 04658a3..0276222 100644
--- a/sdnr/wt/odlux/apps/inventoryApp/src/components/refreshInventoryDialog.tsx
+++ b/sdnr/wt/odlux/apps/inventoryApp/src/components/refreshInventoryDialog.tsx
@@ -24,78 +24,74 @@
import DialogContentText from '@mui/material/DialogContentText';
import DialogTitle from '@mui/material/DialogTitle';
+import { connect, Connect, IDispatcher } from '../../../../framework/src/flux/connect';
import { inventoryElementsReloadAction } from '../handlers/inventoryElementsHandler';
-import { IDispatcher, connect, Connect } from '../../../../framework/src/flux/connect';
import { InventoryType } from '../models/inventory';
export enum RefreshInventoryDialogMode {
- None = "none",
- RefreshInventoryTable = "RefreshInventoryTable",
+ None = 'none',
+ RefreshInventoryTable = 'RefreshInventoryTable',
}
const mapDispatch = (dispatcher: IDispatcher) => ({
- refreshInventory: () => dispatcher.dispatch(inventoryElementsReloadAction)
+ refreshInventory: () => dispatcher.dispatch(inventoryElementsReloadAction),
});
type DialogSettings = {
- dialogTitle: string,
- dialogDescription: string,
- applyButtonText: string,
- cancelButtonText: string,
- enableMountIdEditor: boolean,
- enableUsernameEditor: boolean,
- enableExtendedEditor: boolean,
-}
+ dialogTitle: string;
+ dialogDescription: string;
+ applyButtonText: string;
+ cancelButtonText: string;
+ enableMountIdEditor: boolean;
+ enableUsernameEditor: boolean;
+ enableExtendedEditor: boolean;
+};
const settings: { [key: string]: DialogSettings } = {
[RefreshInventoryDialogMode.None]: {
- dialogTitle: "",
- dialogDescription: "",
- applyButtonText: "",
- cancelButtonText: "",
+ dialogTitle: '',
+ dialogDescription: '',
+ applyButtonText: '',
+ cancelButtonText: '',
enableMountIdEditor: false,
enableUsernameEditor: false,
enableExtendedEditor: false,
},
[RefreshInventoryDialogMode.RefreshInventoryTable]: {
- dialogTitle: "Do you want to refresh the Inventory table?",
- dialogDescription: "",
- applyButtonText: "Yes",
- cancelButtonText: "Cancel",
+ dialogTitle: 'Do you want to refresh the Inventory table?',
+ dialogDescription: '',
+ applyButtonText: 'Yes',
+ cancelButtonText: 'Cancel',
enableMountIdEditor: true,
enableUsernameEditor: true,
enableExtendedEditor: true,
- }
-}
+ },
+};
type RefreshInventoryDialogComponentProps = Connect<undefined, typeof mapDispatch> & {
mode: RefreshInventoryDialogMode;
onClose: () => void;
};
-type RefreshInventoryDialogComponentState = InventoryType & { isNameValid: boolean, isHostSet: boolean };
+type RefreshInventoryDialogComponentState = InventoryType & { isNameValid: boolean; isHostSet: boolean };
class RefreshInventoryDialogComponent extends React.Component<RefreshInventoryDialogComponentProps, RefreshInventoryDialogComponentState> {
- constructor(props: RefreshInventoryDialogComponentProps) {
- super(props);
- }
-
render(): JSX.Element {
const setting = settings[this.props.mode];
return (
<Dialog open={this.props.mode !== RefreshInventoryDialogMode.None}>
- <DialogTitle id="form-dialog-title" aria-label={`${setting.dialogTitle.replace(/ /g, "-").toLowerCase()}-dialog`}>{setting.dialogTitle}</DialogTitle>
+ <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={(event) => {
+ <Button aria-label="dialog-confirm-button" onClick={() => {
this.onRefresh();
}} color="inherit" > {setting.applyButtonText} </Button>
- <Button aria-label="dialog-cancel-button" onClick={(event) => {
+ <Button aria-label="dialog-cancel-button" onClick={() => {
this.onCancel();
}} color="secondary"> {setting.cancelButtonText} </Button>
</DialogActions>
@@ -110,7 +106,7 @@
private onCancel = () => {
this.props.onClose();
- }
+ };
}
export const RefreshInventoryDialog = connect(undefined, mapDispatch)(RefreshInventoryDialogComponent);
diff --git a/sdnr/wt/odlux/apps/inventoryApp/src/fakeData/index.ts b/sdnr/wt/odlux/apps/inventoryApp/src/fakeData/index.ts
index 46827e8..136b908 100644
--- a/sdnr/wt/odlux/apps/inventoryApp/src/fakeData/index.ts
+++ b/sdnr/wt/odlux/apps/inventoryApp/src/fakeData/index.ts
@@ -16,11 +16,10 @@
* ============LICENSE_END==========================================================================
*/
-import { InventoryTreeNode, InventoryType } from "models/inventory";
import { convertPropertyNames, replaceHyphen } from "../../../../framework/src/utilities/yangHelper";
-// Tree mittels tree-level und parent UUID (incl)
-// einzelabfrage mit db-id
+import { InventoryTreeNode, InventoryType } from "../models/inventory";
+
const data = [
{ "manufacturer-identifier": "ONF-Wireless-Transport", "version": "a2.module-newest", "uuid": "a2.module-1.1.1.5", "part-type-id": "3FE25774AA01", "model-identifier": "VAUIAEYAAA", "tree-level": 2, "node-id": "robot_sim_2_equipment", "description": "WS/CORE-MAIN/a2.module#5", "type-name": "a2.module", "serial": "0003548168", "id": "robot_sim_2_equipment/a2.module-1.1.1.5", "parent-uuid": "CARD-1.1.1.0", "contained-holder": ["SUBRACK-1.15.0.0"], "date": "2005-11-09T00:00:00.0Z" },
{ "manufacturer-identifier": "SAN", "version": "234", "uuid": "CARD-1.1.6.0", "part-type-id": "part-number-12", "model-identifier": "model-id-12", "tree-level": 1, "node-id": "robot_sim_2_equipment", "description": "WS/p8.module", "type-name": "p8.module", "serial": "serial-number-124", "id": "robot_sim_2_equipment/CARD-1.1.6.0", "parent-uuid": "SHELF-1.1.0.0", "contained-holder": ["PORT-1.1.6.5", "PORT-1.1.6.8", "PORT-1.1.6.7", "PORT-1.1.6.6"], "date": "2013-11-23T00:00:00.0Z" },
diff --git a/sdnr/wt/odlux/apps/inventoryApp/src/handlers/connectedNetworkElementsHandler.ts b/sdnr/wt/odlux/apps/inventoryApp/src/handlers/connectedNetworkElementsHandler.ts
deleted file mode 100644
index e6138cc..0000000
--- a/sdnr/wt/odlux/apps/inventoryApp/src/handlers/connectedNetworkElementsHandler.ts
+++ /dev/null
@@ -1,36 +0,0 @@
-/**
- * ============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 { NetworkElementConnection } from '../models/networkElementConnection';
-
-export interface IConnectedNetworkElementsState extends IExternalTableState<NetworkElementConnection> { }
-
-// create eleactic search material data fetch handler
-const connectedNetworkElementsSearchHandler = createSearchDataHandler<NetworkElementConnection>('network-element-connection', false, { status: "Connected" });
-
-export const {
- actionHandler: connectedNetworkElementsActionHandler,
- createActions: createConnectedNetworkElementsActions,
- createProperties: createConnectedNetworkElementsProperties,
- reloadAction: connectedNetworkElementsReloadAction,
-
- // set value action, to change a value
-} = createExternal<NetworkElementConnection>(connectedNetworkElementsSearchHandler, appState => appState.inventory.connectedNetworkElements);
diff --git a/sdnr/wt/odlux/apps/inventoryApp/src/handlers/inventoryAppRootHandler.ts b/sdnr/wt/odlux/apps/inventoryApp/src/handlers/inventoryAppRootHandler.ts
index 0e857ff..b1a0c58 100644
--- a/sdnr/wt/odlux/apps/inventoryApp/src/handlers/inventoryAppRootHandler.ts
+++ b/sdnr/wt/odlux/apps/inventoryApp/src/handlers/inventoryAppRootHandler.ts
@@ -18,27 +18,23 @@
// main state handler
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 { IActionHandler } from '../../../../framework/src/flux/action';
-import { IInvenroryTree, inventoryTreeHandler } from './inventoryTreeHandler';
-import { IConnectedNetworkElementsState, connectedNetworkElementsActionHandler } from './connectedNetworkElementsHandler';
import { PanelId } from '../models/panelId';
+import { IInventoryDeviceListState, inventoryDeviceListActionHandler } from './inventoryDeviceListActionHandler';
+import { IInventoryElementsState, inventoryElementsActionHandler } from './inventoryElementsHandler';
+import { IInvenroryTree, inventoryTreeHandler } from './inventoryTreeHandler';
import { currentOpenPanelHandler } from './panelHandler';
-import { inventoryElementsActionHandler, IInventoryElementsState } from './inventoryElementsHandler';
export interface IInventoryAppStateState {
inventoryTree: IInvenroryTree;
- connectedNetworkElements: IConnectedNetworkElementsState; // used for ne selection
currentOpenPanel: PanelId;
inventoryElements: IInventoryElementsState;
+ inventoryDeviceList: IInventoryDeviceListState;
}
-
-
-
declare module '../../../../framework/src/store/applicationStore' {
interface IApplicationStoreState {
inventory: IInventoryAppStateState;
@@ -47,9 +43,9 @@
const actionHandlers = {
inventoryTree: inventoryTreeHandler,
- connectedNetworkElements: connectedNetworkElementsActionHandler,
currentOpenPanel: currentOpenPanelHandler,
- inventoryElements: inventoryElementsActionHandler
+ inventoryElements: inventoryElementsActionHandler,
+ inventoryDeviceList: inventoryDeviceListActionHandler,
};
export const inventoryAppRootHandler = combineActionHandler<IInventoryAppStateState>(actionHandlers);
diff --git a/sdnr/wt/odlux/apps/inventoryApp/src/handlers/inventoryDeviceListActionHandler.ts b/sdnr/wt/odlux/apps/inventoryApp/src/handlers/inventoryDeviceListActionHandler.ts
new file mode 100644
index 0000000..7c06cad
--- /dev/null
+++ b/sdnr/wt/odlux/apps/inventoryApp/src/handlers/inventoryDeviceListActionHandler.ts
@@ -0,0 +1,56 @@
+/**
+ * ============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 { AllInventoryDeviceListLoadedAction, LoadAllInventoryDeviceListAction } from '../actions/inventoryDeviceListActions';
+import { InventoryDeviceListType } from '../models/inventoryDeviceListType';
+
+export interface IInventoryDeviceListState {
+ inventoryDeviceList: InventoryDeviceListType[];
+ busy: boolean;
+}
+
+const inventoryDeviceListListStateInit: IInventoryDeviceListState = {
+ inventoryDeviceList: [],
+ busy: false,
+};
+
+export const inventoryDeviceListActionHandler: IActionHandler<IInventoryDeviceListState> = (state = inventoryDeviceListListStateInit, action) => {
+ if (action instanceof LoadAllInventoryDeviceListAction) {
+
+ state = {
+ ...state,
+ busy: true,
+ };
+
+ } else if (action instanceof AllInventoryDeviceListLoadedAction) {
+ if (!action.error && action.inventoryDeviceList) {
+ state = {
+ ...state,
+ inventoryDeviceList: action.inventoryDeviceList,
+ busy: false,
+ };
+ } else {
+ state = {
+ ...state,
+ busy: false,
+ };
+ }
+ }
+ return state;
+};
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/inventoryApp/src/handlers/inventoryElementsHandler.ts b/sdnr/wt/odlux/apps/inventoryApp/src/handlers/inventoryElementsHandler.ts
index a65319e..7bac8f6 100644
--- a/sdnr/wt/odlux/apps/inventoryApp/src/handlers/inventoryElementsHandler.ts
+++ b/sdnr/wt/odlux/apps/inventoryApp/src/handlers/inventoryElementsHandler.ts
@@ -15,7 +15,7 @@
* the License.
* ============LICENSE_END==========================================================================
*/
-import { createExternal,IExternalTableState } from '../../../../framework/src/components/material-table/utilities';
+import { createExternal, IExternalTableState } from '../../../../framework/src/components/material-table/utilities';
import { createSearchDataHandler } from '../../../../framework/src/utilities/elasticSearch';
import { InventoryType } from '../models/inventory';
@@ -23,7 +23,7 @@
export interface IInventoryElementsState extends IExternalTableState<InventoryType> { }
// create eleactic search material data fetch handler
-const inventoryElementsSearchHandler = createSearchDataHandler<InventoryType>("inventory");
+const inventoryElementsSearchHandler = createSearchDataHandler<InventoryType>('inventory');
export const {
actionHandler: inventoryElementsActionHandler,
diff --git a/sdnr/wt/odlux/apps/inventoryApp/src/handlers/inventoryTreeHandler.ts b/sdnr/wt/odlux/apps/inventoryApp/src/handlers/inventoryTreeHandler.ts
index 9029a67..fe90d98 100644
--- a/sdnr/wt/odlux/apps/inventoryApp/src/handlers/inventoryTreeHandler.ts
+++ b/sdnr/wt/odlux/apps/inventoryApp/src/handlers/inventoryTreeHandler.ts
@@ -16,10 +16,10 @@
* ============LICENSE_END==========================================================================
*/
-import { IActionHandler } from "../../../../framework/src/flux/action";
+import { IActionHandler } from '../../../../framework/src/flux/action';
-import { SetBusyAction, UpdateInventoryTreeAction, UpdateSelectedNodeAction, SetSearchTextAction, UpdateExpandedNodesAction } from "../actions/inventoryTreeActions";
-import { InventoryTreeNode, InventoryType, TreeDemoItem } from "../models/inventory";
+import { SetBusyAction, SetSearchTextAction, UpdateExpandedNodesAction, UpdateInventoryTreeAction, UpdateSelectedNodeAction } from '../actions/inventoryTreeActions';
+import { InventoryTreeNode, InventoryType, TreeDemoItem } from '../models/inventory';
export interface IInvenroryTree {
@@ -33,10 +33,10 @@
const initialState: IInvenroryTree = {
isBusy: false,
rootNodes: [],
- searchTerm: "",
+ searchTerm: '',
selectedNode: undefined,
expandedItems: [],
-}
+};
const getTreeDataFromInvetoryTreeNode = (node: InventoryTreeNode): TreeDemoItem[] => Object.keys(node).reduce<TreeDemoItem[]>((acc, key) => {
@@ -61,8 +61,8 @@
} else if (action instanceof UpdateSelectedNodeAction) {
state = { ...state, selectedNode: action.selectedNode };
} else if (action instanceof UpdateExpandedNodesAction) {
- state = { ...state, expandedItems: action.expandedNodes || []}
+ state = { ...state, expandedItems: action.expandedNodes || [] };
}
return state;
-}
\ No newline at end of file
+};
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/inventoryApp/src/handlers/panelHandler.ts b/sdnr/wt/odlux/apps/inventoryApp/src/handlers/panelHandler.ts
index 7612531..7912d0e 100644
--- a/sdnr/wt/odlux/apps/inventoryApp/src/handlers/panelHandler.ts
+++ b/sdnr/wt/odlux/apps/inventoryApp/src/handlers/panelHandler.ts
@@ -1,11 +1,11 @@
-import { PanelId } from "../models/panelId";
-import { IActionHandler } from "../../../../framework/src/flux/action";
-import { SetPanelAction } from "../actions/panelActions";
+import { IActionHandler } from '../../../../framework/src/flux/action';
+import { SetPanelAction } from '../actions/panelActions';
+import { PanelId } from '../models/panelId';
export const currentOpenPanelHandler: IActionHandler<PanelId> = (state = null, action) => {
- if (action instanceof SetPanelAction) {
- state = action.panelId;
- }
- return state;
- }
\ No newline at end of file
+ if (action instanceof SetPanelAction) {
+ state = action.panelId;
+ }
+ return state;
+};
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/inventoryApp/src/models/inventory.ts b/sdnr/wt/odlux/apps/inventoryApp/src/models/inventory.ts
index a6c9905..a09fd7e 100644
--- a/sdnr/wt/odlux/apps/inventoryApp/src/models/inventory.ts
+++ b/sdnr/wt/odlux/apps/inventoryApp/src/models/inventory.ts
@@ -35,7 +35,7 @@
partTypeId: string;
modelIdentifier: string;
typeName: string;
-}
+};
export type InventoryTreeNode = {
[key: string]: {
@@ -44,7 +44,7 @@
isMatch?: boolean;
ownSeverity?: string;
childrenSeveritySummary?: string;
- }
-}
+ };
+};
export type TreeDemoItem = ExternalTreeItem<string>;
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/maintenanceApp/src/models/maintenenceEntryType.ts b/sdnr/wt/odlux/apps/inventoryApp/src/models/inventoryDeviceListType.ts
similarity index 77%
copy from sdnr/wt/odlux/apps/maintenanceApp/src/models/maintenenceEntryType.ts
copy to sdnr/wt/odlux/apps/inventoryApp/src/models/inventoryDeviceListType.ts
index 989bfbd..ab24114 100644
--- a/sdnr/wt/odlux/apps/maintenanceApp/src/models/maintenenceEntryType.ts
+++ b/sdnr/wt/odlux/apps/inventoryApp/src/models/inventoryDeviceListType.ts
@@ -15,19 +15,11 @@
* the License.
* ============LICENSE_END==========================================================================
*/
-/** Represents the elestic search db type for maintenence enrties */
+/**
+ * Represents all the distinct devices from the inventory history data.
+ */
-export const spoofSymbol = Symbol("Spoof");
-
-/** Represents the type for an maintenence entry. */
-export type MaintenenceEntry = {
- _id: string;
+export type InventoryDeviceListType = {
nodeId: string;
- description?: string,
- end: string,
- start: string
- active: boolean
- [spoofSymbol]?: boolean;
-}
-
+};
diff --git a/sdnr/wt/odlux/apps/inventoryApp/src/models/networkElementConnection.ts b/sdnr/wt/odlux/apps/inventoryApp/src/models/networkElementConnection.ts
index 88f7018..e1ef1ea 100644
--- a/sdnr/wt/odlux/apps/inventoryApp/src/models/networkElementConnection.ts
+++ b/sdnr/wt/odlux/apps/inventoryApp/src/models/networkElementConnection.ts
@@ -24,7 +24,7 @@
username?: string;
password?: string;
isRequired?: boolean;
- status?: "connected" | "mounted" | "unmounted" | "connecting" | "disconnected" | "idle";
+ status?: 'connected' | 'mounted' | 'unmounted' | 'connecting' | 'disconnected' | 'idle';
coreModelCapability?: string;
deviceType?: string;
nodeDetails?: {
@@ -33,5 +33,5 @@
failureReason: string;
capability: string;
}[];
- }
-}
+ };
+};
diff --git a/sdnr/wt/odlux/apps/inventoryApp/src/models/panelId.ts b/sdnr/wt/odlux/apps/inventoryApp/src/models/panelId.ts
index b05c1db..8f8224c 100644
--- a/sdnr/wt/odlux/apps/inventoryApp/src/models/panelId.ts
+++ b/sdnr/wt/odlux/apps/inventoryApp/src/models/panelId.ts
@@ -16,4 +16,4 @@
* ============LICENSE_END==========================================================================
*/
-export type PanelId = null | "InventoryElementsTable" | "TreeviewTable";
\ No newline at end of file
+export type PanelId = null | 'Equipment' | 'TreeView';
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/inventoryApp/src/pluginInventory.tsx b/sdnr/wt/odlux/apps/inventoryApp/src/pluginInventory.tsx
index 50339c0..8198599 100644
--- a/sdnr/wt/odlux/apps/inventoryApp/src/pluginInventory.tsx
+++ b/sdnr/wt/odlux/apps/inventoryApp/src/pluginInventory.tsx
@@ -16,38 +16,33 @@
* ============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 * as React from "react";
-import { withRouter, RouteComponentProps, Route, Switch, Redirect } from 'react-router-dom';
-import { faShoppingBag } from '@fortawesome/free-solid-svg-icons'; // select app icon
+import { connect, Connect, IDispatcher } from '../../../framework/src/flux/connect';
import applicationManager from '../../../framework/src/services/applicationManager';
-import connect, { Connect, IDispatcher } from '../../../framework/src/flux/connect';
-import { IApplicationStoreState } from "../../../framework/src/store/applicationStore";
-
-import { InventoryTreeView } from './views/treeview';
-import Dashboard from './views/dashboard';
-
-import { PanelId } from "./models/panelId";
-import { SetPanelAction } from "./actions/panelActions";
-
+import { IApplicationStoreState } from '../../../framework/src/store/applicationStore';
+import { SetPanelAction } from './actions/panelActions';
import inventoryAppRootHandler from './handlers/inventoryAppRootHandler';
-import { createInventoryElementsActions, createInventoryElementsProperties } from "./handlers/inventoryElementsHandler";
-import { createConnectedNetworkElementsProperties, createConnectedNetworkElementsActions } from "./handlers/connectedNetworkElementsHandler";
+import { createInventoryElementsActions, createInventoryElementsProperties } from './handlers/inventoryElementsHandler';
+import { PanelId } from './models/panelId';
+import Dashboard from './views/dashboard';
+import { InventoryTreeView } from './views/treeview';
+
+const appIcon = require('./assets/icons/inventoryAppIcon.svg'); // select app icon
let currentMountId: string | undefined = undefined;
const mapProps = (state: IApplicationStoreState) => ({
inventoryProperties: createInventoryElementsProperties(state),
panelId: state.inventory.currentOpenPanel,
- connectedNetworkElementsProperties: createConnectedNetworkElementsProperties(state),
});
-const mapDisp = (dispatcher: IDispatcher) => ({
+const mapDispatch = (dispatcher: IDispatcher) => ({
inventoryActions: createInventoryElementsActions(dispatcher.dispatch, true),
- connectedNetworkElementsActions: createConnectedNetworkElementsActions(dispatcher.dispatch, true),
setCurrentPanel: (panelId: PanelId) => dispatcher.dispatch(new SetPanelAction(panelId)),
});
-const InventoryTableApplicationRouteAdapter = connect(mapProps, mapDisp)((props: RouteComponentProps<{ mountId?: string }> & Connect<typeof mapProps, typeof mapDisp>) => {
+const InventoryTableApplicationRouteAdapter = 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;
@@ -56,26 +51,20 @@
if (currentMountId) {
if (props.panelId) {
props.setCurrentPanel(props.panelId);
+ } else {
+ props.setCurrentPanel('Equipment');
}
- else {
- props.setCurrentPanel("InventoryElementsTable");
- }
- props.inventoryActions.onFilterChanged("nodeId", currentMountId);
- props.connectedNetworkElementsActions.onFilterChanged("nodeId", currentMountId);
+ props.inventoryActions.onFilterChanged('nodeId', currentMountId);
if (!props.inventoryProperties.showFilter) {
props.inventoryActions.onToggleFilter(false);
}
- if (!props.connectedNetworkElementsProperties.showFilter) {
- props.connectedNetworkElementsActions.onToggleFilter(false);
- }
props.inventoryActions.onRefresh();
- props.connectedNetworkElementsActions.onRefresh();
}
});
}
return (
<Dashboard />
- )
+ );
});
const App = withRouter((props: RouteComponentProps) => (
@@ -89,11 +78,11 @@
export function register() {
applicationManager.registerApplication({
- name: "inventory",
- icon: faShoppingBag,
+ name: 'inventory',
+ icon: appIcon,
rootActionHandler: inventoryAppRootHandler,
rootComponent: App,
- menuEntry: "Inventory"
+ menuEntry: 'Inventory',
});
}
diff --git a/sdnr/wt/odlux/apps/inventoryApp/src/services/inventoryService.ts b/sdnr/wt/odlux/apps/inventoryApp/src/services/inventoryService.ts
index cb70bf5..4014fcf 100644
--- a/sdnr/wt/odlux/apps/inventoryApp/src/services/inventoryService.ts
+++ b/sdnr/wt/odlux/apps/inventoryApp/src/services/inventoryService.ts
@@ -15,54 +15,76 @@
* the License.
* ============LICENSE_END==========================================================================
*/
+import { Result } from '../../../../framework/src/models/elasticSearch';
import { requestRest } from '../../../../framework/src/services/restService';
-import { convertPropertyNames, replaceHyphen } from '../../../../framework/src/utilities/yangHelper';
import { InventoryTreeNode, InventoryType } from '../models/inventory';
-import { getTree, getElement } from '../fakeData';
+import { InventoryDeviceListType } from '../models/inventoryDeviceListType';
/**
* Represents a web api accessor service for all maintenence entries related actions.
*/
class InventoryService {
- public async getInventoryTree(mountId: string, searchTerm: string = ""): Promise<InventoryTreeNode | null> {
+ public async getInventoryTree(mountId: string, searchTerm: string = ''): Promise<InventoryTreeNode | null> {
//return await getTree(searchTerm);
const path = `/tree/read-inventoryequipment-tree/${mountId}`;
const body = {
- "query": searchTerm
+ 'query': searchTerm,
};
- const inventoryTree = await requestRest<InventoryTreeNode>(path, { method: "POST" , body: JSON.stringify(body)});
+ const inventoryTree = await requestRest<InventoryTreeNode>(path, { method: 'POST', body: JSON.stringify(body) });
return inventoryTree && inventoryTree || null;
}
public async getInventoryEntry(id: string): Promise<InventoryType | undefined> {
- const path = `/rests/operations/data-provider:read-inventory-list`;
+ const path = '/rests/operations/data-provider:read-inventory-list';
const body = {
- "data-provider:input": {
- "filter": [
- { property: "id", filtervalue: id },
+ 'data-provider:input': {
+ 'filter': [
+ { property: 'id', filtervalue: id },
],
- "sortorder": [],
- "pagination": {
- "size": 1,
- "page": 1
- }
- }
+ 'sortorder': [],
+ 'pagination': {
+ 'size': 1,
+ 'page': 1,
+ },
+ },
};
const inventoryTreeElement = await requestRest<{
- "data-provider:output": {
- "pagination": {
- "size": number,
- "page": number,
- "total": number
- },
- "data": InventoryType[]
- }
- }>(path, { method: "POST", body: JSON.stringify(body) });
+ 'data-provider:output': {
+ 'pagination': {
+ 'size': number;
+ 'page': number;
+ 'total': number;
+ };
+ 'data': InventoryType[];
+ };
+ }>(path, { method: 'POST', body: JSON.stringify(body) });
- return inventoryTreeElement && inventoryTreeElement["data-provider:output"] && inventoryTreeElement["data-provider:output"].pagination && inventoryTreeElement["data-provider:output"].pagination.total >= 1 &&
- inventoryTreeElement["data-provider:output"].data && inventoryTreeElement["data-provider:output"].data[0] || undefined;
- // return await getElement(id);
+ return inventoryTreeElement && inventoryTreeElement['data-provider:output'] && inventoryTreeElement['data-provider:output'].pagination && inventoryTreeElement['data-provider:output'].pagination.total >= 1 &&
+ inventoryTreeElement['data-provider:output'].data && inventoryTreeElement['data-provider:output'].data[0] || undefined;
+ // return await getElement(id);
+ }
+
+ /**
+ * Gets all nodes from the inventory device list.
+ */
+ public async getInventoryDeviceList(): Promise<(InventoryDeviceListType)[] | null> {
+ const path = '/rests/operations/data-provider:read-inventory-device-list';
+ const query = {
+ 'data-provider:input': {
+ 'filter': [],
+ 'sortorder': [],
+ 'pagination': {
+ 'size': 20,
+ 'page': 1,
+ },
+ },
+ };
+
+ const result = await requestRest<Result<any>>(path, { method: 'POST', body: JSON.stringify(query) });
+ return result && result['data-provider:output'] && result['data-provider:output'].data && result['data-provider:output'].data.map(ne => ({
+ nodeId: ne,
+ })) || null;
}
}
diff --git a/sdnr/wt/odlux/apps/inventoryApp/src/views/dashboard.tsx b/sdnr/wt/odlux/apps/inventoryApp/src/views/dashboard.tsx
index 284f702..acd2c62 100644
--- a/sdnr/wt/odlux/apps/inventoryApp/src/views/dashboard.tsx
+++ b/sdnr/wt/odlux/apps/inventoryApp/src/views/dashboard.tsx
@@ -16,99 +16,93 @@
* ============LICENSE_END==========================================================================
*/
-import * as React from 'react';
+import React from 'react';
import { RouteComponentProps, withRouter } from 'react-router-dom';
-import connect, { IDispatcher, Connect } from "../../../../framework/src/flux/connect";
-import { IApplicationStoreState } from "../../../../framework/src/store/applicationStore";
-import { MaterialTable, MaterialTableCtorType, ColumnType } from "../../../../framework/src/components/material-table";
-import { AppBar, Tabs, Tab, MenuItem, Typography } from "@mui/material";
import Refresh from '@mui/icons-material/Refresh';
-import { PanelId } from "../models/panelId";
-import { setPanelAction } from "../actions/panelActions";
+import { AppBar, MenuItem, Tab, Tabs, Typography } from '@mui/material';
-
-import { createConnectedNetworkElementsProperties, createConnectedNetworkElementsActions } from "../handlers/connectedNetworkElementsHandler";
-
-import { NetworkElementConnection } from "../models/networkElementConnection";
-
-import { InventoryType } from '../models/inventory';
-
-import { createInventoryElementsProperties, createInventoryElementsActions } from "../handlers/inventoryElementsHandler";
import { NavigateToApplication } from '../../../../framework/src/actions/navigationActions';
+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 { loadAllInventoryDeviceListAsync } from '../actions/inventoryDeviceListActions';
import { updateInventoryTreeAsyncAction } from '../actions/inventoryTreeActions';
+import { setPanelAction } from '../actions/panelActions';
import RefreshInventoryDialog, { RefreshInventoryDialogMode } from '../components/refreshInventoryDialog';
+import { createInventoryElementsActions, createInventoryElementsProperties } from '../handlers/inventoryElementsHandler';
+import { InventoryType } from '../models/inventory';
+import { InventoryDeviceListType } from '../models/inventoryDeviceListType';
+import { PanelId } from '../models/panelId';
const InventoryTable = MaterialTable as MaterialTableCtorType<InventoryType & { _id: string }>;
const mapProps = (state: IApplicationStoreState) => ({
- connectedNetworkElementsProperties: createConnectedNetworkElementsProperties(state),
panelId: state.inventory.currentOpenPanel,
inventoryElementsProperties: createInventoryElementsProperties(state),
- inventoryElements: state.inventory.inventoryElements
+ inventoryElements: state.inventory.inventoryElements,
+ inventoryDeviceList: state.inventory.inventoryDeviceList.inventoryDeviceList,
});
const mapDispatch = (dispatcher: IDispatcher) => ({
- connectedNetworkElementsActions: createConnectedNetworkElementsActions(dispatcher.dispatch),
switchActivePanel: (panelId: PanelId) => {
dispatcher.dispatch(setPanelAction(panelId));
},
inventoryElementsActions: createInventoryElementsActions(dispatcher.dispatch),
navigateToApplication: (applicationName: string, path?: string) => dispatcher.dispatch(new NavigateToApplication(applicationName, path)),
updateInventoryTree: (mountId: string, searchTerm?: string) => dispatcher.dispatch(updateInventoryTreeAsyncAction(mountId, searchTerm)),
+ getAllInventoryDeviceList: async () => {
+ await dispatcher.dispatch(loadAllInventoryDeviceListAsync);
+ },
});
let treeViewInitialSorted = false;
let inventoryInitialSorted = false;
-const ConnectedElementTable = MaterialTable as MaterialTableCtorType<NetworkElementConnection>;
+const InventoryDeviceListTable = MaterialTable as MaterialTableCtorType<InventoryDeviceListType>;
type DashboardComponentProps = RouteComponentProps & Connect<typeof mapProps, typeof mapDispatch>;
type DashboardComponentState = {
- refreshInventoryEditorMode: RefreshInventoryDialogMode
-}
+ refreshInventoryEditorMode: RefreshInventoryDialogMode;
+};
class DashboardSelectorComponent extends React.Component<DashboardComponentProps, DashboardComponentState> {
constructor(props: DashboardComponentProps) {
super(props);
this.state = {
- refreshInventoryEditorMode: RefreshInventoryDialogMode.None
+ refreshInventoryEditorMode: RefreshInventoryDialogMode.None,
};
}
private onHandleTabChange = (event: React.SyntheticEvent, newValue: PanelId) => {
this.onTogglePanel(newValue);
- }
+ };
private onTogglePanel = (panelId: PanelId) => {
const nextActivePanel = panelId;
this.props.switchActivePanel(nextActivePanel);
switch (nextActivePanel) {
- case 'InventoryElementsTable':
+ case 'Equipment':
if (!inventoryInitialSorted) {
- this.props.inventoryElementsActions.onHandleExplicitRequestSort("nodeId", "asc");
+ this.props.inventoryElementsActions.onHandleExplicitRequestSort('nodeId', 'asc');
inventoryInitialSorted = true;
} else {
this.props.inventoryElementsActions.onRefresh();
}
break;
- case 'TreeviewTable':
- if (!treeViewInitialSorted) {
- this.props.connectedNetworkElementsActions.onHandleExplicitRequestSort("nodeId", "asc");
- treeViewInitialSorted = true;
- } else {
- this.props.connectedNetworkElementsActions.onRefresh();
- }
+ case 'TreeView':
+ this.props.getAllInventoryDeviceList();
break;
case null:
// do nothing if all panels are closed
break;
default:
- console.warn("Unknown nextActivePanel [" + nextActivePanel + "] in connectView");
+ console.warn('Unknown nextActivePanel [' + nextActivePanel + '] in connectView');
break;
}
@@ -116,47 +110,47 @@
getContextMenu = (rowData: InventoryType) => {
return [
- <MenuItem aria-label={"inventory-button"} onClick={event => { this.props.updateInventoryTree(rowData.nodeId, rowData.uuid); this.props.navigateToApplication("inventory", rowData.nodeId) }}><Typography>View in Treeview</Typography></MenuItem>,
+ <MenuItem aria-label={'inventory-button'} onClick={() => { this.props.updateInventoryTree(rowData.nodeId, rowData.uuid); this.props.navigateToApplication('inventory', rowData.nodeId); }}><Typography>View in Treeview</Typography></MenuItem>,
];
- }
+ };
render() {
const refreshInventoryAction = {
icon: Refresh, tooltip: 'Refresh Inventory', ariaLabel: 'refresh', onClick: () => {
this.setState({
- refreshInventoryEditorMode: RefreshInventoryDialogMode.RefreshInventoryTable
+ refreshInventoryEditorMode: RefreshInventoryDialogMode.RefreshInventoryTable,
});
- }
+ },
};
const { panelId: activePanelId } = this.props;
return (
<>
<AppBar enableColorOnDark position="static">
<Tabs indicatorColor="secondary" textColor="inherit" value={activePanelId} onChange={this.onHandleTabChange} aria-label="inventory-app-tabs">
- <Tab label="Table View" value="InventoryElementsTable" aria-label="table-tab" />
- <Tab label="Tree view" value="TreeviewTable" aria-label="treeview-tab" />
+ <Tab label="Equipment" value="Equipment" aria-label="equipment-tab" />
+ <Tab label="Tree View" value="TreeView" aria-label="treeview-tab" />
</Tabs>
</AppBar>
{
- activePanelId === "InventoryElementsTable" &&
+ activePanelId === 'Equipment' &&
<>
- <InventoryTable stickyHeader title="Inventory" idProperty="_id" tableId="inventory-table" customActionButtons={[refreshInventoryAction]} columns={[
- { property: "nodeId", title: "Node Name" },
- { property: "manufacturerIdentifier", title: "Manufacturer" },
- { property: "parentUuid", title: "Parent" },
- { property: "uuid", title: "Name" },
- { property: "serial", title: "Serial" },
- { property: "version", title: "Version" },
- { property: "date", title: "Date" },
- { property: "description", title: "Description" },
- { property: "partTypeId", title: "Part Type Id" },
- { property: "modelIdentifier", title: "Model Identifier" },
- { property: "typeName", title: "Type" },
- { property: "treeLevel", title: "Containment Level" },
+ <InventoryTable stickyHeader idProperty="_id" tableId="inventory-table" customActionButtons={[refreshInventoryAction]} columns={[
+ { property: 'nodeId', title: 'Node Name' },
+ { property: 'manufacturerIdentifier', title: 'Manufacturer' },
+ { property: 'parentUuid', title: 'Parent' },
+ { property: 'uuid', title: 'Name' },
+ { property: 'serial', title: 'Serial' },
+ { property: 'version', title: 'Version' },
+ { property: 'date', title: 'Date' },
+ { property: 'description', title: 'Description' },
+ { property: 'partTypeId', title: 'Part Type Id' },
+ { property: 'modelIdentifier', title: 'Model Identifier' },
+ { property: 'typeName', title: 'Type' },
+ { property: 'treeLevel', title: 'Containment Level' },
]} {...this.props.inventoryElementsActions} {...this.props.inventoryElementsProperties}
createContextMenu={rowData => {
@@ -171,22 +165,20 @@
}
{
- activePanelId === "TreeviewTable" &&
-
- <ConnectedElementTable stickyHeader tableId="treeview-networkelement-selection-table"
- onHandleClick={(e, row) => {
- this.props.navigateToApplication("inventory", row.nodeId);
- this.props.updateInventoryTree(row.nodeId, '*');
- }}
- columns={[
- { property: "nodeId", title: "Node Name", type: ColumnType.text },
- { property: "isRequired", title: "Required", type: ColumnType.boolean },
- { property: "host", title: "Host", type: ColumnType.text },
- { property: "port", title: "Port", type: ColumnType.numeric },
- { property: "coreModelCapability", title: "Core Model", type: ColumnType.text },
- { property: "deviceType", title: "Type", type: ColumnType.text },
- ]} idProperty="id" {...this.props.connectedNetworkElementsActions} {...this.props.connectedNetworkElementsProperties} asynchronus >
- </ConnectedElementTable>
+ activePanelId === 'TreeView' &&
+ <>
+ <InventoryDeviceListTable stickyHeader tableId="treeview-networkelement-selection-table"
+ defaultSortColumn={'nodeId'} defaultSortOrder="asc"
+ onHandleClick={(e, row) => {
+ this.props.navigateToApplication('inventory', row.nodeId);
+ this.props.updateInventoryTree(row.nodeId, '*');
+ }}
+ rows={this.props.inventoryDeviceList} asynchronus
+ columns={[
+ { property: 'nodeId', title: 'Node Name', type: ColumnType.text },
+ ]} idProperty="nodeId" >
+ </InventoryDeviceListTable>
+ </>
}
</>
);
@@ -194,15 +186,14 @@
private onCloseRefreshInventoryDialog = () => {
this.setState({
- refreshInventoryEditorMode: RefreshInventoryDialogMode.None
+ refreshInventoryEditorMode: RefreshInventoryDialogMode.None,
});
- }
+ };
+
componentDidMount() {
-
if (this.props.panelId === null) { //set default tab if none is set
- this.onTogglePanel("InventoryElementsTable");
+ this.onTogglePanel('Equipment');
}
-
}
}
diff --git a/sdnr/wt/odlux/apps/inventoryApp/src/views/detail.tsx b/sdnr/wt/odlux/apps/inventoryApp/src/views/detail.tsx
index 2526639..8d47ec3 100644
--- a/sdnr/wt/odlux/apps/inventoryApp/src/views/detail.tsx
+++ b/sdnr/wt/odlux/apps/inventoryApp/src/views/detail.tsx
@@ -15,20 +15,19 @@
* the License.
* ============LICENSE_END==========================================================================
*/
-import * as React from "react";
-import { withRouter, RouteComponentProps } from 'react-router-dom';
+import React from 'react';
+import { RouteComponentProps, withRouter } from 'react-router-dom';
import Button from '@mui/material/Button';
import { Theme } from '@mui/material/styles'; // infra for styling
-
import { WithStyles } from '@mui/styles';
-import withStyles from '@mui/styles/withStyles';
import createStyles from '@mui/styles/createStyles';
+import withStyles from '@mui/styles/withStyles';
const styles = (theme: Theme) => createStyles({
warnButton: {
- backgroundColor: theme.palette.primary.dark
- }
+ backgroundColor: theme.palette.primary.dark,
+ },
});
type DetailProps = RouteComponentProps<{ id: string }> & WithStyles<typeof styles>;
@@ -37,8 +36,8 @@
<div>
<h1>Detail {props.match.params.id}</h1>
<p>This are the information about {props.staticContext}.</p>
- <Button color={"secondary"} variant={"contained"}>Start</Button>
- <Button color="inherit" className={ props.classes.warnButton } variant={"contained"}>Stop</Button>
+ <Button color={'secondary'} variant={'contained'}>Start</Button>
+ <Button color="inherit" className={ props.classes.warnButton } variant={'contained'}>Stop</Button>
</div>
)));
diff --git a/sdnr/wt/odlux/apps/inventoryApp/src/views/treeview.tsx b/sdnr/wt/odlux/apps/inventoryApp/src/views/treeview.tsx
index b0e962d..954c074 100644
--- a/sdnr/wt/odlux/apps/inventoryApp/src/views/treeview.tsx
+++ b/sdnr/wt/odlux/apps/inventoryApp/src/views/treeview.tsx
@@ -15,42 +15,38 @@
* the License.
* ============LICENSE_END==========================================================================
*/
-import * as React from "react";
-import { Theme } from '@mui/material/styles';
-
-import { WithStyles } from '@mui/styles';
-import withStyles from '@mui/styles/withStyles';
-import createStyles from '@mui/styles/createStyles';
-
-import { renderObject } from '../../../../framework/src/components/objectDump';
-import { Connect, connect, IDispatcher } from '../../../../framework/src/flux/connect';
-import { TreeView, TreeViewCtorType, SearchMode } from '../../../../framework/src/components/material-ui/treeView';
-
-import { IApplicationStoreState } from "../../../../framework/src/store/applicationStore";
+import React from 'react';
import Breadcrumbs from '@mui/material/Breadcrumbs';
import Link from '@mui/material/Link';
-
-import { updateInventoryTreeAsyncAction, selectInventoryNodeAsyncAction, UpdateSelectedNodeAction, UpdateExpandedNodesAction, setSearchTermAction } from "../actions/inventoryTreeActions";
-import { TreeDemoItem } from "../models/inventory";
-
+import { Theme } from '@mui/material/styles';
+import { WithStyles } from '@mui/styles';
+import createStyles from '@mui/styles/createStyles';
+import withStyles from '@mui/styles/withStyles';
import { RouteComponentProps } from 'react-router-dom';
+import { SearchMode, TreeView, TreeViewCtorType } from '../../../../framework/src/components/material-ui/treeView';
+import { renderObject } from '../../../../framework/src/components/objectDump';
+import { Connect, connect, IDispatcher } from '../../../../framework/src/flux/connect';
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+
+import { selectInventoryNodeAsyncAction, setSearchTermAction, UpdateExpandedNodesAction, updateInventoryTreeAsyncAction, UpdateSelectedNodeAction } from '../actions/inventoryTreeActions';
+import { TreeDemoItem } from '../models/inventory';
const styles = (theme: Theme) => createStyles({
root: {
- flex: "1 0 0%",
- display: "flex",
- flexDirection: "row",
+ flex: '1 0 0%',
+ display: 'flex',
+ flexDirection: 'row',
},
tree: {
- flex: "1 0 0%",
- minWidth: "250px",
- padding: `0px ${theme.spacing(1)}`
+ wordWrap: 'break-word',
+ minWidth: '250px',
+ padding: `0px ${theme.spacing(1)}`,
},
details: {
- flex: "5 0 0%",
- padding: `0px ${theme.spacing(1)}`
- }
+ flex: '5 0 0%',
+ padding: `0px ${theme.spacing(1)}`,
+ },
});
const mapProps = (state: IApplicationStoreState) => ({
@@ -68,19 +64,19 @@
setSearchTerm: (searchTerm: string) => dispatcher.dispatch(setSearchTermAction(searchTerm)),
});
-const propsChache = Symbol("PropsCache");
+const propsChache = Symbol('PropsCache');
const InventoryTree = TreeView as any as TreeViewCtorType<string>;
-type TreeviewComponentProps = RouteComponentProps<{ mountId: string }> & WithStyles<typeof styles> & Connect<typeof mapProps, typeof mapDispatch>
+type TreeviewComponentProps = RouteComponentProps<{ mountId: string }> & WithStyles<typeof styles> & Connect<typeof mapProps, typeof mapDispatch>;
type TreeviewComponentState = {
[propsChache]: {
rootNodes?: TreeDemoItem[];
};
rootNodes: TreeDemoItem[];
-}
+};
class DashboardComponent extends React.Component<TreeviewComponentProps, TreeviewComponentState> {
@@ -96,14 +92,15 @@
static getDerivedStateFromProps(props: TreeviewComponentProps, state: TreeviewComponentState) {
if (state[propsChache].rootNodes != props.rootNodes) {
- state = { ...state, rootNodes: props.rootNodes }
+ // eslint-disable-next-line no-param-reassign
+ state = { ...state, rootNodes: props.rootNodes };
}
return state;
}
render() {
const { classes, updateInventoryTree, updateExpendedNodes, expendedItems, selectedNode, selectTreeNode, searchTerm, match: { params: { mountId } } } = this.props;
- const scrollbar = { overflow: "auto", paddingRight: "20px" }
+ const scrollbar = { overflow: 'auto', paddingRight: '20px' };
let filteredDashboardPath = `/inventory/dashboard/${this.props.match.params.mountId}`;
let basePath = `/inventory/${this.props.match.params.mountId}`;
@@ -128,6 +125,7 @@
<br />
<div style={scrollbar} className={classes.root}>
<InventoryTree className={classes.tree} items={this.state.rootNodes} enableSearchBar initialSearchTerm={searchTerm} searchMode={SearchMode.OnEnter} searchTerm={searchTerm}
+ // eslint-disable-next-line @typescript-eslint/no-shadow
onSearch={(searchTerm) => updateInventoryTree(mountId, searchTerm)} expandedItems={expendedItems} onFolderClick={(item) => {
const indexOfItemToToggle = expendedItems.indexOf(item);
if (indexOfItemToToggle === -1) {
@@ -141,20 +139,15 @@
}}
onItemClick={(elm) => selectTreeNode(elm.value)} />
<div className={classes.details}>{
- selectedNode && renderObject(selectedNode, "tree-view") || null
+ selectedNode && renderObject(selectedNode, 'tree-view') || null
}</div>
</div>
</div>
);
}
- componentDidMount() {
- const { updateInventoryTree, searchTerm, match: { params: { mountId } } } = this.props;
- updateInventoryTree(mountId, searchTerm);
- }
-
componentWillUnmount() {
- this.props.setSearchTerm("*");
+ this.props.setSearchTerm('*');
}
}
diff --git a/sdnr/wt/odlux/apps/inventoryApp/tsconfig.json b/sdnr/wt/odlux/apps/inventoryApp/tsconfig.json
index a66b5d8..ca65092 100644
--- a/sdnr/wt/odlux/apps/inventoryApp/tsconfig.json
+++ b/sdnr/wt/odlux/apps/inventoryApp/tsconfig.json
@@ -4,7 +4,7 @@
"outDir": "./dist",
"sourceMap": true,
"forceConsistentCasingInFileNames": true,
- "allowSyntheticDefaultImports": false,
+ "allowSyntheticDefaultImports": true,
"allowUnreachableCode": false,
"allowUnusedLabels": false,
"noFallthroughCasesInSwitch": true,
diff --git a/sdnr/wt/odlux/apps/inventoryApp/webpack.config.js b/sdnr/wt/odlux/apps/inventoryApp/webpack.config.js
index 403cc53..6a78056 100644
--- a/sdnr/wt/odlux/apps/inventoryApp/webpack.config.js
+++ b/sdnr/wt/odlux/apps/inventoryApp/webpack.config.js
@@ -57,6 +57,16 @@
use: [{
loader: "babel-loader"
}]
+ },{
+ //don't minify images
+ test: /\.(png|gif|jpg|svg)$/,
+ use: [{
+ loader: 'url-loader',
+ options: {
+ limit: 10,
+ name: './images/[name].[ext]'
+ }
+ }]
}]
},
@@ -127,37 +137,37 @@
},
proxy: {
"/oauth2/": {
- target: "http://localhost:8181",
+ target: "http://sdnc-web:8080",
secure: false
},
"/database/": {
- target: "http://localhost:8181",
+ target: "http://sdnc-web:8080",
secure: false
},
"/restconf/": {
- target: "http://localhost:8181",
+ target: "http://sdnc-web:8080",
secure: false
},
"/rests/": {
- target: "http://localhost:8181",
+ target: "http://sdnc-web:8080",
secure: false
},
"/help/": {
- target: "http://localhost:8181",
+ target: "http://sdnc-web:8080",
secure: false
},
"/tree/": {
- target: "http://localhost:8181",
+ target: "http://sdnc-web:8080",
secure: false
},
"/websocket": {
- target: "http://localhost:8181",
+ target: "http://sdnc-web:8080",
ws: true,
changeOrigin: true,
secure: false
},
"/yang-schema": {
- target: "http://localhost:8181",
+ target: "http://sdnc-web:8080",
ws: true,
changeOrigin: true,
secure: false
diff --git a/sdnr/wt/odlux/apps/maintenanceApp/package.json b/sdnr/wt/odlux/apps/maintenanceApp/package.json
index dd678d6..d7c3254 100644
--- a/sdnr/wt/odlux/apps/maintenanceApp/package.json
+++ b/sdnr/wt/odlux/apps/maintenanceApp/package.json
@@ -39,6 +39,8 @@
"jquery": "3.3.1",
"react": "17.0.2",
"react-dom": "17.0.2",
- "react-router-dom": "5.2.0"
+ "react-router-dom": "5.2.0",
+ "@fortawesome/free-solid-svg-icons": "5.6.3",
+ "@fortawesome/react-fontawesome": "0.1.14"
}
}
diff --git a/sdnr/wt/odlux/apps/maintenanceApp/pom.xml b/sdnr/wt/odlux/apps/maintenanceApp/pom.xml
index f70e5fd..b296a0a 100644
--- a/sdnr/wt/odlux/apps/maintenanceApp/pom.xml
+++ b/sdnr/wt/odlux/apps/maintenanceApp/pom.xml
@@ -19,6 +19,7 @@
~ ============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>
@@ -139,7 +140,7 @@
<!-- optional: default phase is "generate-resources" -->
<phase>initialize</phase>
<configuration>
- <nodeVersion>v12.13.0</nodeVersion>
+ <nodeVersion>v12.22.0</nodeVersion>
<yarnVersion>v1.22.10</yarnVersion>
</configuration>
</execution>
diff --git a/sdnr/wt/odlux/apps/maintenanceApp/src/actions/maintenenceActions.ts b/sdnr/wt/odlux/apps/maintenanceApp/src/actions/maintenenceActions.ts
index 162d943..740abff 100644
--- a/sdnr/wt/odlux/apps/maintenanceApp/src/actions/maintenenceActions.ts
+++ b/sdnr/wt/odlux/apps/maintenanceApp/src/actions/maintenenceActions.ts
@@ -1,3 +1,4 @@
+/* eslint-disable @typescript-eslint/no-unused-expressions */
/**
* ============LICENSE_START========================================================================
* ONAP : ccsdk feature sdnr wt odlux
@@ -15,16 +16,13 @@
* the License.
* ============LICENSE_END==========================================================================
*/
+import { AddSnackbarNotification } from '../../../../framework/src/actions/snackbarActions';
import { Action } from '../../../../framework/src/flux/action';
import { Dispatch } from '../../../../framework/src/flux/store';
-import { MaintenenceEntry, spoofSymbol } from '../models/maintenenceEntryType';
-import { AddSnackbarNotification } from '../../../../framework/src/actions/snackbarActions';
-import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
-
-
+import { maintenanceEntriesReloadAction } from '../handlers/maintenanceEntriesHandler';
+import { MaintenanceEntry, spoofSymbol } from '../models/maintenanceEntryType';
import { maintenenceService } from '../services/maintenenceService';
-import { maintenanceEntriesReloadAction } from '../handlers/maintenenceEntriesHandler';
export class BaseAction extends Action { }
@@ -32,7 +30,7 @@
export class AllMainteneceEntriesLoadedAction extends BaseAction {
- constructor (public maintenenceEntries: MaintenenceEntry[] | null, error?:string) {
+ constructor(public maintenenceEntries: MaintenanceEntry[] | null) {
super();
}
@@ -40,39 +38,39 @@
export class UpdateMaintenanceEntry extends BaseAction {
- constructor(public maintenenceEntry: MaintenenceEntry) {
+ constructor(public maintenenceEntry: MaintenanceEntry) {
super();
}
}
/** Represents an async thunk action creator to add an element to the maintenence entries. */
-export const addOrUpdateMaintenenceEntryAsyncActionCreator = (entry: MaintenenceEntry) => (dispatch: Dispatch) => {
+export const addOrUpdateMaintenenceEntryAsyncActionCreator = (entry: MaintenanceEntry) => (dispatch: Dispatch) => {
maintenenceService.writeMaintenenceEntry(entry).then(result => {
result && window.setTimeout(() => {
// dispatch(loadAllMountedNetworkElementsAsync);
dispatch(new UpdateMaintenanceEntry(entry));
- dispatch(new AddSnackbarNotification({ message: `Successfully ${result && result.created ? "created" : "updated"} maintenance settings for [${entry.nodeId}]`, options: { variant: 'success' } }));
+ dispatch(new AddSnackbarNotification({ message: `Successfully ${result && result.created ? 'created' : 'updated'} maintenance settings for [${entry.nodeId}]`, options: { variant: 'success' } }));
}, 900);
- dispatch(maintenanceEntriesReloadAction)
+ dispatch(maintenanceEntriesReloadAction);
});
};
/** Represents an async thunk action creator to delete an element from the maintenence entries. */
-export const removeFromMaintenenceEntrysAsyncActionCreator = (entry: MaintenenceEntry) => (dispatch: Dispatch) => {
+export const removeFromMaintenenceEntrysAsyncActionCreator = (entry: MaintenanceEntry) => (dispatch: Dispatch) => {
maintenenceService.deleteMaintenenceEntry(entry).then(result => {
result && window.setTimeout(() => {
dispatch(new UpdateMaintenanceEntry({
[spoofSymbol]: true,
- _id: entry._id,
+ mId: entry.mId,
nodeId: entry.nodeId,
- description: "",
- start: "",
- end: "",
- active: false
+ description: '',
+ start: '',
+ end: '',
+ active: false,
}));
dispatch(new AddSnackbarNotification({ message: `Successfully removed [${entry.nodeId}]`, options: { variant: 'success' } }));
}, 900);
- dispatch(maintenanceEntriesReloadAction)
+ dispatch(maintenanceEntriesReloadAction);
});
};
diff --git a/sdnr/wt/odlux/apps/maintenanceApp/src/assets/icons/maintenanceAppIcon.svg b/sdnr/wt/odlux/apps/maintenanceApp/src/assets/icons/maintenanceAppIcon.svg
new file mode 100644
index 0000000..8b99a5e
--- /dev/null
+++ b/sdnr/wt/odlux/apps/maintenanceApp/src/assets/icons/maintenanceAppIcon.svg
@@ -0,0 +1,50 @@
+<!-- highstreet technologies GmbH colour scheme
+ Grey #565656
+ LBlue #36A9E1
+ DBlue #246DA2
+ Green #003F2C / #006C4B
+ Yellw #C8D400
+ Red #D81036
+-->
+
+<svg version="1.0" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 684.000000 684.000000">
+
+<g transform="translate(0.000000,684.000000) scale(0.100000,-0.100000)">
+
+<path fill="#565656" d="M3044 6693 c-12 -2 -33 -17 -48 -32 -35 -37 -55 -136 -96 -476 -17
+-142 -32 -260 -33 -260 -1 -1 -60 -19 -132 -40 -243 -71 -406 -139 -600 -250
+-99 -57 -120 -66 -138 -57 -12 6 -124 91 -249 189 -124 98 -252 193 -283 212
+-57 34 -57 34 -89 17 -81 -43 -421 -374 -513 -500 -24 -32 -43 -67 -43 -78 0
+-36 98 -173 337 -472 57 -70 103 -132 103 -138 0 -5 -17 -35 -39 -66 -98 -144
+-275 -566 -301 -715 -14 -78 26 -65 -335 -112 -384 -51 -423 -62 -447 -125 -5
+-14 -9 -179 -9 -376 0 -414 0 -416 78 -433 43 -10 213 -35 518 -77 183 -25
+167 -12 221 -182 75 -238 160 -433 278 -637 l35 -61 -175 -219 c-206 -259
+-274 -357 -274 -393 0 -22 50 -76 258 -282 142 -141 275 -269 295 -284 l36
+-28 38 23 c62 38 177 124 380 286 l193 153 92 -57 c168 -102 383 -193 633
+-269 66 -19 123 -39 127 -43 9 -8 19 -76 53 -361 14 -113 33 -243 42 -289 23
+-119 0 -114 455 -113 237 0 373 4 386 11 44 23 61 101 106 485 l32 269 149 46
+c227 71 395 139 395 160 0 5 -125 127 -277 272 -194 186 -283 263 -297 262
+-12 -1 -75 -11 -141 -23 -318 -56 -700 -29 -973 69 -278 101 -476 226 -685
+435 -275 275 -445 609 -504 988 -23 152 -23 432 1 586 60 394 215 705 493 984
+166 169 314 278 498 368 292 143 539 191 912 176 194 -8 297 -24 446 -72 485
+-156 879 -500 1098 -959 134 -278 196 -617 170 -918 -6 -73 -21 -186 -33 -251
+l-22 -119 274 -268 c268 -261 275 -268 292 -248 23 27 88 198 133 351 31 104
+41 127 59 132 11 3 131 19 266 36 402 50 463 65 477 118 5 15 8 192 8 393 0
+353 -1 368 -20 389 -36 40 -79 49 -469 100 -132 18 -249 36 -261 40 -18 7 -29
+33 -59 137 -66 223 -139 392 -292 669 l-28 51 126 159 c193 246 265 343 294
+399 l27 52 -31 45 c-101 147 -505 538 -555 538 -30 0 -234 -146 -506 -362
+l-104 -82 -51 28 c-244 136 -390 201 -606 271 -63 21 -136 46 -161 57 l-46 19
+-36 297 c-50 403 -58 430 -136 452 -34 9 -671 12 -717 3z"/>
+
+<path fill="#006C4B" d="M3080 4653 c-77 -8 -195 -35 -232 -54 -21 -10 -45 -30 -54 -44 -15
+-23 -15 -27 0 -49 22 -35 111 -101 277 -207 247 -158 343 -239 384 -326 35
+-74 -5 -237 -108 -438 -40 -77 -68 -116 -122 -170 -77 -77 -194 -145 -249
+-145 -39 0 -127 48 -339 184 -194 124 -291 176 -330 176 -60 0 -105 -86 -86
+-167 28 -127 262 -492 423 -662 101 -106 236 -191 333 -211 27 -5 138 -14 248
+-20 372 -20 506 -66 689 -240 87 -83 629 -652 1291 -1355 181 -192 439 -465
+573 -607 244 -255 245 -256 281 -251 220 32 406 139 512 295 50 73 98 174 106
+222 5 32 0 42 -53 108 -113 140 -296 342 -1073 1183 -513 554 -980 1066 -1074
+1178 -117 137 -174 252 -196 394 -6 39 -15 171 -21 294 -6 123 -15 257 -20
+297 -28 207 -209 414 -464 532 -97 45 -172 66 -286 80 -78 9 -330 11 -410 3z"/>
+</g>
+</svg>
diff --git a/sdnr/wt/odlux/apps/maintenanceApp/src/components/editMaintenenceEntryDialog.tsx b/sdnr/wt/odlux/apps/maintenanceApp/src/components/editMaintenenceEntryDialog.tsx
index 8292892..9ab147c 100644
--- a/sdnr/wt/odlux/apps/maintenanceApp/src/components/editMaintenenceEntryDialog.tsx
+++ b/sdnr/wt/odlux/apps/maintenanceApp/src/components/editMaintenenceEntryDialog.tsx
@@ -1,3 +1,4 @@
+/* eslint-disable @typescript-eslint/no-unused-expressions */
/**
* ============LICENSE_START========================================================================
* ONAP : ccsdk feature sdnr wt odlux
@@ -18,90 +19,89 @@
import * as React from 'react';
import Button from '@mui/material/Button';
-import TextField from '@mui/material/TextField';
import Dialog from '@mui/material/Dialog';
import DialogActions from '@mui/material/DialogActions';
import DialogContent from '@mui/material/DialogContent';
import DialogContentText from '@mui/material/DialogContentText';
import DialogTitle from '@mui/material/DialogTitle';
+import TextField from '@mui/material/TextField';
-import { IDispatcher, connect, Connect } from '../../../../framework/src/flux/connect';
+import { connect, Connect, IDispatcher } from '../../../../framework/src/flux/connect';
+import { FormControl, InputLabel, MenuItem, Select, Typography } from '@mui/material';
import {
addOrUpdateMaintenenceEntryAsyncActionCreator,
- removeFromMaintenenceEntrysAsyncActionCreator
+ removeFromMaintenenceEntrysAsyncActionCreator,
} from '../actions/maintenenceActions';
-
-import { MaintenenceEntry } from '../models/maintenenceEntryType';
-import { FormControl, InputLabel, Select, MenuItem, Typography } from '@mui/material';
+import { MaintenanceEntry } from '../models/maintenanceEntryType';
export enum EditMaintenenceEntryDialogMode {
- None = "none",
- AddMaintenenceEntry = "addMaintenenceEntry",
- EditMaintenenceEntry = "editMaintenenceEntry",
- RemoveMaintenenceEntry = "removeMaintenenceEntry"
+ None = 'none',
+ AddMaintenenceEntry = 'addMaintenenceEntry',
+ EditMaintenenceEntry = 'editMaintenenceEntry',
+ RemoveMaintenenceEntry = 'removeMaintenenceEntry',
}
const mapDispatch = (dispatcher: IDispatcher) => ({
- addOrUpdateMaintenenceEntry: (entry: MaintenenceEntry) => {
+ addOrUpdateMaintenenceEntry: (entry: MaintenanceEntry) => {
dispatcher.dispatch(addOrUpdateMaintenenceEntryAsyncActionCreator(entry));
},
- removeMaintenenceEntry: (entry: MaintenenceEntry) => {
+ removeMaintenenceEntry: (entry: MaintenanceEntry) => {
dispatcher.dispatch(removeFromMaintenenceEntrysAsyncActionCreator(entry));
},
});
type DialogSettings = {
- dialogTitle: string,
- dialogDescription: string,
- applyButtonText: string,
- cancelButtonText: string,
- enableMountIdEditor: boolean,
- enableTimeEditor: boolean,
-}
+ dialogTitle: string;
+ dialogDescription: string;
+ applyButtonText: string;
+ cancelButtonText: string;
+ enableMountIdEditor: boolean;
+ enableTimeEditor: boolean;
+};
const settings: { [key: string]: DialogSettings } = {
[EditMaintenenceEntryDialogMode.None]: {
- dialogTitle: "",
- dialogDescription: "",
- applyButtonText: "",
- cancelButtonText: "",
+ dialogTitle: '',
+ dialogDescription: '',
+ applyButtonText: '',
+ cancelButtonText: '',
enableMountIdEditor: false,
enableTimeEditor: false,
},
[EditMaintenenceEntryDialogMode.AddMaintenenceEntry]: {
- dialogTitle: "Add new maintenence entry",
- dialogDescription: "",
- applyButtonText: "Add",
- cancelButtonText: "Cancel",
+ dialogTitle: 'Add new maintenence entry',
+ dialogDescription: '',
+ applyButtonText: 'Add',
+ cancelButtonText: 'Cancel',
enableMountIdEditor: true,
enableTimeEditor: true,
},
[EditMaintenenceEntryDialogMode.EditMaintenenceEntry]: {
- dialogTitle: "Edit maintenence entry",
- dialogDescription: "",
- applyButtonText: "Save",
- cancelButtonText: "Cancel",
+ dialogTitle: 'Edit maintenence entry',
+ dialogDescription: '',
+ applyButtonText: 'Save',
+ cancelButtonText: 'Cancel',
enableMountIdEditor: false,
enableTimeEditor: true,
},
[EditMaintenenceEntryDialogMode.RemoveMaintenenceEntry]: {
- dialogTitle: "Remove maintenence entry",
- dialogDescription: "",
- applyButtonText: "Remove",
- cancelButtonText: "Cancel",
+ dialogTitle: 'Remove maintenence entry',
+ dialogDescription: '',
+ applyButtonText: 'Remove',
+ cancelButtonText: 'Cancel',
enableMountIdEditor: false,
enableTimeEditor: false,
},
-}
+};
type EditMaintenenceEntryDIalogComponentProps = Connect<undefined, typeof mapDispatch> & {
mode: EditMaintenenceEntryDialogMode;
- initialMaintenenceEntry: MaintenenceEntry;
+ initialMaintenenceEntry: MaintenanceEntry;
onClose: () => void;
};
-type EditMaintenenceEntryDIalogComponentState = MaintenenceEntry & { isErrorVisible: boolean };
+type EditMaintenenceEntryDIalogComponentState = MaintenanceEntry & { isErrorVisible: boolean };
class EditMaintenenceEntryDIalogComponent extends React.Component<EditMaintenenceEntryDIalogComponentProps, EditMaintenenceEntryDIalogComponentState> {
constructor(props: EditMaintenenceEntryDIalogComponentProps) {
@@ -109,7 +109,7 @@
this.state = {
...this.props.initialMaintenenceEntry,
- isErrorVisible: false
+ isErrorVisible: false,
};
}
@@ -122,10 +122,12 @@
<DialogContentText>
{setting.dialogDescription}
</DialogContentText>
- <TextField variant="standard" disabled={!setting.enableMountIdEditor} spellCheck={false} autoFocus margin="dense" id="name" label="Name" type="text" fullWidth value={this.state.nodeId} onChange={(event) => { this.setState({ nodeId: event.target.value }); }} />
+ <TextField variant="standard" disabled={!setting.enableMountIdEditor} spellCheck={false} autoFocus margin="dense" id="name" label="Name" type="text" fullWidth value={this.state.nodeId} onChange={(event) => { this.setState({ nodeId: event.target.value }); }} />
{this.state.isErrorVisible && <Typography variant="body1" color="error" >Name must not be empty.</Typography>}
- <TextField variant="standard" disabled={!setting.enableTimeEditor} spellCheck={false} autoFocus margin="dense" id="start" label="Start (Local DateTime)" type="datetime-local" fullWidth value={this.state.start} onChange={(event) => { this.setState({ start: event.target.value }); }} />
- <TextField variant="standard" disabled={!setting.enableTimeEditor} spellCheck={false} autoFocus margin="dense" id="end" label="End (Local DateTime)" type="datetime-local" fullWidth value={this.state.end} onChange={(event) => { this.setState({ end: event.target.value }); }} />
+ <TextField variant="standard" disabled={!setting.enableTimeEditor} spellCheck={false} autoFocus margin="dense" id="start"
+ label="Start (Local DateTime)" type="datetime-local" fullWidth value={this.state.start} onChange={(event) => { this.setState({ start: event.target.value }); }} />
+ <TextField variant="standard" disabled={!setting.enableTimeEditor} spellCheck={false} autoFocus margin="dense" id="end"
+ label="End (Local DateTime)" type="datetime-local" fullWidth value={this.state.end} onChange={(event) => { this.setState({ end: event.target.value }); }} />
<FormControl variant="standard" fullWidth disabled={!setting.enableTimeEditor}>
<InputLabel htmlFor="active">Active</InputLabel>
<Select variant="standard" value={this.state.active || false} onChange={(event) => {
@@ -143,12 +145,12 @@
this.setState({ isErrorVisible: true });
} else {
this.onApply({
- _id: this.state._id || this.state.nodeId,
+ mId: this.state.mId || this.state.nodeId,
nodeId: this.state.nodeId,
description: this.state.description,
start: this.state.start,
end: this.state.end,
- active: this.state.active
+ active: this.state.active,
});
this.setState({ isErrorVisible: false });
}
@@ -164,10 +166,10 @@
}} color="secondary"> {setting.cancelButtonText} </Button>
</DialogActions>
</Dialog>
- )
+ );
}
- private onApply = (entry: MaintenenceEntry) => {
+ private onApply = (entry: MaintenanceEntry) => {
this.props.onClose && this.props.onClose();
switch (this.props.mode) {
case EditMaintenenceEntryDialogMode.AddMaintenenceEntry:
@@ -185,14 +187,15 @@
private onCancel = () => {
this.props.onClose && this.props.onClose();
- }
+ };
- static getDerivedStateFromProps(props: EditMaintenenceEntryDIalogComponentProps, state: EditMaintenenceEntryDIalogComponentState & { _initialMaintenenceEntry: MaintenenceEntry }): EditMaintenenceEntryDIalogComponentState & { _initialMaintenenceEntry: MaintenenceEntry } {
- if (props.initialMaintenenceEntry !== state._initialMaintenenceEntry) {
+ static getDerivedStateFromProps(props: EditMaintenenceEntryDIalogComponentProps, state: EditMaintenenceEntryDIalogComponentState & { initialMaintenenceEntrie: MaintenanceEntry }): EditMaintenenceEntryDIalogComponentState & { initialMaintenenceEntrie: MaintenanceEntry } {
+ if (props.initialMaintenenceEntry !== state.initialMaintenenceEntrie) {
+ // eslint-disable-next-line no-param-reassign
state = {
...state,
...props.initialMaintenenceEntry,
- _initialMaintenenceEntry: props.initialMaintenenceEntry,
+ initialMaintenenceEntrie: props.initialMaintenenceEntry,
};
}
return state;
diff --git a/sdnr/wt/odlux/apps/maintenanceApp/src/components/refreshMaintenanceEntries.tsx b/sdnr/wt/odlux/apps/maintenanceApp/src/components/refreshMaintenanceEntries.tsx
index c66b6f4..e8bd635 100644
--- a/sdnr/wt/odlux/apps/maintenanceApp/src/components/refreshMaintenanceEntries.tsx
+++ b/sdnr/wt/odlux/apps/maintenanceApp/src/components/refreshMaintenanceEntries.tsx
@@ -24,78 +24,74 @@
import DialogContentText from '@mui/material/DialogContentText';
import DialogTitle from '@mui/material/DialogTitle';
-import { IDispatcher, connect, Connect } from '../../../../framework/src/flux/connect';
+import { connect, Connect, IDispatcher } from '../../../../framework/src/flux/connect';
-import { maintenanceEntriesReloadAction } from '../handlers/maintenenceEntriesHandler';
-import { MaintenenceEntry } from '../models/maintenenceEntryType';
+import { maintenanceEntriesReloadAction } from '../handlers/maintenanceEntriesHandler';
+import { MaintenanceEntry } from '../models/maintenanceEntryType';
export enum RefreshMaintenanceEntriesDialogMode {
- None = "none",
- RefreshMaintenanceEntriesTable = "RefreshMaintenanceEntriesTable",
+ None = 'none',
+ RefreshMaintenanceEntriesTable = 'RefreshMaintenanceEntriesTable',
}
const mapDispatch = (dispatcher: IDispatcher) => ({
- refreshMaintenanceEntries: () => dispatcher.dispatch(maintenanceEntriesReloadAction)
+ refreshMaintenanceEntries: () => dispatcher.dispatch(maintenanceEntriesReloadAction),
});
type DialogSettings = {
- dialogTitle: string,
- dialogDescription: string,
- applyButtonText: string,
- cancelButtonText: string,
- enableMountIdEditor: boolean,
- enableUsernameEditor: boolean,
- enableExtendedEditor: boolean,
-}
+ dialogTitle: string;
+ dialogDescription: string;
+ applyButtonText: string;
+ cancelButtonText: string;
+ enableMountIdEditor: boolean;
+ enableUsernameEditor: boolean;
+ enableExtendedEditor: boolean;
+};
const settings: { [key: string]: DialogSettings } = {
[RefreshMaintenanceEntriesDialogMode.None]: {
- dialogTitle: "",
- dialogDescription: "",
- applyButtonText: "",
- cancelButtonText: "",
+ dialogTitle: '',
+ dialogDescription: '',
+ applyButtonText: '',
+ cancelButtonText: '',
enableMountIdEditor: false,
enableUsernameEditor: false,
enableExtendedEditor: false,
},
[RefreshMaintenanceEntriesDialogMode.RefreshMaintenanceEntriesTable]: {
- dialogTitle: "Do you want to refresh Maintenance Entries?",
- dialogDescription: "",
- applyButtonText: "Yes",
- cancelButtonText: "Cancel",
+ dialogTitle: 'Do you want to refresh Maintenance Entries?',
+ dialogDescription: '',
+ applyButtonText: 'Yes',
+ cancelButtonText: 'Cancel',
enableMountIdEditor: true,
enableUsernameEditor: true,
enableExtendedEditor: true,
- }
-}
+ },
+};
type RefreshMaintenanceEntriesDialogComponentProps = Connect<undefined, typeof mapDispatch> & {
mode: RefreshMaintenanceEntriesDialogMode;
onClose: () => void;
};
-type RefreshMaintenanceEntriesDialogComponentState = MaintenenceEntry & { isNameValid: boolean, isHostSet: boolean };
+type RefreshMaintenanceEntriesDialogComponentState = MaintenanceEntry & { isNameValid: boolean; isHostSet: boolean };
class RefreshMaintenanceEntriesDialogComponent extends React.Component<RefreshMaintenanceEntriesDialogComponentProps, RefreshMaintenanceEntriesDialogComponentState> {
- constructor(props: RefreshMaintenanceEntriesDialogComponentProps) {
- super(props);
- }
-
render(): JSX.Element {
const setting = settings[this.props.mode];
return (
<Dialog open={this.props.mode !== RefreshMaintenanceEntriesDialogMode.None}>
- <DialogTitle id="form-dialog-title" aria-label={`${setting.dialogTitle.replace(/ /g, "-").toLowerCase()}-dialog`}>{setting.dialogTitle}</DialogTitle>
+ <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={(event) => {
+ <Button aria-label="dialog-confirm-button" onClick={() => {
this.onRefresh();
}} color="inherit" > {setting.applyButtonText} </Button>
- <Button aria-label="dialog-cancel-button" onClick={(event) => {
+ <Button aria-label="dialog-cancel-button" onClick={() => {
this.onCancel();
}} color="secondary"> {setting.cancelButtonText} </Button>
</DialogActions>
@@ -110,7 +106,7 @@
private onCancel = () => {
this.props.onClose();
- }
+ };
}
export const RefreshMaintenanceEntriesDialog = connect(undefined, mapDispatch)(RefreshMaintenanceEntriesDialogComponent);
diff --git a/sdnr/wt/odlux/apps/maintenanceApp/src/handlers/maintenanceAppRootHandler.ts b/sdnr/wt/odlux/apps/maintenanceApp/src/handlers/maintenanceAppRootHandler.ts
index 71b4bf7..ced7f21 100644
--- a/sdnr/wt/odlux/apps/maintenanceApp/src/handlers/maintenanceAppRootHandler.ts
+++ b/sdnr/wt/odlux/apps/maintenanceApp/src/handlers/maintenanceAppRootHandler.ts
@@ -19,22 +19,20 @@
import { combineActionHandler } from '../../../../framework/src/flux/middleware';
-import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
-
-import { IMaintenanceEntriesState, maintenanceEntriesActionHandler } from './maintenenceEntriesHandler';
+import { IMaintenanceEntriesState, maintenanceEntriesActionHandler } from './maintenanceEntriesHandler';
export interface IMaintenanceAppStoreState {
- maintenenceEntries : IMaintenanceEntriesState
+ maintenanceEntries : IMaintenanceEntriesState;
}
declare module '../../../../framework/src/store/applicationStore' {
interface IApplicationStoreState {
- maintenance: IMaintenanceAppStoreState
+ maintenance: IMaintenanceAppStoreState;
}
}
const actionHandlers = {
- maintenenceEntries: maintenanceEntriesActionHandler
+ maintenanceEntries: maintenanceEntriesActionHandler,
};
export const maintenanceAppRootHandler = combineActionHandler<IMaintenanceAppStoreState>(actionHandlers);
diff --git a/sdnr/wt/odlux/apps/maintenanceApp/src/handlers/maintenenceEntriesHandler.ts b/sdnr/wt/odlux/apps/maintenanceApp/src/handlers/maintenanceEntriesHandler.ts
similarity index 79%
rename from sdnr/wt/odlux/apps/maintenanceApp/src/handlers/maintenenceEntriesHandler.ts
rename to sdnr/wt/odlux/apps/maintenanceApp/src/handlers/maintenanceEntriesHandler.ts
index 4455418..c3fe51e 100644
--- a/sdnr/wt/odlux/apps/maintenanceApp/src/handlers/maintenenceEntriesHandler.ts
+++ b/sdnr/wt/odlux/apps/maintenanceApp/src/handlers/maintenanceEntriesHandler.ts
@@ -15,14 +15,14 @@
* the License.
* ============LICENSE_END==========================================================================
*/
-import { createExternal,IExternalTableState } from '../../../../framework/src/components/material-table/utilities';
+import { createExternal, IExternalTableState } from '../../../../framework/src/components/material-table/utilities';
import { createSearchDataHandler } from '../../../../framework/src/utilities/elasticSearch';
-import { MaintenenceEntry } from '../models/maintenenceEntryType';
-export interface IMaintenanceEntriesState extends IExternalTableState<MaintenenceEntry> { }
+import { MaintenanceEntry } from '../models/maintenanceEntryType';
+export interface IMaintenanceEntriesState extends IExternalTableState<MaintenanceEntry> { }
-// create eleactic search material data fetch handler
-const maintenanceEntriesSearchHandler = createSearchDataHandler<MaintenenceEntry>('maintenance');
+// create elastic search material data fetch handler
+const maintenanceEntriesSearchHandler = createSearchDataHandler<MaintenanceEntry>('maintenance');
export const {
actionHandler: maintenanceEntriesActionHandler,
@@ -31,5 +31,5 @@
reloadAction: maintenanceEntriesReloadAction,
// set value action, to change a value
-} = createExternal<MaintenenceEntry>(maintenanceEntriesSearchHandler, appState => appState.maintenance.maintenenceEntries);
+} = createExternal<MaintenanceEntry>(maintenanceEntriesSearchHandler, appState => appState.maintenance.maintenanceEntries);
diff --git a/sdnr/wt/odlux/apps/maintenanceApp/src/models/maintenenceEntryType.ts b/sdnr/wt/odlux/apps/maintenanceApp/src/models/maintenanceEntryType.ts
similarity index 88%
rename from sdnr/wt/odlux/apps/maintenanceApp/src/models/maintenenceEntryType.ts
rename to sdnr/wt/odlux/apps/maintenanceApp/src/models/maintenanceEntryType.ts
index 989bfbd..27cdc8c 100644
--- a/sdnr/wt/odlux/apps/maintenanceApp/src/models/maintenenceEntryType.ts
+++ b/sdnr/wt/odlux/apps/maintenanceApp/src/models/maintenanceEntryType.ts
@@ -18,16 +18,16 @@
/** Represents the elestic search db type for maintenence enrties */
-export const spoofSymbol = Symbol("Spoof");
+export const spoofSymbol = Symbol('Spoof');
/** Represents the type for an maintenence entry. */
-export type MaintenenceEntry = {
- _id: string;
+export type MaintenanceEntry = {
+ mId: string;
nodeId: string;
- description?: string,
- end: string,
- start: string
- active: boolean
+ description?: string;
+ end: string;
+ start: string;
+ active: boolean;
[spoofSymbol]?: boolean;
-}
+};
diff --git a/sdnr/wt/odlux/apps/maintenanceApp/src/pluginMaintenance.tsx b/sdnr/wt/odlux/apps/maintenanceApp/src/pluginMaintenance.tsx
index e6ab977..0f686cb 100644
--- a/sdnr/wt/odlux/apps/maintenanceApp/src/pluginMaintenance.tsx
+++ b/sdnr/wt/odlux/apps/maintenanceApp/src/pluginMaintenance.tsx
@@ -17,27 +17,27 @@
*/
// app configuration and main entry point for the app
-import * as React from "react";
-
-import { faLock } from '@fortawesome/free-solid-svg-icons'; // select app icon
+import React, { FC } from 'react';
import applicationManager from '../../../framework/src/services/applicationManager';
import { maintenanceAppRootHandler } from './handlers/maintenanceAppRootHandler';
-import MaintenenceView from "./views/maintenenceView";
+import { MaintenanceView } from './views/maintenanceView';
-const App : React.SFC = (props) => {
- return <MaintenenceView />
+const appIcon = require('./assets/icons/maintenanceAppIcon.svg'); // select app icon
+
+const App : FC = () => {
+ return <MaintenanceView />;
};
export function register() {
applicationManager.registerApplication({
- name: "maintenance",
- icon: faLock,
+ name: 'maintenance',
+ icon: appIcon,
rootComponent: App,
rootActionHandler: maintenanceAppRootHandler,
- menuEntry: "Maintenance"
+ menuEntry: 'Maintenance',
});
}
diff --git a/sdnr/wt/odlux/apps/maintenanceApp/src/services/maintenenceService.ts b/sdnr/wt/odlux/apps/maintenanceApp/src/services/maintenenceService.ts
index 613b478..5fdccc3 100644
--- a/sdnr/wt/odlux/apps/maintenanceApp/src/services/maintenenceService.ts
+++ b/sdnr/wt/odlux/apps/maintenanceApp/src/services/maintenenceService.ts
@@ -15,15 +15,15 @@
* the License.
* ============LICENSE_END==========================================================================
*/
+import { DeleteResponse, PostResponse } from '../../../../framework/src/models/elasticSearch';
import { requestRest } from '../../../../framework/src/services/restService';
-import { Result, HitEntry, PostResponse, DeleteResponse } from '../../../../framework/src/models/elasticSearch';
-
-import { MaintenenceEntry } from '../models/maintenenceEntryType';
-import { convertToLocaleString, convertToGMTString, convertToISODateString } from '../utils/timeUtils';
import { convertPropertyNames, replaceUpperCase } from '../../../../framework/src/utilities/yangHelper';
+import { MaintenanceEntry } from '../models/maintenanceEntryType';
+
+import { convertToISODateString } from '../utils/timeUtils';
-export const maintenenceEntryDatabasePath = "mwtn/maintenancemode";
+export const maintenenceEntryDatabasePath = 'mwtn/maintenancemode';
/**
* Represents a web api accessor service for all maintenence entries related actions.
@@ -33,37 +33,37 @@
/**
* Adds or updates one maintenence entry to the backend.
*/
- public async writeMaintenenceEntry(maintenenceEntry: MaintenenceEntry): Promise<PostResponse | null> {
- const path = `/rests/operations/data-provider:create-maintenance`;
+ public async writeMaintenenceEntry(maintenenceEntry: MaintenanceEntry): Promise<PostResponse | null> {
+ const path = '/rests/operations/data-provider:create-maintenance';
const query = {
- "id": maintenenceEntry._id,
- "node-id": maintenenceEntry.nodeId,
- "active": maintenenceEntry.active,
- "description": maintenenceEntry.description,
- "end": convertToISODateString(maintenenceEntry.end),
- "start": convertToISODateString(maintenenceEntry.start)
+ 'id': maintenenceEntry.mId,
+ 'node-id': maintenenceEntry.nodeId,
+ 'active': maintenenceEntry.active,
+ 'description': maintenenceEntry.description,
+ 'end': convertToISODateString(maintenenceEntry.end),
+ 'start': convertToISODateString(maintenenceEntry.start),
};
- const result = await requestRest<PostResponse>(path, { method: "POST", body: JSON.stringify(convertPropertyNames({ "data-provider:input": query }, replaceUpperCase)) });
+ const result = await requestRest<PostResponse>(path, { method: 'POST', body: JSON.stringify(convertPropertyNames({ 'data-provider:input': query }, replaceUpperCase)) });
return result || null;
}
/**
* Deletes one maintenence entry by its mountId from the backend.
*/
- public async deleteMaintenenceEntry(maintenenceEntry: MaintenenceEntry): Promise<(DeleteResponse) | null> {
- const path = `/rests/operations/data-provider:delete-maintenance`;
+ public async deleteMaintenenceEntry(maintenenceEntry: MaintenanceEntry): Promise<(DeleteResponse) | null> {
+ const path = '/rests/operations/data-provider:delete-maintenance';
const query = {
- "id": maintenenceEntry._id,
- "node-id": maintenenceEntry.nodeId,
- "active": maintenenceEntry.active,
- "description": maintenenceEntry.description,
- "end": convertToISODateString(maintenenceEntry.end),
- "start": convertToISODateString(maintenenceEntry.start)
+ 'id': maintenenceEntry.mId,
+ 'node-id': maintenenceEntry.nodeId,
+ 'active': maintenenceEntry.active,
+ 'description': maintenenceEntry.description,
+ 'end': convertToISODateString(maintenenceEntry.end),
+ 'start': convertToISODateString(maintenenceEntry.start),
};
- const result = await requestRest<DeleteResponse>(path, { method: "POST", body: JSON.stringify(convertPropertyNames({ "data-provider:input": query }, replaceUpperCase)) });
+ const result = await requestRest<DeleteResponse>(path, { method: 'POST', body: JSON.stringify(convertPropertyNames({ 'data-provider:input': query }, replaceUpperCase)) });
return result || null;
}
}
diff --git a/sdnr/wt/odlux/apps/maintenanceApp/src/utils/timeUtils.ts b/sdnr/wt/odlux/apps/maintenanceApp/src/utils/timeUtils.ts
index 676be1a..0fde5fc 100644
--- a/sdnr/wt/odlux/apps/maintenanceApp/src/utils/timeUtils.ts
+++ b/sdnr/wt/odlux/apps/maintenanceApp/src/utils/timeUtils.ts
@@ -27,7 +27,7 @@
'+00:00';
}
-export function convertToLocaleString(rawDate: string| number): string {
+export function convertToLocaleString(rawDate: string | number): string {
const date = new Date(rawDate);
const pad = (n: number) => (n < 10) ? '0' + n : n;
@@ -38,7 +38,7 @@
':' + pad(date.getMinutes());
}
-export function convertToISODateString(rawDate: string| number): string {
+export function convertToISODateString(rawDate: string | number): string {
const date = new Date(rawDate);
const displayDate = date.toISOString();
return displayDate.replace(/\.[0-9]{2}/, '.');
diff --git a/sdnr/wt/odlux/apps/maintenanceApp/src/views/maintenenceView.tsx b/sdnr/wt/odlux/apps/maintenanceApp/src/views/maintenanceView.tsx
similarity index 69%
rename from sdnr/wt/odlux/apps/maintenanceApp/src/views/maintenenceView.tsx
rename to sdnr/wt/odlux/apps/maintenanceApp/src/views/maintenanceView.tsx
index d040e3d..d54d63c 100644
--- a/sdnr/wt/odlux/apps/maintenanceApp/src/views/maintenenceView.tsx
+++ b/sdnr/wt/odlux/apps/maintenanceApp/src/views/maintenanceView.tsx
@@ -15,62 +15,57 @@
* the License.
* ============LICENSE_END==========================================================================
*/
-import * as React from 'react';
+import React from 'react';
-import { Theme, Tooltip } from '@mui/material';
-
+import { faBan } from '@fortawesome/free-solid-svg-icons';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import AddIcon from '@mui/icons-material/Add';
+import EditIcon from '@mui/icons-material/Edit';
+import Refresh from '@mui/icons-material/Refresh';
+import RemoveIcon from '@mui/icons-material/RemoveCircleOutline';
+import { Divider, MenuItem, Theme, Typography } from '@mui/material';
import { WithStyles } from '@mui/styles';
import createStyles from '@mui/styles/createStyles';
import withStyles from '@mui/styles/withStyles';
-import { faBan } from '@fortawesome/free-solid-svg-icons';
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-
-import AddIcon from '@mui/icons-material/Add';
-import EditIcon from '@mui/icons-material/Edit';
-import RemoveIcon from '@mui/icons-material/RemoveCircleOutline';
-import Refresh from '@mui/icons-material/Refresh';
-import { MenuItem, Divider, Typography } from '@mui/material';
-
-import connect, { IDispatcher, Connect } from '../../../../framework/src/flux/connect';
-import MaterialTable, { MaterialTableCtorType, ColumnType } from '../../../../framework/src/components/material-table';
+import MaterialTable, { ColumnType, MaterialTableCtorType } from '../../../../framework/src/components/material-table';
+import { connect, Connect, IDispatcher } from '../../../../framework/src/flux/connect';
import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
-import { MaintenenceEntry, spoofSymbol } from '../models/maintenenceEntryType';
-
import EditMaintenenceEntryDialog, { EditMaintenenceEntryDialogMode } from '../components/editMaintenenceEntryDialog';
import RefreshMaintenanceEntriesDialog, { RefreshMaintenanceEntriesDialogMode } from '../components/refreshMaintenanceEntries';
+import { createmaintenanceEntriesActions, createmaintenanceEntriesProperties, maintenanceEntriesReloadAction } from '../handlers/maintenanceEntriesHandler';
+import { MaintenanceEntry } from '../models/maintenanceEntryType';
import { convertToLocaleString } from '../utils/timeUtils';
-import { createmaintenanceEntriesActions, createmaintenanceEntriesProperties, maintenanceEntriesReloadAction } from '../handlers/maintenenceEntriesHandler';
const styles = (theme: Theme) => createStyles({
button: {
margin: 0,
- padding: "6px 6px",
- minWidth: 'unset'
+ padding: '6px 6px',
+ minWidth: 'unset',
},
spacer: {
marginLeft: theme.spacing(1),
marginRight: theme.spacing(1),
- display: "inline"
- }
+ display: 'inline',
+ },
});
-const MaintenenceEntriesTable = MaterialTable as MaterialTableCtorType<MaintenenceEntry>;
+const MaintenanceEntriesTable = MaterialTable as MaterialTableCtorType<MaintenanceEntry>;
const mapProps = (state: IApplicationStoreState) => ({
- maintenanceEntriesProperties: createmaintenanceEntriesProperties(state)
+ maintenanceEntriesProperties: createmaintenanceEntriesProperties(state),
});
const mapDispatcher = (dispatcher: IDispatcher) => ({
maintenanceEntriesActions: createmaintenanceEntriesActions(dispatcher.dispatch),
onLoadMaintenanceEntries: async () => {
- await dispatcher.dispatch(maintenanceEntriesReloadAction)
- }
+ await dispatcher.dispatch(maintenanceEntriesReloadAction);
+ },
});
-const emptyMaintenenceEntry: MaintenenceEntry = {
- _id: '',
+const emptyMaintenenceEntry: MaintenanceEntry = {
+ mId: '',
nodeId: '',
description: '',
start: convertToLocaleString(new Date().valueOf()),
@@ -78,44 +73,41 @@
active: false,
};
-type MaintenenceViewComponentProps = Connect<typeof mapProps, typeof mapDispatcher> & WithStyles<typeof styles> & {
-
-}
+type MaintenanceViewComponentProps = Connect<typeof mapProps, typeof mapDispatcher> & WithStyles<typeof styles> & {};
type MaintenenceViewComponentState = {
- maintenenceEntryToEdit: MaintenenceEntry;
- maintenenceEntryEditorMode: EditMaintenenceEntryDialogMode;
+ maintenenceEntryToEdit: MaintenanceEntry;
+ maintenanceEntryEditorMode: EditMaintenenceEntryDialogMode;
refreshMaintenenceEntriesEditorMode: RefreshMaintenanceEntriesDialogMode;
};
let initialSorted = false;
-class MaintenenceViewComponent extends React.Component<MaintenenceViewComponentProps, MaintenenceViewComponentState> {
+class MaintenenceViewComponent extends React.Component<MaintenanceViewComponentProps, MaintenenceViewComponentState> {
- constructor(props: MaintenenceViewComponentProps) {
+ constructor(props: MaintenanceViewComponentProps) {
super(props);
this.state = {
maintenenceEntryToEdit: emptyMaintenenceEntry,
- maintenenceEntryEditorMode: EditMaintenenceEntryDialogMode.None,
- refreshMaintenenceEntriesEditorMode: RefreshMaintenanceEntriesDialogMode.None
+ maintenanceEntryEditorMode: EditMaintenenceEntryDialogMode.None,
+ refreshMaintenenceEntriesEditorMode: RefreshMaintenanceEntriesDialogMode.None,
};
}
- getContextMenu(rowData: MaintenenceEntry): JSX.Element[] {
+ getContextMenu(rowData: MaintenanceEntry): JSX.Element[] {
let buttonArray = [
- <MenuItem aria-label={"1hr-from-now"} onClick={event => this.onOpenPlus1hEditMaintenenceEntryDialog(event, rowData)}><Typography>+1h</Typography></MenuItem>,
- <MenuItem aria-label={"8hr-from-now"} onClick={event => this.onOpenPlus8hEditMaintenenceEntryDialog(event, rowData)}><Typography>+8h</Typography></MenuItem>,
+ <MenuItem aria-label={'1hr-from-now'} onClick={event => this.onOpenPlus1hEditMaintenenceEntryDialog(event, rowData)}><Typography>+1h</Typography></MenuItem>,
+ <MenuItem aria-label={'8hr-from-now'} onClick={event => this.onOpenPlus8hEditMaintenenceEntryDialog(event, rowData)}><Typography>+8h</Typography></MenuItem>,
<Divider />,
- <MenuItem aria-label={"edit"} onClick={event => this.onOpenEditMaintenenceEntryDialog(event, rowData)}><EditIcon /><Typography>Edit</Typography></MenuItem>,
- <MenuItem aria-label={"remove"} onClick={event => this.onOpenRemoveMaintenenceEntryDialog(event, rowData)}><RemoveIcon /><Typography>Remove</Typography></MenuItem>
+ <MenuItem aria-label={'edit'} onClick={event => this.onOpenEditMaintenenceEntryDialog(event, rowData)}><EditIcon /><Typography>Edit</Typography></MenuItem>,
+ <MenuItem aria-label={'remove'} onClick={event => this.onOpenRemoveMaintenenceEntryDialog(event, rowData)}><RemoveIcon /><Typography>Remove</Typography></MenuItem>,
];
return buttonArray;
}
render() {
- const { classes } = this.props;
const addMaintenenceEntryAction = {
icon: AddIcon, tooltip: 'Add', ariaLabel:'add-element', onClick: () => {
const startTime = (new Date().valueOf());
@@ -126,39 +118,39 @@
start: convertToLocaleString(startTime),
end: convertToLocaleString(endTime),
},
- maintenenceEntryEditorMode: EditMaintenenceEntryDialogMode.AddMaintenenceEntry
+ maintenanceEntryEditorMode: EditMaintenenceEntryDialogMode.AddMaintenenceEntry,
});
- }
+ },
};
const refreshMaintenanceEntriesAction = {
icon: Refresh, tooltip: 'Refresh Maintenance Entries', ariaLabel: 'refresh', onClick: () => {
this.setState({
- refreshMaintenenceEntriesEditorMode: RefreshMaintenanceEntriesDialogMode.RefreshMaintenanceEntriesTable
+ refreshMaintenenceEntriesEditorMode: RefreshMaintenanceEntriesDialogMode.RefreshMaintenanceEntriesTable,
});
- }
+ },
};
const now = new Date().valueOf();
return (
<>
- <MaintenenceEntriesTable stickyHeader tableId="maintenance-table" title={"Maintenance"} customActionButtons={[refreshMaintenanceEntriesAction, addMaintenenceEntryAction]} columns={
+ <MaintenanceEntriesTable stickyHeader tableId="maintenance-table" title={'Maintenance'} customActionButtons={[refreshMaintenanceEntriesAction, addMaintenenceEntryAction]} columns={
[
- { property: "nodeId", title: "Node Name", type: ColumnType.text },
+ { property: 'nodeId', title: 'Node Name', type: ColumnType.text },
{
- property: "notifications", title: "Notification", width: 50, align: "center", type: ColumnType.custom, customControl: ({ rowData }) => (
+ property: 'notifications', title: 'Notification', width: 50, align: 'center', type: ColumnType.custom, customControl: ({ rowData }) => (
rowData.active && (Date.parse(rowData.start).valueOf() <= now) && (Date.parse(rowData.end).valueOf() >= now) && <FontAwesomeIcon icon={faBan} /> || null
- )
+ ),
},
- { property: "active", title: "Activation State", type: ColumnType.boolean, labels: { "true": "active", "false": "not active" }, },
- { property: "start", title: "Start Date (UTC)", type: ColumnType.text },
- { property: "end", title: "End Date (UTC)", type: ColumnType.text }
+ { property: 'active', title: 'Activation State', type: ColumnType.boolean, labels: { 'true': 'active', 'false': 'not active' } },
+ { property: 'start', title: 'Start Date (UTC)', type: ColumnType.text },
+ { property: 'end', title: 'End Date (UTC)', type: ColumnType.text },
]
- } idProperty={'_id'}{...this.props.maintenanceEntriesActions} {...this.props.maintenanceEntriesProperties} asynchronus createContextMenu={rowData => {
+ } idProperty={'mId'}{...this.props.maintenanceEntriesActions} {...this.props.maintenanceEntriesProperties} asynchronus createContextMenu={rowData => {
return this.getContextMenu(rowData);
}} >
- </MaintenenceEntriesTable>
- <EditMaintenenceEntryDialog initialMaintenenceEntry={this.state.maintenenceEntryToEdit} mode={this.state.maintenenceEntryEditorMode}
+ </MaintenanceEntriesTable>
+ <EditMaintenenceEntryDialog initialMaintenenceEntry={this.state.maintenenceEntryToEdit} mode={this.state.maintenanceEntryEditorMode}
onClose={this.onCloseEditMaintenenceEntryDialog} />
<RefreshMaintenanceEntriesDialog mode={this.state.refreshMaintenenceEntriesEditorMode}
onClose={this.onCloseRefreshMaintenenceEntryDialog} />
@@ -170,7 +162,7 @@
if (!initialSorted) {
initialSorted = true;
- this.props.maintenanceEntriesActions.onHandleRequestSort("node-id");
+ this.props.maintenanceEntriesActions.onHandleRequestSort('node-id');
} else {
this.props.onLoadMaintenanceEntries();
}
@@ -178,7 +170,7 @@
}
- private onOpenPlus1hEditMaintenenceEntryDialog = (event: React.MouseEvent<HTMLElement>, entry: MaintenenceEntry) => {
+ private onOpenPlus1hEditMaintenenceEntryDialog = (event: React.MouseEvent<HTMLElement>, entry: MaintenanceEntry) => {
// event.preventDefault();
// event.stopPropagation();
const startTime = (new Date().valueOf());
@@ -189,11 +181,11 @@
start: convertToLocaleString(startTime),
end: convertToLocaleString(endTime),
},
- maintenenceEntryEditorMode: EditMaintenenceEntryDialogMode.EditMaintenenceEntry
+ maintenanceEntryEditorMode: EditMaintenenceEntryDialogMode.EditMaintenenceEntry,
});
- }
+ };
- private onOpenPlus8hEditMaintenenceEntryDialog = (event: React.MouseEvent<HTMLElement>, entry: MaintenenceEntry) => {
+ private onOpenPlus8hEditMaintenenceEntryDialog = (event: React.MouseEvent<HTMLElement>, entry: MaintenanceEntry) => {
// event.preventDefault();
// event.stopPropagation();
const startTime = (new Date().valueOf());
@@ -204,11 +196,11 @@
start: convertToLocaleString(startTime),
end: convertToLocaleString(endTime),
},
- maintenenceEntryEditorMode: EditMaintenenceEntryDialogMode.EditMaintenenceEntry
+ maintenanceEntryEditorMode: EditMaintenenceEntryDialogMode.EditMaintenenceEntry,
});
- }
+ };
- private onOpenEditMaintenenceEntryDialog = (event: React.MouseEvent<HTMLElement>, entry: MaintenenceEntry) => {
+ private onOpenEditMaintenenceEntryDialog = (event: React.MouseEvent<HTMLElement>, entry: MaintenanceEntry) => {
// event.preventDefault();
// event.stopPropagation();
const startTime = (new Date().valueOf());
@@ -216,13 +208,13 @@
this.setState({
maintenenceEntryToEdit: {
...entry,
- ...(entry.start && endTime ? { start: convertToLocaleString(entry.start), end: convertToLocaleString(entry.end) } : { start: convertToLocaleString(startTime), end: convertToLocaleString(endTime) })
+ ...(entry.start && endTime ? { start: convertToLocaleString(entry.start), end: convertToLocaleString(entry.end) } : { start: convertToLocaleString(startTime), end: convertToLocaleString(endTime) }),
},
- maintenenceEntryEditorMode: EditMaintenenceEntryDialogMode.EditMaintenenceEntry
+ maintenanceEntryEditorMode: EditMaintenenceEntryDialogMode.EditMaintenenceEntry,
});
- }
+ };
- private onOpenRemoveMaintenenceEntryDialog = (event: React.MouseEvent<HTMLElement>, entry: MaintenenceEntry) => {
+ private onOpenRemoveMaintenenceEntryDialog = (event: React.MouseEvent<HTMLElement>, entry: MaintenanceEntry) => {
// event.preventDefault();
// event.stopPropagation();
const startTime = (new Date().valueOf());
@@ -230,25 +222,25 @@
this.setState({
maintenenceEntryToEdit: {
...entry,
- ...(entry.start && endTime ? { start: convertToLocaleString(entry.start), end: convertToLocaleString(entry.end) } : { start: convertToLocaleString(startTime), end: convertToLocaleString(endTime) })
+ ...(entry.start && endTime ? { start: convertToLocaleString(entry.start), end: convertToLocaleString(entry.end) } : { start: convertToLocaleString(startTime), end: convertToLocaleString(endTime) }),
},
- maintenenceEntryEditorMode: EditMaintenenceEntryDialogMode.RemoveMaintenenceEntry
+ maintenanceEntryEditorMode: EditMaintenenceEntryDialogMode.RemoveMaintenenceEntry,
});
- }
+ };
private onCloseEditMaintenenceEntryDialog = () => {
this.setState({
maintenenceEntryToEdit: emptyMaintenenceEntry,
- maintenenceEntryEditorMode: EditMaintenenceEntryDialogMode.None,
+ maintenanceEntryEditorMode: EditMaintenenceEntryDialogMode.None,
});
- }
+ };
private onCloseRefreshMaintenenceEntryDialog = () => {
this.setState({
refreshMaintenenceEntriesEditorMode: RefreshMaintenanceEntriesDialogMode.None,
});
- }
+ };
}
-export const MaintenenceView = withStyles(styles)(connect(mapProps, mapDispatcher)(MaintenenceViewComponent));
-export default MaintenenceView;
+export const MaintenanceView = withStyles(styles)(connect(mapProps, mapDispatcher)(MaintenenceViewComponent));
+
diff --git a/sdnr/wt/odlux/apps/maintenanceApp/tsconfig.json b/sdnr/wt/odlux/apps/maintenanceApp/tsconfig.json
index a66b5d8..ca65092 100644
--- a/sdnr/wt/odlux/apps/maintenanceApp/tsconfig.json
+++ b/sdnr/wt/odlux/apps/maintenanceApp/tsconfig.json
@@ -4,7 +4,7 @@
"outDir": "./dist",
"sourceMap": true,
"forceConsistentCasingInFileNames": true,
- "allowSyntheticDefaultImports": false,
+ "allowSyntheticDefaultImports": true,
"allowUnreachableCode": false,
"allowUnusedLabels": false,
"noFallthroughCasesInSwitch": true,
diff --git a/sdnr/wt/odlux/apps/maintenanceApp/webpack.config.js b/sdnr/wt/odlux/apps/maintenanceApp/webpack.config.js
index da5cf58..845fc43 100644
--- a/sdnr/wt/odlux/apps/maintenanceApp/webpack.config.js
+++ b/sdnr/wt/odlux/apps/maintenanceApp/webpack.config.js
@@ -57,6 +57,16 @@
use: [{
loader: "babel-loader"
}]
+ }, {
+ //don't minify images
+ test: /\.(png|gif|jpg|svg)$/,
+ use: [{
+ loader: 'url-loader',
+ options: {
+ limit: 10,
+ name: './images/[name].[ext]'
+ }
+ }]
}]
},
diff --git a/sdnr/wt/odlux/apps/mediatorApp/pom.xml b/sdnr/wt/odlux/apps/mediatorApp/pom.xml
index 2f8a147..2406c6c 100644
--- a/sdnr/wt/odlux/apps/mediatorApp/pom.xml
+++ b/sdnr/wt/odlux/apps/mediatorApp/pom.xml
@@ -19,6 +19,7 @@
~ ============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>
@@ -139,7 +140,7 @@
<!-- optional: default phase is "generate-resources" -->
<phase>initialize</phase>
<configuration>
- <nodeVersion>v12.13.0</nodeVersion>
+ <nodeVersion>v12.22.0</nodeVersion>
<yarnVersion>v1.22.10</yarnVersion>
</configuration>
</execution>
diff --git a/sdnr/wt/odlux/apps/mediatorApp/src/assets/icons/mediatorAppIcon.svg b/sdnr/wt/odlux/apps/mediatorApp/src/assets/icons/mediatorAppIcon.svg
new file mode 100644
index 0000000..b819aa6
--- /dev/null
+++ b/sdnr/wt/odlux/apps/mediatorApp/src/assets/icons/mediatorAppIcon.svg
@@ -0,0 +1,49 @@
+<!-- highstreet technologies GmbH colour scheme
+ Grey #565656
+ LBlue #36A9E1
+ DBlue #246DA2
+ Green #003F2C / #006C4B
+ Yellw #C8D400
+ Red #D81036
+-->
+
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 980 980">
+
+<g transform="translate(0.000000,890.000000) scale(0.100000,-0.100000)">
+
+<path fill="#36A9E1" d="M4704 7791 c-314 -180 -1992 -1183 -1993 -1191 -2 -12 2183 -1311
+2198 -1307 20 5 1595 947 1856 1109 198 123 295 193 295 210 0 7 -22 26 -48
+42 -352 217 -2060 1224 -2103 1241 -9 3 -94 -40 -205 -104z"/>
+
+<path fill="#36A9E1" d="M2530 5147 l0 -1144 1098 -731 1097 -732 3 1217 c2 966 -1 1220 -10
+1229 -19 17 -2169 1304 -2179 1304 -5 0 -9 -475 -9 -1143z"/>
+
+<path fill="#36A9E1" d="M6163 5638 l-1093 -653 0 -1232 c0 -678 2 -1233 4 -1233 8 0 2161
+1293 2179 1308 16 14 17 62 16 761 -1 410 -5 961 -8 1224 l-6 477 -1092 -652z"/>
+
+<path fill="#565656" d="M7598 4488 c-3 -626 -6 -800 -17 -825 -16 -39 -136 -122 -486 -337
+-132 -81 -249 -154 -260 -162 -20 -15 -19 -16 20 -50 44 -39 414 -264 517
+-315 l66 -32 109 63 c107 62 414 243 838 493 383 226 1199 715 1219 730 19 14
+16 17 -50 59 -97 62 -1941 1168 -1948 1168 -3 0 -6 -357 -8 -792z"/>
+
+<path fill="#565656" d="M1280 4736 c-1071 -644 -1095 -659 -1093 -671 0 -5 492 -303 1092
+-661 l1091 -653 400 197 c219 108 399 199 399 202 0 3 -102 73 -226 155 -333
+220 -653 442 -691 479 -24 24 -35 45 -42 86 -6 30 -13 358 -16 728 -5 477 -10
+672 -18 671 -6 0 -409 -240 -896 -533z"/>
+
+<path fill="#565656" d="M0 2612 l0 -1149 872 -578 c1051 -697 1292 -855 1307 -855 8 0 11
+333 11 1213 l0 1212 -1063 637 c-584 350 -1077 643 -1094 652 l-33 17 0 -1149z"/>
+
+<path fill="#565656" d="M9380 3514 c-217 -129 -704 -420 -1082 -647 l-688 -412 0 -1228 0
+-1228 28 15 c56 29 810 476 1692 1003 l465 278 3 1228 c2 978 0 1227 -10 1227
+-7 0 -191 -106 -408 -236z"/>
+
+<path fill="#565656" d="M3019 2685 l-484 -243 2 -1124 c2 -1073 6 -1308 22 -1308 11 0 1943
+1147 2134 1267 l37 23 0 413 0 412 -378 250 c-331 219 -807 530 -838 548 -6 3
+-229 -103 -495 -238z"/>
+
+<path fill="#565656" d="M6249 2821 c-101 -60 -407 -244 -679 -408 l-495 -299 0 -409 0 -410
+440 -263 c1265 -755 1717 -1022 1733 -1022 9 0 12 292 12 1218 0 669 -4 1222
+-8 1228 -13 19 -788 474 -808 474 -6 0 -93 -49 -195 -109z"/>
+</g>
+</svg>
diff --git a/sdnr/wt/odlux/apps/mediatorApp/src/components/showMeditaorInfoDialog.tsx b/sdnr/wt/odlux/apps/mediatorApp/src/components/showMeditaorInfoDialog.tsx
index 2b91079..f8691ab 100644
--- a/sdnr/wt/odlux/apps/mediatorApp/src/components/showMeditaorInfoDialog.tsx
+++ b/sdnr/wt/odlux/apps/mediatorApp/src/components/showMeditaorInfoDialog.tsx
@@ -16,12 +16,12 @@
* ============LICENSE_END==========================================================================
*/
-import * as React from 'react'
+import React from 'react'
import { Dialog, DialogTitle, DialogContent, DialogActions, TextField, DialogContentText, Checkbox, Button, FormControlLabel, FormGroup } from '@mui/material';
import { IApplicationState } from '../../../../framework/src/handlers/applicationStateHandler';
import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
-import connect, { Connect } from '../../../../framework/src/flux/connect';
-import { MediatorConfigResponse } from 'models/mediatorServer';
+import { connect, Connect } from '../../../../framework/src/flux/connect';
+import { MediatorConfigResponse } from '../models/mediatorServer';
import { Panel } from '../../../../framework/src/components/material-ui/panel';
export enum MediatorInfoDialogMode {
diff --git a/sdnr/wt/odlux/apps/mediatorApp/src/plugin.tsx b/sdnr/wt/odlux/apps/mediatorApp/src/plugin.tsx
index 5ffd012..1c30cfc 100644
--- a/sdnr/wt/odlux/apps/mediatorApp/src/plugin.tsx
+++ b/sdnr/wt/odlux/apps/mediatorApp/src/plugin.tsx
@@ -17,14 +17,12 @@
*/
// app configuration and main entry point for the app
-import * as React from "react";
+import React from "react";
import { withRouter, RouteComponentProps, Route, Switch, Redirect } from 'react-router-dom';
-import { faGlobe } from '@fortawesome/free-solid-svg-icons'; // select app icon
-
import applicationManager from '../../../framework/src/services/applicationManager';
-import { IApplicationStoreState } from "../../../framework/src/store/applicationStore";
-import connect, { Connect, IDispatcher } from '../../../framework/src/flux/connect';
+
+import { connect, Connect, IDispatcher } from '../../../framework/src/flux/connect';
import { mediatorAppRootHandler } from './handlers/mediatorAppRootHandler';
import { avaliableMediatorServersReloadAction } from "./handlers/avaliableMediatorServersHandler";
@@ -33,6 +31,8 @@
import { MediatorServerSelection } from "./views/mediatorServerSelection";
import { initializeMediatorServerAsyncActionCreator } from "./actions/mediatorServerActions";
+const appIcon = require('./assets/icons/mediatorAppIcon.svg'); // select app icon
+
let currentMediatorServerId: string | undefined = undefined;
const mapDisp = (dispatcher: IDispatcher) => ({
@@ -70,13 +70,13 @@
export function register() {
const applicationApi = applicationManager.registerApplication({
name: "mediator",
- icon: faGlobe,
+ icon: appIcon,
rootComponent: FinalApp,
rootActionHandler: mediatorAppRootHandler,
menuEntry: "Mediator"
});
- // prefetch all avaliable mediator servers
+ // prefetch all available mediator servers
applicationApi.applicationStoreInitialized.then(applicationStore => {
applicationStore.dispatch(avaliableMediatorServersReloadAction)
});
diff --git a/sdnr/wt/odlux/apps/mediatorApp/src/views/mediatorApplication.tsx b/sdnr/wt/odlux/apps/mediatorApp/src/views/mediatorApplication.tsx
index 55d9b40..03ce453 100644
--- a/sdnr/wt/odlux/apps/mediatorApp/src/views/mediatorApplication.tsx
+++ b/sdnr/wt/odlux/apps/mediatorApp/src/views/mediatorApplication.tsx
@@ -15,7 +15,7 @@
* the License.
* ============LICENSE_END==========================================================================
*/
-import * as React from 'react';
+import React from 'react';
import { Theme, Tooltip } from '@mui/material';
import { WithStyles } from '@mui/styles';
@@ -33,7 +33,7 @@
import CircularProgress from '@mui/material/CircularProgress'
import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
-import connect, { Connect, IDispatcher } from '../../../../framework/src/flux/connect';
+import { connect, Connect, IDispatcher } from '../../../../framework/src/flux/connect';
import MaterialTable, { MaterialTableCtorType, ColumnType } from '../../../../framework/src/components/material-table';
import { MediatorConfig, BusySymbol, MediatorConfigResponse } from '../models/mediatorServer';
diff --git a/sdnr/wt/odlux/apps/mediatorApp/src/views/mediatorServerSelection.tsx b/sdnr/wt/odlux/apps/mediatorApp/src/views/mediatorServerSelection.tsx
index 456ed6d..fb12f26 100644
--- a/sdnr/wt/odlux/apps/mediatorApp/src/views/mediatorServerSelection.tsx
+++ b/sdnr/wt/odlux/apps/mediatorApp/src/views/mediatorServerSelection.tsx
@@ -15,7 +15,7 @@
* the License.
* ============LICENSE_END==========================================================================
*/
-import * as React from 'react';
+import React from 'react';
import { Theme, Tooltip } from '@mui/material';
import { WithStyles } from '@mui/styles';
@@ -29,7 +29,7 @@
import Refresh from '@mui/icons-material/Refresh';
import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
-import connect, { IDispatcher, Connect } from '../../../../framework/src/flux/connect';
+import { connect, IDispatcher, Connect } from '../../../../framework/src/flux/connect';
import MaterialTable, { MaterialTableCtorType, ColumnType } from '../../../../framework/src/components/material-table';
import { createAvaliableMediatorServersProperties, createAvaliableMediatorServersActions } from '../handlers/avaliableMediatorServersHandler';
diff --git a/sdnr/wt/odlux/apps/mediatorApp/tsconfig.json b/sdnr/wt/odlux/apps/mediatorApp/tsconfig.json
index b0c9b42..c950056 100644
--- a/sdnr/wt/odlux/apps/mediatorApp/tsconfig.json
+++ b/sdnr/wt/odlux/apps/mediatorApp/tsconfig.json
@@ -4,7 +4,7 @@
"outDir": "./dist",
"sourceMap": true,
"forceConsistentCasingInFileNames": true,
- "allowSyntheticDefaultImports": false,
+ "allowSyntheticDefaultImports": true,
"allowUnreachableCode": false,
"allowUnusedLabels": false,
"noFallthroughCasesInSwitch": true,
diff --git a/sdnr/wt/odlux/apps/mediatorApp/webpack.config.js b/sdnr/wt/odlux/apps/mediatorApp/webpack.config.js
index f626632..813c28f 100644
--- a/sdnr/wt/odlux/apps/mediatorApp/webpack.config.js
+++ b/sdnr/wt/odlux/apps/mediatorApp/webpack.config.js
@@ -57,6 +57,16 @@
use: [{
loader: "babel-loader"
}]
+ },{
+ //don't minify images
+ test: /\.(png|gif|jpg|svg)$/,
+ use: [{
+ loader: 'url-loader',
+ options: {
+ limit: 10,
+ name: './images/[name].[ext]'
+ }
+ }]
}]
},
diff --git a/sdnr/wt/odlux/apps/minimumApp/pom.xml b/sdnr/wt/odlux/apps/minimumApp/pom.xml
index 57b0883..a58acd3 100644
--- a/sdnr/wt/odlux/apps/minimumApp/pom.xml
+++ b/sdnr/wt/odlux/apps/minimumApp/pom.xml
@@ -19,6 +19,7 @@
~ ============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>
@@ -139,7 +140,7 @@
<!-- optional: default phase is "generate-resources" -->
<phase>initialize</phase>
<configuration>
- <nodeVersion>v12.13.0</nodeVersion>
+ <nodeVersion>v12.22.0</nodeVersion>
<yarnVersion>v1.22.10</yarnVersion>
</configuration>
</execution>
diff --git a/sdnr/wt/odlux/apps/minimumApp/src/assets/icons/minimumAppIcon.svg b/sdnr/wt/odlux/apps/minimumApp/src/assets/icons/minimumAppIcon.svg
new file mode 100644
index 0000000..298eaa1
--- /dev/null
+++ b/sdnr/wt/odlux/apps/minimumApp/src/assets/icons/minimumAppIcon.svg
@@ -0,0 +1,27 @@
+<!-- highstreet technologies GmbH colour scheme
+ Grey #565656
+ LBlue #36A9E1
+ DBlue #246DA2
+ Green #003F2C / #006C4B
+ Yellw #C8D400
+ Red #D81036
+-->
+
+<svg version="1.0" xmlns="http://www.w3.org/2000/svg" viewBox="310 250 400 400">
+
+<g transform="translate(0,1024) scale(0.1,-0.1)">
+
+<path fill="#565656" d="M4926 7634 c-126 -17 -209 -38 -318 -79 -79 -31 -195 -89 -208 -104
+-10 -12 -69 -51 -77 -51 -4 0 -42 -28 -83 -63 -227 -190 -375 -475 -375 -722
+0 -81 3 -95 30 -143 111 -201 365 -252 514 -103 46 46 88 124 121 226 28 87
+109 255 153 315 67 95 172 168 275 192 86 20 268 21 346 2 113 -28 152 -50
+240 -137 64 -63 88 -95 104 -137 49 -125 52 -225 12 -332 -38 -102 -132 -209
+-360 -409 -153 -134 -329 -309 -375 -374 -97 -136 -148 -274 -166 -448 -19
+-192 12 -305 104 -379 64 -50 141 -72 228 -65 82 7 125 24 177 71 49 45 73
+100 105 241 59 258 63 263 528 687 218 198 295 284 374 419 134 230 138 543 9
+803 -101 202 -252 349 -474 461 -246 124 -573 172 -884 129z"/>
+
+<path fill="#36A9E1" d="M 5098 4587 C 4582 4587 4582 3845 5098 3845 C 5614 3847 5614 4585 5098 4587 Z"/>
+
+</g>
+</svg>
diff --git a/sdnr/wt/odlux/apps/minimumApp/src/handlers/minimumAppRootHandler.ts b/sdnr/wt/odlux/apps/minimumApp/src/handlers/minimumAppRootHandler.ts
index 463ad21..4a4dc61 100644
--- a/sdnr/wt/odlux/apps/minimumApp/src/handlers/minimumAppRootHandler.ts
+++ b/sdnr/wt/odlux/apps/minimumApp/src/handlers/minimumAppRootHandler.ts
@@ -19,6 +19,7 @@
import { combineActionHandler } from '../../../../framework/src/flux/middleware';
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
export interface IMinimumAppStoreState {
@@ -26,7 +27,7 @@
declare module '../../../../framework/src/store/applicationStore' {
interface IApplicationStoreState {
- minimum: IMinimumAppStoreState
+ minimum: IMinimumAppStoreState;
}
}
diff --git a/sdnr/wt/odlux/apps/minimumApp/src/plugin.tsx b/sdnr/wt/odlux/apps/minimumApp/src/plugin.tsx
index 3095ba7..5c8500a 100644
--- a/sdnr/wt/odlux/apps/minimumApp/src/plugin.tsx
+++ b/sdnr/wt/odlux/apps/minimumApp/src/plugin.tsx
@@ -17,19 +17,19 @@
*/
// app configuration and main entry point for the app
-import * as React from "react";
-import { withRouter, RouteComponentProps, Route, Switch, Redirect } from 'react-router-dom';
-
-import { faLock } from '@fortawesome/free-solid-svg-icons'; // select app icon
+import React, { FC } from 'react';
+import { withRouter, RouteComponentProps } from 'react-router-dom';
import applicationManager from '../../../framework/src/services/applicationManager';
-import connect, { Connect } from '../../../framework/src/flux/connect';
+import { connect, Connect } from '../../../framework/src/flux/connect';
import { minimumAppRootHandler } from './handlers/minimumAppRootHandler';
+// const appIcon = require('./assets/icons/minimunAppIcon.svg'); // select app icon
+
type AppProps = RouteComponentProps & Connect;
-const App = (props: AppProps) => (
+const App: FC<AppProps> = (_props) => (
<div>Start your app here!!</div>
);
@@ -37,11 +37,11 @@
export function register() {
applicationManager.registerApplication({
- name: "minimum",
- icon: faLock,
+ name: 'minimum',
+ // icon: appIcon,
rootComponent: FinalApp,
rootActionHandler: minimumAppRootHandler,
- menuEntry: "Minimum"
+ menuEntry: 'Minimum',
});
}
diff --git a/sdnr/wt/odlux/apps/minimumApp/tsconfig.json b/sdnr/wt/odlux/apps/minimumApp/tsconfig.json
index a66b5d8..ca65092 100644
--- a/sdnr/wt/odlux/apps/minimumApp/tsconfig.json
+++ b/sdnr/wt/odlux/apps/minimumApp/tsconfig.json
@@ -4,7 +4,7 @@
"outDir": "./dist",
"sourceMap": true,
"forceConsistentCasingInFileNames": true,
- "allowSyntheticDefaultImports": false,
+ "allowSyntheticDefaultImports": true,
"allowUnreachableCode": false,
"allowUnusedLabels": false,
"noFallthroughCasesInSwitch": true,
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/pom.xml b/sdnr/wt/odlux/apps/performanceHistoryApp/pom.xml
index 9c594ef..78e38c0 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/pom.xml
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/pom.xml
@@ -19,6 +19,7 @@
~ ============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>
@@ -139,7 +140,7 @@
<!-- optional: default phase is "generate-resources" -->
<phase>initialize</phase>
<configuration>
- <nodeVersion>v12.13.0</nodeVersion>
+ <nodeVersion>v12.22.0</nodeVersion>
<yarnVersion>v1.22.10</yarnVersion>
</configuration>
</execution>
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/actions/deviceListActions.ts b/sdnr/wt/odlux/apps/performanceHistoryApp/src/actions/deviceListActions.ts
index 2b8e6e2..fbbf2c5 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/actions/deviceListActions.ts
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/actions/deviceListActions.ts
@@ -17,6 +17,7 @@
*/
import { Action } from '../../../../framework/src/flux/action';
import { Dispatch } from '../../../../framework/src/flux/store';
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
import { DeviceListType } from '../models/deviceListType';
@@ -56,7 +57,7 @@
deviceListFromPerf24History.forEach(deviceList24h => {
if (deviceListFromPerfHistory.findIndex(deviceList15min => deviceList15min.nodeId === deviceList24h.nodeId) < 0) {
deviceListFromPerfHistory.push(deviceList24h);
- };
+ }
});
return deviceListFromPerfHistory && dispatch(new AllDeviceListLoadedAction(deviceListFromPerfHistory));
};
@@ -75,4 +76,4 @@
*/
export const updateMountIdActionCreator = (nodeId: string) => async (dispatch: Dispatch) => {
return dispatch(new UpdateMountId(nodeId));
-}
+};
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/actions/ltpAction.ts b/sdnr/wt/odlux/apps/performanceHistoryApp/src/actions/ltpAction.ts
index a678ed7..1c333ab 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/actions/ltpAction.ts
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/actions/ltpAction.ts
@@ -50,18 +50,23 @@
}
}
-export class NoLtpsFoundAction extends BaseAction {
- constructor() {
- super();
- }
-}
+export class NoLtpsFoundAction extends BaseAction { }
-export class ResetLtpsAction extends BaseAction {
- constructor() {
- super();
- }
-}
+export class ResetLtpsAction extends BaseAction { }
+const getDistinctLtps = (distinctLtps: LtpIds[], selectedLtp: string, selectFirstLtp?: Function, resetLtp?: Function) => {
+ let ltpNotSelected: boolean = true;
+ // eslint-disable-next-line @typescript-eslint/no-unused-expressions
+ selectFirstLtp && selectFirstLtp(distinctLtps[0].key);
+ distinctLtps.forEach((value: LtpIds) => {
+ if (value.key === selectedLtp) {
+ ltpNotSelected = false;
+ }
+ });
+ // eslint-disable-next-line @typescript-eslint/no-unused-expressions
+ resetLtp && resetLtp(ltpNotSelected);
+ return distinctLtps;
+};
/**
* Represents an asynchronous thunk action to load available distinctLtps by networkElement from the database and set the returned first Ltp as default.
@@ -87,14 +92,3 @@
});
};
-const getDistinctLtps = (distinctLtps: LtpIds[], selectedLtp: string, selectFirstLtp?: Function, resetLtp?: Function) => {
- let ltpNotSelected: boolean = true;
- selectFirstLtp && selectFirstLtp(distinctLtps[0].key);
- distinctLtps.forEach((value: LtpIds) => {
- if (value.key === selectedLtp) {
- ltpNotSelected = false;
- }
- });
- resetLtp && resetLtp(ltpNotSelected);
- return distinctLtps;
-}
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/actions/reloadAction.ts b/sdnr/wt/odlux/apps/performanceHistoryApp/src/actions/reloadAction.ts
index 7d6ecfe..6bd54ce 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/actions/reloadAction.ts
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/actions/reloadAction.ts
@@ -16,10 +16,10 @@
* ============LICENSE_END==========================================================================
*/
-import { Action } from "../../../../framework/src/flux/action";
+import { Action } from '../../../../framework/src/flux/action';
export class ReloadAction extends Action {
- constructor(public show: boolean) {
- super();
- }
+ constructor(public show: boolean) {
+ super();
+ }
}
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/actions/timeChangeAction.ts b/sdnr/wt/odlux/apps/performanceHistoryApp/src/actions/timeChangeAction.ts
index a069af1..13214b2 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/actions/timeChangeAction.ts
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/actions/timeChangeAction.ts
@@ -16,6 +16,7 @@
* ============LICENSE_END==========================================================================
*/
import { Action } from '../../../../framework/src/flux/action';
+
import { PmDataInterval } from '../models/performanceDataType';
export class TimeChangeAction extends Action {
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/actions/toggleActions.ts b/sdnr/wt/odlux/apps/performanceHistoryApp/src/actions/toggleActions.ts
index 0efaaae..7921ea5 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/actions/toggleActions.ts
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/actions/toggleActions.ts
@@ -16,24 +16,21 @@
* ============LICENSE_END==========================================================================
*/
-import { Action } from "../../../../framework/src/flux/action";
-import { currentViewType } from "../models/toggleDataType";
+import { Action } from '../../../../framework/src/flux/action';
+
+import { currentViewType } from '../models/toggleDataType';
export class SetSubViewAction extends Action {
- constructor(public currentView: currentViewType, public selectedTab: "chart" | "table") {
- super();
- }
+ constructor(public currentView: currentViewType, public selectedTab: 'chart' | 'table') {
+ super();
+ }
}
-export class ResetAllSubViewsAction extends Action {
- constructor() {
- super();
- }
-}
+export class ResetAllSubViewsAction extends Action { }
export class SetFilterVisibility extends Action {
- constructor(public currentView: currentViewType, public isVisible: boolean) {
- super();
- }
+ constructor(public currentView: currentViewType, public isVisible: boolean) {
+ super();
+ }
}
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/assets/icons/performanceHistoryAppIcon.svg b/sdnr/wt/odlux/apps/performanceHistoryApp/src/assets/icons/performanceHistoryAppIcon.svg
new file mode 100644
index 0000000..982f1ee
--- /dev/null
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/assets/icons/performanceHistoryAppIcon.svg
@@ -0,0 +1,50 @@
+<!-- highstreet technologies GmbH colour scheme
+ Grey #565656
+ LBlue #36A9E1
+ DBlue #246DA2
+ Green #003F2C / #006C4B
+ Yellw #C8D400
+ Red #D81036
+-->
+
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 500 500">
+<g>
+ <g>
+ <path fill="#006C4B" d="M 0 447.672 C 0 460.238 4.471 470.99 13.417 479.936 C 22.368 488.882 33.119 493.355 45.681 493.355 H 429.405 C 441.965 493.355 452.717 488.882 461.663 479.936 C 470.608 470.991 475.085 460.239 475.085 447.672 L 0 447.672 Z"/>
+ <rect fill="#565656" x="73.092" y="310.635" width="73.089" height="109.632"/>
+ <rect fill="#565656" x="182.728" y="164.452" width="73.085" height="255.814"/>
+ <rect fill="#565656" x="292.362" y="237.541" width="73.083" height="182.726"/>
+ <rect fill="#565656" x="401.994" y="127.907" width="73.091" height="292.36"/>
+ </g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+</svg>
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/adaptiveModulation.tsx b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/adaptiveModulation.tsx
index 17b1374..5dac0bc 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/adaptiveModulation.tsx
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/adaptiveModulation.tsx
@@ -15,37 +15,36 @@
* the License.
* ============LICENSE_END==========================================================================
*/
-import * as React from 'react';
+import React from 'react';
+import { RouteComponentProps, withRouter } from 'react-router-dom';
-import { withRouter, RouteComponentProps } from 'react-router-dom';
-
-import { MaterialTable, ColumnType, ColumnModel, MaterialTableCtorType } from '../../../../framework/src/components/material-table';
+import { ColumnModel, 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 connect, { Connect, IDispatcher } from '../../../../framework/src/flux/connect';
-import { AdaptiveModulationDataType, AdaptiveModulationDatabaseDataType } from '../models/adaptiveModulationDataType';
+import { SetFilterVisibility, SetSubViewAction } from '../actions/toggleActions';
+import { createAdaptiveModulationActions, createAdaptiveModulationProperties } from '../handlers/adaptiveModulationHandler';
+import { AdaptiveModulationDatabaseDataType, AdaptiveModulationDataType } from '../models/adaptiveModulationDataType';
import { IDataSet, IDataSetsObject } from '../models/chartTypes';
-import { createAdaptiveModulationProperties, createAdaptiveModulationActions } from '../handlers/adaptiveModulationHandler';
import { lineChart, sortDataByTimeStamp } from '../utils/chartUtils';
import { addColumnLabels } from '../utils/tableUtils';
import ToggleContainer from './toggleContainer';
-import { SetSubViewAction, SetFilterVisibility } from '../actions/toggleActions';
const mapProps = (state: IApplicationStoreState) => ({
adaptiveModulationProperties: createAdaptiveModulationProperties(state),
currentView: state.performanceHistory.subViews.adaptiveModulation.subView,
isFilterVisible: state.performanceHistory.subViews.adaptiveModulation.isFilterVisible,
- existingFilter: state.performanceHistory.adaptiveModulation.filter
+ existingFilter: state.performanceHistory.adaptiveModulation.filter,
});
const mapDisp = (dispatcher: IDispatcher) => ({
adaptiveModulationActions: createAdaptiveModulationActions(dispatcher.dispatch),
- setSubView: (value: "chart" | "table") => dispatcher.dispatch(new SetSubViewAction("adaptiveModulation", value)),
- toggleFilterButton: (value: boolean) => { dispatcher.dispatch(new SetFilterVisibility("adaptiveModulation", value)) },
+ setSubView: (value: 'chart' | 'table') => dispatcher.dispatch(new SetSubViewAction('adaptiveModulation', value)),
+ toggleFilterButton: (value: boolean) => { dispatcher.dispatch(new SetFilterVisibility('adaptiveModulation', value)); },
});
type AdaptiveModulationComponentProps = RouteComponentProps & Connect<typeof mapProps, typeof mapDisp> & {
- selectedTimePeriod: string
+ selectedTimePeriod: string;
};
const AdaptiveModulationTable = MaterialTable as MaterialTableCtorType<AdaptiveModulationDataType>;
@@ -53,21 +52,20 @@
/**
* The Component which gets the adaptiveModulation data from the database based on the selected time period.
*/
-class AdaptiveModulationComponent extends React.Component<AdaptiveModulationComponentProps>{
-
+class AdaptiveModulationComponent extends React.Component<AdaptiveModulationComponentProps> {
onToggleFilterButton = () => {
this.props.toggleFilterButton(!this.props.isFilterVisible);
- }
+ };
- onChange = (value: "chart" | "table") => {
+ onChange = (value: 'chart' | 'table') => {
this.props.setSubView(value);
- }
+ };
onFilterChanged = (property: string, filterTerm: string) => {
this.props.adaptiveModulationActions.onFilterChanged(property, filterTerm);
if (!this.props.adaptiveModulationProperties.showFilter)
this.props.adaptiveModulationActions.onToggleFilter(false);
- }
+ };
render(): JSX.Element {
const properties = this.props.adaptiveModulationProperties;
@@ -75,11 +73,11 @@
const chartPagedData = this.getChartDataValues(properties.rows);
const adaptiveModulationColumns: ColumnModel<AdaptiveModulationDataType>[] = [
- { property: "radioSignalId", title: "Radio signal", type: ColumnType.text },
- { property: "scannerId", title: "Scanner ID", type: ColumnType.text },
- { property: "timeStamp", title: "End Time", type: ColumnType.text },
+ { property: 'radioSignalId', title: 'Radio signal', type: ColumnType.text },
+ { property: 'scannerId', title: 'Scanner ID', type: ColumnType.text },
+ { property: 'timeStamp', title: 'End Time', type: ColumnType.text },
{
- property: "suspectIntervalFlag", title: "Suspect Interval", type: ColumnType.boolean
+ property: 'suspectIntervalFlag', title: 'Suspect Interval', type: ColumnType.boolean,
}];
chartPagedData.datasets.forEach(ds => {
@@ -88,13 +86,14 @@
return (
<>
- <ToggleContainer onToggleFilterButton={this.onToggleFilterButton} showFilter={this.props.isFilterVisible} existingFilter={this.props.adaptiveModulationProperties.filter} onFilterChanged={this.onFilterChanged} selectedValue={this.props.currentView} onChange={this.onChange}>
+ <ToggleContainer onToggleFilterButton={this.onToggleFilterButton} showFilter={this.props.isFilterVisible}
+ existingFilter={this.props.adaptiveModulationProperties.filter} onFilterChanged={this.onFilterChanged} selectedValue={this.props.currentView} onChange={this.onChange}>
{lineChart(chartPagedData)}
- <AdaptiveModulationTable stickyHeader idProperty={"_id"} tableId="adaptive-modulation-table" columns={adaptiveModulationColumns} {...properties} {...actions} />
+ <AdaptiveModulationTable stickyHeader idProperty={'_id'} tableId="adaptive-modulation-table" columns={adaptiveModulationColumns} {...properties} {...actions} />
</ToggleContainer>
</>
);
- };
+ }
/**
* This function gets the performance values for Adaptive modulation according on the chartjs dataset structure
@@ -102,345 +101,345 @@
*/
private getChartDataValues = (rows: AdaptiveModulationDataType[]): IDataSetsObject => {
- const _rows = [...rows];
- sortDataByTimeStamp(_rows);
+ const data_rows = [...rows];
+ sortDataByTimeStamp(data_rows);
const datasets: IDataSet[] = [{
- name: "time2StatesS",
- label: "QAM2S",
+ name: 'time2StatesS',
+ label: 'QAM2S',
borderColor: '#62a309fc',
bezierCurve: false,
lineTension: 0,
fill: false,
data: [],
- columnLabel: "QAM2S",
+ columnLabel: 'QAM2S',
}, {
- name: "time2States",
- label: "QAM2",
+ name: 'time2States',
+ label: 'QAM2',
borderColor: '#62a309fc',
bezierCurve: false,
lineTension: 0,
fill: false,
data: [],
- columnLabel: "QAM2",
+ columnLabel: 'QAM2',
}, {
- name: "time2StatesL",
- label: "QAM2L",
+ name: 'time2StatesL',
+ label: 'QAM2L',
borderColor: '#62a309fc',
bezierCurve: false,
lineTension: 0,
fill: false,
data: [],
- columnLabel: "QAM2L",
+ columnLabel: 'QAM2L',
}, {
- name: "time4StatesS",
- label: "QAM4S",
+ name: 'time4StatesS',
+ label: 'QAM4S',
borderColor: '#b308edde',
bezierCurve: false,
lineTension: 0,
fill: false,
data: [],
- columnLabel: "QAM4S",
+ columnLabel: 'QAM4S',
}, {
- name: "time4States",
- label: "QAM4",
+ name: 'time4States',
+ label: 'QAM4',
borderColor: '#b308edde',
bezierCurve: false,
lineTension: 0,
fill: false,
data: [],
- columnLabel: "QAM4",
+ columnLabel: 'QAM4',
}, {
- name: "time4StatesL",
- label: "QAM4L",
+ name: 'time4StatesL',
+ label: 'QAM4L',
borderColor: '#b308edde',
bezierCurve: false,
lineTension: 0,
fill: false,
data: [],
- columnLabel: "QAM4L",
+ columnLabel: 'QAM4L',
}, {
- name: "time16StatesS",
- label: "QAM16S",
+ name: 'time16StatesS',
+ label: 'QAM16S',
borderColor: '#9b15e2',
bezierCurve: false,
lineTension: 0,
fill: false,
data: [],
- columnLabel: "QAM16S",
+ columnLabel: 'QAM16S',
}, {
- name: "time16States",
- label: "QAM16",
+ name: 'time16States',
+ label: 'QAM16',
borderColor: '#9b15e2',
bezierCurve: false,
lineTension: 0,
fill: false,
data: [],
- columnLabel: "QAM16",
+ columnLabel: 'QAM16',
}, {
- name: "time16StatesL",
- label: "QAM16L",
+ name: 'time16StatesL',
+ label: 'QAM16L',
borderColor: '#9b15e2',
bezierCurve: false,
lineTension: 0,
fill: false,
data: [],
- columnLabel: "QAM16L",
+ columnLabel: 'QAM16L',
}, {
- name: "time32StatesS",
- label: "QAM32S",
+ name: 'time32StatesS',
+ label: 'QAM32S',
borderColor: '#2704f5f0',
bezierCurve: false,
lineTension: 0,
fill: false,
data: [],
- columnLabel: "QAM32S",
+ columnLabel: 'QAM32S',
}, {
- name: "time32States",
- label: "QAM32",
+ name: 'time32States',
+ label: 'QAM32',
borderColor: '#2704f5f0',
bezierCurve: false,
lineTension: 0,
fill: false,
data: [],
- columnLabel: "QAM32",
+ columnLabel: 'QAM32',
}, {
- name: "time32StatesL",
- label: "QAM32L",
+ name: 'time32StatesL',
+ label: 'QAM32L',
borderColor: '#2704f5f0',
bezierCurve: false,
lineTension: 0,
fill: false,
data: [],
- columnLabel: "QAM32L",
+ columnLabel: 'QAM32L',
}, {
- name: "time64StatesS",
- label: "QAM64S",
+ name: 'time64StatesS',
+ label: 'QAM64S',
borderColor: '#347692',
bezierCurve: false,
lineTension: 0,
fill: false,
data: [],
- columnLabel: "QAM64S",
+ columnLabel: 'QAM64S',
}, {
- name: "time64States",
- label: "QAM64",
+ name: 'time64States',
+ label: 'QAM64',
borderColor: '#347692',
bezierCurve: false,
lineTension: 0,
fill: false,
data: [],
- columnLabel: "QAM64",
+ columnLabel: 'QAM64',
}, {
- name: "time64StatesL",
- label: "QAM64L",
+ name: 'time64StatesL',
+ label: 'QAM64L',
borderColor: '#347692',
bezierCurve: false,
lineTension: 0,
fill: false,
data: [],
- columnLabel: "QAM64L",
+ columnLabel: 'QAM64L',
}, {
- name: "time128StatesS",
- label: "QAM128S",
+ name: 'time128StatesS',
+ label: 'QAM128S',
borderColor: '#885e22',
bezierCurve: false,
lineTension: 0,
fill: false,
data: [],
- columnLabel: "QAM128S",
+ columnLabel: 'QAM128S',
}, {
- name: "time128States",
- label: "QAM128",
+ name: 'time128States',
+ label: 'QAM128',
borderColor: '#885e22',
bezierCurve: false,
lineTension: 0,
fill: false,
data: [],
- columnLabel: "QAM128",
+ columnLabel: 'QAM128',
}, {
- name: "time128StatesL",
- label: "QAM128L",
+ name: 'time128StatesL',
+ label: 'QAM128L',
borderColor: '#885e22',
bezierCurve: false,
lineTension: 0,
fill: false,
data: [],
- columnLabel: "QAM128L",
+ columnLabel: 'QAM128L',
}, {
- name: "time256StatesS",
- label: "QAM256S",
+ name: 'time256StatesS',
+ label: 'QAM256S',
borderColor: '#de07807a',
bezierCurve: false,
lineTension: 0,
fill: false,
data: [],
- columnLabel: "QAM256S",
+ columnLabel: 'QAM256S',
}, {
- name: "time256States",
- label: "QAM256",
+ name: 'time256States',
+ label: 'QAM256',
borderColor: '#de07807a',
bezierCurve: false,
lineTension: 0,
fill: false,
data: [],
- columnLabel: "QAM256",
+ columnLabel: 'QAM256',
}, {
- name: "time256StatesL",
- label: "QAM256L",
+ name: 'time256StatesL',
+ label: 'QAM256L',
borderColor: '#de07807a',
bezierCurve: false,
lineTension: 0,
fill: false,
data: [],
- columnLabel: "QAM256L",
+ columnLabel: 'QAM256L',
}, {
- name: "time512StatesS",
- label: "QAM512S",
+ name: 'time512StatesS',
+ label: 'QAM512S',
borderColor: '#8fdaacde',
bezierCurve: false,
lineTension: 0,
fill: false,
data: [],
- columnLabel: "QAM512S",
+ columnLabel: 'QAM512S',
}, {
- name: "time512States",
- label: "QAM512",
+ name: 'time512States',
+ label: 'QAM512',
borderColor: '#8fdaacde',
bezierCurve: false,
lineTension: 0,
fill: false,
data: [],
- columnLabel: "QAM512",
+ columnLabel: 'QAM512',
}, {
- name: "time512StatesL",
- label: "QAM512L",
+ name: 'time512StatesL',
+ label: 'QAM512L',
borderColor: '#8fdaacde',
bezierCurve: false,
lineTension: 0,
fill: false,
data: [],
- columnLabel: "QAM512L",
+ columnLabel: 'QAM512L',
}, {
- name: "time1024StatesS",
- label: "QAM1024S",
+ name: 'time1024StatesS',
+ label: 'QAM1024S',
borderColor: '#435b22',
bezierCurve: false,
lineTension: 0,
fill: false,
data: [],
- columnLabel: "QAM1024S",
+ columnLabel: 'QAM1024S',
}, {
- name: "time1024States",
- label: "QAM1024",
+ name: 'time1024States',
+ label: 'QAM1024',
borderColor: '#435b22',
bezierCurve: false,
lineTension: 0,
fill: false,
data: [],
- columnLabel: "QAM1024",
+ columnLabel: 'QAM1024',
}, {
- name: "time1024StatesL",
- label: "QAM1024L",
+ name: 'time1024StatesL',
+ label: 'QAM1024L',
borderColor: '#435b22',
bezierCurve: false,
lineTension: 0,
fill: false,
data: [],
- columnLabel: "QAM1024L",
+ columnLabel: 'QAM1024L',
}, {
- name: "time2048StatesS",
- label: "QAM2048S",
+ name: 'time2048StatesS',
+ label: 'QAM2048S',
borderColor: '#e87a5b',
bezierCurve: false,
lineTension: 0,
fill: false,
data: [],
- columnLabel: "QAM2048S",
+ columnLabel: 'QAM2048S',
}, {
- name: "time2048States",
- label: "QAM2048",
+ name: 'time2048States',
+ label: 'QAM2048',
borderColor: '#e87a5b',
bezierCurve: false,
lineTension: 0,
fill: false,
data: [],
- columnLabel: "QAM2048",
+ columnLabel: 'QAM2048',
}, {
- name: "time2048StatesL",
- label: "QAM2048L",
+ name: 'time2048StatesL',
+ label: 'QAM2048L',
borderColor: '#e87a5b',
bezierCurve: false,
lineTension: 0,
fill: false,
data: [],
- columnLabel: "QAM2048L",
+ columnLabel: 'QAM2048L',
}, {
- name: "time4096StatesS",
- label: "QAM4096S",
+ name: 'time4096StatesS',
+ label: 'QAM4096S',
borderColor: '#5be878',
bezierCurve: false,
lineTension: 0,
fill: false,
data: [],
- columnLabel: "QAM4096S",
+ columnLabel: 'QAM4096S',
}, {
- name: "time4096States",
- label: "QAM4096",
+ name: 'time4096States',
+ label: 'QAM4096',
borderColor: '#5be878',
bezierCurve: false,
lineTension: 0,
fill: false,
data: [],
- columnLabel: "QAM4096",
+ columnLabel: 'QAM4096',
}, {
- name: "time4096StatesL",
- label: "QAM4096L",
+ name: 'time4096StatesL',
+ label: 'QAM4096L',
borderColor: '#5be878',
bezierCurve: false,
lineTension: 0,
fill: false,
data: [],
- columnLabel: "QAM4096L",
+ columnLabel: 'QAM4096L',
}, {
- name: "time8192StatesS",
- label: "QAM8192s",
+ name: 'time8192StatesS',
+ label: 'QAM8192s',
borderColor: '#cb5be8',
bezierCurve: false,
lineTension: 0,
fill: false,
data: [],
- columnLabel: "QAM8192S",
+ columnLabel: 'QAM8192S',
}, {
- name: "time8192States",
- label: "QAM8192",
+ name: 'time8192States',
+ label: 'QAM8192',
borderColor: '#cb5be8',
bezierCurve: false,
lineTension: 0,
fill: false,
data: [],
- columnLabel: "QAM8192",
+ columnLabel: 'QAM8192',
}, {
- name: "time8192StatesL",
- label: "QAM8192L",
+ name: 'time8192StatesL',
+ label: 'QAM8192L',
borderColor: '#cb5be8',
bezierCurve: false,
lineTension: 0,
fill: false,
data: [],
- columnLabel: "QAM8192L",
- }
+ columnLabel: 'QAM8192L',
+ },
];
- _rows.forEach(row => {
- row.time2StatesS = row.performanceData.time2StatesS
+ data_rows.forEach(row => {
+ row.time2StatesS = row.performanceData.time2StatesS;
row.time2States = row.performanceData.time2States;
row.time2StatesL = row.performanceData.time2StatesL;
- row.time4StatesS = row.performanceData.time4StatesS
+ row.time4StatesS = row.performanceData.time4StatesS;
row.time4States = row.performanceData.time4States;
row.time4StatesL = row.performanceData.time4StatesL;
row.time16StatesS = row.performanceData.time16StatesS;
@@ -475,16 +474,16 @@
row.time8192StatesL = row.performanceData.time8192StatesL;
datasets.forEach(ds => {
ds.data.push({
- x: row["timeStamp" as keyof AdaptiveModulationDataType] as string,
- y: row.performanceData[ds.name as keyof AdaptiveModulationDatabaseDataType] as string
+ x: row['timeStamp' as keyof AdaptiveModulationDataType] as string,
+ y: row.performanceData[ds.name as keyof AdaptiveModulationDatabaseDataType] as string,
});
});
});
return {
- datasets: datasets
+ datasets: datasets,
};
- }
+ };
}
const AdaptiveModulation = withRouter(connect(mapProps, mapDisp)(AdaptiveModulationComponent));
export default AdaptiveModulation;
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/chartFilter.tsx b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/chartFilter.tsx
index e66e6c1..021f74a 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/chartFilter.tsx
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/chartFilter.tsx
@@ -18,57 +18,58 @@
import * as React from 'react';
-import { TextField, Typography, Select, MenuItem, FormControl, InputLabel } from '@mui/material';
+
+import { TextField, Select, MenuItem, FormControl, InputLabel } from '@mui/material';
import makeStyles from '@mui/styles/makeStyles';
const styles = makeStyles({
- filterInput: {
- marginRight: "15px"
- },
- filterContainer: {
- marginLeft: "90px"
- }
+ filterInput: {
+ marginRight: '15px',
+ },
+ filterContainer: {
+ marginLeft: '90px',
+ },
});
-type filterProps = { isVisible: boolean, onFilterChanged: (property: string, filterTerm: string) => void, filters: any };
+type filterProps = { isVisible: boolean; onFilterChanged: (property: string, filterTerm: string) => void; filters: any };
const ChartFilter: React.FunctionComponent<filterProps> = (props) => {
- const classes = styles();
+ const classes = styles();
- // make sure suspectIntervalFlag is a string to show the correct value in the select element
+ // make sure suspectIntervalFlag is a string to show the correct value in the select element
- const suspectIntervalFlag = props.filters.suspectIntervalFlag === undefined ? undefined : props.filters.suspectIntervalFlag.toString();
- return (
- <>
- {
- props.isVisible &&
- <div className={classes.filterContainer}>
- <TextField variant="standard" inputProps={{'aria-label': 'radio-signal-filter'}} className={classes.filterInput} label="Radio Signal" value={props.filters.radioSignalId || ''} onChange={(event) => props.onFilterChanged("radioSignalId", event.target.value)} InputLabelProps={{
- shrink: true,
- }} />
- <TextField variant="standard" inputProps={{'aria-label': 'scanner-id-filter'}} className={classes.filterInput} label="Scanner ID" value={props.filters.scannerId || ''} onChange={(event) => props.onFilterChanged("scannerId", event.target.value)} InputLabelProps={{
- shrink: true,
- }} />
- <TextField variant="standard" inputProps={{'aria-label': 'end-time-filter'}} className={classes.filterInput} label="End Time" value={props.filters.timeStamp || ''} onChange={(event) => props.onFilterChanged("timeStamp", event.target.value)} InputLabelProps={{
- shrink: true,
- }} />
- <FormControl variant="standard">
- <InputLabel id="suspect-interval-label" shrink>Suspect Interval</InputLabel>
+ const suspectIntervalFlag = props.filters.suspectIntervalFlag === undefined ? undefined : props.filters.suspectIntervalFlag.toString();
+ return (
+ <>
+ {
+ props.isVisible &&
+ <div className={classes.filterContainer}>
+ <TextField variant="standard" inputProps={{ 'aria-label': 'radio-signal-filter' }} className={classes.filterInput}
+ label="Radio Signal" value={props.filters.radioSignalId || ''} onChange={(event) => props.onFilterChanged('radioSignalId', event.target.value)} InputLabelProps={{
+ shrink: true,
+ }} />
+ <TextField variant="standard" inputProps={{ 'aria-label': 'scanner-id-filter' }} className={classes.filterInput} label="Scanner ID" value={props.filters.scannerId || ''} onChange={(event) => props.onFilterChanged('scannerId', event.target.value)} InputLabelProps={{
+ shrink: true,
+ }} />
+ <TextField variant="standard" inputProps={{ 'aria-label': 'end-time-filter' }} className={classes.filterInput} label="End Time" value={props.filters.timeStamp || ''} onChange={(event) => props.onFilterChanged('timeStamp', event.target.value)} InputLabelProps={{
+ shrink: true,
+ }} />
+ <FormControl variant="standard">
+ <InputLabel id="suspect-interval-label" shrink>Suspect Interval</InputLabel>
- <Select variant="standard" aria-label="suspect-interval-selection" labelId="suspect-interval-label" value={suspectIntervalFlag || ''} onChange={(event) => props.onFilterChanged("suspectIntervalFlag", event.target.value as string)}>
- <MenuItem value={undefined} aria-label="none">None</MenuItem>
- <MenuItem value={"true"} aria-label="true">true</MenuItem>
- <MenuItem value={"false"} aria-label="false">false</MenuItem>
- </Select>
- </FormControl>
- </ div>
- }
- </>
- )
-
-}
+ <Select variant="standard" aria-label="suspect-interval-selection" labelId="suspect-interval-label" value={suspectIntervalFlag || ''} onChange={(event) => props.onFilterChanged('suspectIntervalFlag', event.target.value as string)}>
+ <MenuItem value={undefined} aria-label="none">None</MenuItem>
+ <MenuItem value={'true'} aria-label="true">true</MenuItem>
+ <MenuItem value={'false'} aria-label="false">false</MenuItem>
+ </Select>
+ </FormControl>
+ </ div>
+ }
+ </>
+ );
+};
export default ChartFilter;
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/crossPolarDiscrimination.tsx b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/crossPolarDiscrimination.tsx
index 14cc02d..5f925a9 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/crossPolarDiscrimination.tsx
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/crossPolarDiscrimination.tsx
@@ -15,20 +15,19 @@
* the License.
* ============LICENSE_END==========================================================================
*/
-import * as React from 'react';
+import React from 'react';
+import { RouteComponentProps, withRouter } from 'react-router-dom';
-import { withRouter, RouteComponentProps } from 'react-router-dom';
-
-import { MaterialTable, ColumnType, MaterialTableCtorType, ColumnModel } from '../../../../framework/src/components/material-table';
+import { ColumnModel, 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 connect, { Connect, IDispatcher } from '../../../../framework/src/flux/connect';
-import { CrossPolarDiscriminationDataType, CrossPolarDiscriminationDatabaseDataType } from '../models/crossPolarDiscriminationDataType';
+import { SetFilterVisibility, SetSubViewAction } from '../actions/toggleActions';
+import { createCrossPolarDiscriminationActions, createCrossPolarDiscriminationProperties } from '../handlers/crossPolarDiscriminationHandler';
import { IDataSet, IDataSetsObject } from '../models/chartTypes';
-import { createCrossPolarDiscriminationProperties, createCrossPolarDiscriminationActions } from '../handlers/crossPolarDiscriminationHandler';
+import { CrossPolarDiscriminationDatabaseDataType, CrossPolarDiscriminationDataType } from '../models/crossPolarDiscriminationDataType';
import { lineChart, sortDataByTimeStamp } from '../utils/chartUtils';
import { addColumnLabels } from '../utils/tableUtils';
-import { SetSubViewAction, SetFilterVisibility } from '../actions/toggleActions';
import ToggleContainer from './toggleContainer';
@@ -36,18 +35,18 @@
crossPolarDiscriminationProperties: createCrossPolarDiscriminationProperties(state),
currentView: state.performanceHistory.subViews.CPD.subView,
isFilterVisible: state.performanceHistory.subViews.CPD.isFilterVisible,
- existingFilter: state.performanceHistory.crossPolarDiscrimination.filter
+ existingFilter: state.performanceHistory.crossPolarDiscrimination.filter,
});
const mapDisp = (dispatcher: IDispatcher) => ({
crossPolarDiscriminationActions: createCrossPolarDiscriminationActions(dispatcher.dispatch),
- setSubView: (value: "chart" | "table") => dispatcher.dispatch(new SetSubViewAction("CPD", value)),
- toggleFilterButton: (value: boolean) => { dispatcher.dispatch(new SetFilterVisibility("CPD", value)) },
+ setSubView: (value: 'chart' | 'table') => dispatcher.dispatch(new SetSubViewAction('CPD', value)),
+ toggleFilterButton: (value: boolean) => { dispatcher.dispatch(new SetFilterVisibility('CPD', value));},
});
type CrossPolarDiscriminationComponentProps = RouteComponentProps & Connect<typeof mapProps, typeof mapDisp> & {
- selectedTimePeriod: string
+ selectedTimePeriod: string;
};
const CrossPolarDiscriminationTable = MaterialTable as MaterialTableCtorType<CrossPolarDiscriminationDataType>;
@@ -55,21 +54,20 @@
/**
* The Component which gets the crossPolarDiscrimination data from the database based on the selected time period.
*/
-class CrossPolarDiscriminationComponent extends React.Component<CrossPolarDiscriminationComponentProps>{
-
+class CrossPolarDiscriminationComponent extends React.Component<CrossPolarDiscriminationComponentProps> {
onToggleFilterButton = () => {
this.props.toggleFilterButton(!this.props.isFilterVisible);
- }
+ };
- onChange = (value: "chart" | "table") => {
+ onChange = (value: 'chart' | 'table') => {
this.props.setSubView(value);
- }
+ };
onFilterChanged = (property: string, filterTerm: string) => {
this.props.crossPolarDiscriminationActions.onFilterChanged(property, filterTerm);
if (!this.props.crossPolarDiscriminationProperties.showFilter)
this.props.crossPolarDiscriminationActions.onToggleFilter(false);
- }
+ };
render(): JSX.Element {
const properties = this.props.crossPolarDiscriminationProperties;
@@ -78,12 +76,12 @@
const chartPagedData = this.getChartDataValues(properties.rows);
const cpdColumns: ColumnModel<CrossPolarDiscriminationDataType>[] = [
- { property: "radioSignalId", title: "Radio signal", type: ColumnType.text },
- { property: "scannerId", title: "Scanner ID", type: ColumnType.text },
- { property: "timeStamp", title: "End Time", type: ColumnType.text },
+ { property: 'radioSignalId', title: 'Radio signal', type: ColumnType.text },
+ { property: 'scannerId', title: 'Scanner ID', type: ColumnType.text },
+ { property: 'timeStamp', title: 'End Time', type: ColumnType.text },
{
- property: "suspectIntervalFlag", title: "Suspect Interval", type: ColumnType.boolean
- }
+ property: 'suspectIntervalFlag', title: 'Suspect Interval', type: ColumnType.boolean,
+ },
];
chartPagedData.datasets.forEach(ds => {
@@ -91,66 +89,67 @@
});
return (
<>
- <ToggleContainer onToggleFilterButton={this.onToggleFilterButton} showFilter={this.props.isFilterVisible} existingFilter={this.props.crossPolarDiscriminationProperties.filter} onFilterChanged={this.onFilterChanged} selectedValue={this.props.currentView} onChange={this.onChange}>
+ <ToggleContainer onToggleFilterButton={this.onToggleFilterButton} showFilter={this.props.isFilterVisible}
+ existingFilter={this.props.crossPolarDiscriminationProperties.filter} onFilterChanged={this.onFilterChanged} selectedValue={this.props.currentView} onChange={this.onChange}>
{lineChart(chartPagedData)}
- <CrossPolarDiscriminationTable stickyHeader idProperty={"_id"} tableId="cross-polar-discrimination-table" columns={cpdColumns} {...properties} {...actions} />
+ <CrossPolarDiscriminationTable stickyHeader idProperty={'_id'} tableId="cross-polar-discrimination-table" columns={cpdColumns} {...properties} {...actions} />
</ToggleContainer>
</>
);
- };
+ }
/**
* This function gets the performance values for CPD according on the chartjs dataset structure
* which is to be sent to the chart.
*/
private getChartDataValues = (rows: CrossPolarDiscriminationDataType[]): IDataSetsObject => {
- const _rows = [...rows];
- sortDataByTimeStamp(_rows);
+ const data_rows = [...rows];
+ sortDataByTimeStamp(data_rows);
const datasets: IDataSet[] = [{
- name: "xpdMin",
- label: "xpd-min",
+ name: 'xpdMin',
+ label: 'xpd-min',
borderColor: '#0e17f3de',
bezierCurve: false,
lineTension: 0,
fill: false,
data: [],
- columnLabel: "CPD (min)[db]"
+ columnLabel: 'CPD (min)[db]',
}, {
- name: "xpdAvg",
- label: "xpd-avg",
+ name: 'xpdAvg',
+ label: 'xpd-avg',
borderColor: '#08edb6de',
bezierCurve: false,
lineTension: 0,
fill: false,
data: [],
- columnLabel: "CPD (avg)[db]"
+ columnLabel: 'CPD (avg)[db]',
}, {
- name: "xpdMax",
- label: "xpd-max",
+ name: 'xpdMax',
+ label: 'xpd-max',
borderColor: '#b308edde',
bezierCurve: false,
lineTension: 0,
fill: false,
data: [],
- columnLabel: "CPD (max)[db]"
+ columnLabel: 'CPD (max)[db]',
}];
- _rows.forEach(row => {
+ data_rows.forEach(row => {
row.xpdMin = row.performanceData.xpdMin;
row.xpdAvg = row.performanceData.xpdAvg;
row.xpdMax = row.performanceData.xpdMax;
datasets.forEach(ds => {
ds.data.push({
- x: row["timeStamp" as keyof CrossPolarDiscriminationDataType] as string,
- y: row.performanceData[ds.name as keyof CrossPolarDiscriminationDatabaseDataType] as string
+ x: row['timeStamp' as keyof CrossPolarDiscriminationDataType] as string,
+ y: row.performanceData[ds.name as keyof CrossPolarDiscriminationDatabaseDataType] as string,
});
});
});
return {
- datasets: datasets
+ datasets: datasets,
};
- }
+ };
}
const CrossPolarDiscrimination = withRouter(connect(mapProps, mapDisp)(CrossPolarDiscriminationComponent));
export default CrossPolarDiscrimination;
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/ltpSelection.tsx b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/ltpSelection.tsx
index ef6cfc7..bd6333b 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/ltpSelection.tsx
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/ltpSelection.tsx
@@ -15,90 +15,91 @@
* the License.
* ============LICENSE_END==========================================================================
*/
+import React from 'react';
-import * as React from 'react';
-import { MenuItem, Select, FormControl, Typography, SelectChangeEvent } from '@mui/material';
-import makeStyles from '@mui/styles/makeStyles';
-import { LtpIds } from 'models/availableLtps';
-import { Loader } from '../../../../framework/src/components/material-ui';
-
+import { FormControl, MenuItem, Select, SelectChangeEvent, Typography } from '@mui/material';
import { Theme } from '@mui/material/styles';
+import makeStyles from '@mui/styles/makeStyles';
+import { Loader } from '../../../../framework/src/components/material-ui';
+import { LtpIds } from '../models/availableLtps';
const useStyles = makeStyles((theme: Theme) => ({
- display: {
- display: "inline-block"
- },
- selectDropdown: {
- borderRadius: 1,
- position: "relative",
- backgroundColor: theme.palette.background.paper,
- border: "1px solid #ced4da",
- fontSize: 16,
- width: "auto",
- padding: "5px 5px 5px 5px",
- transition: theme.transitions.create(["border-color", "box-shadow"]),
- },
- center: {
- "flex": "1",
- "height": "100%",
- "display": "flex",
- "alignItems": "center",
- "justifyContent": "center",
- flexDirection: "column"
- }
+ display: {
+ display: 'inline-block',
+ },
+ selectDropdown: {
+ borderRadius: 1,
+ position: 'relative',
+ backgroundColor: theme.palette.background.paper,
+ border: '1px solid #ced4da',
+ fontSize: 16,
+ width: 'auto',
+ padding: '5px 5px 5px 5px',
+ transition: theme.transitions.create(['border-color', 'box-shadow']),
+ },
+ center: {
+ 'flex': '1',
+ 'height': '100%',
+ 'display': 'flex',
+ 'alignItems': 'center',
+ 'justifyContent': 'center',
+ flexDirection: 'column',
+ },
}));
-type LtpSelectionProps = { selectedNE: string, error?: string, finishedLoading: boolean, selectedLtp: string,
- availableLtps: LtpIds[],
- onChangeLtp(event: SelectChangeEvent<HTMLSelectElement | string> ): void,
- selectedTimePeriod: string,
- onChangeTimePeriod(event: SelectChangeEvent<HTMLSelectElement | string> ): void };
+type LtpSelectionProps = {
+ selectedNE: string; error?: string; finishedLoading: boolean; selectedLtp: string;
+ availableLtps: LtpIds[];
+ onChangeLtp(event: SelectChangeEvent<HTMLSelectElement | string>): void;
+ selectedTimePeriod: string;
+ onChangeTimePeriod(event: SelectChangeEvent<HTMLSelectElement | string>): void;
+};
export const LtpSelection = (props: LtpSelectionProps) => {
- const classes = useStyles();
- return (
- <>
- <h3>Selected Network Element: {props.selectedNE} </h3>
- <FormControl variant="standard" className={classes.display}>
- <span>
- Select LTP
- </span>
- <Select variant="standard" className={classes.selectDropdown} value={props.selectedLtp} onChange={props.onChangeLtp} aria-label="ltp-selection" >
- <MenuItem value={"-1"} aria-label="none"><em>--Select--</em></MenuItem>
- {props.availableLtps.map(ltp =>
- (<MenuItem value={ltp.key} key={ltp.key} aria-label={ltp.key}>{ltp.key}</MenuItem>))}
- </Select>
- <span> Time-Period </span>
- <Select variant="standard" className={classes.selectDropdown} value={props.selectedTimePeriod} onChange={props.onChangeTimePeriod} aria-label="time-period-selection">
- <MenuItem value={"15min"} aria-label="15minutes">15min</MenuItem>
- <MenuItem value={"24hours"} aria-label="24hours">24hours</MenuItem>
- </Select>
- </FormControl>
- {
- !props.finishedLoading && !props.error &&
- <div className={classes.center}>
- <Loader />
- <h3>Collecting Data ...</h3>
- </div>
- }
- {
- props.finishedLoading && props.error &&
- <div className={classes.center}>
- <h3>Data couldn't be loaded</h3>
- <Typography variant="body1">{props.error}</Typography>
- </div>
- }
- {
- props.selectedLtp === "-1" && props.finishedLoading && !props.error && (props.availableLtps.length > 0 ?
- <div className={classes.center}>
- <h3>Please select a LTP</h3>
- </div>
- :
- <div className={classes.center}>
- <h3>No performance data found</h3>
- </div>)
- }
- </>)
-}
+ const classes = useStyles();
+ return (
+ <>
+ <h3>Selected Network Element: {props.selectedNE} </h3>
+ <FormControl variant="standard" className={classes.display}>
+ <span>
+ Select LTP
+ </span>
+ <Select variant="standard" className={classes.selectDropdown} value={props.selectedLtp} onChange={props.onChangeLtp} aria-label="ltp-selection" >
+ <MenuItem value={'-1'} aria-label="none"><em>--Select--</em></MenuItem>
+ {props.availableLtps.map(ltp =>
+ (<MenuItem value={ltp.key} key={ltp.key} aria-label={ltp.key}>{ltp.key}</MenuItem>))}
+ </Select>
+ <span> Time-Period </span>
+ <Select variant="standard" className={classes.selectDropdown} value={props.selectedTimePeriod} onChange={props.onChangeTimePeriod} aria-label="time-period-selection">
+ <MenuItem value={'15min'} aria-label="15minutes">15min</MenuItem>
+ <MenuItem value={'24hours'} aria-label="24hours">24hours</MenuItem>
+ </Select>
+ </FormControl>
+ {
+ !props.finishedLoading && !props.error &&
+ <div className={classes.center}>
+ <Loader />
+ <h3>Collecting Data ...</h3>
+ </div>
+ }
+ {
+ props.finishedLoading && props.error &&
+ <div className={classes.center}>
+ <h3>Data couldn't be loaded</h3>
+ <Typography variant="body1">{props.error}</Typography>
+ </div>
+ }
+ {
+ props.selectedLtp === '-1' && props.finishedLoading && !props.error && (props.availableLtps.length > 0 ?
+ <div className={classes.center}>
+ <h3>Please select a LTP</h3>
+ </div>
+ :
+ <div className={classes.center}>
+ <h3>No performance data found</h3>
+ </div>)
+ }
+ </>);
+};
export default LtpSelection;
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/performanceData.tsx b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/performanceData.tsx
index 6a06ea3..fb608aa 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/performanceData.tsx
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/performanceData.tsx
@@ -15,36 +15,36 @@
* the License.
* ============LICENSE_END==========================================================================
*/
-import * as React from 'react';
+import React from 'react';
+import { RouteComponentProps, withRouter } from 'react-router-dom';
-import { withRouter, RouteComponentProps } from 'react-router-dom';
-
-import { MaterialTable, ColumnType, ColumnModel, MaterialTableCtorType } from '../../../../framework/src/components/material-table';
+import { ColumnModel, 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 connect, { Connect, IDispatcher } from '../../../../framework/src/flux/connect';
-import { PerformanceDataType, PerformanceDatabaseDataType } from '../models/performanceDataType';
+
+import { SetFilterVisibility, SetSubViewAction } from '../actions/toggleActions';
+import { createPerformanceDataActions, createPerformanceDataProperties } from '../handlers/performanceDataHandler';
import { IDataSet, IDataSetsObject } from '../models/chartTypes';
-import { createPerformanceDataProperties, createPerformanceDataActions } from '../handlers/performanceDataHandler';
+import { PerformanceDatabaseDataType, PerformanceDataType } from '../models/performanceDataType';
import { lineChart, sortDataByTimeStamp } from '../utils/chartUtils';
import { addColumnLabels } from '../utils/tableUtils';
import ToggleContainer from './toggleContainer';
-import { SetSubViewAction, SetFilterVisibility } from '../actions/toggleActions';
const mapProps = (state: IApplicationStoreState) => ({
performanceDataProperties: createPerformanceDataProperties(state),
currentView: state.performanceHistory.subViews.performanceData.subView,
isFilterVisible: state.performanceHistory.subViews.performanceData.isFilterVisible,
- existingFilter: state.performanceHistory.performanceData.filter
+ existingFilter: state.performanceHistory.performanceData.filter,
});
const mapDisp = (dispatcher: IDispatcher) => ({
performanceDataActions: createPerformanceDataActions(dispatcher.dispatch),
- setSubView: (value: "chart" | "table") => dispatcher.dispatch(new SetSubViewAction("performanceData", value)),
- toggleFilterButton: (value: boolean) => { dispatcher.dispatch(new SetFilterVisibility("performanceData", value)) }
+ setSubView: (value: 'chart' | 'table') => dispatcher.dispatch(new SetSubViewAction('performanceData', value)),
+ toggleFilterButton: (value: boolean) => { dispatcher.dispatch(new SetFilterVisibility('performanceData', value)); },
});
type PerformanceDataComponentProps = RouteComponentProps & Connect<typeof mapProps, typeof mapDisp> & {
- selectedTimePeriod: string
+ selectedTimePeriod: string;
};
const PerformanceDataTable = MaterialTable as MaterialTableCtorType<PerformanceDataType>;
@@ -52,17 +52,16 @@
/**
* The Component which gets the performance data from the database based on the selected time period.
*/
-class PerformanceDataComponent extends React.Component<PerformanceDataComponentProps>{
-
+class PerformanceDataComponent extends React.Component<PerformanceDataComponentProps> {
onToggleFilterButton = () => {
this.props.toggleFilterButton(!this.props.isFilterVisible);
- }
+ };
onFilterChanged = (property: string, filterTerm: string) => {
this.props.performanceDataActions.onFilterChanged(property, filterTerm);
if (!this.props.performanceDataProperties.showFilter)
this.props.performanceDataActions.onToggleFilter(false);
- }
+ };
render(): JSX.Element {
const properties = this.props.performanceDataProperties;
@@ -70,12 +69,12 @@
const chartPagedData = this.getChartDataValues(properties.rows);
const performanceColumns: ColumnModel<PerformanceDataType>[] = [
- { property: "radioSignalId", title: "Radio signal", type: ColumnType.text },
- { property: "scannerId", title: "Scanner ID", type: ColumnType.text },
- { property: "timeStamp", title: "End Time", type: ColumnType.text },
+ { property: 'radioSignalId', title: 'Radio signal', type: ColumnType.text },
+ { property: 'scannerId', title: 'Scanner ID', type: ColumnType.text },
+ { property: 'timeStamp', title: 'End Time', type: ColumnType.text },
{
- property: "suspectIntervalFlag", title: "Suspect Interval", type: ColumnType.boolean
- }
+ property: 'suspectIntervalFlag', title: 'Suspect Interval', type: ColumnType.boolean,
+ },
];
chartPagedData.datasets.forEach(ds => {
@@ -83,67 +82,68 @@
});
return (
<>
- <ToggleContainer onToggleFilterButton={() => this.props.toggleFilterButton(!this.props.isFilterVisible)} existingFilter={this.props.existingFilter} onFilterChanged={this.onFilterChanged} selectedValue={this.props.currentView} showFilter={this.props.isFilterVisible} onChange={this.props.setSubView}>
+ <ToggleContainer onToggleFilterButton={() => this.props.toggleFilterButton(!this.props.isFilterVisible)}
+ existingFilter={this.props.existingFilter} onFilterChanged={this.onFilterChanged} selectedValue={this.props.currentView} showFilter={this.props.isFilterVisible} onChange={this.props.setSubView}>
{lineChart(chartPagedData)}
- <PerformanceDataTable stickyHeader idProperty={"_id"} tableId="performance-data-table" columns={performanceColumns} {...properties} {...actions} />
+ <PerformanceDataTable stickyHeader idProperty={'_id'} tableId="performance-data-table" columns={performanceColumns} {...properties} {...actions} />
</ToggleContainer>
</>
);
- };
+ }
/**
* This function gets the performance values for PerformanceData according on the chartjs dataset structure
* which is to be sent to the chart.
*/
private getChartDataValues = (rows: PerformanceDataType[]): IDataSetsObject => {
- const _rows = [...rows];
- sortDataByTimeStamp(_rows);
+ const data_rows = [...rows];
+ sortDataByTimeStamp(data_rows);
const datasets: IDataSet[] = [{
- name: "es",
- label: "es",
+ name: 'es',
+ label: 'es',
borderColor: '#0e17f3de',
bezierCurve: false,
lineTension: 0,
fill: false,
data: [],
- columnLabel: "ES"
+ columnLabel: 'ES',
}, {
- name: "ses",
- label: "ses",
+ name: 'ses',
+ label: 'ses',
borderColor: '#08edb6de',
bezierCurve: false,
lineTension: 0,
fill: false,
data: [],
- columnLabel: "SES"
+ columnLabel: 'SES',
}, {
- name: "unavailability",
- label: "unavailability",
+ name: 'unavailability',
+ label: 'unavailability',
borderColor: '#b308edde',
bezierCurve: false,
lineTension: 0,
fill: false,
data: [],
- columnLabel: "Unavailability"
+ columnLabel: 'Unavailability',
}];
- _rows.forEach(row => {
+ data_rows.forEach(row => {
row.es = row.performanceData.es;
row.ses = row.performanceData.ses;
row.unavailability = row.performanceData.unavailability;
datasets.forEach(ds => {
ds.data.push({
- x: row["timeStamp" as keyof PerformanceDataType] as string,
- y: row.performanceData[ds.name as keyof PerformanceDatabaseDataType] as string
+ x: row['timeStamp' as keyof PerformanceDataType] as string,
+ y: row.performanceData[ds.name as keyof PerformanceDatabaseDataType] as string,
});
});
});
return {
- datasets: datasets
+ datasets: datasets,
};
- }
+ };
}
const PerformanceData = withRouter(connect(mapProps, mapDisp)(PerformanceDataComponent));
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/receiveLevel.tsx b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/receiveLevel.tsx
index 8dc92b8..125cc6e 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/receiveLevel.tsx
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/receiveLevel.tsx
@@ -15,37 +15,36 @@
* the License.
* ============LICENSE_END==========================================================================
*/
-import * as React from 'react';
+import React from 'react';
+import { RouteComponentProps, withRouter } from 'react-router-dom';
-import { withRouter, RouteComponentProps } from 'react-router-dom';
-
-import { MaterialTable, ColumnType, ColumnModel, MaterialTableCtorType } from '../../../../framework/src/components/material-table';
+import { ColumnModel, 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 connect, { Connect, IDispatcher } from '../../../../framework/src/flux/connect';
-import { ReceiveLevelDataType, ReceiveLevelDatabaseDataType } from '../models/receiveLevelDataType';
+import { SetFilterVisibility, SetSubViewAction } from '../actions/toggleActions';
+import { createReceiveLevelActions, createReceiveLevelProperties } from '../handlers/receiveLevelHandler';
import { IDataSet, IDataSetsObject } from '../models/chartTypes';
-import { createReceiveLevelProperties, createReceiveLevelActions } from '../handlers/receiveLevelHandler';
+import { ReceiveLevelDatabaseDataType, ReceiveLevelDataType } from '../models/receiveLevelDataType';
import { lineChart, sortDataByTimeStamp } from '../utils/chartUtils';
import { addColumnLabels } from '../utils/tableUtils';
-import { SetSubViewAction, SetFilterVisibility } from '../actions/toggleActions';
import ToggleContainer from './toggleContainer';
const mapProps = (state: IApplicationStoreState) => ({
receiveLevelProperties: createReceiveLevelProperties(state),
currentView: state.performanceHistory.subViews.receiveLevel.subView,
isFilterVisible: state.performanceHistory.subViews.receiveLevel.isFilterVisible,
- existingFilter: state.performanceHistory.receiveLevel.filter
+ existingFilter: state.performanceHistory.receiveLevel.filter,
});
const mapDisp = (dispatcher: IDispatcher) => ({
receiveLevelActions: createReceiveLevelActions(dispatcher.dispatch),
- setSubView: (value: "chart" | "table") => dispatcher.dispatch(new SetSubViewAction("receiveLevel", value)),
- toggleFilterButton: (value: boolean) => { dispatcher.dispatch(new SetFilterVisibility("receiveLevel", value)) },
+ setSubView: (value: 'chart' | 'table') => dispatcher.dispatch(new SetSubViewAction('receiveLevel', value)),
+ toggleFilterButton: (value: boolean) => { dispatcher.dispatch(new SetFilterVisibility('receiveLevel', value)); },
});
type ReceiveLevelComponentProps = RouteComponentProps & Connect<typeof mapProps, typeof mapDisp> & {
- selectedTimePeriod: string
+ selectedTimePeriod: string;
};
const ReceiveLevelTable = MaterialTable as MaterialTableCtorType<ReceiveLevelDataType>;
@@ -53,22 +52,21 @@
/**
* The Component which gets the receiveLevel data from the database based on the selected time period.
*/
-class ReceiveLevelComponent extends React.Component<ReceiveLevelComponentProps>{
-
+class ReceiveLevelComponent extends React.Component<ReceiveLevelComponentProps> {
onToggleFilterButton = () => {
this.props.toggleFilterButton(!this.props.isFilterVisible);
- }
+ };
- onChange = (value: "chart" | "table") => {
+ onChange = (value: 'chart' | 'table') => {
this.props.setSubView(value);
- }
+ };
onFilterChanged = (property: string, filterTerm: string) => {
this.props.receiveLevelActions.onFilterChanged(property, filterTerm);
if (!this.props.receiveLevelProperties.showFilter)
this.props.receiveLevelActions.onToggleFilter(false);
- }
+ };
render(): JSX.Element {
const properties = this.props.receiveLevelProperties;
@@ -76,12 +74,12 @@
const chartPagedData = this.getChartDataValues(properties.rows);
const receiveLevelColumns: ColumnModel<ReceiveLevelDataType>[] = [
- { property: "radioSignalId", title: "Radio signal", type: ColumnType.text },
- { property: "scannerId", title: "Scanner ID", type: ColumnType.text },
- { property: "timeStamp", title: "End Time", type: ColumnType.text },
+ { property: 'radioSignalId', title: 'Radio signal', type: ColumnType.text },
+ { property: 'scannerId', title: 'Scanner ID', type: ColumnType.text },
+ { property: 'timeStamp', title: 'End Time', type: ColumnType.text },
{
- property: "suspectIntervalFlag", title: "Suspect Interval", type: ColumnType.boolean
- }
+ property: 'suspectIntervalFlag', title: 'Suspect Interval', type: ColumnType.boolean,
+ },
];
chartPagedData.datasets.forEach(ds => {
@@ -92,64 +90,64 @@
<>
<ToggleContainer onToggleFilterButton={this.onToggleFilterButton} showFilter={this.props.isFilterVisible} existingFilter={this.props.receiveLevelProperties.filter} onFilterChanged={this.onFilterChanged} selectedValue={this.props.currentView} onChange={this.onChange}>
{lineChart(chartPagedData)}
- <ReceiveLevelTable stickyHeader idProperty={"_id"} tableId="receive-level-table" columns={receiveLevelColumns} {...properties} {...actions} />
+ <ReceiveLevelTable stickyHeader idProperty={'_id'} tableId="receive-level-table" columns={receiveLevelColumns} {...properties} {...actions} />
</ToggleContainer>
</>
);
- };
+ }
/**
* This function gets the performance values for ReceiveLevel according on the chartjs dataset structure
* which is to be sent to the chart.
*/
private getChartDataValues = (rows: ReceiveLevelDataType[]): IDataSetsObject => {
- const _rows = [...rows];
- sortDataByTimeStamp(_rows);
+ const data_rows = [...rows];
+ sortDataByTimeStamp(data_rows);
const datasets: IDataSet[] = [{
- name: "rxLevelMin",
- label: "rx-level-min",
+ name: 'rxLevelMin',
+ label: 'rx-level-min',
borderColor: '#0e17f3de',
bezierCurve: false,
lineTension: 0,
fill: false,
data: [],
- columnLabel: "Rx min"
+ columnLabel: 'Rx min',
}, {
- name: "rxLevelAvg",
- label: "rx-level-avg",
+ name: 'rxLevelAvg',
+ label: 'rx-level-avg',
borderColor: '#08edb6de',
bezierCurve: false,
lineTension: 0,
fill: false,
data: [],
- columnLabel: "Rx avg"
+ columnLabel: 'Rx avg',
}, {
- name: "rxLevelMax",
- label: "rx-level-max",
+ name: 'rxLevelMax',
+ label: 'rx-level-max',
borderColor: '#b308edde',
bezierCurve: false,
lineTension: 0,
fill: false,
data: [],
- columnLabel: "Rx max"
+ columnLabel: 'Rx max',
}];
- _rows.forEach(row => {
+ data_rows.forEach(row => {
row.rxLevelMin = row.performanceData.rxLevelMin;
row.rxLevelAvg = row.performanceData.rxLevelAvg;
row.rxLevelMax = row.performanceData.rxLevelMax;
datasets.forEach(ds => {
ds.data.push({
- x: row["timeStamp" as keyof ReceiveLevelDataType] as string,
- y: row.performanceData[ds.name as keyof ReceiveLevelDatabaseDataType] as string
+ x: row['timeStamp' as keyof ReceiveLevelDataType] as string,
+ y: row.performanceData[ds.name as keyof ReceiveLevelDatabaseDataType] as string,
});
});
});
return {
- datasets: datasets
+ datasets: datasets,
};
- }
+ };
}
const ReceiveLevel = withRouter(connect(mapProps, mapDisp)(ReceiveLevelComponent));
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/signalToInterference.tsx b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/signalToInterference.tsx
index ee7fe34..85241fb 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/signalToInterference.tsx
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/signalToInterference.tsx
@@ -15,37 +15,36 @@
* the License.
* ============LICENSE_END==========================================================================
*/
-import * as React from 'react';
+import React from 'react';
+import { RouteComponentProps, withRouter } from 'react-router-dom';
-import { withRouter, RouteComponentProps } from 'react-router-dom';
-
-import { MaterialTable, ColumnType, ColumnModel, MaterialTableCtorType } from '../../../../framework/src/components/material-table';
+import { ColumnModel, 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 connect, { Connect, IDispatcher } from '../../../../framework/src/flux/connect';
-import { SignalToInterferenceDataType, SignalToInterferenceDatabaseDataType } from '../models/signalToInteferenceDataType';
+import { SetFilterVisibility, SetSubViewAction } from '../actions/toggleActions';
+import { createSignalToInterferenceActions, createSignalToInterferenceProperties } from '../handlers/signalToInterferenceHandler';
import { IDataSet, IDataSetsObject } from '../models/chartTypes';
-import { createSignalToInterferenceProperties, createSignalToInterferenceActions } from '../handlers/signalToInterferenceHandler';
+import { SignalToInterferenceDatabaseDataType, SignalToInterferenceDataType } from '../models/signalToInteferenceDataType';
import { lineChart, sortDataByTimeStamp } from '../utils/chartUtils';
import { addColumnLabels } from '../utils/tableUtils';
-import { SetSubViewAction, SetFilterVisibility } from '../actions/toggleActions';
import ToggleContainer from './toggleContainer';
const mapProps = (state: IApplicationStoreState) => ({
signalToInterferenceProperties: createSignalToInterferenceProperties(state),
currentView: state.performanceHistory.subViews.SINR.subView,
isFilterVisible: state.performanceHistory.subViews.SINR.isFilterVisible,
- existingFilter: state.performanceHistory.signalToInterference.filter
+ existingFilter: state.performanceHistory.signalToInterference.filter,
});
const mapDisp = (dispatcher: IDispatcher) => ({
signalToInterferenceActions: createSignalToInterferenceActions(dispatcher.dispatch),
- setSubView: (value: "chart" | "table") => dispatcher.dispatch(new SetSubViewAction("SINR", value)),
- toggleFilterButton: (value: boolean) => { dispatcher.dispatch(new SetFilterVisibility("SINR", value)) },
+ setSubView: (value: 'chart' | 'table') => dispatcher.dispatch(new SetSubViewAction('SINR', value)),
+ toggleFilterButton: (value: boolean) => { dispatcher.dispatch(new SetFilterVisibility('SINR', value)); },
});
type SignalToInterferenceComponentProps = RouteComponentProps & Connect<typeof mapProps, typeof mapDisp> & {
- selectedTimePeriod: string
+ selectedTimePeriod: string;
};
const SignalToInterferenceTable = MaterialTable as MaterialTableCtorType<SignalToInterferenceDataType>;
@@ -53,21 +52,20 @@
/**
* The Component which gets the signal to interference data from the database based on the selected time period.
*/
-class SignalToInterferenceComponent extends React.Component<SignalToInterferenceComponentProps>{
-
+class SignalToInterferenceComponent extends React.Component<SignalToInterferenceComponentProps> {
onToggleFilterButton = () => {
this.props.toggleFilterButton(!this.props.isFilterVisible);
- }
+ };
- onChange = (value: "chart" | "table") => {
+ onChange = (value: 'chart' | 'table') => {
this.props.setSubView(value);
- }
+ };
onFilterChanged = (property: string, filterTerm: string) => {
this.props.signalToInterferenceActions.onFilterChanged(property, filterTerm);
if (!this.props.signalToInterferenceProperties.showFilter)
this.props.signalToInterferenceActions.onToggleFilter(false);
- }
+ };
render(): JSX.Element {
const properties = this.props.signalToInterferenceProperties;
@@ -76,12 +74,12 @@
const chartPagedData = this.getChartDataValues(properties.rows);
const sinrColumns: ColumnModel<SignalToInterferenceDataType>[] = [
- { property: "radioSignalId", title: "Radio signal", type: ColumnType.text },
- { property: "scannerId", title: "Scanner ID", type: ColumnType.text },
- { property: "timeStamp", title: "End Time", type: ColumnType.text },
+ { property: 'radioSignalId', title: 'Radio signal', type: ColumnType.text },
+ { property: 'scannerId', title: 'Scanner ID', type: ColumnType.text },
+ { property: 'timeStamp', title: 'End Time', type: ColumnType.text },
{
- property: "suspectIntervalFlag", title: "Suspect Interval", type: ColumnType.boolean
- }
+ property: 'suspectIntervalFlag', title: 'Suspect Interval', type: ColumnType.boolean,
+ },
];
chartPagedData.datasets.forEach(ds => {
@@ -89,14 +87,15 @@
});
return (
<>
- <ToggleContainer onToggleFilterButton={this.onToggleFilterButton} showFilter={this.props.isFilterVisible} existingFilter={this.props.signalToInterferenceProperties.filter} onFilterChanged={this.onFilterChanged} selectedValue={this.props.currentView} onChange={this.onChange}>
+ <ToggleContainer onToggleFilterButton={this.onToggleFilterButton} showFilter={this.props.isFilterVisible}
+ existingFilter={this.props.signalToInterferenceProperties.filter} onFilterChanged={this.onFilterChanged} selectedValue={this.props.currentView} onChange={this.onChange}>
{lineChart(chartPagedData)}
- <SignalToInterferenceTable stickyHeader idProperty={"_id"} tableId="signal-to-interference-table" columns={sinrColumns} {...properties} {...actions}
+ <SignalToInterferenceTable stickyHeader idProperty={'_id'} tableId="signal-to-interference-table" columns={sinrColumns} {...properties} {...actions}
/>
</ToggleContainer>
</>
);
- };
+ }
/**
* This function gets the performance values for SINR according on the chartjs dataset structure
@@ -104,53 +103,53 @@
*/
private getChartDataValues = (rows: SignalToInterferenceDataType[]): IDataSetsObject => {
- const _rows = [...rows];
- sortDataByTimeStamp(_rows);
+ const data_rows = [...rows];
+ sortDataByTimeStamp(data_rows);
const datasets: IDataSet[] = [{
- name: "snirMin",
- label: "snir-min",
+ name: 'snirMin',
+ label: 'snir-min',
borderColor: '#0e17f3de',
bezierCurve: false,
lineTension: 0,
fill: false,
data: [],
- columnLabel: "SINR (min)[db]"
+ columnLabel: 'SINR (min)[db]',
}, {
- name: "snirAvg",
- label: "snir-avg",
+ name: 'snirAvg',
+ label: 'snir-avg',
borderColor: '#08edb6de',
bezierCurve: false,
lineTension: 0,
fill: false,
data: [],
- columnLabel: "SINR (avg)[db]"
+ columnLabel: 'SINR (avg)[db]',
}, {
- name: "snirMax",
- label: "snir-max",
+ name: 'snirMax',
+ label: 'snir-max',
borderColor: '#b308edde',
bezierCurve: false,
lineTension: 0,
fill: false,
data: [],
- columnLabel: "SINR (max)[db]"
+ columnLabel: 'SINR (max)[db]',
}];
- _rows.forEach(row => {
+ data_rows.forEach(row => {
row.snirMin = row.performanceData.snirMin;
row.snirAvg = row.performanceData.snirAvg;
row.snirMax = row.performanceData.snirMax;
datasets.forEach(ds => {
ds.data.push({
- x: row["timeStamp" as keyof SignalToInterferenceDataType] as string,
- y: row.performanceData[ds.name as keyof SignalToInterferenceDatabaseDataType] as string
+ x: row['timeStamp' as keyof SignalToInterferenceDataType] as string,
+ y: row.performanceData[ds.name as keyof SignalToInterferenceDatabaseDataType] as string,
});
});
});
return {
- datasets: datasets
+ datasets: datasets,
};
- }
+ };
}
const SignalToInterference = withRouter(connect(mapProps, mapDisp)(SignalToInterferenceComponent));
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/temperature.tsx b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/temperature.tsx
index 31e1d36..d4b8233 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/temperature.tsx
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/temperature.tsx
@@ -15,38 +15,37 @@
* the License.
* ============LICENSE_END==========================================================================
*/
-import * as React from 'react';
+import React from 'react';
+import { RouteComponentProps, withRouter } from 'react-router-dom';
-import { withRouter, RouteComponentProps } from 'react-router-dom';
-
-import { MaterialTable, ColumnType, ColumnModel, MaterialTableCtorType } from '../../../../framework/src/components/material-table';
+import { ColumnModel, 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 connect, { Connect, IDispatcher } from '../../../../framework/src/flux/connect';
-import { TemperatureDataType, TemperatureDatabaseDataType } from '../models/temperatureDataType';
+import { SetFilterVisibility, SetSubViewAction } from '../actions/toggleActions';
+import { createTemperatureActions, createTemperatureProperties } from '../handlers/temperatureHandler';
import { IDataSet, IDataSetsObject } from '../models/chartTypes';
-import { createTemperatureProperties, createTemperatureActions } from '../handlers/temperatureHandler';
+import { TemperatureDatabaseDataType, TemperatureDataType } from '../models/temperatureDataType';
import { lineChart, sortDataByTimeStamp } from '../utils/chartUtils';
import { addColumnLabels } from '../utils/tableUtils';
import ToggleContainer from './toggleContainer';
-import { SetSubViewAction, SetFilterVisibility } from '../actions/toggleActions';
const mapProps = (state: IApplicationStoreState) => ({
temperatureProperties: createTemperatureProperties(state),
currentView: state.performanceHistory.subViews.temperatur.subView,
isFilterVisible: state.performanceHistory.subViews.temperatur.isFilterVisible,
- existingFilter: state.performanceHistory.temperature.filter
+ existingFilter: state.performanceHistory.temperature.filter,
});
const mapDisp = (dispatcher: IDispatcher) => ({
temperatureActions: createTemperatureActions(dispatcher.dispatch),
- setSubView: (value: "chart" | "table") => dispatcher.dispatch(new SetSubViewAction("Temp", value)),
- toggleFilterButton: (value: boolean) => { dispatcher.dispatch(new SetFilterVisibility("Temp", value)) },
+ setSubView: (value: 'chart' | 'table') => dispatcher.dispatch(new SetSubViewAction('Temp', value)),
+ toggleFilterButton: (value: boolean) => { dispatcher.dispatch(new SetFilterVisibility('Temp', value)); },
});
type TemperatureComponentProps = RouteComponentProps & Connect<typeof mapProps, typeof mapDisp> & {
- selectedTimePeriod: string
+ selectedTimePeriod: string;
};
const TemperatureTable = MaterialTable as MaterialTableCtorType<TemperatureDataType>;
@@ -54,22 +53,21 @@
/**
* The Component which gets the temperature data from the database based on the selected time period.
*/
-class TemperatureComponent extends React.Component<TemperatureComponentProps>{
-
+class TemperatureComponent extends React.Component<TemperatureComponentProps> {
onToggleFilterButton = () => {
this.props.toggleFilterButton(!this.props.isFilterVisible);
- }
+ };
- onChange = (value: "chart" | "table") => {
+ onChange = (value: 'chart' | 'table') => {
this.props.setSubView(value);
- }
+ };
onFilterChanged = (property: string, filterTerm: string) => {
this.props.temperatureActions.onFilterChanged(property, filterTerm);
if (!this.props.temperatureProperties.showFilter)
this.props.temperatureActions.onToggleFilter(false);
- }
+ };
render(): JSX.Element {
const properties = this.props.temperatureProperties;
@@ -77,12 +75,12 @@
const chartPagedData = this.getChartDataValues(properties.rows);
const temperatureColumns: ColumnModel<TemperatureDataType>[] = [
- { property: "radioSignalId", title: "Radio signal", type: ColumnType.text },
- { property: "scannerId", title: "Scanner ID", type: ColumnType.text },
- { property: "timeStamp", title: "End Time", type: ColumnType.text },
+ { property: 'radioSignalId', title: 'Radio signal', type: ColumnType.text },
+ { property: 'scannerId', title: 'Scanner ID', type: ColumnType.text },
+ { property: 'timeStamp', title: 'End Time', type: ColumnType.text },
{
- property: "suspectIntervalFlag", title: "Suspect Interval", type: ColumnType.boolean
- }
+ property: 'suspectIntervalFlag', title: 'Suspect Interval', type: ColumnType.boolean,
+ },
];
chartPagedData.datasets.forEach(ds => {
@@ -93,11 +91,11 @@
<ToggleContainer onToggleFilterButton={this.onToggleFilterButton} showFilter={this.props.isFilterVisible} existingFilter={this.props.temperatureProperties.filter} onFilterChanged={this.onFilterChanged} selectedValue={this.props.currentView} onChange={this.onChange}>
{lineChart(chartPagedData)}
- <TemperatureTable stickyHeader idProperty={"_id"} tableId="temperature-table" columns={temperatureColumns} {...properties} {...actions} />
+ <TemperatureTable stickyHeader idProperty={'_id'} tableId="temperature-table" columns={temperatureColumns} {...properties} {...actions} />
</ToggleContainer>
</>
);
- };
+ }
/**
* This function gets the performance values for Temperature according on the chartjs dataset structure
@@ -105,53 +103,53 @@
*/
private getChartDataValues = (rows: TemperatureDataType[]): IDataSetsObject => {
- const _rows = [...rows];
- sortDataByTimeStamp(_rows);
+ const data_rows = [...rows];
+ sortDataByTimeStamp(data_rows);
const datasets: IDataSet[] = [{
- name: "rfTempMin",
- label: "rf-temp-min",
+ name: 'rfTempMin',
+ label: 'rf-temp-min',
borderColor: '#0e17f3de',
bezierCurve: false,
lineTension: 0,
fill: false,
data: [],
- columnLabel: "Rf Temp Min[deg C]"
+ columnLabel: 'Rf Temp Min[deg C]',
}, {
- name: "rfTempAvg",
- label: "rf-temp-avg",
+ name: 'rfTempAvg',
+ label: 'rf-temp-avg',
borderColor: '#08edb6de',
bezierCurve: false,
lineTension: 0,
fill: false,
data: [],
- columnLabel: "Rf Temp Avg[deg C]"
+ columnLabel: 'Rf Temp Avg[deg C]',
}, {
- name: "rfTempMax",
- label: "rf-temp-max",
+ name: 'rfTempMax',
+ label: 'rf-temp-max',
borderColor: '#b308edde',
bezierCurve: false,
lineTension: 0,
fill: false,
data: [],
- columnLabel: "Rf Temp Max[deg C]"
+ columnLabel: 'Rf Temp Max[deg C]',
}];
- _rows.forEach(row => {
+ data_rows.forEach(row => {
row.rfTempMin = row.performanceData.rfTempMin;
row.rfTempAvg = row.performanceData.rfTempAvg;
row.rfTempMax = row.performanceData.rfTempMax;
datasets.forEach(ds => {
ds.data.push({
- x: row["timeStamp" as keyof TemperatureDataType] as string,
- y: row.performanceData[ds.name as keyof TemperatureDatabaseDataType] as string
+ x: row['timeStamp' as keyof TemperatureDataType] as string,
+ y: row.performanceData[ds.name as keyof TemperatureDatabaseDataType] as string,
});
});
});
return {
- datasets: datasets
+ datasets: datasets,
};
- }
+ };
}
const Temperature = withRouter(connect(mapProps, mapDisp)(TemperatureComponent));
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/toggleContainer.tsx b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/toggleContainer.tsx
index 8696fe4..e883aef 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/toggleContainer.tsx
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/toggleContainer.tsx
@@ -17,52 +17,54 @@
*/
import * as React from 'react';
+
+import BarChartIcon from '@mui/icons-material/BarChart';
+import FilterListIcon from '@mui/icons-material/FilterList';
+import TableChartIcon from '@mui/icons-material/TableChart';
import ToggleButton from '@mui/material/ToggleButton';
import ToggleButtonGroup from '@mui/material/ToggleButtonGroup';
-import BarChartIcon from '@mui/icons-material/BarChart';
-import TableChartIcon from '@mui/icons-material/TableChart';
-import makeStyles from '@mui/styles/makeStyles';
import Tooltip from '@mui/material/Tooltip';
-import ChartFilter from './chartFilter'
-import FilterListIcon from '@mui/icons-material/FilterList';
+import makeStyles from '@mui/styles/makeStyles';
+
+import ChartFilter from './chartFilter';
const styles = makeStyles({
- toggleButtonContainer: {
- display: "flex",
- alignItems: "center",
- justifyContent: "center",
- padding: "10px",
- },
- subViewGroup: {
- padding: "10px"
- },
- filterGroup: {
- marginLeft: "10px"
- }
+ toggleButtonContainer: {
+ display: 'flex',
+ alignItems: 'center',
+ justifyContent: 'center',
+ padding: '10px',
+ },
+ subViewGroup: {
+ padding: '10px',
+ },
+ filterGroup: {
+ marginLeft: '10px',
+ },
});
-type toggleProps = { selectedValue: string, onChange(value: string): void, showFilter: boolean, onToggleFilterButton(): void, onFilterChanged: (property: string, filterTerm: string) => void, existingFilter: any };
+type toggleProps = { selectedValue: string; onChange(value: string): void; showFilter: boolean; onToggleFilterButton(): void; onFilterChanged: (property: string, filterTerm: string) => void; existingFilter: any };
const ToggleContainer: React.FunctionComponent<toggleProps> = (props) => {
- const classes = styles();
+ const classes = styles();
- const handleChange = (event: React.MouseEvent<HTMLElement>, newView: string) => {
- if (newView !== null) {
- props.onChange(newView)
- }
- };
+ const handleChange = (event: React.MouseEvent<HTMLElement>, newView: string) => {
+ if (newView !== null) {
+ props.onChange(newView);
+ }
+ };
- const handleFilterChange = (event: React.MouseEvent<HTMLElement>, newView: string) => {
- props.onToggleFilterButton();
- };
+ const handleFilterChange = (_event: React.MouseEvent<HTMLElement>) => {
+ props.onToggleFilterButton();
+ };
- const children = React.Children.toArray(props.children);
+ const children = React.Children.toArray(props.children);
- //hide filter if visible + table
- //put current name into state, let container handle stuff itelf, register for togglestate, get right via set name
+ //hide filter if visible + table
+ //put current name into state, let container handle stuff itelf, register for togglestate, get right via set name
- return (
+ return (
<>
<div className={classes.toggleButtonContainer} >
<ToggleButtonGroup className={classes.subViewGroup} size="medium" value={props.selectedValue} exclusive onChange={handleChange}>
@@ -79,7 +81,7 @@
</ToggleButtonGroup>
<ToggleButtonGroup className={classes.filterGroup} onChange={handleFilterChange} >
- <ToggleButton value="" aria-label="show-filter" selected={props.showFilter as boolean} disabled={props.selectedValue !== "chart"}>
+ <ToggleButton value="" aria-label="show-filter" selected={props.showFilter as boolean} disabled={props.selectedValue !== 'chart'}>
<Tooltip disableInteractive title={props.showFilter ? 'Hide filter' : 'Show available filter'}>
<FilterListIcon />
</Tooltip>
@@ -89,13 +91,12 @@
</div>
{
- props.selectedValue === "chart" &&
+ props.selectedValue === 'chart' &&
<ChartFilter filters={props.existingFilter} onFilterChanged={props.onFilterChanged} isVisible={props.showFilter} />
}
- {props.selectedValue === "chart" ? children[0] : props.selectedValue === "table" && children[1]}
+ {props.selectedValue === 'chart' ? children[0] : props.selectedValue === 'table' && children[1]}
</>);
-
-}
+};
export default ToggleContainer;
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/transmissionPower.tsx b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/transmissionPower.tsx
index 97a35da..db9a7c0 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/transmissionPower.tsx
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/transmissionPower.tsx
@@ -15,75 +15,73 @@
* the License.
* ============LICENSE_END==========================================================================
*/
-import * as React from 'react';
+import React from 'react';
+import { RouteComponentProps, withRouter } from 'react-router-dom';
-import { withRouter, RouteComponentProps } from 'react-router-dom';
-
-import { MaterialTable, ColumnType, ColumnModel, MaterialTableCtorType } from '../../../../framework/src/components/material-table';
+import { ColumnModel, 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 connect, { Connect, IDispatcher } from '../../../../framework/src/flux/connect';
-import { TransmissionPowerDataType, TransmissionPowerDatabaseDataType } from '../models/transmissionPowerDataType';
+import { SetFilterVisibility, SetSubViewAction } from '../actions/toggleActions';
+import { createTransmissionPowerActions, createTransmissionPowerProperties } from '../handlers/transmissionPowerHandler';
import { IDataSet, IDataSetsObject } from '../models/chartTypes';
-import { createTransmissionPowerProperties, createTransmissionPowerActions } from '../handlers/transmissionPowerHandler';
+import { TransmissionPowerDatabaseDataType, TransmissionPowerDataType } from '../models/transmissionPowerDataType';
import { lineChart, sortDataByTimeStamp } from '../utils/chartUtils';
import { addColumnLabels } from '../utils/tableUtils';
-import { SetSubViewAction, SetFilterVisibility } from '../actions/toggleActions';
import ToggleContainer from './toggleContainer';
const mapProps = (state: IApplicationStoreState) => ({
transmissionPowerProperties: createTransmissionPowerProperties(state),
currentView: state.performanceHistory.subViews.transmissionPower.subView,
isFilterVisible: state.performanceHistory.subViews.transmissionPower.isFilterVisible,
- existingFilter: state.performanceHistory.transmissionPower.filter
+ existingFilter: state.performanceHistory.transmissionPower.filter,
});
const mapDisp = (dispatcher: IDispatcher) => ({
transmissionPowerActions: createTransmissionPowerActions(dispatcher.dispatch),
- setSubView: (value: "chart" | "table") => dispatcher.dispatch(new SetSubViewAction("transmissionPower", value)),
- toggleFilterButton: (value: boolean) => { dispatcher.dispatch(new SetFilterVisibility("transmissionPower", value)) },
+ setSubView: (value: 'chart' | 'table') => dispatcher.dispatch(new SetSubViewAction('transmissionPower', value)),
+ toggleFilterButton: (value: boolean) => { dispatcher.dispatch(new SetFilterVisibility('transmissionPower', value)); },
});
type TransmissionPowerComponentProps = RouteComponentProps & Connect<typeof mapProps, typeof mapDisp> & {
- selectedTimePeriod: string
-}
+ selectedTimePeriod: string;
+};
const TransmissionPowerTable = MaterialTable as MaterialTableCtorType<TransmissionPowerDataType>;
/**
* The Component which gets the transmission power data from the database based on the selected time period.
*/
-class TransmissionPowerComponent extends React.Component<TransmissionPowerComponentProps>{
-
+class TransmissionPowerComponent extends React.Component<TransmissionPowerComponentProps> {
onToggleFilterButton = () => {
this.props.toggleFilterButton(!this.props.isFilterVisible);
- }
+ };
- onChange = (value: "chart" | "table") => {
+ onChange = (value: 'chart' | 'table') => {
this.props.setSubView(value);
- }
+ };
onFilterChanged = (property: string, filterTerm: string) => {
this.props.transmissionPowerActions.onFilterChanged(property, filterTerm);
if (!this.props.transmissionPowerProperties.showFilter)
this.props.transmissionPowerActions.onToggleFilter(false);
- }
+ };
render(): JSX.Element {
- const properties = this.props.transmissionPowerProperties
- const actions = this.props.transmissionPowerActions
+ const properties = this.props.transmissionPowerProperties;
+ const actions = this.props.transmissionPowerActions;
const chartPagedData = this.getChartDataValues(properties.rows);
const transmissionColumns: ColumnModel<TransmissionPowerDataType>[] = [
- { property: "radioSignalId", title: "Radio signal", type: ColumnType.text },
- { property: "scannerId", title: "Scanner ID", type: ColumnType.text },
- { property: "timeStamp", title: "End Time", type: ColumnType.text },
+ { property: 'radioSignalId', title: 'Radio signal', type: ColumnType.text },
+ { property: 'scannerId', title: 'Scanner ID', type: ColumnType.text },
+ { property: 'timeStamp', title: 'End Time', type: ColumnType.text },
{
- property: "suspectIntervalFlag", title: "Suspect Interval", type: ColumnType.boolean
- }
+ property: 'suspectIntervalFlag', title: 'Suspect Interval', type: ColumnType.boolean,
+ },
];
chartPagedData.datasets.forEach(ds => {
@@ -92,13 +90,14 @@
return (
<>
- <ToggleContainer onChange={this.onChange} onToggleFilterButton={this.onToggleFilterButton} showFilter={this.props.isFilterVisible} existingFilter={this.props.transmissionPowerProperties.filter} onFilterChanged={this.onFilterChanged} selectedValue={this.props.currentView} >
+ <ToggleContainer onChange={this.onChange} onToggleFilterButton={this.onToggleFilterButton} showFilter={this.props.isFilterVisible}
+ existingFilter={this.props.transmissionPowerProperties.filter} onFilterChanged={this.onFilterChanged} selectedValue={this.props.currentView} >
{lineChart(chartPagedData)}
- <TransmissionPowerTable stickyHeader idProperty={"_id"} tableId="transmission-power-table" columns={transmissionColumns} {...properties} {...actions} />
+ <TransmissionPowerTable stickyHeader idProperty={'_id'} tableId="transmission-power-table" columns={transmissionColumns} {...properties} {...actions} />
</ToggleContainer>
</>
);
- };
+ }
/**
* This function gets the performance values for TransmissionPower according on the chartjs dataset structure
@@ -106,53 +105,53 @@
*/
private getChartDataValues = (rows: TransmissionPowerDataType[]): IDataSetsObject => {
- const _rows = [...rows];
- sortDataByTimeStamp(_rows);
+ const data_rows = [...rows];
+ sortDataByTimeStamp(data_rows);
const datasets: IDataSet[] = [{
- name: "txLevelMin",
- label: "tx-level-min",
+ name: 'txLevelMin',
+ label: 'tx-level-min',
borderColor: '#0e17f3de',
bezierCurve: false,
lineTension: 0,
fill: false,
data: [],
- columnLabel: "Tx min"
+ columnLabel: 'Tx min',
}, {
- name: "txLevelAvg",
- label: "tx-level-avg",
+ name: 'txLevelAvg',
+ label: 'tx-level-avg',
borderColor: '#08edb6de',
bezierCurve: false,
lineTension: 0,
fill: false,
data: [],
- columnLabel: "Tx avg"
+ columnLabel: 'Tx avg',
}, {
- name: "txLevelMax",
- label: "tx-level-max",
+ name: 'txLevelMax',
+ label: 'tx-level-max',
borderColor: '#b308edde',
bezierCurve: false,
lineTension: 0,
fill: false,
data: [],
- columnLabel: "Tx max"
+ columnLabel: 'Tx max',
}];
- _rows.forEach(row => {
+ data_rows.forEach(row => {
row.txLevelMin = row.performanceData.txLevelMin;
row.txLevelAvg = row.performanceData.txLevelAvg;
row.txLevelMax = row.performanceData.txLevelMax;
datasets.forEach(ds => {
ds.data.push({
- x: row["timeStamp" as keyof TransmissionPowerDataType] as string,
- y: row.performanceData[ds.name as keyof TransmissionPowerDatabaseDataType] as string
+ x: row['timeStamp' as keyof TransmissionPowerDataType] as string,
+ y: row.performanceData[ds.name as keyof TransmissionPowerDatabaseDataType] as string,
});
});
});
return {
- datasets: datasets
+ datasets: datasets,
};
- }
+ };
}
const TransmissionPower = withRouter(connect(mapProps, mapDisp)(TransmissionPowerComponent));
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/adaptiveModulationHandler.ts b/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/adaptiveModulationHandler.ts
index 8857845..9baf545 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/adaptiveModulationHandler.ts
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/adaptiveModulationHandler.ts
@@ -26,12 +26,12 @@
/**
* Creates elastic search material data fetch handler for Adaptive modulation from historicalperformance database.
*/
-const adaptiveModulationSearchHandler = createSearchDataHandler<AdaptiveModulationDataType>(getFilter, false, null)
+const adaptiveModulationSearchHandler = createSearchDataHandler<AdaptiveModulationDataType>(getFilter, false, null);
export const {
- actionHandler: adaptiveModulationActionHandler,
- createActions: createAdaptiveModulationActions,
- createProperties: createAdaptiveModulationProperties,
- createPreActions: createAdaptiveModulationPreActions,
- reloadAction: adaptiveModulationReloadAction,
+ actionHandler: adaptiveModulationActionHandler,
+ createActions: createAdaptiveModulationActions,
+ createProperties: createAdaptiveModulationProperties,
+ createPreActions: createAdaptiveModulationPreActions,
+ reloadAction: adaptiveModulationReloadAction,
} = createExternal<AdaptiveModulationDataType>(adaptiveModulationSearchHandler, appState => appState.performanceHistory.adaptiveModulation);
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/availableLtpsActionHandler.ts b/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/availableLtpsActionHandler.ts
index 4605efd..f943ef4 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/availableLtpsActionHandler.ts
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/availableLtpsActionHandler.ts
@@ -38,7 +38,7 @@
distinctLtps: [],
busy: false,
loadedOnce: false,
- error: undefined
+ error: undefined,
};
export const availableLtpsActionHandler: IActionHandler<IAvailableLtpsState> = (state = ltpListStateInit, action) => {
@@ -46,7 +46,7 @@
state = {
...state,
- busy: true
+ busy: true,
};
} else if (action instanceof AllAvailableLtpsLoadedAction) {
@@ -56,21 +56,21 @@
distinctLtps: action.availableLtps,
busy: false,
error: undefined,
- loadedOnce: true
+ loadedOnce: true,
};
} else if (action.error) {
state = {
...state,
busy: false,
loadedOnce: true,
- error: action.error
- }
+ error: action.error,
+ };
}
} else if (action instanceof SetInitialLoadedAction) {
state = {
...state,
- loadedOnce: action.initialLoaded
+ loadedOnce: action.initialLoaded,
};
} else if (action instanceof NoLtpsFoundAction) {
state = {
@@ -78,22 +78,20 @@
busy: false,
error: undefined,
loadedOnce: true,
- distinctLtps: []
- }
+ distinctLtps: [],
+ };
} else if (action instanceof ResetLtpsAction) {
state = {
...state,
busy: false,
error: undefined,
loadedOnce: false,
- distinctLtps: []
- }
- }
-
- else {
+ distinctLtps: [],
+ };
+ } else {
state = {
...state,
- busy: false
+ busy: false,
};
}
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/crossPolarDiscriminationHandler.ts b/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/crossPolarDiscriminationHandler.ts
index 5008dd5..96cabfa 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/crossPolarDiscriminationHandler.ts
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/crossPolarDiscriminationHandler.ts
@@ -26,13 +26,13 @@
/**
* Creates elastic search material data fetch handler for CPD from historicalperformance database.
*/
-const crossPolarDiscriminationSearchHandler = createSearchDataHandler<CrossPolarDiscriminationDataType>(getFilter, false, null)
+const crossPolarDiscriminationSearchHandler = createSearchDataHandler<CrossPolarDiscriminationDataType>(getFilter, false, null);
export const {
- actionHandler: crossPolarDiscriminationActionHandler,
- createActions: createCrossPolarDiscriminationActions,
- createProperties: createCrossPolarDiscriminationProperties,
- createPreActions: createCrossPolarDiscriminationPreActions,
- reloadAction: crossPolarDiscriminationReloadAction,
+ actionHandler: crossPolarDiscriminationActionHandler,
+ createActions: createCrossPolarDiscriminationActions,
+ createProperties: createCrossPolarDiscriminationProperties,
+ createPreActions: createCrossPolarDiscriminationPreActions,
+ reloadAction: crossPolarDiscriminationReloadAction,
} = createExternal<CrossPolarDiscriminationDataType>(crossPolarDiscriminationSearchHandler, appState => appState.performanceHistory.crossPolarDiscrimination);
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/deviceListActionHandler.ts b/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/deviceListActionHandler.ts
index b3c0db4..11e380a 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/deviceListActionHandler.ts
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/deviceListActionHandler.ts
@@ -27,7 +27,7 @@
const deviceListStateInit: IDeviceListState = {
deviceList: [],
- busy: false
+ busy: false,
};
export const deviceListActionHandler: IActionHandler<IDeviceListState> = (state = deviceListStateInit, action) => {
@@ -35,7 +35,7 @@
state = {
...state,
- busy: true
+ busy: true,
};
} else if (action instanceof AllDeviceListLoadedAction) {
@@ -43,12 +43,12 @@
state = {
...state,
deviceList: action.deviceList,
- busy: false
+ busy: false,
};
} else {
state = {
...state,
- busy: false
+ busy: false,
};
}
}
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/performanceDataHandler.ts b/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/performanceDataHandler.ts
index a7b63a3..664c7cd 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/performanceDataHandler.ts
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/performanceDataHandler.ts
@@ -15,12 +15,11 @@
* the License.
* ============LICENSE_END==========================================================================
*/
-import * as moment from 'moment';
import { createExternal, IExternalTableState } from '../../../../framework/src/components/material-table/utilities';
import { createSearchDataHandler } from '../../../../framework/src/utilities/elasticSearch';
-import { PerformanceDataType } from '../models/performanceDataType';
+import { PerformanceDataType } from '../models/performanceDataType';
import { getFilter } from '../utils/tableUtils';
export interface IPerformanceDataState extends IExternalTableState<PerformanceDataType> { }
@@ -31,10 +30,10 @@
const performanceDataSearchHandler = createSearchDataHandler<PerformanceDataType>(getFilter, false, null);
export const {
- actionHandler: performanceDataActionHandler,
- createActions: createPerformanceDataActions,
- createProperties: createPerformanceDataProperties,
- createPreActions: createPerformanceDataPreActions,
- reloadAction: performanceDataReloadAction
+ actionHandler: performanceDataActionHandler,
+ createActions: createPerformanceDataActions,
+ createProperties: createPerformanceDataProperties,
+ createPreActions: createPerformanceDataPreActions,
+ reloadAction: performanceDataReloadAction,
} = createExternal<PerformanceDataType>(performanceDataSearchHandler, appState => appState.performanceHistory.performanceData);
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/performanceHistoryRootHandler.ts b/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/performanceHistoryRootHandler.ts
index a05ff37..c0cee46 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/performanceHistoryRootHandler.ts
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/performanceHistoryRootHandler.ts
@@ -17,29 +17,29 @@
*/
// main state handler
-import { combineActionHandler } from '../../../../framework/src/flux/middleware';
-
-// ** do not remove **
-import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
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 { IConnectAppStoreState } from '../../../connectApp/src/handlers/connectAppRootHandler';
+import { UpdateMountId } from '../actions/deviceListActions';
+import { SetPanelAction } from '../actions/panelChangeActions';
+import { ReloadAction } from '../actions/reloadAction';
+import { TimeChangeAction } from '../actions/timeChangeAction';
+import { ResetAllSubViewsAction, SetFilterVisibility, SetSubViewAction } from '../actions/toggleActions';
+import { PmDataInterval } from '../models/performanceDataType';
+import { currentViewType, SubTabType } from '../models/toggleDataType';
+import { adaptiveModulationActionHandler, IAdaptiveModulationState } from './adaptiveModulationHandler';
+import { availableLtpsActionHandler, IAvailableLtpsState } from './availableLtpsActionHandler';
+import { crossPolarDiscriminationActionHandler, ICrossPolarDiscriminationState } from './crossPolarDiscriminationHandler';
+import { deviceListActionHandler, IDeviceListState } from './deviceListActionHandler';
import { IPerformanceDataState, performanceDataActionHandler } from './performanceDataHandler';
import { IReceiveLevelState, receiveLevelActionHandler } from './receiveLevelHandler';
-import { ITransmissionPowerState, transmissionPowerActionHandler } from './transmissionPowerHandler';
-import { IAdaptiveModulationState, adaptiveModulationActionHandler } from './adaptiveModulationHandler';
-import { ITemperatureState, temperatureActionHandler } from './temperatureHandler';
import { ISignalToInterferenceState, signalToInterferenceActionHandler } from './signalToInterferenceHandler';
-import { ICrossPolarDiscriminationState, crossPolarDiscriminationActionHandler } from './crossPolarDiscriminationHandler';
-import { SetPanelAction } from '../actions/panelChangeActions';
-import { IDeviceListState, deviceListActionHandler } from './deviceListActionHandler';
-import { IAvailableLtpsState, availableLtpsActionHandler } from './availableLtpsActionHandler';
-import { PmDataInterval } from '../models/performanceDataType';
-import { TimeChangeAction } from '../actions/timeChangeAction';
-import { UpdateMountId } from '../actions/deviceListActions';
-import { SetSubViewAction, ResetAllSubViewsAction, SetFilterVisibility } from '../actions/toggleActions';
-import { SubTabType, currentViewType } from '../models/toggleDataType';
-import { ReloadAction } from '../actions/reloadAction';
+import { ITemperatureState, temperatureActionHandler } from './temperatureHandler';
+import { ITransmissionPowerState, transmissionPowerActionHandler } from './transmissionPowerHandler';
export interface IPerformanceHistoryStoreState {
nodeId: string;
@@ -58,15 +58,15 @@
isReloadSchedueled: boolean;
}
-const mountIdHandler: IActionHandler<string> = (state = "", action) => {
+const mountIdHandler: IActionHandler<string> = (state = '', action) => {
if (action instanceof UpdateMountId) {
- state = "";
+ state = '';
if (action.nodeId) {
state = action.nodeId;
}
}
return state;
-}
+};
const reloadHandler: IActionHandler<boolean> = (state = false, action) => {
@@ -74,7 +74,7 @@
state = action.show;
}
return state;
-}
+};
const currentOpenPanelHandler: IActionHandler<string | null> = (state = null, action) => {
@@ -82,59 +82,75 @@
state = action.panelId;
}
return state;
-}
+};
const currentPMDataIntervalHandler: IActionHandler<PmDataInterval> = (state = PmDataInterval.pmInterval15Min, action) => {
if (action instanceof TimeChangeAction) {
state = action.time;
}
return state;
-}
+};
-type filterableSubview = { subView: SubTabType, isFilterVisible: boolean };
-type toggleViewDataType = { currentSubView: currentViewType, performanceData: filterableSubview, receiveLevel: filterableSubview, transmissionPower: filterableSubview, adaptiveModulation: filterableSubview, temperatur: filterableSubview, SINR: filterableSubview, CPD: filterableSubview };
+type filterableSubview = { subView: SubTabType; isFilterVisible: boolean };
+type toggleViewDataType = {
+ currentSubView: currentViewType;
+ performanceData: filterableSubview;
+ receiveLevel: filterableSubview;
+ transmissionPower: filterableSubview;
+ adaptiveModulation: filterableSubview;
+ temperatur: filterableSubview;
+ SINR: filterableSubview;
+ CPD: filterableSubview;
+};
-const toogleViewDataHandler: IActionHandler<toggleViewDataType> = (state = { currentSubView: "performanceData", performanceData: { subView: "chart", isFilterVisible: true }, receiveLevel: { subView: "chart", isFilterVisible: true }, adaptiveModulation: { subView: "chart", isFilterVisible: true }, transmissionPower: { subView: "chart", isFilterVisible: true }, temperatur: { subView: "chart", isFilterVisible: true }, SINR: { subView: "chart", isFilterVisible: true }, CPD: { subView: "chart", isFilterVisible: true } }, action) => {
+const toogleViewDataHandler: IActionHandler<toggleViewDataType> = (
+ state = {
+ currentSubView: 'performanceData',
+ performanceData: { subView: 'chart', isFilterVisible: true },
+ receiveLevel: { subView: 'chart', isFilterVisible: true },
+ adaptiveModulation: { subView: 'chart', isFilterVisible: true },
+ transmissionPower: { subView: 'chart', isFilterVisible: true },
+ temperatur: { subView: 'chart', isFilterVisible: true },
+ SINR: { subView: 'chart', isFilterVisible: true },
+ CPD: { subView: 'chart', isFilterVisible: true },
+ }, action) => {
if (action instanceof SetSubViewAction) {
switch (action.currentView) {
- case "performanceData": state = { ...state, performanceData: { ...state.performanceData, subView: action.selectedTab } }; break;
- case "adaptiveModulation": state = { ...state, adaptiveModulation: { ...state.adaptiveModulation, subView: action.selectedTab } }; break;
- case "receiveLevel": state = { ...state, receiveLevel: { ...state.receiveLevel, subView: action.selectedTab } }; break;
- case "transmissionPower": state = { ...state, transmissionPower: { ...state.transmissionPower, subView: action.selectedTab } }; break;
- case "Temp": state = { ...state, temperatur: { ...state.temperatur, subView: action.selectedTab } }; break;
- case "SINR": state = { ...state, SINR: { ...state.SINR, subView: action.selectedTab } }; break;
- case "CPD": state = { ...state, CPD: { ...state.CPD, subView: action.selectedTab } }; break;
+ case 'performanceData': state = { ...state, performanceData: { ...state.performanceData, subView: action.selectedTab } }; break;
+ case 'adaptiveModulation': state = { ...state, adaptiveModulation: { ...state.adaptiveModulation, subView: action.selectedTab } }; break;
+ case 'receiveLevel': state = { ...state, receiveLevel: { ...state.receiveLevel, subView: action.selectedTab } }; break;
+ case 'transmissionPower': state = { ...state, transmissionPower: { ...state.transmissionPower, subView: action.selectedTab } }; break;
+ case 'Temp': state = { ...state, temperatur: { ...state.temperatur, subView: action.selectedTab } }; break;
+ case 'SINR': state = { ...state, SINR: { ...state.SINR, subView: action.selectedTab } }; break;
+ case 'CPD': state = { ...state, CPD: { ...state.CPD, subView: action.selectedTab } }; break;
}
- }
- else if (action instanceof SetFilterVisibility) {
+ } else if (action instanceof SetFilterVisibility) {
switch (action.currentView) {
- case "performanceData": state = {
- ...state, performanceData: { ...state.performanceData, isFilterVisible: action.isVisible }
+ case 'performanceData': state = {
+ ...state, performanceData: { ...state.performanceData, isFilterVisible: action.isVisible },
}; break;
- case "adaptiveModulation": state = { ...state, adaptiveModulation: { ...state.performanceData, isFilterVisible: action.isVisible } }; break;
- case "receiveLevel": state = { ...state, receiveLevel: { ...state.receiveLevel, isFilterVisible: action.isVisible } }; break;
- case "transmissionPower": state = { ...state, transmissionPower: { ...state.transmissionPower, isFilterVisible: action.isVisible } }; break;
- case "Temp": state = { ...state, temperatur: { ...state.temperatur, isFilterVisible: action.isVisible } }; break;
- case "SINR": state = { ...state, SINR: { ...state.SINR, isFilterVisible: action.isVisible } }; break;
- case "CPD": state = { ...state, CPD: { ...state.CPD, isFilterVisible: action.isVisible } }; break;
+ case 'adaptiveModulation': state = { ...state, adaptiveModulation: { ...state.performanceData, isFilterVisible: action.isVisible } }; break;
+ case 'receiveLevel': state = { ...state, receiveLevel: { ...state.receiveLevel, isFilterVisible: action.isVisible } }; break;
+ case 'transmissionPower': state = { ...state, transmissionPower: { ...state.transmissionPower, isFilterVisible: action.isVisible } }; break;
+ case 'Temp': state = { ...state, temperatur: { ...state.temperatur, isFilterVisible: action.isVisible } }; break;
+ case 'SINR': state = { ...state, SINR: { ...state.SINR, isFilterVisible: action.isVisible } }; break;
+ case 'CPD': state = { ...state, CPD: { ...state.CPD, isFilterVisible: action.isVisible } }; break;
}
-
} else if (action instanceof ResetAllSubViewsAction) {
state = {
- ...state, performanceData: { ...state.performanceData, subView: "chart" },
- adaptiveModulation: { ...state.adaptiveModulation, subView: "chart" },
- receiveLevel: { ...state.receiveLevel, subView: "chart" },
- transmissionPower: { ...state.transmissionPower, subView: "chart" },
- temperatur: { ...state.temperatur, subView: "chart" },
- SINR: { ...state.SINR, subView: "chart" },
- CPD: { ...state.CPD, subView: "chart" }
- }
+ ...state, performanceData: { ...state.performanceData, subView: 'chart' },
+ adaptiveModulation: { ...state.adaptiveModulation, subView: 'chart' },
+ receiveLevel: { ...state.receiveLevel, subView: 'chart' },
+ transmissionPower: { ...state.transmissionPower, subView: 'chart' },
+ temperatur: { ...state.temperatur, subView: 'chart' },
+ SINR: { ...state.SINR, subView: 'chart' },
+ CPD: { ...state.CPD, subView: 'chart' },
+ };
}
-
return state;
-}
+};
declare module '../../../../framework/src/store/applicationStore' {
interface IApplicationStoreState {
@@ -157,7 +173,7 @@
currentOpenPanel: currentOpenPanelHandler,
pmDataIntervalType: currentPMDataIntervalHandler,
subViews: toogleViewDataHandler,
- isReloadSchedueled: reloadHandler
+ isReloadSchedueled: reloadHandler,
};
const performanceHistoryRootHandler = combineActionHandler<IPerformanceHistoryStoreState>(actionHandlers);
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/receiveLevelHandler.ts b/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/receiveLevelHandler.ts
index 34fd3eb..78626eb 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/receiveLevelHandler.ts
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/receiveLevelHandler.ts
@@ -29,10 +29,10 @@
const receiveLevelSearchHandler = createSearchDataHandler<ReceiveLevelDataType>(getFilter, false, null);
export const {
- actionHandler: receiveLevelActionHandler,
- createActions: createReceiveLevelActions,
- createProperties: createReceiveLevelProperties,
- createPreActions: createReceiveLevelPreActions,
- reloadAction: receiveLevelReloadAction,
+ actionHandler: receiveLevelActionHandler,
+ createActions: createReceiveLevelActions,
+ createProperties: createReceiveLevelProperties,
+ createPreActions: createReceiveLevelPreActions,
+ reloadAction: receiveLevelReloadAction,
} = createExternal<ReceiveLevelDataType>(receiveLevelSearchHandler, appState => appState.performanceHistory.receiveLevel);
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/signalToInterferenceHandler.ts b/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/signalToInterferenceHandler.ts
index 5fd5c0c..ab6efab 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/signalToInterferenceHandler.ts
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/signalToInterferenceHandler.ts
@@ -29,10 +29,10 @@
const signalToInterferenceSearchHandler = createSearchDataHandler<SignalToInterferenceDataType>(getFilter, false, null);
export const {
- actionHandler: signalToInterferenceActionHandler,
- createActions: createSignalToInterferenceActions,
- createProperties: createSignalToInterferenceProperties,
- createPreActions: createSignalToInterferencePreActions,
- reloadAction: signalToInterferenceReloadAction,
+ actionHandler: signalToInterferenceActionHandler,
+ createActions: createSignalToInterferenceActions,
+ createProperties: createSignalToInterferenceProperties,
+ createPreActions: createSignalToInterferencePreActions,
+ reloadAction: signalToInterferenceReloadAction,
} = createExternal<SignalToInterferenceDataType>(signalToInterferenceSearchHandler, appState => appState.performanceHistory.signalToInterference);
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/temperatureHandler.ts b/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/temperatureHandler.ts
index 130b818..02bf69b 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/temperatureHandler.ts
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/temperatureHandler.ts
@@ -26,13 +26,13 @@
/**
* Creates elastic search material data fetch handler for Temperature from historicalperformance database.
*/
-const temperatureSearchHandler = createSearchDataHandler< TemperatureDataType>(getFilter, false, null);
+const temperatureSearchHandler = createSearchDataHandler<TemperatureDataType>(getFilter, false, null);
export const {
- actionHandler: temperatureActionHandler,
- createActions: createTemperatureActions,
- createProperties: createTemperatureProperties,
- createPreActions: createTemperaturePreActions,
- reloadAction: temperatureReloadAction,
+ actionHandler: temperatureActionHandler,
+ createActions: createTemperatureActions,
+ createProperties: createTemperatureProperties,
+ createPreActions: createTemperaturePreActions,
+ reloadAction: temperatureReloadAction,
} = createExternal<TemperatureDataType>(temperatureSearchHandler, appState => appState.performanceHistory.temperature);
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/transmissionPowerHandler.ts b/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/transmissionPowerHandler.ts
index 2a09e58..9cf70dc 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/transmissionPowerHandler.ts
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/transmissionPowerHandler.ts
@@ -26,13 +26,13 @@
/**
* Creates elastic search material data fetch handler for Transmission power from historicalperformance database.
*/
-const transmissionPowerSearchHandler = createSearchDataHandler<TransmissionPowerDataType>(getFilter, false, null)
+const transmissionPowerSearchHandler = createSearchDataHandler<TransmissionPowerDataType>(getFilter, false, null);
export const {
- actionHandler: transmissionPowerActionHandler,
- createActions: createTransmissionPowerActions,
- createProperties: createTransmissionPowerProperties,
- createPreActions: createTransmissionPowerPreActions,
- reloadAction: transmissionPowerReloadAction,
+ actionHandler: transmissionPowerActionHandler,
+ createActions: createTransmissionPowerActions,
+ createProperties: createTransmissionPowerProperties,
+ createPreActions: createTransmissionPowerPreActions,
+ reloadAction: transmissionPowerReloadAction,
} = createExternal<TransmissionPowerDataType>(transmissionPowerSearchHandler, appState => appState.performanceHistory.transmissionPower);
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/availableLtps.ts b/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/availableLtps.ts
index dc6c7bc..6006157 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/availableLtps.ts
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/availableLtps.ts
@@ -15,7 +15,7 @@
* the License.
* ============LICENSE_END==========================================================================
*/
- export type LtpIds = {
- key : string
- }
+export type LtpIds = {
+ key: string;
+};
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/chartTypes.ts b/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/chartTypes.ts
index 53039fa..969c0b3 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/chartTypes.ts
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/chartTypes.ts
@@ -24,21 +24,21 @@
* Structure of chartjs dataset with the chart properties.
*/
export interface IDataSet {
- name: string,
- label: string,
- lineTension: 0,
+ name: string;
+ label: string;
+ lineTension: 0;
bezierCurve: boolean;
- fill: boolean,
- borderColor: string,
- data: IData[],
- columnLabel: string
+ fill: boolean;
+ borderColor: string;
+ data: IData[];
+ columnLabel: string;
}
/**
* Structure of chartjs dataset which is sent to the chart.
*/
export interface IDataSetsObject {
- datasets: IDataSet[]
+ datasets: IDataSet[];
}
/**
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/crossPolarDiscriminationDataType.ts b/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/crossPolarDiscriminationDataType.ts
index 8adb16f..749624b 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/crossPolarDiscriminationDataType.ts
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/crossPolarDiscriminationDataType.ts
@@ -32,7 +32,7 @@
* Internally used type to provide table and chart data
*/
export type CrossPolarDiscriminationDataType = {
- performanceData: CrossPolarDiscriminationDatabaseDataType
+ performanceData: CrossPolarDiscriminationDatabaseDataType;
radioSignalId: string;
scannerId: string;
timeStamp: string;
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/deviceListType.ts b/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/deviceListType.ts
index db8f2d7..fbe3141 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/deviceListType.ts
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/deviceListType.ts
@@ -22,4 +22,4 @@
export type DeviceListType = {
nodeId: string;
-}
+};
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/panelId.ts b/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/panelId.ts
index 5889a64..08bf7f8 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/panelId.ts
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/panelId.ts
@@ -19,4 +19,4 @@
/**
* Represents PanelIds for the available Expansional panels.
*/
-export type PanelId = null | "PerformanceData" | "ReceiveLevel" | "TransmissionPower" | "AdaptiveModulation" | "Temperature" | "SINR" | "CPD";
\ No newline at end of file
+export type PanelId = null | 'PerformanceData' | 'ReceiveLevel' | 'TransmissionPower' | 'AdaptiveModulation' | 'Temperature' | 'SINR' | 'CPD';
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/performanceDataType.ts b/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/performanceDataType.ts
index 30f97fb..f71e09d 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/performanceDataType.ts
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/performanceDataType.ts
@@ -15,7 +15,6 @@
* the License.
* ============LICENSE_END==========================================================================
*/
-import { Moment } from "moment";
//export { HitEntry, Result } from '../../../../framework/src/models';
@@ -50,5 +49,5 @@
*/
export const enum PmDataInterval {
pmInterval15Min,
- pmInterval24Hours
+ pmInterval24Hours,
}
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/temperatureDataType.ts b/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/temperatureDataType.ts
index 3b0cb76..5798d5c 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/temperatureDataType.ts
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/temperatureDataType.ts
@@ -32,7 +32,7 @@
* Internally used type to provide table and chart data
*/
export type TemperatureDataType = {
- performanceData: TemperatureDatabaseDataType
+ performanceData: TemperatureDatabaseDataType;
radioSignalId: string;
scannerId: string;
timeStamp: string;
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/toggleDataType.ts b/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/toggleDataType.ts
index f705e10..0e71c94 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/toggleDataType.ts
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/toggleDataType.ts
@@ -19,7 +19,7 @@
/**
* Specifies possible sub views
*/
-export type SubTabType = "chart" | "table";
+export type SubTabType = 'chart' | 'table';
-export type currentViewType = "performanceData" | "receiveLevel" | "transmissionPower" | "adaptiveModulation" | "Temp" | "SINR" | "CPD";
+export type currentViewType = 'performanceData' | 'receiveLevel' | 'transmissionPower' | 'adaptiveModulation' | 'Temp' | 'SINR' | 'CPD';
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/topologyNetconf.ts b/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/topologyNetconf.ts
index 99123f5..f52af97 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/topologyNetconf.ts
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/topologyNetconf.ts
@@ -17,10 +17,10 @@
*/
export interface TopologyNode {
- "node-id": string;
+ 'node-id': string;
}
export interface Topology {
- "topology-id": string;
+ 'topology-id': string;
node: TopologyNode[];
}
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/pluginPerformance.tsx b/sdnr/wt/odlux/apps/performanceHistoryApp/src/pluginPerformance.tsx
index a8aaca2..ef939fd 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/pluginPerformance.tsx
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/pluginPerformance.tsx
@@ -16,45 +16,64 @@
* ============LICENSE_END==========================================================================
*/
-import * as React from "react";
-import { faBook } from '@fortawesome/free-solid-svg-icons';
+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';
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
+import { IApplicationStoreState } from '../../../framework/src/store/applicationStore';
+import { ApplicationStore } from '../../../framework/src/store/applicationStore';
-import { withRouter, RouteComponentProps, Route, Switch, Redirect } from 'react-router-dom';
+import { updateMountIdActionCreator } from './actions/deviceListActions';
+import { ResetLtpsAction } from './actions/ltpAction';
+import { ReloadAction } from './actions/reloadAction';
+import { ResetAllSubViewsAction } from './actions/toggleActions';
import performanceHistoryRootHandler from './handlers/performanceHistoryRootHandler';
import { PmDataInterval } from './models/performanceDataType';
import PerformanceHistoryApplication from './views/performanceHistoryApplication';
-import { ApplicationStore } from '../../../framework/src/store/applicationStore';
-import connect, { Connect, IDispatcher } from '../../../framework/src/flux/connect';
-import { IApplicationStoreState } from "../../../framework/src/store/applicationStore";
-import { updateMountIdActionCreator } from "./actions/deviceListActions";
-import { ResetAllSubViewsAction } from "./actions/toggleActions";
-import { ResetLtpsAction } from "./actions/ltpAction";
-import { ReloadAction } from "./actions/reloadAction";
+const appIcon = require('./assets/icons/performanceHistoryAppIcon.svg'); // select app icon
let api: {
readonly applicationStore: ApplicationStore | null;
readonly applicationStoreInitialized: Promise<ApplicationStore>;
-}
+};
-const mapProps = (state: IApplicationStoreState) => ({
+const mapProps = () => ({
});
const mapDisp = (dispatcher: IDispatcher) => ({
updateMountId: (mountId: string) => dispatcher.dispatch(updateMountIdActionCreator(mountId)),
resetLtps: () => dispatcher.dispatch(new ResetLtpsAction()),
resetSubViews: () => dispatcher.dispatch(new ResetAllSubViewsAction()),
- setScheduleReload: (show: boolean) => dispatcher.dispatch(new ReloadAction(show))
+ setScheduleReload: (show: boolean) => dispatcher.dispatch(new ReloadAction(show)),
});
let currentMountId: string | null = null;
-let lastUrl: string = "/performanceHistory";
+let lastUrl: string = '/performanceHistory';
const PerformanceHistoryApplicationRouteAdapter = connect(mapProps, mapDisp)((props: RouteComponentProps<{ mountId?: string }> & Connect<typeof mapProps, typeof mapDisp>) => {
- let mountId: string = "";
+ let mountId: string = '';
- // called when component finshed mounting
+ const getMountId = (last_url: string) => {
+ let index = last_url.lastIndexOf('performanceHistory/');
+ if (index >= 0) {
+ mountId = last_url.substring(index + 19);
+ } else {
+ mountId = '';
+ }
+
+ return mountId;
+ };
+
+ const scheduleReload = (current_mount_id: string) => {
+ props.updateMountId(current_mount_id);
+ props.resetLtps();
+ props.resetSubViews();
+ props.setScheduleReload(true);
+ };
+
+ // called when component finished mounting
React.useEffect(() => {
lastUrl = props.location.pathname;
@@ -62,11 +81,11 @@
if (currentMountId !== mountId) { // new element is loaded
currentMountId = mountId;
- schedueleReload(currentMountId);
+ scheduleReload(currentMountId);
} else
- if (currentMountId !== "") { // same element is loaded again
- schedueleReload(currentMountId);
- }
+ if (currentMountId !== '') { // same element is loaded again
+ scheduleReload(currentMountId);
+ }
}, []);
// called when component gets updated
@@ -77,52 +96,34 @@
if (currentMountId !== mountId) {
currentMountId = mountId;
- schedueleReload(currentMountId);
+ scheduleReload(currentMountId);
}
});
- const getMountId = (lastUrl: string) => {
- let index = lastUrl.lastIndexOf("performanceHistory/");
- if (index >= 0) {
- mountId = lastUrl.substr(index + 19);
- } else {
- mountId = "";
- }
-
- return mountId;
- }
-
- const schedueleReload = (currentMountId: string) => {
- props.updateMountId(currentMountId);
- props.resetLtps();
- props.resetSubViews();
- props.setScheduleReload(true);
- }
-
return (
<PerformanceHistoryApplication />
);
});
const PerformanceHistoryRouterApp = withRouter((props: RouteComponentProps) => {
- props.history.action = "POP";
+ props.history.action = 'POP';
return (
<Switch>
<Route path={`${props.match.path}/:mountId`} component={PerformanceHistoryApplicationRouteAdapter} />
<Route path={`${props.match.path}`} component={PerformanceHistoryApplicationRouteAdapter} />
<Redirect to={`${props.match.path}`} />
</Switch>
- )
+ );
});
export function register() {
api = applicationManager.registerApplication({
- name: "performanceHistory",
- icon: faBook,
+ name: 'performanceHistory',
+ icon: appIcon,
rootComponent: PerformanceHistoryRouterApp,
rootActionHandler: performanceHistoryRootHandler,
- menuEntry: "Performance"
+ menuEntry: 'Performance',
});
}
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/services/performanceHistoryService.ts b/sdnr/wt/odlux/apps/performanceHistoryApp/src/services/performanceHistoryService.ts
index 70a8771..ef013f1 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/services/performanceHistoryService.ts
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/services/performanceHistoryService.ts
@@ -15,13 +15,12 @@
* the License.
* ============LICENSE_END==========================================================================
*/
-import { requestRest } from '../../../../framework/src/services/restService';
import { Result } from '../../../../framework/src/models/elasticSearch';
+import { requestRest } from '../../../../framework/src/services/restService';
import { convertPropertyNames, replaceUpperCase } from '../../../../framework/src/utilities/yangHelper';
import { LtpIds } from '../models/availableLtps';
import { DeviceListType } from '../models/deviceListType';
-import { Topology, TopologyNode } from '../models/topologyNetconf';
/**
* Represents a web api accessor service for Network elements actions.
@@ -34,26 +33,26 @@
public async getDistinctLtpsFromDatabase(networkElement: string, selectedTimePeriod: string): Promise<LtpIds[] | null> {
let path;
const query = {
- "filter": [{
- "property": "node-name",
- "filtervalue": networkElement
+ 'filter': [{
+ 'property': 'node-name',
+ 'filtervalue': networkElement,
}],
- "sortorder": [],
- "pagination": {
- "size": 20,
- "page": 1
- }
- }
+ 'sortorder': [],
+ 'pagination': {
+ 'size': 20,
+ 'page': 1,
+ },
+ };
- if (selectedTimePeriod === "15min") {
+ if (selectedTimePeriod === '15min') {
path = '/rests/operations/data-provider:read-pmdata-15m-ltp-list';
} else {
path = '/rests/operations/data-provider:read-pmdata-24h-ltp-list';
}
- const result = await requestRest<Result<string>>(path, { method: "POST", body: JSON.stringify(convertPropertyNames({ input: query }, replaceUpperCase)) });
- return result && result["data-provider:output"] && result["data-provider:output"].data && result["data-provider:output"].data.map(ne => ({ key: ne })) || null;
+ const result = await requestRest<Result<string>>(path, { method: 'POST', body: JSON.stringify(convertPropertyNames({ input: query }, replaceUpperCase)) });
+ return result && result['data-provider:output'] && result['data-provider:output'].data && result['data-provider:output'].data.map(ne => ({ key: ne })) || null;
}
@@ -64,19 +63,19 @@
public async getDeviceListfromPerf15minHistory(): Promise<(DeviceListType)[] | null> {
const path = '/rests/operations/data-provider:read-pmdata-15m-device-list';
const query = {
- "data-provider:input": {
- "filter": [],
- "sortorder": [],
- "pagination": {
- "size": 20,
- "page": 1
- }
- }
+ 'data-provider:input': {
+ 'filter': [],
+ 'sortorder': [],
+ 'pagination': {
+ 'size': 20,
+ 'page': 1,
+ },
+ },
};
- const result = await requestRest<Result<string>>(path, { method: "POST", body: JSON.stringify(query) });
- return result && result["data-provider:output"] && result["data-provider:output"].data && result["data-provider:output"].data.map(ne => ({
- nodeId: ne
+ const result = await requestRest<Result<string>>(path, { method: 'POST', body: JSON.stringify(query) });
+ return result && result['data-provider:output'] && result['data-provider:output'].data && result['data-provider:output'].data.map(ne => ({
+ nodeId: ne,
})) || null;
}
@@ -86,19 +85,19 @@
public async getDeviceListfromPerf24hHistory(): Promise<(DeviceListType)[] | null> {
const path = '/rests/operations/data-provider:read-pmdata-24h-device-list';
const query = {
- "data-provider:input": {
- "filter": [],
- "sortorder": [],
- "pagination": {
- "size": 20,
- "page": 1
- }
- }
+ 'data-provider:input': {
+ 'filter': [],
+ 'sortorder': [],
+ 'pagination': {
+ 'size': 20,
+ 'page': 1,
+ },
+ },
};
- const result = await requestRest<Result<string>>(path, { method: "POST", body: JSON.stringify(query) });
- return result && result["data-provider:output"] && result["data-provider:output"].data && result["data-provider:output"].data.map(ne => ({
- nodeId: ne
+ const result = await requestRest<Result<string>>(path, { method: 'POST', body: JSON.stringify(query) });
+ return result && result['data-provider:output'] && result['data-provider:output'].data && result['data-provider:output'].data.map(ne => ({
+ nodeId: ne,
})) || null;
}
}
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/utils/chartUtils.tsx b/sdnr/wt/odlux/apps/performanceHistoryApp/src/utils/chartUtils.tsx
index f58638e..38abb3e 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/utils/chartUtils.tsx
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/utils/chartUtils.tsx
@@ -15,15 +15,17 @@
* the License.
* ============LICENSE_END==========================================================================
*/
-import * as React from 'react';
-import { IDataSetsObject } from '../models/chartTypes';
+import React from 'react';
+import moment from 'moment';
import { Line } from 'react-chartjs-2';
-import * as moment from 'moment';
-import { ITimeStamp } from 'models/chartTypes';
+
+import { IDataSetsObject } from '../models/chartTypes';
+import { ITimeStamp } from '../models/chartTypes';
const style: React.CSSProperties = {
- height: "80%"
-}
+ height: '80%',
+};
+
export const lineChart = (chartPagedData: IDataSetsObject) => {
return (
<div style={style}>
@@ -44,32 +46,32 @@
let offsetValue = new Date().getTimezoneOffset();
var utcDate = moment(date, 'YYYY-MM-DDTHH:mm:ss').utcOffset(offsetValue).utc(false);
return utcDate;
- }
+ },
},
display: true,
scaleLabel: {
display: true,
- labelString: 'Timestamp'
- }
+ labelString: 'Timestamp',
+ },
}],
yAxes: [{
ticks: {
- beginAtZero: true
+ beginAtZero: true,
},
scaleLabel: {
display: true,
- labelString: 'Value'
- }
- }]
- }
+ labelString: 'Value',
+ },
+ }],
+ },
}} />
</div>
);
-}
+};
export const sortDataByTimeStamp = <T extends ITimeStamp>(_rows: T[]): T[] => {
return (_rows.sort((a, b) => {
- const result = Date.parse(a["timeStamp"]) - Date.parse(b["timeStamp"]);
+ const result = Date.parse(a.timeStamp) - Date.parse(b.timeStamp);
return isNaN(result) ? 0 : result;
}));
-}
\ No newline at end of file
+};
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/utils/tableUtils.ts b/sdnr/wt/odlux/apps/performanceHistoryApp/src/utils/tableUtils.ts
index b5a3a3f..37fe962 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/utils/tableUtils.ts
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/utils/tableUtils.ts
@@ -15,22 +15,22 @@
* the License.
* ============LICENSE_END==========================================================================
*/
-import { ColumnType, ColumnModel } from '../../../../framework/src/components/material-table';
+import { ColumnModel, ColumnType } from '../../../../framework/src/components/material-table';
import { PmDataInterval } from '../models/performanceDataType';
import { getPmDataInterval } from '../pluginPerformance';
export const addColumnLabels = <T>(name: string, title: string, disableFilter = true, disableSorting = true): ColumnModel<T> => {
return { property: name as keyof T, title: title, type: ColumnType.text, disableFilter: disableFilter, disableSorting: disableSorting };
-}
+};
export function getFilter(): string {
switch (getPmDataInterval()) {
- case PmDataInterval.pmInterval15Min:
- return "pmdata-15m";
- case PmDataInterval.pmInterval24Hours:
- return "pmdata-24h";
- default:
- throw new Error("Unknown time intervall");
+ case PmDataInterval.pmInterval15Min:
+ return 'pmdata-15m';
+ case PmDataInterval.pmInterval24Hours:
+ return 'pmdata-24h';
+ default:
+ throw new Error('Unknown time intervall');
}
}
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/views/performanceHistoryApplication.tsx b/sdnr/wt/odlux/apps/performanceHistoryApp/src/views/performanceHistoryApplication.tsx
index b33b442..a4b9686 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/views/performanceHistoryApplication.tsx
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/views/performanceHistoryApplication.tsx
@@ -15,57 +15,54 @@
* the License.
* ============LICENSE_END==========================================================================
*/
-import * as React from 'react';
+import React from 'react';
+import { connect, Connect, IDispatcher } from '../../../../framework/src/flux/connect';
import { Theme } from '@mui/material/styles';
import { WithStyles } from '@mui/styles';
import createStyles from '@mui/styles/createStyles';
import withStyles from '@mui/styles/withStyles';
-import FormControl from '@mui/material/FormControl';
-import MenuItem from '@mui/material/MenuItem';
-import Select from '@mui/material/Select';
-import connect, { Connect, IDispatcher } from '../../../../framework/src/flux/connect';
-import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
-import { Panel, Loader } from '../../../../framework/src/components/material-ui';
+
import { NavigateToApplication } from '../../../../framework/src/actions/navigationActions';
import { Dispatch } from '../../../../framework/src/flux/store';
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
-import { PanelId } from '../models/panelId';
-import { PmDataInterval } from '../models/performanceDataType';
-import PerformanceData from '../components/performanceData';
-import ReceiveLevel from '../components/receiveLevel';
-import TransmissionPower from '../components/transmissionPower';
-import AdaptiveModulation from '../components/adaptiveModulation';
-import Temperature from '../components/temperature';
-import SignalToInterference from '../components/signalToInterference';
-import CrossPolarDiscrimination from '../components/crossPolarDiscrimination';
import { loadAllDeviceListAsync } from '../actions/deviceListActions';
-import { TimeChangeAction } from '../actions/timeChangeAction';
import { loadDistinctLtpsbyNetworkElementAsync, ResetLtpsAction } from '../actions/ltpAction';
import { SetPanelAction } from '../actions/panelChangeActions';
-import { createPerformanceDataPreActions, performanceDataReloadAction, createPerformanceDataActions } from '../handlers/performanceDataHandler';
-import { createReceiveLevelPreActions, receiveLevelReloadAction, createReceiveLevelActions } from '../handlers/receiveLevelHandler';
-import { createTransmissionPowerPreActions, transmissionPowerReloadAction, createTransmissionPowerActions } from '../handlers/transmissionPowerHandler';
-import { createAdaptiveModulationPreActions, adaptiveModulationReloadAction, createAdaptiveModulationActions } from '../handlers/adaptiveModulationHandler';
-import { createTemperaturePreActions, temperatureReloadAction, createTemperatureActions } from '../handlers/temperatureHandler';
-import { createSignalToInterferencePreActions, signalToInterferenceReloadAction, createSignalToInterferenceActions } from '../handlers/signalToInterferenceHandler';
-import { createCrossPolarDiscriminationPreActions, crossPolarDiscriminationReloadAction, createCrossPolarDiscriminationActions } from '../handlers/crossPolarDiscriminationHandler';
+import { TimeChangeAction } from '../actions/timeChangeAction';
+import AdaptiveModulation from '../components/adaptiveModulation';
+import CrossPolarDiscrimination from '../components/crossPolarDiscrimination';
+import PerformanceData from '../components/performanceData';
+import ReceiveLevel from '../components/receiveLevel';
+import SignalToInterference from '../components/signalToInterference';
+import Temperature from '../components/temperature';
+import TransmissionPower from '../components/transmissionPower';
+import { adaptiveModulationReloadAction, createAdaptiveModulationActions, createAdaptiveModulationPreActions } from '../handlers/adaptiveModulationHandler';
+import { createCrossPolarDiscriminationActions, createCrossPolarDiscriminationPreActions, crossPolarDiscriminationReloadAction } from '../handlers/crossPolarDiscriminationHandler';
+import { createPerformanceDataActions, createPerformanceDataPreActions, performanceDataReloadAction } from '../handlers/performanceDataHandler';
+import { createReceiveLevelActions, createReceiveLevelPreActions, receiveLevelReloadAction } from '../handlers/receiveLevelHandler';
+import { createSignalToInterferenceActions, createSignalToInterferencePreActions, signalToInterferenceReloadAction } from '../handlers/signalToInterferenceHandler';
+import { createTemperatureActions, createTemperaturePreActions, temperatureReloadAction } from '../handlers/temperatureHandler';
+import { createTransmissionPowerActions, createTransmissionPowerPreActions, transmissionPowerReloadAction } from '../handlers/transmissionPowerHandler';
+import { PanelId } from '../models/panelId';
+import { PmDataInterval } from '../models/performanceDataType';
+import { AppBar, SelectChangeEvent, Tab, Tabs } from '@mui/material';
import { MaterialTable, MaterialTableCtorType } from '../../../../framework/src/components/material-table';
-import { AppBar, Tabs, Tab, SelectChangeEvent } from '@mui/material';
-import LtpSelection from '../components/ltpSelection';
-import { ResetAllSubViewsAction } from '../actions/toggleActions';
import { ReloadAction } from '../actions/reloadAction';
+import { ResetAllSubViewsAction } from '../actions/toggleActions';
+import LtpSelection from '../components/ltpSelection';
const PerformanceHistoryComponentStyles = (theme: Theme) => createStyles({
root: {
- display: "flex",
- flexWrap: "wrap",
+ display: 'flex',
+ flexWrap: 'wrap',
},
margin: {
margin: theme.spacing(1),
- }
+ },
});
const mapProps = (state: IApplicationStoreState) => ({
@@ -75,7 +72,7 @@
networkElements: state.performanceHistory.networkElements.deviceList,
initialLoaded: state.performanceHistory.ltps.loadedOnce,
error: state.performanceHistory.ltps.error,
- shouldReload: state.performanceHistory.isReloadSchedueled
+ shouldReload: state.performanceHistory.isReloadSchedueled,
});
const mapDispatcher = (dispatcher: IDispatcher) => ({
@@ -103,112 +100,117 @@
getAllDevicesPMdata: async () => {
await dispatcher.dispatch(loadAllDeviceListAsync);
},
- getDistinctLtpsIds: (selectedNetworkElement: string, selectedTimePeriod: string, selectedLtp: string, selectFirstLtp?: Function, resetLTP?: Function) => dispatcher.dispatch(loadDistinctLtpsbyNetworkElementAsync(selectedNetworkElement, selectedTimePeriod, selectedLtp, selectFirstLtp, resetLTP)),
+ getDistinctLtpsIds: (
+ selectedNetworkElement: string,
+ selectedTimePeriod: string,
+ selectedLtp: string,
+ selectFirstLtp?: Function,
+ resetLTP?: Function,
+ ) => dispatcher.dispatch(loadDistinctLtpsbyNetworkElementAsync(selectedNetworkElement, selectedTimePeriod, selectedLtp, selectFirstLtp, resetLTP)),
setCurrentPanel: (panelId: PanelId) => dispatcher.dispatch(new SetPanelAction(panelId)),
timeIntervalChange: (time: PmDataInterval) => dispatcher.dispatch(new TimeChangeAction(time)),
changeNode: (nodeId: string) => dispatcher.dispatch((dispatch: Dispatch) => {
- dispatch(new NavigateToApplication("performanceHistory", nodeId));
+ dispatch(new NavigateToApplication('performanceHistory', nodeId));
}),
resetLtps: () => dispatcher.dispatch((dispatch: Dispatch) => { dispatch(new ResetLtpsAction()); }),
resetSubViews: () => dispatcher.dispatch(new ResetAllSubViewsAction()),
- setShouldReload: (show: boolean) => dispatcher.dispatch(new ReloadAction(show))
+ setShouldReload: (show: boolean) => dispatcher.dispatch(new ReloadAction(show)),
});
export type NetworkElementType = {
- nodeId: string,
-}
+ nodeId: string;
+};
+
const NetworkElementTable = MaterialTable as MaterialTableCtorType<NetworkElementType>;
type PerformanceHistoryComponentProps = Connect<typeof mapProps, typeof mapDispatcher> & WithStyles<typeof PerformanceHistoryComponentStyles>;
type PerformanceHistoryComponentState = {
- selectedNetworkElement: string,
- selectedTimePeriod: string,
- selectedLtp: string,
- showNetworkElementsTable: boolean,
- showLtps: boolean,
- showPanels: boolean,
+ selectedNetworkElement: string;
+ selectedTimePeriod: string;
+ selectedLtp: string;
+ showNetworkElementsTable: boolean;
+ showLtps: boolean;
+ showPanels: boolean;
preFilter:
{
- "node-name": string,
- "uuid-interface": string
- } | {}
+ 'node-name': string;
+ 'uuid-interface': string;
+ } | {};
};
/**
* Represents the component for Performance history application.
*/
-class PerformanceHistoryComponent extends React.Component<PerformanceHistoryComponentProps, PerformanceHistoryComponentState>{
+class PerformanceHistoryComponent extends React.Component<PerformanceHistoryComponentProps, PerformanceHistoryComponentState> {
/**
* Initialises this instance
*/
constructor(props: PerformanceHistoryComponentProps) {
super(props);
this.state = {
- selectedNetworkElement: props.nodeId !== "" ? props.nodeId : "-1",
- selectedTimePeriod: "15min",
- selectedLtp: "-1",
+ selectedNetworkElement: props.nodeId !== '' ? props.nodeId : '-1',
+ selectedTimePeriod: '15min',
+ selectedLtp: '-1',
showNetworkElementsTable: true,
showLtps: false,
showPanels: false,
- preFilter: {}
+ preFilter: {},
};
}
onChangeTabs = (event: React.SyntheticEvent, newValue: PanelId) => {
const nextActivePanel = newValue;
this.changeTabs(nextActivePanel);
- }
+ };
changeTabs = (nextActivePanel: PanelId) => {
this.props.setCurrentPanel(nextActivePanel);
const preFilter = this.state.preFilter;
switch (nextActivePanel) {
- case "PerformanceData":
+ case 'PerformanceData':
if (this.props.performanceData.preFilter !== {} && this.props.performanceData.preFilter === preFilter) {
this.props.reloadPerformanceData();
} else {
this.props.performanceDataPreActions.onPreFilterChanged(preFilter);
}
break;
- case "ReceiveLevel":
+ case 'ReceiveLevel':
if (this.props.receiveLevel.preFilter !== {} && this.props.receiveLevel.preFilter === preFilter) {
this.props.reloadReceiveLevel();
- }
- else {
+ } else {
this.props.receiveLevelPreActions.onPreFilterChanged(preFilter);
}
break;
- case "TransmissionPower":
+ case 'TransmissionPower':
if (this.props.transmissionPower.preFilter !== {} && this.props.transmissionPower.preFilter === preFilter) {
this.props.reloadTransmissionPower();
- }
- else {
+ } else {
this.props.transmissionPowerPreActions.onPreFilterChanged(preFilter);
}
break;
- case "AdaptiveModulation":
+ case 'AdaptiveModulation':
if (this.props.adaptiveModulation.preFilter !== {} && this.props.adaptiveModulation.preFilter === preFilter) {
this.props.reloadAdaptiveModulation();
} else {
this.props.adaptiveModulationPreActions.onPreFilterChanged(preFilter);
}
break;
- case "Temperature":
+ case 'Temperature':
if (this.props.temperature.preFilter !== {} && this.props.temperature.preFilter === preFilter) {
this.props.reloadTemperature();
} else {
this.props.temperaturePreActions.onPreFilterChanged(preFilter);
}
break;
- case "SINR":
+ case 'SINR':
if (this.props.signalToInterference.preFilter !== {} && this.props.signalToInterference.preFilter === preFilter) {
this.props.reloadSignalToInterference();
} else {
this.props.signalToInterferencePreActions.onPreFilterChanged(preFilter);
}
break;
- case "CPD":
+ case 'CPD':
if (this.props.crossPolarDiscrimination.preFilter !== {} && this.props.crossPolarDiscrimination.preFilter === preFilter) {
this.props.reloadCrossPolarDiscrimination();
} else {
@@ -219,21 +221,20 @@
// do nothing if all panels are closed
break;
}
- }
+ };
render(): JSX.Element {
const { activePanel, nodeId } = this.props;
- if (nodeId === "") {
+ if (nodeId === '') {
return (
<>
- <NetworkElementTable tableId="performance-data-element-selection-table" defaultSortColumn={"nodeId"} defaultSortOrder="asc" stickyHeader title={"Please select the network element!"} idProperty={"nodeId"} rows={this.props.networkElements} asynchronus
- onHandleClick={(event, rowData) => { this.handleNetworkElementSelect(rowData.nodeId) }} columns={
- [{ property: "nodeId", title: "Node Name" }]
+ <NetworkElementTable tableId="performance-data-element-selection-table" defaultSortColumn={'nodeId'} defaultSortOrder="asc" stickyHeader title={'Please select the network element!'} idProperty={'nodeId'} rows={this.props.networkElements} asynchronus
+ onHandleClick={(event, rowData) => { this.handleNetworkElementSelect(rowData.nodeId); }} columns={
+ [{ property: 'nodeId', title: 'Node Name' }]
} />
</>
- )
- }
- else {
+ );
+ } else {
this.handleURLChange(nodeId);
return (
<>
@@ -259,42 +260,42 @@
</Tabs>
</AppBar>
{
- activePanel === "PerformanceData" &&
+ activePanel === 'PerformanceData' &&
<PerformanceData selectedTimePeriod={this.state.selectedTimePeriod} />
}
{
- activePanel === "ReceiveLevel" &&
+ activePanel === 'ReceiveLevel' &&
<ReceiveLevel selectedTimePeriod={this.state.selectedTimePeriod} />
}
{
- activePanel === "TransmissionPower" &&
+ activePanel === 'TransmissionPower' &&
<TransmissionPower selectedTimePeriod={this.state.selectedTimePeriod} />
}
{
- activePanel === "AdaptiveModulation" &&
+ activePanel === 'AdaptiveModulation' &&
<AdaptiveModulation selectedTimePeriod={this.state.selectedTimePeriod} />
}
{
- activePanel === "Temperature" &&
+ activePanel === 'Temperature' &&
<Temperature selectedTimePeriod={this.state.selectedTimePeriod} />
}
{
- activePanel === "SINR" &&
+ activePanel === 'SINR' &&
<SignalToInterference selectedTimePeriod={this.state.selectedTimePeriod} />
}
{
- activePanel === "CPD" &&
+ activePanel === 'CPD' &&
<CrossPolarDiscrimination selectedTimePeriod={this.state.selectedTimePeriod} />
}
</>
}
</>
- )
+ );
}
}
@@ -310,19 +311,19 @@
private selectFirstLtp = (firstLtp: string) => {
this.setState({
showPanels: true,
- selectedLtp: firstLtp
+ selectedLtp: firstLtp,
});
this.preFilterChangeAndReload(this.state.selectedNetworkElement, this.state.selectedTimePeriod, firstLtp);
- this.changeTabs("PerformanceData");
- }
+ this.changeTabs('PerformanceData');
+ };
/**
* A function which reloads the visible table, if available, based on prefilters defined by network element and ltp on selected time period.
*/
private preFilterChangeAndReload = (networkElement: string, timePeriod: string, ltp: string) => {
const newPreFilter = {
- "node-name": networkElement,
- "uuid-interface": ltp
+ 'node-name': networkElement,
+ 'uuid-interface': ltp,
};
const activePanel = this.props.activePanel;
@@ -331,25 +332,25 @@
// set prefilter and reload data if panel is open
switch (activePanel) {
- case "PerformanceData":
+ case 'PerformanceData':
this.props.performanceDataPreActions.onPreFilterChanged(newPreFilter);
break;
- case "ReceiveLevel":
+ case 'ReceiveLevel':
this.props.receiveLevelPreActions.onPreFilterChanged(newPreFilter);
break;
- case "TransmissionPower":
+ case 'TransmissionPower':
this.props.transmissionPowerPreActions.onPreFilterChanged(newPreFilter);
break;
- case "AdaptiveModulation":
+ case 'AdaptiveModulation':
this.props.adaptiveModulationPreActions.onPreFilterChanged(newPreFilter);
break;
- case "Temperature":
+ case 'Temperature':
this.props.temperaturePreActions.onPreFilterChanged(newPreFilter);
break;
- case "SINR":
+ case 'SINR':
this.props.signalToInterferencePreActions.onPreFilterChanged(newPreFilter);
break;
- case "CPD":
+ case 'CPD':
this.props.crossPolarDiscriminationPreActions.onPreFilterChanged(newPreFilter);
break;
default:
@@ -359,9 +360,9 @@
}
// set prefilter
- this.setState({ preFilter: newPreFilter })
+ this.setState({ preFilter: newPreFilter });
- }
+ };
/**
* Function which handles network element changes.
@@ -373,15 +374,15 @@
selectedNetworkElement: selectedNetworkElement,
showNetworkElementsTable: false,
showPanels: false,
- selectedLtp: "-1"
+ selectedLtp: '-1',
});
this.props.resetSubViews();
this.props.resetLtps();
this.setState({ preFilter: {} });
this.props.changeNode(selectedNetworkElement);
- this.props.getDistinctLtpsIds(selectedNetworkElement, this.state.selectedTimePeriod, "-1", this.selectFirstLtp);
- }
+ this.props.getDistinctLtpsIds(selectedNetworkElement, this.state.selectedTimePeriod, '-1', this.selectFirstLtp);
+ };
private handleURLChange = (selectedNetworkElement: string) => {
@@ -391,12 +392,12 @@
showLtps: true,
selectedNetworkElement: selectedNetworkElement,
showPanels: false,
- selectedLtp: "-1"
+ selectedLtp: '-1',
});
- this.props.getDistinctLtpsIds(selectedNetworkElement, this.state.selectedTimePeriod, "-1", this.selectFirstLtp);
+ this.props.getDistinctLtpsIds(selectedNetworkElement, this.state.selectedTimePeriod, '-1', this.selectFirstLtp);
this.props.setShouldReload(false);
}
- }
+ };
/**
* Function which resets the ltps to "--select--" in the state if the passed parameter @ltpNotSelected is true.
@@ -405,18 +406,18 @@
private resetLtpDropdown = (ltpNotSelected: boolean) => {
if (ltpNotSelected) {
this.setState({
- selectedLtp: "-1",
- showPanels: false
+ selectedLtp: '-1',
+ showPanels: false,
});
}
- }
+ };
/**
* Function which handles the time period changes.
*/
private handleTimePeriodChange = (event: SelectChangeEvent<HTMLSelectElement>) => {
- const selectedTimeInterval = event.target.value === "15min"
+ const selectedTimeInterval = event.target.value === '15min'
? PmDataInterval.pmInterval15Min
: PmDataInterval.pmInterval24Hours;
@@ -427,28 +428,28 @@
this.props.timeIntervalChange(selectedTimeInterval);
this.props.getDistinctLtpsIds(this.state.selectedNetworkElement, event.target.value as string, this.state.selectedLtp, undefined, this.resetLtpDropdown);
this.preFilterChangeAndReload(this.state.selectedNetworkElement, event.target.value as string, this.state.selectedLtp);
- }
+ };
/**
* Function which handles the ltp changes.
*/
private handleLtpChange = (event:SelectChangeEvent<HTMLSelectElement> ) => {
- if (event.target.value === "-1") {
+ if (event.target.value === '-1') {
this.setState({
showPanels: false,
- selectedLtp: event.target.value
+ selectedLtp: event.target.value,
});
} else if (event.target.value !== this.state.selectedLtp) {
this.setState({
showPanels: true,
- selectedLtp: event.target.value as string
+ selectedLtp: event.target.value as string,
});
this.preFilterChangeAndReload(this.state.selectedNetworkElement, this.state.selectedTimePeriod, event.target.value as string);
}
- }
+ };
}
const PerformanceHistoryApplication = withStyles(PerformanceHistoryComponentStyles)(connect(mapProps, mapDispatcher)(PerformanceHistoryComponent));
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/tsconfig.json b/sdnr/wt/odlux/apps/performanceHistoryApp/tsconfig.json
index a66b5d8..ca65092 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/tsconfig.json
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/tsconfig.json
@@ -4,7 +4,7 @@
"outDir": "./dist",
"sourceMap": true,
"forceConsistentCasingInFileNames": true,
- "allowSyntheticDefaultImports": false,
+ "allowSyntheticDefaultImports": true,
"allowUnreachableCode": false,
"allowUnusedLabels": false,
"noFallthroughCasesInSwitch": true,
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/webpack.config.js b/sdnr/wt/odlux/apps/performanceHistoryApp/webpack.config.js
index 8f2192f..2f25d0d 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/webpack.config.js
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/webpack.config.js
@@ -57,6 +57,16 @@
use: [{
loader: "babel-loader"
}]
+ },{
+ //don't minify images
+ test: /\.(png|gif|jpg|svg)$/,
+ use: [{
+ loader: 'url-loader',
+ options: {
+ limit: 10,
+ name: './images/[name].[ext]'
+ }
+ }]
}]
},