+++ /dev/null
-.. contents::
- :depth: 3
-..
-
-Log
-===
-
-The application displays (UX) application logs. SDN-R offer a common log
-server, so that PNFs or other ONAP components could log there data in a
-common way.
+++ /dev/null
-.. contents::
- :depth: 3
-..
-
-Test
-====
-
-The view offers in a generic way data fetched from ONF-TR-532 devices
-for test and debug purposes.
+++ /dev/null
-.. contents::
- :depth: 3
-..
-
-Event Log
-=========
-
-The 'EventLog' application displays application logs and messages
-automatically created by the different active applications. SDN-R offers
-a common log service so that PNFs or other ONAP components can log their
-data and users can analyze and export the data in a common way.
+++ /dev/null
-.. contents::
- :depth: 3
-..
-
-SDN controller persona for 'Radio' (SDN-R)
-==========================================
-
-SDN-R adds features and functionality to the OpenDaylight-based ONAP
-controller 'CCSDK/SDNC'. It is built on the Common Controller Framework
-to control and manage wireless resources. Wireless resources are virtual
-network functions (e.g. vBBU, vEPC) or physical network functions (e.g.
-microwave and millimeter wave radios, eNodeB, RRH, DAS equipment).
-
-| SDN-R is integrated into ONAP using DMaaP APIs. It is interfacing with
- PNFs and VNFs and with other ONAP components, such as A&AI, DCAE and
- SO.
-| `See abbreviations <abbreviations.md>`__
-
-.. figure:: ./ONAP-SDN-R.png
- :alt: SDN-R in ONAP
-
- SDN-R in ONAP
-chttps://raw.githubusercontent.com/openstack/requirements/stable/yoga/upper-constraints.txt
-chttps://git.onap.org/doc/plain/etc/upper-constraints.onap.txt
commands =
- sphinx-build -b html -n -d {envtmpdir}/doctrees ./ {toxinidir}/_build/html
+ sphinx-build -W -b html -n -d {envtmpdir}/doctrees ./ {toxinidir}/_build/html
echo "Generated docs available in {toxinidir}/_build/html"
whitelist_externals =
echo
basepython = python3.8
#deps = -r{toxinidir}/requirements-docs.txt
commands = echo "Link Checking not enforced"
-#commands = sphinx-build -b linkcheck -d {envtmpdir}/doctrees ./ {toxinidir}/_build/linkcheck
+#commands = sphinx-build -b -W linkcheck -d {envtmpdir}/doctrees ./ {toxinidir}/_build/linkcheck
whitelist_externals = echo
[testenv:docs-spellcheck]
--- /dev/null
+**/dist/**
+**/build/**
+**/node_modules/**
+apps/eventApp/**/*
+apps/faultApp/**/*
+apps/helpApp/**/*
+apps/inventoryApp/**/*
+apps/lineOfSightApp/**/*
+apps/maintenanceApp/**/*
+apps/mediatorApp/**/*
+apps/performanceHistoryApp/**/*
+apps/siteManagerApp/**/*
\ No newline at end of file
"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",
~ ============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>
<!-- 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>
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);
import { ModulesRequestSuccess } from '../actions/modulesSuccess';
import { Module } from '../models/module';
-export type IModules = Module[]
+export type IModules = Module[];
const modulesInit: IModules = [];
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
* 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 ) => (
<>
);
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',
});
"outDir": "./dist",
"sourceMap": true,
"forceConsistentCasingInFileNames": true,
- "allowSyntheticDefaultImports": false,
+ "allowSyntheticDefaultImports": true,
"allowUnreachableCode": false,
"allowUnusedLabels": false,
"noFallthroughCasesInSwitch": true,
"@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",
~ ============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>
<!-- 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>
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 ) {
}
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;
-};
-
-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 ) => {
-}
-
-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);
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);
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;
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;
}, {});
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];
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));
}
}
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;
}
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
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
}
}
? 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,
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;
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;
: 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 || ''}`);
}
}
};
// 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));
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;
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));
// }
}
- 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;
: 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));
--- /dev/null
+<!-- highstreet technologies GmbH colour scheme \r
+ Grey #565656\r
+ LBlue #36A9E1\r
+ DBlue #246DA2\r
+ Green #003F2C / #006C4B\r
+ Yellw #C8D400\r
+ Red #D81036\r
+-->\r
+\r
+\r
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 142 140" >\r
+<g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" transform="scale(10,10)">\r
+\r
+\r
+ <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>\r
+\r
+ <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>\r
+\r
+</g>\r
+</svg>
\ No newline at end of file
* ============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
* ============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
* ============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
* ============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 { BaseProps } from "./baseProps";
+import { ViewElement } from '../models/uiModels';
-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';
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);
};
{ !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 }
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 }
</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>
</>
* ============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) => {
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 }}
*/
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',
},
}));
};
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
* ============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
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 ;
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 }}
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;
};
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) }}
+++ /dev/null
-/**
- * ============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
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
declare module '../../../../framework/src/store/applicationStore' {
interface IApplicationStoreState {
- configuration: IConfigurationAppStoreState,
+ configuration: IConfigurationAppStoreState;
}
}
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,
const neUrl = restService.getNetworkElementUri(ne.id);
const policy = getAccessPolicyByUrl(neUrl);
return !(policy.GET && policy.POST);
- }
+ },
);
* ============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) => {
...state,
nodeId: action.nodeId,
modules: action.modules,
- views: action.views
+ views: action.views,
};
}
return state;
* ============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;
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) => {
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: [],
};
}
* ============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;
} | {
displayMode: DisplayModeType.displayAsMessage;
renderMessage: string;
-}
+};
export interface IViewDescriptionState {
vPath: string | null;
displaySpecification: DisplaySpecification;
- viewData: any,
- outputData?: any,
+ viewData: any;
+ outputData?: any;
}
const viewDescriptionStateInit: IViewDescriptionState = {
};
export const viewDescriptionHandler: IActionHandler<IViewDescriptionState> = (state = viewDescriptionStateInit, action) => {
- if (action instanceof UpdatViewDescription) {
+ if (action instanceof UpdateViewDescription) {
state = {
...state,
vPath: action.vPath,
outputData: undefined,
displaySpecification: action.displaySpecification,
};
- } else if (action instanceof UpdatOutputData) {
+ } else if (action instanceof UpdateOutputData) {
state = {
...state,
outputData: action.outputData,
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?: {
failureReason: string;
capability: string;
}[];
- }
-}
+ };
+};
* ============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
| 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
* ============LICENSE_END==========================================================================
*/
-import { ViewElement, ViewSpecification } from "./uiModels";
+import { ViewElement, ViewSpecification } from './uiModels';
export enum ModuleState {
stable,
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 = {
views: { [view: string]: ViewSpecification };
elements: { [view: string]: ViewElement };
executionOrder?: number;
-}
\ No newline at end of file
+};
\ No newline at end of file
* ============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 = '';
// 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);
export function register() {
applicationManager.registerApplication({
- name: "configuration",
- icon: faAdjust,
+ name: 'configuration',
+ icon: appIcon,
rootComponent: App,
rootActionHandler: configurationAppRootHandler,
- menuEntry: "Configuration"
+ menuEntry: 'Configuration',
});
}
* ============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 ? {
} : 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 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
? await this.getImportOnlyModules(nodeId)
: null;
// 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.
* @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.
* @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.
* @returns The restconf result.
*/
public removeConfigElement(path: string) {
- return requestRestExt<{ [key: string]: any }>(path, { method: "DELETE" });
+ return requestRestExt<{ [key: string]: any }>(path, { method: 'DELETE' });
}
}
* ============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;
-};
-
-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;
+ 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
--- /dev/null
+/**
+ * ============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 };
+};
+
+
+
+
--- /dev/null
+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
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 { getAccessPolicyByUrl } from "../../../../framework/src/services/restService";
+import {
+ SetSelectedValue,
+ updateDataActionAsyncCreator,
+ updateViewActionAsyncCreator,
+ removeElementActionAsyncCreator,
+ executeRpcActionAsyncCreator,
+} from '../actions/deviceActions';
+
+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';
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 InputLabel from "@mui/material/InputLabel";
-import Select from "@mui/material/Select";
-import MenuItem from "@mui/material/MenuItem";
-import Breadcrumbs from "@mui/material/Breadcrumbs";
+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 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';
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': {
},
},
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) => ({
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>) => {
);
};
-const OldProps = Symbol("OldProps");
+const OldProps = Symbol('OldProps');
class ConfigurationApplicationComponent extends React.Component<ConfigurationApplicationComponentProps, ConfigurationApplicationComponentState> {
/**
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 => {
};
}
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;
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) {
}
});
return;
- };
+ }
Object.keys(caseElements).forEach(caseElementKey => {
acc.push(caseElements[caseElementKey]);
});
}
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)) {
} 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);
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 {
value={uiElement}
readOnly={!canEdit}
disabled={editMode && !canEdit}
- onChange={(e) => { this.changeValueFor(uiElement.id, e) }}
+ onChange={(e) => { this.changeValueFor(uiElement.id, e); }}
/>)
: null;
}
// }
// };
- 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 (
<>
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}`,
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>
);
})
}
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;
}
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;
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);
? (
<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
}
? (
<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
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];
{
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)} >
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.
tooltip: 'Add',
ariaLabel:'add-element',
onClick: () => {
- navigate("[]"); // empty key means new element
+ navigate('[]'); // empty key means new element
},
disabled: !config,
};
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}
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">
</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>
);
}
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);
</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
}
</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}>
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="#"
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;
</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}
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);
}
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 (
<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;
* ============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) => ({
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>
);
--- /dev/null
+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
+/* 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
* 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[] = [];
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',
private _isAlpha(char: string): boolean {
return (char >= 'a' && char <= 'z') ||
- (char >= 'A' && char <= 'Z')
+ (char >= 'A' && char <= 'Z');
}
private _isAlphanum(char: string): boolean {
char === '_' || char === '-' || char === '.';
}
- private _skipNontokens() {
+ private _skipNonTokens() {
while (this.pos < this.buf.length) {
const char = this.buf.charAt(this.pos);
if (this._isWhitespace(char)) {
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++;
name: 'STRING',
value: this.buf.substring(start, end),
start,
- end
+ end,
};
this.pos = terminator ? end + 1 : end;
return tok;
++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))) {
name: name,
value: this.buf.substring(this.pos, endpos),
start: this.pos,
- end: endpos
+ end: endpos,
};
this.pos = endpos;
name: 'NUMBER',
value: this.buf.substring(this.pos, endpos),
start: this.pos,
- end: endpos
+ end: endpos,
};
this.pos = endpos;
return tok;
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;
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];
}
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 nodeId: string,
+ private _capabilityRevisionMap: { [capability: string]: string } = {},
+ private _unavailableCapabilities: { failureReason: string; capability: string }[] = [],
+ private _importOnlyModules: { name: string; revision: string }[] = [],
+ ) {
- constructor(private _unavailableCapabilities: { failureReason: string; capability: string; }[] = [], private _importOnlyModules: { name: string; revision: string; }[] = [], private nodeId: string) {
-
}
public get modules() {
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;
}
// // 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) {
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: {},
views: {},
elements: {},
state: isUnavailable
- ? ModuleState.unavailable
- : isImportOnly
- ? ModuleState.importOnly
- : ModuleState.stable,
+ ? ModuleState.unavailable
+ : isImportOnly
+ ? ModuleState.importOnly
+ : ModuleState.stable,
};
await this.handleModule(module, rootStatement, capability);
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
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];
});
// 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}]`);
}
});
* 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 => {
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++;
}
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 => {
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,
};
}));
}
}
}
return result;
- }
+ };
const baseIdentities: Identity[] = [];
Object.keys(this.modules).forEach(modKey => {
}
});
- // 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];
-
- // 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);
- }
+ // // resolve readOnly
+ // const resolveReadOnly = (view: ViewSpecification, parentConfig: boolean) => {
- })
- }
+ // // update view config
+ // view.config = view.config && parentConfig;
- const dump = resolveReadOnly(this.views[0], true);
- };
+ // Object.keys(view.elements).forEach((key) => {
+ // const elm = view.elements[key];
+
+ // // 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++;
}
}
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.`);
/** 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) {
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;
}, []));
}
/** 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) {
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;
}, []));
}
/** 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);
// 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);
}
- 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}`);
}
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,
};
}, []));
}
- // 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),
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;
};
// 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;
}
viewSpec.uses.push(this.resolveReferencePath(groupingName, context));
-
+
resolveFunctions.push((parentElementPath: string) => {
const groupingViewSpec = this.resolveGrouping(groupingName, context);
if (groupingViewSpec) {
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,
};
});
}
}
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);
}
/** 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;
return {
min: minValue,
- max: maxValue
+ max: maxValue,
};
});
return {
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.`);
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.`);
}
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;
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);
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 = () => {
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!,
};
}));
};
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
}
// 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 ({
}
}
- 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,
}
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}`;
}
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);
}
}
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) {
}
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
}
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
}
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
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');
use: [{
loader: "babel-loader"
}]
+ },{
+ //don't minify images
+ test: /\.(png|gif|jpg|svg)$/,
+ use: [{
+ loader: 'url-loader',
+ options: {
+ limit: 10,
+ name: './images/[name].[ext]'
+ }
+ }]
}]
},
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,
}
}];
}
"@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",
~ ============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>
<!-- 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>
-// 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========================================================================
* ============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 {
export const removeWebUriAction = (nodeId: string) => {
return new RemoveWebUri(nodeId);
-}
+};
export class SetWeburiSearchBusy extends Action {
constructor(public isbusy: boolean) {
return;
isBusy = true;
- const { connect: { guiCutThrough, networkElements } } = getState();
+ const { connect: { guiCutThrough: guiCutThrough2, networkElements } } = getState();
let notConnectedElements: string[] = [];
let elementsToSearch: string[] = [];
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);
}
}
// }
// }
// }
- }
- 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);
}
}
}
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);
}
};
* 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
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' } }));
}
/** 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' } }));
};
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' } }));
/** 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());
};
*/
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';
* 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();
+ }
}
/**
*/
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));
+ });
};
--- /dev/null
+<!-- 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>
* 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';
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
/>
</>
);
- };
+ }
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();
}
* 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 { removeWebUriAction } from '../actions/commonNetworkElementsActions';
+import { mountNetworkElementAsyncActionCreator, unmountNetworkElementAsyncActionCreator } from '../actions/mountedNetworkElementsActions';
import {
- editNetworkElementAsyncActionCreator,
- addNewNetworkElementAsyncActionCreator,
- removeNetworkElementAsyncActionCreator
+ addNewNetworkElementAsyncActionCreator, editNetworkElementAsyncActionCreator, removeNetworkElementAsyncActionCreator,
} from '../actions/networkElementsActions';
-
-import { unmountNetworkElementAsyncActionCreator, mountNetworkElementAsyncActionCreator } from '../actions/mountedNetworkElementsActions';
-import { NetworkElementConnection, UpdateNetworkElement, propertyOf } from '../models/networkElementConnection';
-import { removeWebUriAction } from '../actions/commonNetworkElementsActions';
+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));
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)) {
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> {
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];
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}
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>
port: this.state.port,
username: this.state.username,
password: this.state.password,
- tlsKey: this.state.tlsKey
+ tlsKey: this.state.tlsKey,
});
}
event.preventDefault();
} catch (err) {
console.log(err);
}
- }
+ };
public componentDidMount() {
this.renderTlsKeys();
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)
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;
}
};
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 });
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;
}
}
* 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 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 * 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 { 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
* the License.
* ============LICENSE_END==========================================================================
*/
-import * as React from 'react';
-import { Theme } from '@mui/material/styles';
-
-import { WithStyles } from '@mui/styles';
-import createStyles from '@mui/styles/createStyles';
-import withStyles from '@mui/styles/withStyles';
+import React from 'react';
import AddIcon from '@mui/icons-material/Add';
-import Refresh from '@mui/icons-material/Refresh';
+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 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 { 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 { 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 { connectService } from '../services/connectService';
+import EditNetworkElementDialog, { EditNetworkElementDialogMode } from './editNetworkElementDialog';
import InfoNetworkElementDialog, { InfoNetworkElementDialogMode } from './infoNetworkElementDialog';
-import { loadAllInfoElementAsync, loadAllInfoElementFeaturesAsync } from '../actions/infoNetworkElementActions';
-import { connectService } from '../services/connectService';
-import { getAccessPolicyByUrl } from '../../../../framework/src/services/restService';
+import RefreshNetworkElementsDialog, { RefreshNetworkElementsDialogMode } from './refreshNetworkElementsDialog';
const styles = (theme: Theme) => createStyles({
connectionStatusConnected: {
},
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>) => {
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>;
refreshNetworkElementsEditorMode: RefreshNetworkElementsDialogMode.None,
elementInfo: null,
elementInfoFeature: null,
- infoNetworkElementEditorMode: InfoNetworkElementDialogMode.None
+ infoNetworkElementEditorMode: InfoNetworkElementDialogMode.None,
};
}
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;
}
// 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);
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);
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();
}
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,
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);
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));
* 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';
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>
private onCancel = () => {
this.props.onClose();
- }
+ };
}
export const RefreshConnectionStatusLogDialog = connect(undefined, mapDispatch)(RefreshConnectionStatusLogDialogComponent);
* 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';
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>
private onCancel = () => {
this.props.onClose();
- }
+ };
}
export const RefreshNetworkElementsDialog = connect(undefined, mapDispatch)(RefreshNetworkElementsDialogComponent);
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 {
elementInfo: IInfoNetworkElementsState;
elementFeatureInfo: IInfoNetworkElementFeaturesState;
guiCutThrough: guiCutThroughState;
- availableTlsKeys: IAvailableTlsKeysState
+ availableTlsKeys: IAvailableTlsKeysState;
}
const currentOpenPanelHandler: IActionHandler<PanelId> = (state = null, action) => {
state = action.panelId;
}
return state;
-}
+};
interface guiCutThroughState {
searchedElements: guiCutThrough[];
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;
state = { notSearchedElements: knownElements, searchedElements: webUris, unsupportedElements: unsupportedElement };
}
return state;
-}
+};
declare module '../../../../framework/src/store/applicationStore' {
interface IApplicationStoreState {
- connect: IConnectAppStoreState
+ connect: IConnectAppStoreState;
}
}
elementInfo: infoNetworkElementsActionHandler,
elementFeatureInfo: infoNetworkElementFeaturesActionHandler,
guiCutThrough: guiCutThroughHandler,
- availableTlsKeys: availableTlsKeysActionHandler
+ availableTlsKeys: availableTlsKeysActionHandler,
};
export const connectAppRootHandler = combineActionHandler<IConnectAppStoreState>(actionHandlers);
* 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
* 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
* ============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';
createActions: createNetworkElementsActions,
createProperties: createNetworkElementsProperties,
reloadAction: networkElementsReloadAction,
-
+
// set value action, to change a value
} = createExternal<NetworkElementConnection>(networkElementsSearchHandler, appState => {
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);
if (action instanceof LoadAllTlsKeyListAction) {
state = {
...state,
- busy: true
+ busy: true,
};
} else if (action instanceof AllTlsKeyListLoadedAction) {
} else {
state = {
...state,
- busy: false
+ busy: false,
};
}
}
objectId: string;
type: string;
newValue: string;
-}
+};
*/
export type guiCutThrough = {
- id: string,
- weburi?: string
-}
\ No newline at end of file
+ id: string;
+ weburi?: string;
+};
\ No newline at end of file
* ============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
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;
failureReason: string;
capability: string;
}[];
- }
-}
+ };
+};
export type UpdateNetworkElement = {
username?: string;
password?: string;
tlsKey?: string;
-}
+};
export type ConnectionStatus = {
- status: string
-}
+ status: string;
+};
export type TlsKeys = {
- key: string
-}
+ key: string;
+};
/**
export type NetworkElementConnectionLog = {
id: string;
nodeId: string;
- status: "connected" | "mounted" | "unmounted" | "connecting" | "disconnected" | "idle";
+ status: 'connected' | 'mounted' | 'unmounted' | 'connecting' | 'disconnected' | 'idle';
timestamp: string;
-}
+};
* ============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
* ============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[];
}
/**
}
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;
}
* ============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
* ============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 { 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';
-import { PanelId } from "./models/panelId";
-import { NetworkElementsList } from './components/networkElements';
+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),
});
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 />
- )
+ );
});
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) {
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';
*/
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;
}
* 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;
}
*/
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;
}
'<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 {
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> {
method: 'DELETE',
headers: {
'Content-Type': 'application/xml',
- 'Accept': 'application/xml'
+ 'Accept': 'application/xml',
},
});
// expect an empty answer
} 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;
});
}
/** 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;
});
}
* 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;
}
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) {
} else {
webUriList.push({ id: nodeId, weburi: undefined });
}
- throw BreakException;
+ throw new Error();
}
});
} catch (e) { }
* 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 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));
- }
-});
-type ConnectApplicationComponentProps = Connect<typeof mapProps, typeof mapDispatcher>;
+const ConnectApplicationComponent: React.FC<{}> = () => {
-class ConnectApplicationComponent extends React.Component<ConnectApplicationComponentProps>{
+ const panelId = useSelectApplicationState(state => state.connect.currentOpenPanel);
+ const netWorkElements = useSelectApplicationState(state => state.connect.networkElements);
- 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);
- }
- }
+ 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));
- 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
"outDir": "./dist",
"sourceMap": true,
"forceConsistentCasingInFileNames": true,
- "allowSyntheticDefaultImports": false,
+ "allowSyntheticDefaultImports": true,
"allowUnreachableCode": false,
"allowUnusedLabels": false,
"noFallthroughCasesInSwitch": true,
use: [{
loader: "babel-loader"
}]
+ },{
+ //don't minify images
+ test: /\.(png|gif|jpg|svg)$/,
+ use: [{
+ loader: 'url-loader',
+ options: {
+ limit: 10,
+ name: './images/[name].[ext]'
+ }
+ }]
}]
},
"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",
~ ============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>
<!-- 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>
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();
-
}
}
dispatch(new AllAuthorsLoadedAction(null, error));
dispatch(new AddErrorInfoAction(error));
});
-}
+};
* 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
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';
declare module '../../../../framework/src/store/applicationStore' {
interface IApplicationStoreState {
- demo: IDemoAppStoreState
+ demo: IDemoAppStoreState;
}
}
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;
};
const listAuthorsInit: IListAuthors = {
authors: [],
- busy: false
+ busy: false,
};
export const listAuthorsHandler: IActionHandler<IListAuthors> = (state = listAuthorsInit, action) => {
state = {
...state,
- busy: true
+ busy: true,
};
} else if (action instanceof AllAuthorsLoadedAction) {
state = {
...state,
authors: action.authors,
- busy: false
+ busy: false,
};
} else {
state = {
...state,
- busy: false
+ busy: false,
};
}
}
*/
export interface IAuthor {
/**
- * Defines the unique id of the autor.
+ * Defines the unique id of the author.
*/
id: number;
* 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';
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',
});
}
*/
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);
}
* 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';
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>
</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>
</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);
};
}
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;
* 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 {
<div>
<h2>Edit Author { this.props.match.params.authorId }</h2>
</div>
- )
+ );
}
}
"outDir": "./dist",
"sourceMap": true,
"forceConsistentCasingInFileNames": true,
- "allowSyntheticDefaultImports": false,
+ "allowSyntheticDefaultImports": true,
"allowUnreachableCode": false,
"allowUnusedLabels": false,
"noFallthroughCasesInSwitch": true,
~ ============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>
<!-- 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>
--- /dev/null
+<!-- highstreet technologies GmbH colour scheme \r
+ Grey #565656\r
+ LBlue #36A9E1\r
+ DBlue #246DA2\r
+ Green #003F2C / #006C4B\r
+ Yellw #C8D400\r
+ Red #D81036\r
+-->\r
+\r
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 512 512">\r
+\r
+<g>\r
+<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"/>\r
+\r
+<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"/>\r
+\r
+<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\r
+ 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\r
+ c0,17.673-14.328,32-32,32s-32-14.327-32-32C224,46.326,238.328,32,256,32z M384,448H128V96h48v32h160V96h48V448z"/>\r
+</g>\r
+</svg>\r
*/
// 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',
});
}
"outDir": "./dist",
"sourceMap": true,
"forceConsistentCasingInFileNames": true,
- "allowSyntheticDefaultImports": false,
+ "allowSyntheticDefaultImports": true,
"allowUnreachableCode": false,
"allowUnusedLabels": false,
"noFallthroughCasesInSwitch": true,
use: [{
loader: "babel-loader"
}]
+ }, {
+ //don't minify images
+ test: /\.(png|gif|jpg|svg)$/,
+ use: [{
+ loader: 'url-loader',
+ options: {
+ limit: 10,
+ name: './images/[name].[ext]'
+ }
+ }]
}]
},
"@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",
"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"
}
}
~ ============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>
<!-- 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>
*/
-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
* ============LICENSE_END==========================================================================
*/
import { Action } from '../../../../framework/src/flux/action';
+
import { PanelId } from '../models/panelId';
export class SetPanelAction extends Action {
export const setPanelAction = (panelId: PanelId) => {
return new SetPanelAction(panelId);
-}
+};
* 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,
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));
}
-}
+};
--- /dev/null
+<!-- 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>
* ============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[];
-}
-
-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();
+ clearAlarmsSuccessful: boolean;
+ errormessage: string;
+ unclearedAlarms: string[];
+};
+
+class ClearStuckAlarmsDialogComponent extends React.Component<clearStuckAlarmsProps, ClearStuckAlarmsState> {
+ constructor(props: clearStuckAlarmsProps) {
+ super(props);
+ this.state = {
+ clearAlarmsSuccessful: true,
+ errormessage: '',
+ unclearedAlarms: [],
+ };
+ }
+
+ onClose = (event: React.MouseEvent) => {
+ event.stopPropagation();
+ event.preventDefault();
+ this.props.onClose();
+ };
+
+ onRefresh = async (event: React.MouseEvent) => {
+ event.stopPropagation();
+ event.preventDefault();
+ const result = await this.props.clearStuckAlarmsAsync(this.props.stuckAlarms);
+
+ if (result && result['devicemanager:output'].nodenames && result['devicemanager:output'].nodenames.length !== this.props.stuckAlarms.length) { //show errormessage if not all devices were cleared
+ const undeletedAlarm = this.props.stuckAlarms.filter(item => !result['devicemanager:output'].nodenames.includes(item));
+ const error = 'The alarms of the following devices couldn\'t be refreshed: ';
+ this.setState({ clearAlarmsSuccessful: false, errormessage: error, unclearedAlarms: undeletedAlarm });
+ return;
+
+ } else { //show errormessage if no devices were cleared
+ this.setState({ clearAlarmsSuccessful: false, errormessage: 'Alarms couldn\'t be refreshed.', unclearedAlarms: [] });
}
- onRefresh = async (event: React.MouseEvent) => {
- event.stopPropagation();
- event.preventDefault();
- const result = await this.props.clearStuckAlarmsAsync(this.props.stuckAlarms);
-
- if (result && result["devicemanager:output"].nodenames && result["devicemanager:output"].nodenames.length !== this.props.stuckAlarms.length) { //show errormessage if not all devices were cleared
- const undeletedAlarm = this.props.stuckAlarms.filter(item => !result["devicemanager:output"].nodenames.includes(item));
- const error = "The alarms of the following devices couldn't be refreshed: ";
- this.setState({ clearAlarmsSuccessful: false, errormessage: error, unclearedAlarms: undeletedAlarm });
- return;
-
- } else { //show errormessage if no devices were cleared
- this.setState({ clearAlarmsSuccessful: false, errormessage: "Alarms couldn't be refreshed.", unclearedAlarms: [] });
- }
-
- this.props.reloadCurrentProblemsAction();
- this.props.onClose();
- }
-
- onOk = (event: React.MouseEvent) => {
-
- event.stopPropagation();
- event.preventDefault();
- if (this.state.unclearedAlarms.length > 0)
- this.props.reloadCurrentProblemsAction();
- this.props.onClose();
- }
-
- render() {
- console.log(this.props.stuckAlarms);
- const device = this.props.numberDevices > 1 ? 'devices' : 'device'
- const defaultMessage = "Are you sure you want to refresh all alarms for " + this.props.numberDevices + " " + device + "?"
- const message = this.state.clearAlarmsSuccessful ? defaultMessage : this.state.errormessage;
-
- const defaultTitle = "Refresh Confirmation"
- const title = this.state.clearAlarmsSuccessful ? defaultTitle : 'Refresh Result';
-
- return (
- <Dialog open={this.props.mode !== ClearStuckAlarmsDialogMode.None}>
- <DialogTitle>{title}</DialogTitle>
- <DialogContent>
- <DialogContentText>
- {message}
- </DialogContentText>
- {
- this.state.unclearedAlarms.map(item =>
- <DialogContentText>
- {item}
- </DialogContentText>
- )
- }
- </DialogContent>
- <DialogActions>
- {
- this.state.clearAlarmsSuccessful &&
- <>
- <Button 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.props.reloadCurrentAlarmsAction();
+ this.props.onClose();
+ };
+
+ onOk = (event: React.MouseEvent) => {
+
+ event.stopPropagation();
+ event.preventDefault();
+ if (this.state.unclearedAlarms.length > 0)
+ this.props.reloadCurrentAlarmsAction();
+ this.props.onClose();
+ };
+
+ render() {
+ console.log(this.props.stuckAlarms);
+ const device = this.props.numberDevices > 1 ? 'devices' : 'device';
+ const defaultMessage = 'Are you sure you want to refresh all alarms for ' + this.props.numberDevices + ' ' + device + '?';
+ const message = this.state.clearAlarmsSuccessful ? defaultMessage : this.state.errormessage;
+
+ const defaultTitle = 'Refresh Confirmation';
+ const title = this.state.clearAlarmsSuccessful ? defaultTitle : 'Refresh Result';
+
+ return (
+ <Dialog open={this.props.mode !== ClearStuckAlarmsDialogMode.None}>
+ <DialogTitle>{title}</DialogTitle>
+ <DialogContent>
+ <DialogContentText>
+ {message}
+ </DialogContentText>
+ {
+ this.state.unclearedAlarms.map(item =>
+ <DialogContentText>
+ {item}
+ </DialogContentText>,
+ )
+ }
+ </DialogContent>
+ <DialogActions>
+ {
+ this.state.clearAlarmsSuccessful &&
+ <>
+ <Button color="inherit" onClick={this.onRefresh}>Yes</Button>
+ <Button color="inherit" onClick={this.onClose}>No</Button>
+ </>
+ }
+
+ {
+ !this.state.clearAlarmsSuccessful && <Button color="inherit" onClick={this.onOk}>Ok</Button>
+ }
+ </DialogActions>
+ </Dialog>
+ );
+ }
}
const ClearStuckAlarmsDialog = connect(undefined, mapDispatch)(ClearStuckAlarmsDialogComponent);
* 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 { connect, Connect, IDispatcher } from '../../../../framework/src/flux/connect';
+
import { NavigateToApplication } from '../../../../framework/src/actions/navigationActions';
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
-const styles = (theme: Theme) => createStyles({
+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;
let alarmTotalCount = 0;
const mapProps = (state: IApplicationStoreState) => ({
- alarmStatus: state.fault.faultStatus
+ alarmStatus: state.fault.faultStatus,
});
const mapDispatch = (dispatcher: IDispatcher) => ({
constructor(props: HomeComponentProps) {
super(props);
this.state = {
- }
+ };
}
render(): JSX.Element {
- const { classes } = this.props;
if (!this.props.alarmStatus.isLoadingConnectionStatusChart) {
connectionStatusDataLoad = [
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;
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;
'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'],
'rgb(255, 102, 0)',
'rgb(191, 191, 191)',
'rgb(191, 191, 191)',
- 'rgb(242, 240, 240)'
- ]
- }]
+ 'rgb(242, 240, 240)',
+ ],
+ }],
};
datasets: [{
data: [1],
backgroundColor: [
- 'rgb(255, 255, 255)'
- ]
- }]
+ 'rgb(255, 255, 255)',
+ ],
+ }],
};
/** Loading Connection Status chart */
datasets: [{
data: [1],
backgroundColor: [
- 'rgb(255, 255, 255)'
- ]
- }]
+ 'rgb(255, 255, 255)',
+ ],
+ }],
};
/** Loading Alarm Status chart */
datasets: [{
data: [1],
backgroundColor: [
- 'rgb(255, 255, 255)'
- ]
- }]
+ 'rgb(255, 255, 255)',
+ ],
+ }],
};
/** Connection status options */
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 = [{
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 = {
'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'],
'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 = {
datasets: [{
data: [1],
backgroundColor: [
- 'rgb(0, 153, 51)'
- ]
- }]
+ 'rgb(0, 153, 51)',
+ ],
+ }],
};
/** Alarm status Options */
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);
}
},
};
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) {
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 (
<>
</div>
</div>
</>
- )
+ );
}
/** Check if connection status data available */
} else {
return true;
}
- }
+ };
/** Check if connection status chart data is loaded */
public checkElementsAreLoaded = () => {
return !isLoadingCheck.isLoadingConnectionStatusChart;
}
return true;
- }
+ };
/** Check if alarms data available */
public checkAlarmStatus = () => {
}
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 = () => {
return !isLoadingCheck.isLoadingAlarmStatusChart;
}
return true;
- }
+ };
}
export default (withRouter(connect(mapProps, mapDispatch)(DashboardHome)));
\ No newline at end of file
* 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) => ({
</Typography>
</>
);
- };
+ }
}
export const FaultStatus = withStyles(styles)(connect(mapProps)(FaultStatusComponent));
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>
private onCancel = () => {
this.props.onClose();
- }
+ };
}
export const RefreshAlarmLogDialog = connect(undefined, mapDispatch)(RefreshAlarmLogDialogComponent);
--- /dev/null
+/**
+ * ============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
+++ /dev/null
-/**
- * ============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
* 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';
* ============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
* 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);
*/
// main state handler
+import { IActionHandler } from '../../../../framework/src/flux/action';
import { combineActionHandler } from '../../../../framework/src/flux/middleware';
-
// ** do not remove **
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
-import { IActionHandler } from '../../../../framework/src/flux/action';
-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;
state = action.panelId;
}
return state;
-}
+};
declare module '../../../../framework/src/store/applicationStore' {
interface IApplicationStoreState {
}
const actionHandlers = {
- currentProblems: currentProblemsActionHandler,
+ currentAlarms: currentAlarmsActionHandler,
faultNotifications: faultNotificationsHandler,
alarmLogEntries: alarmLogEntriesActionHandler,
currentOpenPanel: currentOpenPanelHandler,
* 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 = {
Undefined: 0,
Unmounted: 0,
total: 0,
- isLoadingConnectionStatusChart: false
+ isLoadingConnectionStatusChart: false,
};
export const faultStatusHandler: IActionHandler<IFaultStatus> = (state = faultStatusInit, action) => {
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
* ============LICENSE_END==========================================================================
*/
import { IActionHandler } from '../../../../framework/src/flux/action';
+
import { AddFaultNotificationAction, ResetFaultNotificationsAction } from '../actions/notificationActions';
import { FaultAlarmNotification } from '../models/fault';
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
severity: null | 'Warning' | 'Minor' | 'Major' | 'Critical' | 'NonAlarmed';
type: string;
sourceType?: string;
-}
+};
export type FaultAlarmNotification = {
id: string;
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
* 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
*/
// 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 { 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 { FaultAlarmNotificationWS } from './models/fault';
+import { PanelId } from './models/panelId';
+import { FaultApplication } from './views/faultApplication';
-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>
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(() => {
return refreshFaultStatus;
}
+ applicationApi.loginEvent.addHandler(()=>{
+ refreshInterval = startRefreshInterval() as any;
+ });
}
* 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,
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
* 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 { 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 Refresh from '@mui/icons-material/Refresh';
+import Sync from '@mui/icons-material/Sync';
+import { AppBar, Tab, Tabs } from '@mui/material';
+import { ColumnType, MaterialTable, MaterialTableCtorType } from '../../../../framework/src/components/material-table';
+import { connect, Connect, IDispatcher } from '../../../../framework/src/flux/connect';
import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
-import connect, { Connect, IDispatcher } from '../../../../framework/src/flux/connect';
-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';
+import RefreshCurrentAlarmsDialog, { RefreshCurrentAlarmsDialogMode } from '../components/refreshCurrentAlarmsDialog';
+import { alarmLogEntriesReloadAction, createAlarmLogEntriesActions, createAlarmLogEntriesProperties } from '../handlers/alarmLogEntriesHandler';
+import { createCurrentAlarmsActions, createCurrentAlarmsProperties, currentAlarmsReloadAction } from '../handlers/currentAlarmsHandler';
+import { Fault, FaultAlarmNotification } from '../models/fault';
+import { PanelId } from '../models/panelId';
const mapProps = (state: IApplicationStoreState) => ({
panelId: state.fault.currentOpenPanel,
- 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));
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();
}
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;
<>
<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}
/>
</>
}
<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 },
]} />
}
<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}
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));
"outDir": "./dist",
"sourceMap": true,
"forceConsistentCasingInFileNames": true,
- "allowSyntheticDefaultImports": false,
+ "allowSyntheticDefaultImports": true,
"allowUnreachableCode": false,
"allowUnusedLabels": false,
"noFallthroughCasesInSwitch": true,
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: {
},
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
~ ============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>
<!-- 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>
--- /dev/null
+<!-- 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>
* 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';
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: {
// 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;
*/
// 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';
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));
}
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
export async function register() {
const applicationApi = applicationManager.registerApplication({
name: "help",
- icon: faFirstAid,
+ icon: appIcon,
rootComponent: App,
rootActionHandler: helpAppRootHandler,
statusBarElement: HelpStatus,
//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);
* 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";
* ============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";
"outDir": "./dist",
"sourceMap": true,
"forceConsistentCasingInFileNames": true,
- "allowSyntheticDefaultImports": false,
+ "allowSyntheticDefaultImports": true,
"allowUnreachableCode": false,
"allowUnusedLabels": false,
"noFallthroughCasesInSwitch": true,
plugins: () => [autoprefixer]
}
}]
+ }, {
+ //don't minify images
+ test: /\.(png|gif|jpg|svg)$/,
+ use: [{
+ loader: 'url-loader',
+ options: {
+ limit: 10,
+ name: './images/[name].[ext]'
+ }
+ }]
}]
},
~ ============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>
<!-- 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>
--- /dev/null
+/**
+ * ============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));
+};
+
* ============LICENSE_END==========================================================================
*/
+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 { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
-import { InventoryType, InventoryTreeNode, TreeDemoItem } from '../models/inventory';
+import { InventoryTreeNode, InventoryType, TreeDemoItem } from '../models/inventory';
import { inventoryService } from '../services/inventoryService';
-import { AddErrorInfoAction } from '../../../../framework/src/actions/errorActions';
-import { NavigateToApplication } from '../../../../framework/src/actions/navigationActions';
/**
* Represents the base action.
}
export class SetSearchTextAction extends BaseAction {
- constructor(public searchTerm: string = "") {
+ constructor(public searchTerm: string = '') {
super();
}
}
}
-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));
}
};
* ============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
--- /dev/null
+<!-- 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>
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>
private onCancel = () => {
this.props.onClose();
- }
+ };
}
export const RefreshInventoryDialog = connect(undefined, mapDispatch)(RefreshInventoryDialogComponent);
* ============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" },
+++ /dev/null
-/**
- * ============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);
// 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;
const actionHandlers = {
inventoryTree: inventoryTreeHandler,
- connectedNetworkElements: connectedNetworkElementsActionHandler,
currentOpenPanel: currentOpenPanelHandler,
- inventoryElements: inventoryElementsActionHandler
+ inventoryElements: inventoryElementsActionHandler,
+ inventoryDeviceList: inventoryDeviceListActionHandler,
};
export const inventoryAppRootHandler = combineActionHandler<IInventoryAppStateState>(actionHandlers);
--- /dev/null
+/**
+ * ============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
* 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';
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,
* ============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 {
const initialState: IInvenroryTree = {
isBusy: false,
rootNodes: [],
- searchTerm: "",
+ searchTerm: '',
selectedNode: undefined,
expandedItems: [],
-}
+};
const getTreeDataFromInvetoryTreeNode = (node: InventoryTreeNode): TreeDemoItem[] => Object.keys(node).reduce<TreeDemoItem[]>((acc, key) => {
} 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
-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
partTypeId: string;
modelIdentifier: string;
typeName: string;
-}
+};
export type InventoryTreeNode = {
[key: string]: {
isMatch?: boolean;
ownSeverity?: string;
childrenSeveritySummary?: string;
- }
-}
+ };
+};
export type TreeDemoItem = ExternalTreeItem<string>;
\ No newline at end of file
--- /dev/null
+/**
+ * ============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==========================================================================
+ */
+
+/**
+ * Represents all the distinct devices from the inventory history data.
+ */
+
+export type InventoryDeviceListType = {
+ nodeId: string;
+};
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?: {
failureReason: string;
capability: string;
}[];
- }
-}
+ };
+};
* ============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
* ============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 { IApplicationStoreState } from '../../../framework/src/store/applicationStore';
+import { SetPanelAction } from './actions/panelActions';
+import inventoryAppRootHandler from './handlers/inventoryAppRootHandler';
+import { createInventoryElementsActions, createInventoryElementsProperties } from './handlers/inventoryElementsHandler';
+import { PanelId } from './models/panelId';
import Dashboard from './views/dashboard';
+import { InventoryTreeView } from './views/treeview';
-import { PanelId } from "./models/panelId";
-import { SetPanelAction } from "./actions/panelActions";
-
-import inventoryAppRootHandler from './handlers/inventoryAppRootHandler';
-import { createInventoryElementsActions, createInventoryElementsProperties } from "./handlers/inventoryElementsHandler";
-import { createConnectedNetworkElementsProperties, createConnectedNetworkElementsActions } from "./handlers/connectedNetworkElementsHandler";
+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;
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) => (
export function register() {
applicationManager.registerApplication({
- name: "inventory",
- icon: faShoppingBag,
+ name: 'inventory',
+ icon: appIcon,
rootActionHandler: inventoryAppRootHandler,
rootComponent: App,
- menuEntry: "Inventory"
+ menuEntry: 'Inventory',
});
}
* 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-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);
+ }
+
+ /**
+ * 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,
},
- "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);
+ 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;
}
}
* ============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;
}
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 => {
}
{
- 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>
+ </>
}
</>
);
private onCloseRefreshInventoryDialog = () => {
this.setState({
- refreshInventoryEditorMode: RefreshInventoryDialogMode.None
+ refreshInventoryEditorMode: RefreshInventoryDialogMode.None,
});
- }
- componentDidMount() {
+ };
+ componentDidMount() {
if (this.props.panelId === null) { //set default tab if none is set
- this.onTogglePanel("InventoryElementsTable");
+ this.onTogglePanel('Equipment');
}
-
}
}
* 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>;
<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>
)));
* the License.
* ============LICENSE_END==========================================================================
*/
-import * as React from "react";
-import { Theme } from '@mui/material/styles';
+import React from 'react';
+import Breadcrumbs from '@mui/material/Breadcrumbs';
+import Link from '@mui/material/Link';
+import { Theme } from '@mui/material/styles';
import { WithStyles } from '@mui/styles';
-import withStyles from '@mui/styles/withStyles';
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 { TreeView, TreeViewCtorType, SearchMode } from '../../../../framework/src/components/material-ui/treeView';
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
-import { IApplicationStoreState } from "../../../../framework/src/store/applicationStore";
-
-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 { RouteComponentProps } from 'react-router-dom';
+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) => ({
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> {
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}`;
<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) {
}}
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('*');
}
}
"outDir": "./dist",
"sourceMap": true,
"forceConsistentCasingInFileNames": true,
- "allowSyntheticDefaultImports": false,
+ "allowSyntheticDefaultImports": true,
"allowUnreachableCode": false,
"allowUnusedLabels": false,
"noFallthroughCasesInSwitch": true,
use: [{
loader: "babel-loader"
}]
+ },{
+ //don't minify images
+ test: /\.(png|gif|jpg|svg)$/,
+ use: [{
+ loader: 'url-loader',
+ options: {
+ limit: 10,
+ name: './images/[name].[ext]'
+ }
+ }]
}]
},
},
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
"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"
}
}
~ ============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>
<!-- 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>
+/* eslint-disable @typescript-eslint/no-unused-expressions */
/**
* ============LICENSE_START========================================================================
* ONAP : ccsdk feature sdnr wt odlux
* 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 { }
export class AllMainteneceEntriesLoadedAction extends BaseAction {
- constructor (public maintenenceEntries: MaintenenceEntry[] | null, error?:string) {
+ constructor(public maintenenceEntries: MaintenanceEntry[] | null) {
super();
}
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);
});
};
--- /dev/null
+<!-- 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>
+/* eslint-disable @typescript-eslint/no-unused-expressions */
/**
* ============LICENSE_START========================================================================
* ONAP : ccsdk feature sdnr wt odlux
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) {
this.state = {
...this.props.initialMaintenenceEntry,
- isErrorVisible: false
+ isErrorVisible: false,
};
}
<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) => {
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 });
}
}} 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:
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;
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>
private onCancel = () => {
this.props.onClose();
- }
+ };
}
export const RefreshMaintenanceEntriesDialog = connect(undefined, mapDispatch)(RefreshMaintenanceEntriesDialogComponent);
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);
* 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,
reloadAction: maintenanceEntriesReloadAction,
// set value action, to change a value
-} = createExternal<MaintenenceEntry>(maintenanceEntriesSearchHandler, appState => appState.maintenance.maintenenceEntries);
+} = createExternal<MaintenanceEntry>(maintenanceEntriesSearchHandler, appState => appState.maintenance.maintenanceEntries);
/** 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;
-}
+};
*/
// 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 appIcon = require('./assets/icons/maintenanceAppIcon.svg'); // select app icon
-const App : React.SFC = (props) => {
- return <MaintenenceView />
+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',
});
}
* 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.
/**
* 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;
}
}
'+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;
':' + 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}/, '.');
* the License.
* ============LICENSE_END==========================================================================
*/
-import * as React from 'react';
-
-import { Theme, Tooltip } from '@mui/material';
-
-import { WithStyles } from '@mui/styles';
-import createStyles from '@mui/styles/createStyles';
-import withStyles from '@mui/styles/withStyles';
+import React from 'react';
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 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 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()),
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());
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} />
if (!initialSorted) {
initialSorted = true;
- this.props.maintenanceEntriesActions.onHandleRequestSort("node-id");
+ this.props.maintenanceEntriesActions.onHandleRequestSort('node-id');
} else {
this.props.onLoadMaintenanceEntries();
}
}
- 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());
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());
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());
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());
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));
+
"outDir": "./dist",
"sourceMap": true,
"forceConsistentCasingInFileNames": true,
- "allowSyntheticDefaultImports": false,
+ "allowSyntheticDefaultImports": true,
"allowUnreachableCode": false,
"allowUnusedLabels": false,
"noFallthroughCasesInSwitch": true,
use: [{
loader: "babel-loader"
}]
+ }, {
+ //don't minify images
+ test: /\.(png|gif|jpg|svg)$/,
+ use: [{
+ loader: 'url-loader',
+ options: {
+ limit: 10,
+ name: './images/[name].[ext]'
+ }
+ }]
}]
},
~ ============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>
<!-- 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>
--- /dev/null
+<!-- 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>
* ============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 {
*/
// 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";
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) => ({
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)
});
* the License.
* ============LICENSE_END==========================================================================
*/
-import * as React from 'react';
+import React from 'react';
import { Theme, Tooltip } from '@mui/material';
import { WithStyles } from '@mui/styles';
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';
* the License.
* ============LICENSE_END==========================================================================
*/
-import * as React from 'react';
+import React from 'react';
import { Theme, Tooltip } from '@mui/material';
import { WithStyles } from '@mui/styles';
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';
"outDir": "./dist",
"sourceMap": true,
"forceConsistentCasingInFileNames": true,
- "allowSyntheticDefaultImports": false,
+ "allowSyntheticDefaultImports": true,
"allowUnreachableCode": false,
"allowUnusedLabels": false,
"noFallthroughCasesInSwitch": true,
use: [{
loader: "babel-loader"
}]
+ },{
+ //don't minify images
+ test: /\.(png|gif|jpg|svg)$/,
+ use: [{
+ loader: 'url-loader',
+ options: {
+ limit: 10,
+ name: './images/[name].[ext]'
+ }
+ }]
}]
},
~ ============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>
<!-- 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>
--- /dev/null
+<!-- 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>
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 {
declare module '../../../../framework/src/store/applicationStore' {
interface IApplicationStoreState {
- minimum: IMinimumAppStoreState
+ minimum: IMinimumAppStoreState;
}
}
*/
// 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>
);
export function register() {
applicationManager.registerApplication({
- name: "minimum",
- icon: faLock,
+ name: 'minimum',
+ // icon: appIcon,
rootComponent: FinalApp,
rootActionHandler: minimumAppRootHandler,
- menuEntry: "Minimum"
+ menuEntry: 'Minimum',
});
}
"outDir": "./dist",
"sourceMap": true,
"forceConsistentCasingInFileNames": true,
- "allowSyntheticDefaultImports": false,
+ "allowSyntheticDefaultImports": true,
"allowUnreachableCode": false,
"allowUnusedLabels": false,
"noFallthroughCasesInSwitch": true,
~ ============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>
<!-- 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>
*/
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';
deviceListFromPerf24History.forEach(deviceList24h => {
if (deviceListFromPerfHistory.findIndex(deviceList15min => deviceList15min.nodeId === deviceList24h.nodeId) < 0) {
deviceListFromPerfHistory.push(deviceList24h);
- };
+ }
});
return deviceListFromPerfHistory && dispatch(new AllDeviceListLoadedAction(deviceListFromPerfHistory));
};
*/
export const updateMountIdActionCreator = (nodeId: string) => async (dispatch: Dispatch) => {
return dispatch(new UpdateMountId(nodeId));
-}
+};
}
}
-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.
});
};
-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
* ============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
* ============LICENSE_END==========================================================================
*/
import { Action } from '../../../../framework/src/flux/action';
+
import { PmDataInterval } from '../models/performanceDataType';
export class TimeChangeAction extends Action {
* ============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
--- /dev/null
+<!-- highstreet technologies GmbH colour scheme \r
+ Grey #565656\r
+ LBlue #36A9E1\r
+ DBlue #246DA2\r
+ Green #003F2C / #006C4B\r
+ Yellw #C8D400\r
+ Red #D81036\r
+-->\r
+\r
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 500 500">\r
+<g>\r
+ <g>\r
+ <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"/>\r
+ <rect fill="#565656" x="73.092" y="310.635" width="73.089" height="109.632"/>\r
+ <rect fill="#565656" x="182.728" y="164.452" width="73.085" height="255.814"/>\r
+ <rect fill="#565656" x="292.362" y="237.541" width="73.083" height="182.726"/>\r
+ <rect fill="#565656" x="401.994" y="127.907" width="73.091" height="292.36"/>\r
+ </g>\r
+</g>\r
+<g>\r
+</g>\r
+<g>\r
+</g>\r
+<g>\r
+</g>\r
+<g>\r
+</g>\r
+<g>\r
+</g>\r
+<g>\r
+</g>\r
+<g>\r
+</g>\r
+<g>\r
+</g>\r
+<g>\r
+</g>\r
+<g>\r
+</g>\r
+<g>\r
+</g>\r
+<g>\r
+</g>\r
+<g>\r
+</g>\r
+<g>\r
+</g>\r
+<g>\r
+</g>\r
+</svg>\r
* 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>;
/**
* 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;
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 => {
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
*/
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;
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;
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();
-
- // make sure suspectIntervalFlag is a string to show the correct value in the select element
+ const classes = styles();
- 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>
+ // make sure suspectIntervalFlag is a string to show the correct value in the select element
- <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>
- }
- </>
- )
+ 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>
+ }
+ </>
+ );
+};
export default ChartFilter;
\ No newline at end of file
* 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';
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>;
/**
* 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;
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 => {
});
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;
* the License.
* ============LICENSE_END==========================================================================
*/
+import React from 'react';
-import * as React from 'react';
-import { MenuItem, Select, FormControl, Typography, SelectChangeEvent } from '@mui/material';
+import { FormControl, MenuItem, Select, SelectChangeEvent, Typography } from '@mui/material';
+import { Theme } from '@mui/material/styles';
import makeStyles from '@mui/styles/makeStyles';
-import { LtpIds } from 'models/availableLtps';
import { Loader } from '../../../../framework/src/components/material-ui';
-
-import { Theme } from '@mui/material/styles';
+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
* 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>;
/**
* 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;
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 => {
});
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));
* 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>;
/**
* 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;
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 => {
<>
<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));
* 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>;
/**
* 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;
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 => {
});
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
*/
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));
* 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>;
/**
* 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;
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 => {
<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
*/
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));
*/
import * as React from 'react';
-import ToggleButton from '@mui/material/ToggleButton';
-import ToggleButtonGroup from '@mui/material/ToggleButtonGroup';
+
import BarChartIcon from '@mui/icons-material/BarChart';
+import FilterListIcon from '@mui/icons-material/FilterList';
import TableChartIcon from '@mui/icons-material/TableChart';
-import makeStyles from '@mui/styles/makeStyles';
+import ToggleButton from '@mui/material/ToggleButton';
+import ToggleButtonGroup from '@mui/material/ToggleButtonGroup';
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}>
</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>
</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
* 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 => {
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
*/
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));
/**
* 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);
distinctLtps: [],
busy: false,
loadedOnce: false,
- error: undefined
+ error: undefined,
};
export const availableLtpsActionHandler: IActionHandler<IAvailableLtpsState> = (state = ltpListStateInit, action) => {
state = {
...state,
- busy: true
+ busy: true,
};
} else if (action instanceof AllAvailableLtpsLoadedAction) {
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 = {
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,
};
}
/**
* 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);
const deviceListStateInit: IDeviceListState = {
deviceList: [],
- busy: false
+ busy: false,
};
export const deviceListActionHandler: IActionHandler<IDeviceListState> = (state = deviceListStateInit, action) => {
state = {
...state,
- busy: true
+ busy: true,
};
} else if (action instanceof AllDeviceListLoadedAction) {
state = {
...state,
deviceList: action.deviceList,
- busy: false
+ busy: false,
};
} else {
state = {
...state,
- busy: false
+ busy: false,
};
}
}
* 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> { }
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);
*/
// main state handler
+import { IActionHandler } from '../../../../framework/src/flux/action';
import { combineActionHandler } from '../../../../framework/src/flux/middleware';
-
// ** do not remove **
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
-import { IActionHandler } from '../../../../framework/src/flux/action';
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;
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) => {
state = action.show;
}
return state;
-}
+};
const currentOpenPanelHandler: IActionHandler<string | null> = (state = null, action) => {
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 {
currentOpenPanel: currentOpenPanelHandler,
pmDataIntervalType: currentPMDataIntervalHandler,
subViews: toogleViewDataHandler,
- isReloadSchedueled: reloadHandler
+ isReloadSchedueled: reloadHandler,
};
const performanceHistoryRootHandler = combineActionHandler<IPerformanceHistoryStoreState>(actionHandlers);
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);
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);
/**
* 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);
/**
* 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);
* the License.
* ============LICENSE_END==========================================================================
*/
- export type LtpIds = {
- key : string
- }
+export type LtpIds = {
+ key: string;
+};
* 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[];
}
/**
* Internally used type to provide table and chart data
*/
export type CrossPolarDiscriminationDataType = {
- performanceData: CrossPolarDiscriminationDatabaseDataType
+ performanceData: CrossPolarDiscriminationDatabaseDataType;
radioSignalId: string;
scannerId: string;
timeStamp: string;
export type DeviceListType = {
nodeId: string;
-}
+};
/**
* 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
* the License.
* ============LICENSE_END==========================================================================
*/
-import { Moment } from "moment";
//export { HitEntry, Result } from '../../../../framework/src/models';
*/
export const enum PmDataInterval {
pmInterval15Min,
- pmInterval24Hours
+ pmInterval24Hours,
}
\ No newline at end of file
* Internally used type to provide table and chart data
*/
export type TemperatureDataType = {
- performanceData: TemperatureDatabaseDataType
+ performanceData: TemperatureDatabaseDataType;
radioSignalId: string;
scannerId: string;
timeStamp: string;
/**
* 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';
*/
export interface TopologyNode {
- "node-id": string;
+ 'node-id': string;
}
export interface Topology {
- "topology-id": string;
+ 'topology-id': string;
node: TopologyNode[];
}
* ============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 = '';
+
+ const getMountId = (last_url: string) => {
+ let index = last_url.lastIndexOf('performanceHistory/');
+ if (index >= 0) {
+ mountId = last_url.substring(index + 19);
+ } else {
+ mountId = '';
+ }
- // called when component finshed mounting
+ 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;
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
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',
});
}
* 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.
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;
}
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;
}
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;
}
}
* 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}>
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
* 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
* 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) => ({
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) => ({
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 {
// 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 (
<>
</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} />
}
</>
}
</>
- )
+ );
}
}
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;
// 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:
}
// set prefilter
- this.setState({ preFilter: newPreFilter })
+ this.setState({ preFilter: newPreFilter });
- }
+ };
/**
* Function which handles network element changes.
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) => {
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.
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;
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));
"outDir": "./dist",
"sourceMap": true,
"forceConsistentCasingInFileNames": true,
- "allowSyntheticDefaultImports": false,
+ "allowSyntheticDefaultImports": true,
"allowUnreachableCode": false,
"allowUnusedLabels": false,
"noFallthroughCasesInSwitch": true,
use: [{
loader: "babel-loader"
}]
+ },{
+ //don't minify images
+ test: /\.(png|gif|jpg|svg)$/,
+ use: [{
+ loader: 'url-loader',
+ options: {
+ limit: 10,
+ name: './images/[name].[ext]'
+ }
+ }]
}]
},
--- /dev/null
+{
+ "root": true,
+ "parser": "@typescript-eslint/parser",
+ "plugins": [
+ "import",
+ "@typescript-eslint",
+ "react",
+ "react-hooks"
+ ],
+ "extends": [
+ "airbnb-typescript"
+ ],
+ "parserOptions": {
+ "project": [
+ "./tsconfig.json"
+ ],
+ "sourceType": "module"
+ },
+ "settings": {
+ "react": {
+ "version": "detect"
+ }
+ },
+ "rules": {
+ "no-console": "off",
+ "no-debugger": "off",
+ "import/no-cycle": "off",
+ "quotes": [ "error", "single" ],
+ "import/prefer-default-export": "off",
+ "lines-between-class-members": "off",
+ "no-nested-ternary": "off",
+ "no-unused-vars": "off",
+ "object-curly-newline": "off", //["error", { "multiline": true, "minProperties": 8, "consistent": true }],
+ "max-len": [ 2, 280, 2, { "ignoreUrls": true } ],
+ "@typescript-eslint/lines-between-class-members": [ "error", "always", { "exceptAfterOverload": true } ],
+ "@typescript-eslint/quotes": [ "error", "single" , { "avoidEscape": true } ],
+ "@typescript-eslint/no-unused-vars": [ "error", { "argsIgnorePattern": "^_", "varsIgnorePattern": "^_", "caughtErrorsIgnorePattern": "^_" } ],
+ "@typescript-eslint/naming-convention": [ "error",
+ { "format": [ "camelCase", "PascalCase", "UPPER_CASE", "snake_case" ], "leadingUnderscore": "allow", "selector": "default", "filter": { "regex": "(^&)|(^\\w+(-\\w+)+)", "match": false } } ],
+ "no-underscore-dangle": [ "error", { "allowAfterThis": true } ],
+ "no-param-reassign": [ "error", { "props": false } ],
+ "react/prop-types": [ "error", { "skipUndeclared": true } ],
+ "@typescript-eslint/member-delimiter-style": ["error"]
+ },
+ "overrides": [
+ {
+ "files": "**/handlers/*Handler.ts",
+ "rules": {
+ "no-param-reassign": "off",
+ "@typescript-eslint/default-param-last": "off"
+ }
+ }
+ ]
+}
\ No newline at end of file
~ ============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>
<properties>
<buildtime>${maven.build.timestamp}</buildtime>
<distversion>ONAP Frankfurt (Neon, mdsal ${odl.mdsal.version})</distversion>
- <buildno>142.63ceae1(22/01/31)</buildno>
+ <buildno>178.3bd8a2a9(23/03/16)</buildno>
<odlux.version>ONAP SDN-R | ONF Wireless for ${distversion} - Build: ${buildtime} ${buildno} ${project.version}</odlux.version>
</properties>
<!-- 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>
import { Dispatch } from "../flux/store";
import { Action } from "../flux/action";
import { GeneralSettings, Settings, TableSettings, TableSettingsColumn } from "../models/settings";
-import { getSettings, putSettings } from "../services/settingsService";
+import { getUserdata, saveUserdata } from "../services/userdataService";
import { startWebsocketSession, suspendWebsocketSession } from "../services/notificationService";
import { IApplicationStoreState } from "../store/applicationStore";
export const updateGeneralSettingsAction = (activateNotifications: boolean) => async (dispatcher: Dispatch) => {
const value: GeneralSettings = { general: { areNotificationsEnabled: activateNotifications } };
- const result = await putSettings("/general", JSON.stringify(value.general));
+ const result = await saveUserdata("/general", JSON.stringify(value.general));
dispatcher(setGeneralSettingsAction(activateNotifications));
}
// would only save latest entry
//const json = JSON.stringify({ [tableName]: { columns: columns } });
- const result = await putSettings("/tables", json);
+ const result = await saveUserdata("/tables", json);
dispatcher(new SetTableSettings(tableName, columns));
}
export const getGeneralSettingsAction = () => async (dispatcher: Dispatch) => {
- const result = await getSettings<GeneralSettings>();
+ const result = await getUserdata<GeneralSettings>();
if (result && result.general) {
dispatcher(new SetGeneralSettingsAction(result.general.areNotificationsEnabled!))
import { ApplicationStoreProvider } from './flux/connect';
import { startHistoryListener } from './middleware/navigation';
-import { startRestService } from './services/restService';
+import { startSoreService } from './services/storeService';
import { startUserSessionService } from './services/userSessionService';
import { startNotificationService } from './services/notificationService';
+import { startBroadcastChannel } from './services/broadcastService';
+
import theme from './design/default';
import '!style-loader!css-loader!./app.css';
-import { startBroadcastChannel } from './services/broadcastService';
declare module '@mui/material/styles' {
};
- startRestService(applicationStore);
+ startSoreService(applicationStore);
startHistoryListener(applicationStore);
startNotificationService(applicationStore);
--- /dev/null
+<!-- highstreet technologies GmbH colour scheme \r
+ Grey #565656\r
+ LBlue #36A9E1\r
+ DBlue #246DA2\r
+ Green #003F2C / #006C4B\r
+ Yellw #C8D400\r
+ Red #D81036\r
+-->\r
+\r
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">\r
+\r
+<path fill="#36A9E1" d="M 13 13 V 17.5 A 1 1 0 0 1 11 17.5 V 13 A 1 1 0 0 1 13 13 Z "/>\r
+\r
+<path fill="#36A9E1" d="M 12 11 A 1 1 0 1 0 11 10 A 1 1 0 0 0 12 11 Z "/>\r
+\r
+<path fill="#565656" d="M 1.125 20.485 A 1 1 0 0 1 1.152 19.47 L 11.152 3.47 A 1.039 1.039 0 0 1 12.852 3.47 L 22.852 19.47 A 1 1 0 0 1 22 21 H 2 A 1 1 0 0 1 1.125 20.485 Z M 3.8 19 H 20.2 L 12 5.887 Z"/>\r
+\r
+</svg>
\ No newline at end of file
--- /dev/null
+<!-- highstreet technologies GmbH colour scheme \r
+ Grey #565656\r
+ LBlue #36A9E1\r
+ DBlue #246DA2\r
+ Green #003F2C / #006C4B\r
+ Yellw #C8D400\r
+ Red #D81036\r
+-->\r
+\r
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 460.298 460.297" style="enable-background:new 0 0 460.298 460.297;"\r
+ xml:space="preserve">\r
+<g>\r
+ <g>\r
+ <path fill="#565656" d="M230.149,120.939L65.986,256.274c0,0.191-0.048,0.472-0.144,0.855c-0.094,0.38-0.144,0.656-0.144,0.852v137.041\r
+ c0,4.948,1.809,9.236,5.426,12.847c3.616,3.613,7.898,5.431,12.847,5.431h109.63V303.664h73.097v109.64h109.629\r
+ c4.948,0,9.236-1.814,12.847-5.435c3.617-3.607,5.432-7.898,5.432-12.847V257.981c0-0.76-0.104-1.334-0.288-1.707L230.149,120.939\r
+ z"/>\r
+ <path fill="#565656" d="M457.122,225.438L394.6,173.476V56.989c0-2.663-0.856-4.853-2.574-6.567c-1.704-1.712-3.894-2.568-6.563-2.568h-54.816\r
+ c-2.666,0-4.855,0.856-6.57,2.568c-1.711,1.714-2.566,3.905-2.566,6.567v55.673l-69.662-58.245\r
+ c-6.084-4.949-13.318-7.423-21.694-7.423c-8.375,0-15.608,2.474-21.698,7.423L3.172,225.438c-1.903,1.52-2.946,3.566-3.14,6.136\r
+ c-0.193,2.568,0.472,4.811,1.997,6.713l17.701,21.128c1.525,1.712,3.521,2.759,5.996,3.142c2.285,0.192,4.57-0.476,6.855-1.998\r
+ L230.149,95.817l197.57,164.741c1.526,1.328,3.521,1.991,5.996,1.991h0.858c2.471-0.376,4.463-1.43,5.996-3.138l17.703-21.125\r
+ c1.522-1.906,2.189-4.145,1.991-6.716C460.068,229.007,459.021,226.961,457.122,225.438z"/>\r
+\r
+<path fill="#246DA2" d="M 457.122 225.438 L 251.849 54.417 L 251.849 54.417 C 245.765 49.468 238.531 46.994 230.155 46.994 C 221.78 46.994 214.547 49.468 208.457 54.417 L 3.172 225.438 C 1.269 226.958 0.226 229.004 0.032 231.574 C -0.161 234.142 0.504 236.385 2.029 238.287 L 19.73 259.415 C 21.255 261.127 23.251 262.174 25.726 262.557 C 28.011 262.749 30.296 262.081 32.581 260.559 L 230.149 95.817 L 427.719 260.558 C 429.245 261.886 431.24 262.549 433.715 262.549 H 434.573 C 437.044 262.173 439.036 261.119 440.569 259.411 L 458.272 238.286 C 459.794 236.38 460.461 234.141 460.263 231.57 C 460.068 229.007 459.021 226.961 457.122 225.438 Z"/>\r
+ </g>\r
+</g>\r
+</svg>\r
--- /dev/null
+<!-- highstreet technologies GmbH colour scheme \r
+ Grey #565656\r
+ LBlue #36A9E1\r
+ DBlue #246DA2\r
+ Green #003F2C / #006C4B\r
+ Yellw #C8D400\r
+ Red #D81036\r
+-->\r
+\r
+<svg viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">\r
+\r
+<path fill="#36A9E1" d="M4,10h24c1.104,0,2-0.896,2-2s-0.896-2-2-2H4C2.896,6,2,6.896,2,8S2.896,10,4,10z"/>\r
+\r
+<path fill="#36A9E1" d="M28,14H4c-1.104,0-2,0.896-2,2 s0.896,2,2,2h24c1.104,0,2-0.896,2-2S29.104,14,28,14z"/>\r
+\r
+<path fill="#36A9E1" d="M28,22H4c-1.104,0-2,0.896-2,2s0.896,2,2,2h24c1.104,0,2-0.896,2-2 S29.104,22,28,22z"/>\r
+\r
+</svg>
\ No newline at end of file
--- /dev/null
+<!-- 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 265 265">
+
+<g transform="translate(0.000000,265.000000) scale(0.100000,-0.100000)">
+
+<path fill="#565656" d="M601 2515 c-35 -8 -66 -17 -69 -20 -3 -3 76 -87 175 -188 243 -244
+243 -246 59 -425 -106 -103 -137 -120 -194 -107 -19 4 -88 66 -207 185 -99 99
+-183 180 -186 180 -17 0 -34 -104 -33 -200 0 -82 6 -120 23 -170 61 -174 191
+-306 362 -367 62 -22 93 -27 187 -28 l113 -2 602 -600 c673 -671 633 -638 777
+-638 93 1 151 27 225 101 99 98 129 219 85 339 -21 57 -49 87 -626 665 l-603
+605 5 70 c18 217 -117 451 -316 549 -127 62 -250 78 -379 51z m1696 -1906 c70
+-34 113 -125 93 -199 -31 -116 -158 -168 -262 -107 -77 45 -107 133 -73 214
+21 50 42 72 90 94 53 24 99 24 152 -2z"/>
+
+<path fill="#565656" d="M2183 2496 c-23 -7 -56 -23 -75 -34 -18 -12 -172 -161 -343 -331
+l-310 -311 45 -45 c24 -25 49 -45 55 -45 5 0 152 142 325 315 264 264 319 315
+340 313 19 -2 26 -10 28 -32 3 -26 -26 -59 -315 -348 l-318 -318 38 -37 37
+-38 319 318 c287 287 321 318 347 315 24 -2 30 -8 32 -32 3 -26 -26 -59 -315
+-348 l-318 -318 48 -47 47 -48 320 320 c225 225 327 333 342 365 31 66 30 159
+-4 225 -66 127 -210 198 -325 161z"/>
+
+<path fill="#36A9E1" d="M800 875 l-175 -175 -85 0 -85 0 -135 -222 c-74 -121 -137 -225 -139
+-231 -4 -11 89 -107 104 -107 5 0 109 60 230 134 l220 133 3 84 3 84 177 178
+177 177 -60 60 -60 60 -175 -175z"/>
+
+</g>
+</svg>
--- /dev/null
+<!-- highstreet technologies GmbH colour scheme \r
+ Grey #565656\r
+ LBlue #36A9E1\r
+ DBlue #246DA2\r
+ Green #003F2C / #006C4B\r
+ Yellw #C8D400\r
+ Red #D81036\r
+-->\r
+\r
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 600 600">\r
+\r
+ <defs>\r
+ <clipPath id="circular-border">\r
+ <circle cx="300" cy="300" r="250" />\r
+ </clipPath>\r
+ </defs>\r
+ \r
+ <circle fill="#36A9E1" cx="300" cy="300" r="280"/>\r
+ <circle fill="#ffffff" cx="300" cy="230" r="100" />\r
+ <circle fill="#ffffff" cx="300" cy="550" r="190" clip-path="url(#circular-border)" />\r
+</svg>
\ No newline at end of file
--- /dev/null
+<!-- 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 795.000000 139.000000">
+
+<g transform="translate(0.000000,139.000000) scale(0.100000,-0.100000)">
+
+<path fill="#565656" d="M355 1163 c-38 -2 -75 -9 -82 -15 -10 -8 -13 -53 -13 -175 0 -175 -9
+-215 -50 -226 -17 -4 -20 -13 -20 -59 0 -48 3 -56 32 -80 l33 -27 3 -190 c4
+-226 -4 -213 135 -209 l92 3 0 70 0 70 -32 3 -33 3 0 148 c0 135 -2 151 -21
+175 l-20 26 20 26 c19 24 21 40 21 170 l0 143 33 3 32 3 0 70 0 70 -30 1 c-16
+0 -61 -1 -100 -3z"/>
+
+<path fill="#565656" d="M7473 1154 c-2 -6 -3 -38 -1 -70 3 -59 3 -59 36 -62 l32 -3 0 -137
+c0 -119 3 -141 20 -169 20 -33 20 -33 0 -65 -17 -29 -20 -51 -20 -175 l0 -142
+-32 -3 -33 -3 0 -70 0 -70 97 -3 c141 -4 138 -9 138 212 0 96 3 182 6 191 4 9
+17 21 30 26 21 8 24 15 24 67 0 53 -3 60 -30 80 l-30 23 0 172 c0 123 -4 178
+-12 189 -16 20 -217 31 -225 12z"/>
+
+<path fill="#246DA2" d="M645 1138 c-3 -7 -4 -215 -3 -463 l3 -450 90 0 90 0 0 195 c0 215 5
+237 65 280 71 50 146 45 178 -13 14 -27 17 -64 19 -247 l2 -215 88 0 88 0 0
+250 0 250 -27 55 c-33 67 -71 97 -138 110 -89 17 -181 -12 -240 -75 l-25 -27
+-5 179 -5 178 -88 3 c-64 2 -89 -1 -92 -10z"/>
+
+<path fill="#C8D400" d="M2499 1111 c-150 -48 -271 -193 -301 -361 -32 -184 85 -406 259 -492
+165 -81 408 -24 514 120 31 43 31 44 13 61 -10 10 -45 33 -76 50 l-57 32 -15
+-28 c-75 -145 -315 -142 -403 6 -135 226 18 510 249 462 69 -15 114 -42 139
+-86 12 -19 26 -35 31 -35 22 0 138 91 132 103 -89 153 -301 227 -485 168z"/>
+
+<path fill="#246DA2" d="M1467 1094 c-4 -4 -7 -51 -7 -105 l0 -98 -42 -3 -43 -3 0 -70 0 -70
+43 -3 42 -3 0 -197 c0 -185 1 -201 23 -242 26 -53 89 -90 152 -90 45 0 171 32
+187 48 7 7 4 30 -9 74 -16 52 -23 62 -39 60 -73 -11 -101 -12 -114 -3 -12 8
+-16 43 -18 180 l-3 170 68 3 68 3 0 70 0 70 -67 3 -67 3 -3 102 -3 102 -80 3
+c-45 1 -84 0 -88 -4z"/>
+
+<path fill="#C8D400" d="M7017 1094 c-4 -4 -7 -51 -7 -105 l0 -98 -37 -3 -38 -3 0 -70 0 -70
+36 -3 36 -3 7 -67 c3 -37 6 -130 6 -208 0 -130 2 -144 23 -175 27 -41 98 -79
+147 -79 36 0 120 19 172 39 l26 10 -15 58 c-19 74 -28 85 -59 72 -35 -13 -88
+-11 -102 3 -8 8 -12 63 -12 180 l0 167 68 3 67 3 0 70 0 70 -67 3 -67 3 -3
+102 -3 102 -85 3 c-47 1 -89 0 -93 -4z"/>
+
+<path fill="#C8D400" d="M3349 890 c-63 -11 -123 -43 -174 -95 -55 -54 -82 -106 -94 -181 -25
+-161 50 -304 198 -372 77 -36 211 -38 285 -4 75 34 129 84 167 154 32 59 34
+69 34 158 0 82 -4 103 -26 151 -46 98 -138 168 -249 189 -59 11 -75 11 -141 0z
+m168 -178 c44 -31 67 -86 67 -157 0 -113 -53 -176 -153 -183 -70 -5 -115 22
+-148 88 -53 103 -11 233 87 273 31 13 117 1 147 -21z"/>
+
+<path fill="#C8D400" d="M4254 890 c-61 -13 -106 -34 -147 -69 l-36 -32 -3 48 -3 48 -80 0
+-80 0 0 -330 0 -330 85 0 85 0 5 202 c5 184 7 204 26 229 45 60 111 88 171 72
+54 -14 58 -31 63 -278 l5 -225 85 0 85 0 0 266 0 266 -30 48 c-46 74 -132 106
+-231 85z"/>
+
+<path fill="#C8D400" d="M5040 890 c-63 -11 -89 -23 -142 -63 l-47 -36 -3 47 -3 47 -80 0 -80
+0 0 -330 0 -330 90 0 90 0 1 196 c1 158 4 201 18 226 37 73 151 111 205 69 28
+-22 35 -68 40 -276 l6 -215 85 0 85 0 0 245 c-1 264 -7 307 -51 360 -47 55
+-122 76 -214 60z"/>
+
+<path fill="#C8D400" d="M5709 890 c-99 -17 -200 -94 -250 -190 -21 -39 -24 -59 -24 -145 0
+-90 3 -105 28 -153 79 -149 241 -220 407 -178 79 21 145 61 188 118 39 51 34
+58 -54 77 -56 13 -56 13 -88 -16 -17 -16 -44 -35 -59 -41 -42 -18 -117 -15
+-157 7 -33 17 -79 81 -80 108 0 10 60 13 253 15 l252 3 -1 70 c-2 211 -197
+364 -415 325z m151 -150 c36 -19 80 -79 80 -110 0 -6 -56 -10 -160 -10 -149 0
+-160 1 -160 19 0 29 43 85 80 103 46 24 112 23 160 -2z"/>
+
+<path fill="#C8D400" d="M6483 890 c-186 -39 -303 -204 -273 -386 19 -114 95 -214 200 -263
+46 -22 69 -26 145 -26 76 0 99 4 145 26 65 30 125 80 146 120 17 33 15 35 -84
+64 l-62 18 -28 -25 c-40 -38 -65 -48 -120 -48 -91 0 -162 80 -162 182 0 84 36
+148 99 174 65 27 133 15 176 -32 l25 -27 80 23 c44 13 83 26 85 30 6 10 -42
+71 -82 104 -68 58 -194 86 -290 66z"/>
+
+<path fill="#36A9E1" d="M1934 407 c-2 -7 -4 -52 -2 -98 l3 -84 70 0 70 0 0 95 0 95 -68 3
+c-50 2 -69 -1 -73 -11z"/>
+
+</g>
+</svg>
* the License.
* ============LICENSE_END==========================================================================
*/
-import * as React from 'react';
+import React from 'react';
import { Theme } from '@mui/material/styles';
import { WithStyles } from '@mui/styles';
import { ClearErrorInfoAction, RemoveErrorInfoAction } from '../actions/errorActions';
-import connect, { Connect } from '../flux/connect';
+import { connect, Connect } from '../flux/connect';
const styles = (theme: Theme) => createStyles({
modal: {
--- /dev/null
+import React from 'react';
+
+type MenuIconPropsBase = {
+ className?: string;
+ size?: number | string;
+};
+
+type MenuIconPropsWithColor = MenuIconPropsBase & {
+ color: string;
+};
+
+type MenuIconProps = MenuIconPropsBase | MenuIconPropsWithColor;
+
+const MenuIcon = (props: MenuIconProps) => {
+ const { className, size = '30px' } = props;
+ const color = 'color' in props ? props.color : '#36A9E1';
+
+ return (
+ <svg className={className} width={size} height={size} viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg" xmlnsXlink="http://www.w3.org/1999/xlink">
+ <path fill={color} d="M4,10h24c1.104,0,2-0.896,2-2s-0.896-2-2-2H4C2.896,6,2,6.896,2,8S2.896,10,4,10z" />
+ <path fill={color} d="M28,14H4c-1.104,0-2,0.896-2,2 s0.896,2,2,2h24c1.104,0,2-0.896,2-2S29.104,14,28,14z" />
+ <path fill={color} d="M28,22H4c-1.104,0-2,0.896-2,2s0.896,2,2,2h24c1.104,0,2-0.896,2-2 S29.104,22,28,22z" />
+ </svg>
+ );
+};
+
+MenuIcon.defaultName = 'MenuIcon';
+
+export default MenuIcon;
\ No newline at end of file
import createStyles from '@mui/styles/createStyles';
-import defaultLogo from '../assets/images/defaultLogo.svg';
+const defaultLogo = require('../assets/icons/ht.Connect.svg');
const styles = (theme: Theme) => createStyles({
headerLogo: {
console.info([
"Logo hidden, because browser window width (",
this.state.windowWidth,
- "px) is lower thershold (",
+ "px) is lower threshold (",
this.hideLogoWhenWindowWidthIsLower,
"px)."].join(''));
}
if (filterExpressionAsString.length === 0 || isNaN(valueAsNumber)) return true;
if (filterExpressionAsString.startsWith('>=')) {
- return valueAsNumber >= Number(filterExpressionAsString.substr(2).trim());
+ return valueAsNumber >= Number(filterExpressionAsString.substring(2).trim());
} else if (filterExpressionAsString.startsWith('<=')) {
- return valueAsNumber <= Number(filterExpressionAsString.substr(2).trim());
+ return valueAsNumber <= Number(filterExpressionAsString.substring(2).trim());
} else if (filterExpressionAsString.startsWith('>')) {
- return valueAsNumber > Number(filterExpressionAsString.substr(1).trim());
+ return valueAsNumber > Number(filterExpressionAsString.substring(1).trim());
} else if (filterExpressionAsString.startsWith('<')) {
- return valueAsNumber < Number(filterExpressionAsString.substr(1).trim());
+ return valueAsNumber < Number(filterExpressionAsString.substring(1).trim());
}
} else if (column.type === ColumnType.date){
const valueAsString = String(dataValue);
const filterExpressionAsString = String(filterExpression).trim();
if (filterExpressionAsString.startsWith('>=')) {
- return valueAsDate >= convertToDate(filterExpressionAsString.substr(2).trim());
+ return valueAsDate >= convertToDate(filterExpressionAsString.substring(2).trim());
} else if (filterExpressionAsString.startsWith('<=')) {
- return valueAsDate <= convertToDate(filterExpressionAsString.substr(2).trim());
+ return valueAsDate <= convertToDate(filterExpressionAsString.substring(2).trim());
} else if (filterExpressionAsString.startsWith('>')) {
- return valueAsDate > convertToDate(filterExpressionAsString.substr(1).trim());
+ return valueAsDate > convertToDate(filterExpressionAsString.substring(1).trim());
} else if (filterExpressionAsString.startsWith('<')) {
- return valueAsDate < convertToDate(filterExpressionAsString.substr(1).trim());
+ return valueAsDate < convertToDate(filterExpressionAsString.substring(1).trim());
}
* ============LICENSE_END==========================================================================
*/
-import { Button, Checkbox, FormControlLabel, MenuItem, Popover, Switch, Typography } from '@mui/material';
-import connect, { Connect, IDispatcher } from '../../flux/connect';
-import * as React from 'react';
+import React from 'react';
+import { Button, FormControlLabel, Popover, Switch, Typography } from '@mui/material';
+import { connect, Connect, IDispatcher } from '../../flux/connect';
import { ColumnModel } from './columnModel';
import { IApplicationStoreState } from '../../store/applicationStore';
onHandleChangeRowsPerPage: (rowsPerPage: number | null) => void;
onHideColumns: (columnName: string[]) => void;
onShowColumns: (columnName: string[]) => void;
+ onClearFilters: () => void;
},
createPreActions: (dispatch: Dispatch, skipRefresh?: boolean) => {
onPreFilterChanged: (preFilter: {
dispatch((dispatch: Dispatch) => {
dispatch(new ShowColumnsAction(columnName));
})
- }
+ },
+ onClearFilters: () => {
+ dispatch((dispatch: Dispatch) => {
+ let filter = { };
+ dispatch(new SetFilterChangedAction(filter));
+ });
+ },
// selected:
};
};
import withStyles from '@mui/styles/withStyles';
import createStyles from '@mui/styles/createStyles';
import { toAriaLabel } from '../../utilities/yangHelper';
+import { IconType } from '../../models/iconDefinition';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
const styles = (theme: Theme) => createStyles({
active: {
});
export interface IListItemLinkProps extends WithStyles<typeof styles> {
- icon: JSX.Element | null;
+ icon: IconType | null;
primary: string | React.ComponentType;
secondary?: React.ComponentType;
to: string;
const renderLink = (itemProps: any): JSX.Element => (
props.external ? <a target="_blank" href={to} { ...itemProps }></a> :
<NavLink exact={ exact } to={ to } activeClassName={ classes.active } { ...itemProps } />);
-
+
+ const customIconHeight = 22;
const ariaLabel = typeof Primary === 'string' ? toAriaLabel("link-to-"+Primary) : toAriaLabel("link-to-"+Primary.displayName);
+
+ //create menu icon, either using an faIcon or a link to a custom svg icon
+ //moved to one place for easier usage
+ const listItemIcon = icon && ( typeof icon === 'string' ? <img height={customIconHeight} src={icon} /> : <FontAwesomeIcon icon={icon} /> );
+
return (
<>
<ListItem button component={ renderLink } aria-label={ariaLabel}>
{ icon
- ? <ListItemIcon>{ icon }</ListItemIcon>
+ ? <ListItemIcon>{ listItemIcon }</ListItemIcon>
: null
}
{ typeof Primary === 'string'
* the License.
* ============LICENSE_END==========================================================================
*/
-import * as React from 'react';
+import React from 'react';
import { Theme } from '@mui/material/styles';
+import classNames from 'classnames';
import { WithStyles } from '@mui/styles';
import withStyles from '@mui/styles/withStyles';
import createStyles from '@mui/styles/createStyles';
-import { faHome, faAddressBook } from '@fortawesome/free-solid-svg-icons';
-
import Drawer from '@mui/material/Drawer';
import List from '@mui/material/List';
import ListItemLink from '../components/material-ui/listItemLink';
-import connect, { Connect } from '../flux/connect';
+import { connect, Connect } from '../flux/connect';
import { MenuAction } from '../actions/menuAction';
-import * as classNames from 'classnames';
import { transportPCEUrl } from '../app';
+const aboutIcon = require('../assets/icons/About.svg');
+const homeIcon = require('../assets/icons/Home.svg');
+const loginIcon = require('../assets/icons/User.svg');
+const settingsIcon = require('../assets/icons/Tools.svg');
const drawerWidth = 240;
window.dispatchEvent(new Event('menu-resized'));
}, [isOpen])
- let menuItems = state.framework.applicationRegistraion && Object.keys(state.framework.applicationRegistraion).map(key => {
- const reg = state.framework.applicationRegistraion[key];
- const icon = !reg.icon ? null :( typeof reg.icon === 'string' ? <img height={22} src={reg.icon} /> : <FontAwesomeIcon icon={reg.icon} /> )
+ let menuItems = state.framework.applicationRegistration && Object.keys(state.framework.applicationRegistration).map(key => {
+ const reg = state.framework.applicationRegistration[key];
return reg && (
<ListItemLink
key={reg.name}
to={reg.path || `/${reg.name}`}
primary={reg.menuEntry || reg.name}
secondary={reg.subMenuEntry}
- icon={icon} />
+ icon={reg.icon || null} />
) || null;
}) || null;
key={"transportPCE"}
to={transportUrl}
primary={"TransportPCE"}
- icon={<FontAwesomeIcon icon={faProjectDiagram} />}
+ icon={faProjectDiagram}
external />;
const linkFound = menuItems.find(obj => obj.key === "linkCalculation");
<div className={classes.toolbar} />
{ /* https://fiffty.github.io/react-treeview-mui/ */}
<List className={classes.menu} component="nav">
- <ListItemLink exact to="/" primary="Home" icon={<FontAwesomeIcon icon={faHome} />} />
+ <ListItemLink exact to="/" primary="Home" icon={homeIcon} />
<Divider />
{
menuItems
}
<Divider />
- <ListItemLink to="/about" primary="About" icon={<FontAwesomeIcon icon={faAddressBook} />} />
+ <ListItemLink to="/about" primary="About" icon={aboutIcon} />
{(false && process.env.NODE_ENV === "development")
? <>
<Divider />
- <ListItemLink to="/test" primary="Test" icon={<FontAwesomeIcon icon={faHome} />} />
+ <ListItemLink to="/test" primary="Test" icon={settingsIcon} />
</>
: null
}
* the License.
* ============LICENSE_END==========================================================================
*/
-import * as React from 'react';
+import React from 'react';
-import connect, { Connect } from '../../flux/connect';
+import { connect, Connect } from '../../flux/connect';
import { SetTitleAction } from '../../actions/titleActions';
import { AddErrorInfoAction } from '../../actions/errorActions';
* ============LICENSE_END==========================================================================
*/
+import React from 'react';
import { Button, FormControlLabel, Switch, Typography } from '@mui/material';
import makeStyles from '@mui/styles/makeStyles';
import { SettingsComponentProps } from '../../models/settings';
-import * as React from 'react';
-import connect, { Connect, IDispatcher } from '../../flux/connect';
+import { connect, Connect, IDispatcher } from '../../flux/connect';
import { IApplicationStoreState } from '../../store/applicationStore';
import { getGeneralSettingsAction, SetGeneralSettingsAction, updateGeneralSettingsAction } from '../../actions/settingsAction';
import { sendMessage, SettingsMessage } from '../../services/broadcastService';
* the License.
* ============LICENSE_END==========================================================================
*/
-import * as React from 'react';
+import React from 'react';
import { withRouter, RouteComponentProps } from 'react-router-dom';
import { Theme } from '@mui/material/styles';
import Typography from '@mui/material/Typography';
import Button from '@mui/material/Button';
import IconButton from '@mui/material/IconButton';
-import Block from '@mui/icons-material/Block';
-import Adjust from '@mui/icons-material/Adjust';
-import MenuIcon from '@mui/icons-material/Menu';
import AccountCircle from '@mui/icons-material/AccountCircle';
import MenuItem from '@mui/material/MenuItem';
import Menu from '@mui/material/Menu';
import { logoutUser } from '../actions/authentication';
import { PushAction, ReplaceAction } from '../actions/navigationActions';
-import connect, { Connect, IDispatcher } from '../flux/connect';
-import Logo from './logo';
+import { connect, Connect, IDispatcher } from '../flux/connect';
import { MenuAction, MenuClosedByUser } from '../actions/menuAction';
+import MenuIcon from './icons/menuIcon';
+import Logo from './logo';
+
const styles = (theme: Theme) => createStyles({
appBar: {
zIndex: theme.zIndex.drawer + 1,
},
icon: {
marginLeft: 16,
- marginRight: 8
+ marginRight: 8,
+ marginBottom: -2,
},
connected: {
color: "green"
// add notificationInfo element before help
- if (state.framework.applicationRegistraion) {
+ if (state.framework.applicationRegistration) {
let isNotificationInfoAdded = false;
- Object.keys(state.framework.applicationRegistraion).map(key => {
- const reg = state.framework.applicationRegistraion[key];
+ Object.keys(state.framework.applicationRegistration).map(key => {
+ const reg = state.framework.applicationRegistration[key];
if (reg && reg.statusBarElement) {
if (key === "help") {
isNotificationInfoAdded = true;
}
const stateIcon = state.framework.applicationState.icon;
- const icon = !stateIcon ? null :( typeof stateIcon === 'string' ? <img className={classes.icon} height={22} src={stateIcon} /> : <FontAwesomeIcon className={classes.icon} icon={stateIcon} /> )
+ const customIconHeight = 22;
+ const icon = !stateIcon
+ ? null
+ : (typeof stateIcon === 'string'
+ ? <img className={classes.icon} height={customIconHeight} src={stateIcon} />
+ : <FontAwesomeIcon className={classes.icon} icon={stateIcon} />)
return (
* the License.
* ============LICENSE_END==========================================================================
*/
-import * as React from 'react';
-import * as PropTypes from 'prop-types';
+import React, { FC, useContext, createContext, useState, useEffect, useRef } from 'react';
-import { Dispatch } from '../flux/store';
+import { Dispatch } from './store';
import { ApplicationStore, IApplicationStoreState } from '../store/applicationStore';
+const LogLevel = +(localStorage.getItem('log.odlux.framework.flux.connect') || 0);
+
interface IApplicationStoreContext {
applicationStore: ApplicationStore;
}
dispatch: Dispatch;
}
-type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>
-
type ComponentDecoratorInfer<TMergedProps> = {
<TProps>(wrappedComponent: React.ComponentType<TProps & TMergedProps>): React.ComponentClass<Omit<TProps & TMergedProps, keyof TMergedProps>>;
};
+const ApplicationStoreContext = createContext<IApplicationStoreContext | undefined>(undefined);
+
export type Connect<TMapProps extends ((...args: any) => any) | undefined = undefined, TMapDispatch extends ((...args: any) => any) | undefined = undefined> =
(TMapProps extends ((...args: any) => any) ? ReturnType<TMapProps> : IApplicationStoreProps) &
(TMapDispatch extends ((...args: any) => any) ? ReturnType<TMapDispatch> : IDispatchProps);
const injectApplicationStore = (WrappedComponent: React.ComponentType<TProps & (IApplicationStoreProps | TStateProps) & IDispatchProps>): React.ComponentType<TProps> => {
class StoreAdapter extends React.Component<TProps, {}> {
- public static contextTypes = { ...WrappedComponent.contextTypes, applicationStore: PropTypes.object.isRequired };
- context: IApplicationStoreContext;
-
+
render(): JSX.Element {
if (isWrappedComponentIsVersion1(WrappedComponent)) {
this.forceUpdate();
}
}
-
+ StoreAdapter.contextType = ApplicationStoreContext;
return StoreAdapter;
}
}
}
-interface ApplicationStoreProviderProps extends React.Props<ApplicationStoreProvider> {
+type ApplicationStoreProviderProps = {
applicationStore: ApplicationStore;
}
-export class ApplicationStoreProvider extends React.Component<ApplicationStoreProviderProps>
- implements /* React.ComponentLifecycle<ApplicationStoreProviderProps, any>, */ React.ChildContextProvider<IApplicationStoreContext> {
+export const ApplicationStoreProvider: FC<ApplicationStoreProviderProps> = (props) => {
+ const { applicationStore, children } = props;
- public static childContextTypes = { applicationStore: PropTypes.object.isRequired };
+ return (
+ <ApplicationStoreContext.Provider value={{ applicationStore }}>
+ {children}
+ </ApplicationStoreContext.Provider>
+ );
+};
- getChildContext(): IApplicationStoreContext {
- return {
- applicationStore: this.props.applicationStore
- };
+export const useApplicationStore = (): ApplicationStore => {
+ const context = useContext(ApplicationStoreContext);
+ if (context == null || context.applicationStore == null) {
+ throw new Error("Requires application store provider!")
}
+ return context.applicationStore
+};
- render(): JSX.Element {
- return React.Children.only(this.props.children) as any; //type error, fix when possible
+export const useSelectApplicationState = <TProp extends unknown >( selector: (state: IApplicationStoreState) => TProp, eqFunc = (a: TProp, b: TProp) => a === b ): TProp => {
+ const context = useContext(ApplicationStoreContext);
+ if (context == null || context.applicationStore == null) {
+ throw new Error("Requires application store provider!")
}
-}
+
+ const [propState, setPropState] = useState<TProp>(selector(context.applicationStore.state));
+
+ const selectorRef = useRef(selector);
+ selectorRef.current = selector;
+
+ const propStateRef = useRef({propState});
+ propStateRef.current.propState = propState;
+
+ useEffect(() => {
+ if (context == null || context.applicationStore == null) {
+ throw new Error("Requires application store provider!")
+ }
+
+ const changedHandler = () => {
+ const newState = selectorRef.current(context.applicationStore.state);
+ if (!eqFunc(newState, propStateRef.current.propState)) {
+ setPropState(newState);
+ }
+ };
+
+ if (LogLevel > 3) {
+ console.log("useSelectApplicationState: adding handler", changedHandler);
+ }
+
+ context.applicationStore.changed.addHandler(changedHandler);
+
+ return () => {
+ if (LogLevel > 3) {
+ console.log("useSelectApplicationState: removing handler", changedHandler);
+ }
-export default connect;
\ No newline at end of file
+ context.applicationStore.changed.removeHandler(changedHandler);
+ }
+ }, [context]);
+
+ return propState;
+
+};
+
+export const useApplicationDispatch = (): Dispatch => {
+ const context = useContext(ApplicationStoreContext);
+ if (context == null || context.applicationStore == null) {
+ throw new Error("Requires application store provider!")
+ }
+ return context.applicationStore.dispatch;
+};
import { Action } from './action';
import { IActionHandler } from './action';
+const LogLevel = +(localStorage.getItem('log.odlux.framework.flux.store') || 0);
+
export interface Dispatch {
<TAction extends Action>(action: TAction): TAction;
}
(store: Store<TStoreState>): Dispatch;
}
-class InitialisationAction extends Action { };
-const initialisationAction = new InitialisationAction();
+class InitializationAction extends Action { };
+const initializationAction = new InitializationAction();
export class Store<TStoreState> {
this._isDispatching = false;
- this.changed = new Event<void>(); // sollten wir hier eventuell sogar den state mit übergeben ?
+ this.changed = new Event<void>();
this._actionHandler = actionHandler;
this._state = initialState as TStoreState;
if (enhancer) this._dispatch = enhancer(this);
- this._dispatch(initialisationAction);
+ this._dispatch(initializationAction);
}
public changed: Event<void>;
private _dispatch: Dispatch = <TAction extends Action>(payload: TAction): TAction => {
+ if (LogLevel > 2) {
+ console.log('Store::Dispatch - ', payload);
+ }
if (payload == null || !(payload instanceof Action)) {
throw new Error(
'Actions must inherit from type Action. ' +
}
if (this._state !== oldState) {
+ if (LogLevel > 3) {
+ console.log('Store::Dispatch - state has changed', this._state);
+ }
this.changed.invoke();
}
import { onLogin, onLogout } from '../services/applicationApi';
import { startWebsocketSession, endWebsocketSession } from '../services/notificationService';
import { startUserSession, endUserSession } from '../services/userSessionService';
-import { getSettings } from '../services/settingsService';
+import { getUserdata } from '../services/userdataService';
export interface IAuthenticationState {
user?: User;
import { Dispatch } from '../flux/store';
import { MiddlewareApi } from '../store/applicationStore';
+const LogLevel = +(localStorage.getItem('log.odlux.framework.middleware.logger') || 0);
function createLoggerMiddleware() {
return function logger({ getState }: MiddlewareApi) {
return (next: Dispatch): Dispatch => action => {
- console.log('will dispatch', action);
+ if (LogLevel > 2) console.log('will dispatch', action);
const returnValue = next(action);
- console.log('state after dispatch', getState());
+ if (LogLevel > 2) console.log('state after dispatch', getState());
return returnValue;
};
- }
+ };
}
export const logger = createLoggerMiddleware();
// ensure user is logged in and token is valid
if (action.pathname.startsWith("/oauth") && (action.search.startsWith("?token="))){
const ind = action.search.lastIndexOf("token=");
- const tokenStr = ind > -1 ? action.search.substr(ind+6) : null;
+ const tokenStr = ind > -1 ? action.search.substring(ind+6) : null;
const token = tokenStr && jwt.decode(tokenStr);
if (tokenStr && token) {
// @ts-ignore
* the License.
* ============LICENSE_END==========================================================================
*/
-import { GeneralSettings } from '../models/settings';
-import { setGeneralSettingsAction, SetGeneralSettingsAction } from '../actions/settingsAction';
+
import { Event } from '../common/event';
import { ApplicationStore } from '../store/applicationStore';
import { AuthMessage, getBroadcastChannel, sendMessage } from './broadcastService';
-import { endWebsocketSession } from './notificationService';
-import { getSettings } from './settingsService';
let resolveApplicationStoreInitialized: (store: ApplicationStore) => void;
let applicationStore: ApplicationStore | null = null;
/** Represents registry to manage all applications. */
class ApplicationManager {
- /** Stores all registerd applications. */
+ /** Stores all registered applications. */
private _applications: { [key: string]: ApplicationInfo };
/** Initializes a new instance of this class. */
this.changed = new Event<void>();
}
- /** The chaged event will fire if the registration has changed. */
+ /** The changed event will fire if the registration has changed. */
public changed: Event<void>;
/** Registers a new application. */
import { User } from "../models/authentication";
import { ApplicationStore } from "../store/applicationStore";
-type Broadcaster = {channel: BroadcastChannel, key: String};
+type Broadcaster = {
+ channel: BroadcastChannel;
+ key: String;
+};
type AuthTypes = 'login' | 'logout';
-export type AuthMessage={key: AuthTypes, data: any};
+export type AuthMessage = {
+ key: AuthTypes;
+ data: any;
+};
type SettingsType = 'general';
-export type SettingsMessage={key: SettingsType, enableNotifications: boolean, user: string};
+export type SettingsMessage = {
+ key: SettingsType;
+ enableNotifications: boolean;
+ user: string;
+};
-let channels: Broadcaster[] = [];
-let store : ApplicationStore | null = null;
+const channels: Broadcaster[] = [];
+let store: ApplicationStore | null = null;
export const saveChannel = (channel: BroadcastChannel, channelName: string) => {
- channels.push({channel: channel, key: channelName});
-}
-
-export const startBroadcastChannel = (applicationStore: ApplicationStore)=>{
- store=applicationStore;
-
- //might decide to use one general broadcast channel with more keys in the future
- createAuthBroadcastChannel();
- createSettingsBroadcastChannel();
-}
-
-const createSettingsBroadcastChannel = () =>{
-
- const name = "odlux_settings";
- const bc: BroadcastChannel = new BroadcastChannel(name);
- channels.push({ channel: bc, key: name });
-
- bc.onmessage = (eventMessage: MessageEvent<SettingsMessage>) => {
- console.log(eventMessage)
-
- if (eventMessage.data.key === 'general') {
-
- if (store?.state.framework.authenticationState.user) {
- const data = eventMessage.data;
- if(store.state.framework.authenticationState.user.user === data.user){
- store?.dispatch(setGeneralSettingsAction(data.enableNotifications));
- }
- }
- }
- }
+ channels.push({ channel: channel, key: channelName });
+};
-}
+export const startBroadcastChannel = (applicationStore: ApplicationStore) => {
+ store = applicationStore;
-const createAuthBroadcastChannel = () => {
- const name = "odlux_auth";
- const bc: BroadcastChannel = new BroadcastChannel(name);
- channels.push({ channel: bc, key: name });
-
- bc.onmessage = (eventMessage: MessageEvent<AuthMessage>) => {
- console.log(eventMessage)
-
- if (eventMessage.data.key === 'login') {
- if (!store?.state.framework.authenticationState.user) {
- const initialToken = localStorage.getItem("userToken");
- if (initialToken) {
- store?.dispatch(loginUserAction(User.fromString(initialToken)));
- store?.dispatch(new ReplaceAction("/"));
- }
- }
- }
- else if (eventMessage.data.key === 'logout') {
+ //might decide to use one general broadcast channel with more keys in the future
+ createAuthBroadcastChannel();
+ createSettingsBroadcastChannel();
+};
- if (store?.state.framework.authenticationState.user) {
- store?.dispatch(logoutUser());
- store?.dispatch(new ReplaceAction("/login"));
- }
- }
- }
-}
+const createSettingsBroadcastChannel = () => {
-export const getBroadcastChannel = (channelName: string) =>{
- const foundChannel = channels.find(s =>s.key===channelName);
- return foundChannel?.channel;
-}
+ const name = "odlux_settings";
+ const bc: BroadcastChannel = new BroadcastChannel(name);
+ channels.push({ channel: bc, key: name });
+ bc.onmessage = (eventMessage: MessageEvent<SettingsMessage>) => {
+ console.log(eventMessage);
-export const sendMessage = (data: any, channel: string) =>{
+ if (eventMessage.data.key === 'general') {
- const foundChannel = channels.find(s =>s.key===channel);
- if(foundChannel){
- foundChannel.channel.postMessage(data);
- }
+ if (store?.state.framework.authenticationState.user) {
+ const data = eventMessage.data;
+ if (store.state.framework.authenticationState.user.user === data.user) {
+ store?.dispatch(setGeneralSettingsAction(data.enableNotifications));
+ }
+ }
+ }
+ }
+};
+
+const createAuthBroadcastChannel = () => {
+ const name = "odlux_auth";
+ const bc: BroadcastChannel = new BroadcastChannel(name);
+ channels.push({ channel: bc, key: name });
+
+ bc.onmessage = (eventMessage: MessageEvent<AuthMessage>) => {
+ console.log(eventMessage)
+
+ if (eventMessage.data.key === 'login') {
+ if (!store?.state.framework.authenticationState.user) {
+ const initialToken = localStorage.getItem("userToken");
+ if (initialToken) {
+ store?.dispatch(loginUserAction(User.fromString(initialToken)));
+ store?.dispatch(new ReplaceAction("/"));
+ }
+ }
+ }
+ else if (eventMessage.data.key === 'logout') {
+ if (store?.state.framework.authenticationState.user) {
+ store?.dispatch(logoutUser());
+ store?.dispatch(new ReplaceAction("/login"));
+ }
}
+ }
+};
+
+export const getBroadcastChannel = (channelName: string) => {
+ const foundChannel = channels.find(s => s.key === channelName);
+ return foundChannel?.channel;
+};
+
+export const sendMessage = (data: any, channel: string) => {
+ const foundChannel = channels.find(s => s.key === channel);
+ if (foundChannel) {
+ foundChannel.channel.postMessage(data);
+ }
+};
export { applicationManager } from './applicationManager';
export { subscribe, unsubscribe } from './notificationService';
export { requestRest } from './restService';
-export { putSettings, getSettings} from './settingsService';
+export { saveUserdata, getUserdata } from './userdataService';
* ============LICENSE_END==========================================================================
*/
+import { ReplaceAction } from '../actions/navigationActions';
+import { AddErrorInfoAction } from '../actions/errorActions';
-import { ApplicationStore } from "../store/applicationStore";
-import { ReplaceAction } from "../actions/navigationActions";
-import { AddErrorInfoAction } from "../actions/errorActions";
+import { storeService } from './storeService';
const baseUri = `${ window.location.origin }`;
const absUrlPattern = /^https?:\/\//;
-let applicationStore: ApplicationStore | null = null;
-
-export const startRestService = (store: ApplicationStore) => {
- applicationStore = store;
-};
export const formEncode = (params: { [key: string]: string | number }) => Object.keys(params).map((key) => {
return encodeURIComponent(key) + '=' + encodeURIComponent(params[key].toString());
DELETE: false,
};
- if (!applicationStore) return result;
+ if (!storeService.applicationStore) return result;
- const { state: { framework: { applicationState: { enablePolicy }, authenticationState: { policies }}} } = applicationStore!;
+ const { state: { framework: { applicationState: { enablePolicy }, authenticationState: { policies } } } } = storeService.applicationStore!;
result.GET = true;
result.POST = true;
return result;
-}
+};
/** Sends a rest request to the given path.
* @returns The data, or null it there was any error
/** Sends a rest request to the given path and reports the server state.
* @returns An object with the server state, a message and the data or undefined in case of a json parse error.
*/
-export async function requestRestExt<TData>(path: string = '', init: RequestInit = {}, authenticate: boolean = true, isResource: boolean = false): Promise<{ status: number, message?: string, data: TData | null | undefined }> {
- const result: { status: number, message?: string, data: TData | null } = {
+export async function requestRestExt<TData>(path: string = '', init: RequestInit = {}, authenticate: boolean = true, isResource: boolean = false): Promise<{ status: number; message?: string; data: TData | null | undefined }> {
+ const result: { status: number; message?: string; data: TData | null } = {
status: -1,
data: null,
};
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
- ...init.headers
- }
+ ...init.headers,
+ },
};
- if (!isAbsUrl && authenticate && applicationStore) {
- const { state: { framework: { authenticationState: { user } } } } = applicationStore;
+ if (!isAbsUrl && authenticate && storeService.applicationStore) {
+ const { state: { framework: { authenticationState: { user } } } } = storeService.applicationStore;
// do not request if the user is not valid
if (!user || !user.isValid) {
return {
...result,
- message: "User is not valid or not logged in."
+ message: 'User is not valid or not logged in.',
};
}
(init.headers = {
...init.headers,
- 'Authorization': `${user.tokenType} ${user.token}`
+ 'Authorization': `${user.tokenType} ${user.token}`,
//'Authorization': 'Basic YWRtaW46YWRtaW4='
});
}
const fetchResult = await fetch(uri, init);
- if(fetchResult.status === 403){
- applicationStore && applicationStore.dispatch(new AddErrorInfoAction({title: "Forbidden", message:"Status: [403], access denied."}));
+ if (fetchResult.status === 403) {
+ storeService.applicationStore && storeService.applicationStore.dispatch(new AddErrorInfoAction({ title: 'Forbidden', message:'Status: [403], access denied.' }));
return {
...result,
status: 403,
- message: "Forbidden."
+ message: 'Forbidden.',
};
- }
- else if (fetchResult.status === 401) {
- applicationStore && applicationStore.dispatch(new ReplaceAction(`/login?returnTo=${applicationStore.state.framework.navigationState.pathname}`));
+ } else if (fetchResult.status === 401) {
+ storeService.applicationStore && storeService.applicationStore.dispatch(new ReplaceAction(`/login?returnTo=${storeService.applicationStore.state.framework.navigationState.pathname}`));
return {
...result,
status: 401,
- message: "Authentication requested by server."
+ message: 'Authentication requested by server.',
};
}
- const contentType = fetchResult.headers.get("Content-Type") || fetchResult.headers.get("content-type");
- const isJson = contentType && (contentType.toLowerCase().startsWith("application/json") || contentType.toLowerCase().startsWith("application/yang-data+json"));
+ const contentType = fetchResult.headers.get('Content-Type') || fetchResult.headers.get('content-type');
+ const isJson = contentType && (contentType.toLowerCase().startsWith('application/json') || contentType.toLowerCase().startsWith('application/yang-data+json'));
try {
const data = (isJson ? await fetchResult.json() : await fetchResult.text()) as TData;
return {
...result,
status: fetchResult.status,
message: fetchResult.statusText,
- data: data
+ data: data,
};
} catch (error) {
return {
...result,
status: fetchResult.status,
message: error && error.message || String(error),
- data: undefined
+ data: undefined,
};
}
}
\ No newline at end of file
--- /dev/null
+import { ApplicationStore } from "../store/applicationStore";
+
+let applicationStore: ApplicationStore | null = null;
+
+export const startSoreService = (store: ApplicationStore) => {
+ applicationStore = store;
+};
+
+export const storeService = {
+ get applicationStore() { return applicationStore; },
+ };
\ No newline at end of file
const settingsPath ="/userdata";
- export function getSettings<TData>(partialPath?: string){
+ export function getUserdata<TData>(partialPath?: string){
let path = settingsPath;
if(partialPath){
path+=partialPath
return result;
}
- export function putSettings<TData>(partialPath: string, data: string){
+ export function saveUserdata<TData>(partialPath: string, data: string){
const result = requestRest<TData>(settingsPath+partialPath, {method: "PUT", body: data})
return result;
export type MiddlewareApi = MiddlewareArg<IApplicationStoreState>;
export interface IFrameworkStoreState {
- applicationRegistraion: IApplicationRegistration;
+ applicationRegistration: IApplicationRegistration;
applicationState: IApplicationState;
authenticationState: IAuthenticationState;
navigationState: INavigationState;
}
const frameworkHandlers = combineActionHandler({
- applicationRegistraion: applicationRegistryHandler,
+ applicationRegistration: applicationRegistryHandler,
applicationState: applicationStateHandler,
authenticationState: authenticationStateHandler,
navigationState: navigationStateHandler
const actionHandlers = Object.keys(applicationService.applications).reduce((acc, cur) => {
const reg = applicationService.applications[cur];
reg && typeof reg.rootActionHandler === 'function' && (acc[cur] = reg.rootActionHandler);
- reg && +(reg.middlewares || 0) && middlewares.push(...(reg.middlewares as Middleware<IApplicationStoreState>[]));
+ reg && reg.middlewares && Array.isArray(reg.middlewares) && middlewares.push(...(reg.middlewares as Middleware<IApplicationStoreState>[]));
return acc;
}, { framework: frameworkHandlers } as any);
--- /dev/null
+export enum LogLevel {
+ Always = 0,
+ Error = 1,
+ Warning = 2,
+ Info = 3,
+ Debug = 4,
+ Trace = 5,
+}
* the License.
* ============LICENSE_END==========================================================================
*/
-import * as React from 'react';
+import React, { FC, useEffect, useState } from 'react';
import * as marked from 'marked';
import * as hljs from 'highlight.js';
import { requestRestExt } from '../services/restService';
import { Button, Typography } from '@mui/material';
+
const defaultRenderer = new marked.Renderer();
defaultRenderer.link = (href, title, text) => (
`<a target="_blank" rel="noopener noreferrer" href="${href}" title="${title}">${text}</a>`
);
-interface AboutState {
- content: string | null;
- isCopiedSuccessfully: boolean;
- isContentLoadedSucessfully: boolean;
-}
-type odluxVersion= {version:string,build:string, framework: string,
+type OdluxVersion= {version:string,build:string, framework: string,
applications:{
configurationApp: string,
connectApp: string,
faultApp: string,
helpApp: string,
inventoryApp: string,
+ linkCalculationApp: string,
maintenanceApp: string,
mediatorApp: string,
+ networkMapApp: string,
permanceHistoryApp: string
}};
-type topologyVersion = {version: string, buildTimestamp: string};
-
-class AboutComponent extends React.Component<any, AboutState> {
- textarea: React.RefObject<HTMLTextAreaElement>;
+type TopologyVersion = {version: string, buildTimestamp: string};
+const AboutComponent: FC = (props) => {
+
+ const textareaRef = React.createRef<HTMLTextAreaElement>();
+ const [content, setContent] = useState<string | null>(null);
+ const [isCopiedSuccessfully, setCopySuccess] = useState(false);
+ const [isContetLoaded, setContentLoaded] = useState(false);
- constructor(props: any) {
- super(props);
- this.state = { content: null, isCopiedSuccessfully:false, isContentLoadedSucessfully: false }
- this.textarea = React.createRef();
- this.loadAboutContent();
- }
+ useEffect(()=>{
+ loadAboutContent();
+ },[]);
- private getMarkOdluxVersionMarkdownTable(data:odluxVersion|null|undefined):string{
+ const getMarkOdluxVersionMarkdownTable = (data:OdluxVersion|null|undefined):string => {
if(!data) {
return "";
}else{
`| InventoryApp | ${data.applications.inventoryApp}|\n `+
`| EventLogApp | ${data.applications.eventLogApp}|\n `+
`| MediatorApp | ${data.applications.mediatorApp}|\n `+
+ `| NetworkMapApp | ${data.applications.networkMapApp}|\n `+
+ `| LinkCalculatorApp | ${data.applications.linkCalculationApp}|\n `+
`| HelpApp | ${data.applications.helpApp}|\n `;
}
}
}
- private getTopologyVersionMarkdownTable(data: topologyVersion|null|undefined){
+ const getTopologyVersionMarkdownTable = (data: TopologyVersion|null|undefined) => {
if(!data){
return "No version";
}
}
}
- private loadAboutContent(): void {
+ const loadAboutContent = (): void => {
const baseUri = window.location.pathname.substring(0,window.location.pathname.lastIndexOf("/")+1);
const init = {
'method': 'GET',
}
};
const p1 = requestRestExt<string>('/about',init);
- const p2 = requestRestExt<odluxVersion>(`${baseUri}version.json`);
+ const p2 = requestRestExt<OdluxVersion>(`${baseUri}version.json`);
const p3 = requestRestExt<any>(`/topology/info/version`);
Promise.all([p1,p2, p3]).then((responses) => {
const response2 = responses[1];
const response3 = responses[2];
const content = response.status == 200 ? response.data : `${response.status} ${response.message}` || "Server error";
- const content2 = `\n## ODLUX Version Info\n`+(response2.status == 200 ? this.getMarkOdluxVersionMarkdownTable(response2.data) : `${response2.message}` || "ODLUX Server error");
- const content3 = `\n## Topology API Version Info\n`+(response3.status == 200 ? this.getTopologyVersionMarkdownTable(response3.data): `Topology API not available`);
+ const content2 = `\n## ODLUX Version Info\n`+(response2.status == 200 ? getMarkOdluxVersionMarkdownTable(response2.data) : `${response2.message}` || "ODLUX Server error");
+ const content3 = `\n## Topology API Version Info\n`+(response3.status == 200 ? getTopologyVersionMarkdownTable(response3.data): `Topology API not available`);
const loadedSucessfully = response.status == 200 ? true : false;
- this.setState({ content: (content + content2 + content3 ) || null, isContentLoadedSucessfully: loadedSucessfully });
+ setContent((content + content2 + content3 ) || null);
+ setContentLoaded(loadedSucessfully);
}).catch((error) => {
- this.setState({ content: error })
- })
+ setContent(error);
+ });
}
- copyToClipboard = (e: React.MouseEvent<HTMLButtonElement>) =>{
+ const copyToClipboard = (e: React.MouseEvent<HTMLButtonElement>) =>{
e.preventDefault();
- if(this.textarea.current!==null){
- this.textarea.current.select();
+ if(textareaRef.current!==null){
+ textareaRef.current.select();
document.execCommand('copy');
if(e.currentTarget != null){ // refocus on button, otherwhise the textarea would be focused
e.currentTarget.focus();
}
- this.setState({isCopiedSuccessfully: true});
- window.setTimeout(()=>{this.setState({isCopiedSuccessfully: false});},2000);
+ setCopySuccess(true);
+ window.setTimeout(()=>{ setCopySuccess(false);},2000);
}
}
- render() {
-
const markedOptions: marked.MarkedOptions = {
gfm: true,
breaks: false,
const style: React.CSSProperties = {};
const containerStyle = { overflow: "auto", paddingRight: "20px" }
- const html = (marked(this.state.content || 'loading', { renderer: markedOptions && markedOptions.renderer || defaultRenderer }));
+ const html = (marked(content || 'loading', { renderer: markedOptions && markedOptions.renderer || defaultRenderer }));
return (
<div style={containerStyle}>
- { this.state.isContentLoadedSucessfully &&
+ { isContetLoaded &&
<div style={{float: "right", marginRight: "10px"}}>
- <Button aria-label="copy-version-information-button" color="inherit" variant="contained" onClick={e => this.copyToClipboard(e)}>
+ <Button aria-label="copy-version-information-button" color="inherit" variant="contained" onClick={e => copyToClipboard(e)}>
Copy to clipboard
</Button>
{
- this.state.isCopiedSuccessfully &&
+ isCopiedSuccessfully &&
<Typography variant="body1" style={{color: "green"}} align="center">
copied successfully
</Typography>
<form>
<textarea
style={{opacity: ".01"}}
- ref={this.textarea}
- value={this.state.content || ''}
+ ref={textareaRef}
+ value={content || ''}
/>
</form>
</div>
);
- }
};
export const About = AboutComponent;
* the License.
* ============LICENSE_END==========================================================================
*/
-import * as React from 'react';
+import React, { FC, memo } from 'react';
import { HashRouter as Router, Route, Redirect, Switch } from 'react-router-dom';
import { Theme } from '@mui/material/styles';
-import { WithStyles } from '@mui/styles';
-import withStyles from '@mui/styles/withStyles';
-import createStyles from '@mui/styles/createStyles';
-import { faHome, faAddressBook, faSignInAlt, faCog } from '@fortawesome/free-solid-svg-icons'
-
+import { makeStyles } from '@mui/styles';
import { SnackbarProvider } from 'notistack';
import { ConfirmProvider } from 'material-ui-confirm';
import applicationService from '../services/applicationManager';
+const aboutIcon = require('../assets/icons/About.svg');
+const homeIcon = require('../assets/icons/Home.svg');
+const loginIcon = require('../assets/icons/User.svg');
+const settingsIcon = require('../assets/icons/Tools.svg');
+
+const styles = makeStyles((theme: Theme) => {
-const styles = (theme: Theme) => createStyles({
+ return {
root: {
flexGrow: 1,
height: '100%',
minWidth: 0, // So the Typography noWrap works
},
toolbar: theme.mixins.toolbar as any
+ };
});
+const FrameComponent: FC = memo(() => {
+ const registrations = applicationService.applications;
+ const classes = styles();
+ return (
+ <ConfirmProvider>
+ <SnackbarProvider maxSnack={3}>
+ <Router>
+ <div className={classes.root}>
+ <SnackDisplay />
+ <ErrorDisplay />
+ <TitleBar />
+ <Menu />
+ <main className={classes.content}>
+ {
+ <div className={classes.toolbar} /> //needed for margins, don't remove!
+ }
+ <Switch>
+ <Route exact path="/" component={() => (
+ <AppFrame title={"Home"} icon={homeIcon} >
+ <Home />
+ </AppFrame>
+ )} />
+ <Route path="/about" component={() => (
+ <AppFrame title={"About"} icon={aboutIcon} >
+ <About />
+ </AppFrame>
+ )} />
+ <Route path="/settings" component={() => (
+ <AppFrame title={"Settings"} icon={settingsIcon} >
+ <UserSettings />
+ </AppFrame>
+ )} />
+ {process.env.NODE_ENV === "development" ? <Route path="/test" component={() => (
+ <AppFrame title={"Test"} icon={settingsIcon} >
+ <Test />
+ </AppFrame>
+ )} /> : null}
+ <Route path="/login" component={() => (
+ <AppFrame title={"Login"} icon={loginIcon} >
+ <Login />
+ </AppFrame>
+ )} />
+ {Object.keys(registrations).map(p => {
+ const application = registrations[p];
+ return (<Route key={application.name} path={application.path || `/${application.name}`} component={() => (
+ <AppFrame title={application.title || (typeof application.menuEntry === 'string' && application.menuEntry) || application.name} icon={application.icon} appId={application.name} >
+ <application.rootComponent />
+ </AppFrame>
+ )} />)
+ })}
+ <Redirect to="/" />
+ </Switch>
+ </main>
+ </div>
+ </Router>
+ </SnackbarProvider>
+ </ConfirmProvider>
+ );
+});
-type FrameProps = WithStyles<typeof styles>;
-
-class FrameComponent extends React.Component<FrameProps>{
-
- render() {
- const registrations = applicationService.applications;
- const { classes } = this.props;
- return (
- <ConfirmProvider>
- <SnackbarProvider maxSnack={3}>
- <Router>
- <div className={classes.root}>
- <SnackDisplay />
- <ErrorDisplay />
- <TitleBar />
- <Menu />
- <main className={classes.content}>
- {
- <div className={classes.toolbar} /> //needed for margins, don't remove!
- }
- <Switch>
- <Route exact path="/" component={() => (
- <AppFrame title={"Home"} icon={faHome} >
- <Home />
- </AppFrame>
- )} />
- <Route path="/about" component={() => (
- <AppFrame title={"About"} icon={faAddressBook} >
- <About />
- </AppFrame>
- )} />
- <Route path="/settings" component={() => (
- <AppFrame title={"Settings"} icon={faCog} >
- <UserSettings />
- </AppFrame>
- )} />
- {process.env.NODE_ENV === "development" ? <Route path="/test" component={() => (
- <AppFrame title={"Test"} icon={faAddressBook} >
- <Test />
- </AppFrame>
- )} /> : null}
- <Route path="/login" component={() => (
- <AppFrame title={"Login"} icon={faSignInAlt} >
- <Login />
- </AppFrame>
- )} />
- { Object.keys(registrations).map(p => {
- const application = registrations[p];
- return (<Route key={application.name} path={application.path || `/${application.name}`} component={() => (
- <AppFrame title={application.title || (typeof application.menuEntry === 'string' && application.menuEntry) || application.name} icon={application.icon} appId={application.name} >
- <application.rootComponent />
- </AppFrame>
- )} />)
- })}
- <Redirect to="/" />
- </Switch>
- </main>
- </div>
- </Router>
- </SnackbarProvider>
- </ConfirmProvider>
- );
- }
-}
-
-export const Frame = withStyles(styles)(FrameComponent);
+export const Frame = FrameComponent;
export default Frame;
* ============LICENSE_END==========================================================================
*/
-import * as React from 'react';
-import { IApplicationStoreState } from "../store/applicationStore";
-import connect, { Connect, IDispatcher } from "../flux/connect";
+import React, {FC, useState} from 'react';
import applicationService from '../services/applicationManager';
-type props = Connect<typeof mapProps, typeof mapDispatch>;
-type SettingsEntry = { name: string, element: JSX.Element }
+type DashboardElement = { name: string, element: JSX.Element };
-
-const mapProps = (state: IApplicationStoreState) => ({
-});
-
-const mapDispatch = (dispatcher: IDispatcher) => ({
-});
-
-const DashboardView: React.FunctionComponent<props> = (props) => {
+const DashboardView: FC = (props) => {
const registrations = applicationService.applications;
- const [selectedIndex] = React.useState(0);
+ const [selectedIndex] = useState(0);
- let settingsArray: SettingsEntry[] = [];
+ let dashboardArray: DashboardElement[] = [];
- let settingsElements: (SettingsEntry)[] = Object.keys(registrations).map(p => {
+ let dashboardElements: (DashboardElement)[] = Object.keys(registrations).map(p => {
const application = registrations[p];
if (application.dashbaordElement) {
- const value: SettingsEntry = { name: application.menuEntry?.toString()!, element: <application.dashbaordElement /> };
+ const value: DashboardElement = { name: application.menuEntry?.toString()!, element: <application.dashbaordElement /> };
return value;
} else {
return null;
}
- }).filter((x): x is SettingsEntry => x !== null);
-
+ }).filter((x): x is DashboardElement => x !== null);
- settingsArray.push(...settingsElements);
+ dashboardArray.push(...dashboardElements);
return <div>
<div>
<div>
{
- settingsArray[selectedIndex]?.element
+ dashboardArray[selectedIndex]?.element
}
</div>
</div>
}
-export default connect(mapProps, mapDispatch)(DashboardView);
+export default DashboardView;
\ No newline at end of file
* the License.
* ============LICENSE_END==========================================================================
*/
-import * as React from 'react';
-import { withRouter, RouteComponentProps } from 'react-router-dom';
+import React, { FC, useEffect, useState } from 'react';
+import { RouteComponentProps, withRouter } from 'react-router-dom';
import Alert from '@mui/material/Alert';
import Avatar from '@mui/material/Avatar';
import Button from '@mui/material/Button';
import CssBaseline from '@mui/material/CssBaseline';
import FormControl from '@mui/material/FormControl';
-import FormControlLabel from '@mui/material/FormControlLabel';
-import Checkbox from '@mui/material/Checkbox';
import Input from '@mui/material/Input';
import InputLabel from '@mui/material/InputLabel';
-import LockIcon from '@mui/icons-material/LockOutlined';
import Paper from '@mui/material/Paper';
-import Typography from '@mui/material/Typography';
import { Theme } from '@mui/material/styles';
+import Typography from '@mui/material/Typography';
-import { WithStyles } from '@mui/styles';
-import withStyles from '@mui/styles/withStyles';
-import createStyles from '@mui/styles/createStyles';
+import { makeStyles } from '@mui/styles';
-import connect, { Connect, IDispatcher } from '../flux/connect';
+import { useApplicationDispatch, useSelectApplicationState } from '../flux/connect';
import authenticationService from '../services/authenticationService';
-import { updateExternalLoginProviderAsyncActionCreator } from '../actions/loginProvider';
import { loginUserAction, UpdatePolicies } from '../actions/authentication';
+import { updateExternalLoginProviderAsyncActionCreator } from '../actions/loginProvider';
-import { IApplicationStoreState } from '../store/applicationStore';
import { AuthPolicy, AuthToken, User } from '../models/authentication';
-import Menu from '@mui/material/Menu';
-import { MenuItem } from '@mui/material';
-const styles = (theme: Theme) => createStyles({
+const loginIcon = require('../assets/icons/User.svg');
+
+const styles = makeStyles((theme: Theme) =>{
+ return{
layout: {
width: 'auto',
display: 'block', // Fix IE11 issue.
padding: '0 10px',
color: 'grey'
}
+};
});
-const mapProps = (state: IApplicationStoreState) => ({
- search: state.framework.navigationState.search,
- authentication: state.framework.applicationState.authentication,
- externalLoginProviders: state.framework.applicationState.externalLoginProviders ,
-});
-
-const mapDispatch = (dispatcher: IDispatcher) => ({
- updateExternalProviders: () => dispatcher.dispatch(updateExternalLoginProviderAsyncActionCreator()),
- updateAuthentication: (token: AuthToken | null) => {
- const user = token && new User(token) || undefined;
- dispatcher.dispatch(loginUserAction(user));
- },
- updatePolicies: (policies?: AuthPolicy[]) => {
- return dispatcher.dispatch(new UpdatePolicies(policies));
- },
-});
-
-type LoginProps = RouteComponentProps<{}> & WithStyles<typeof styles> & Connect<typeof mapProps, typeof mapDispatch>;
-
-interface ILoginState {
- externalProviderAnchor: HTMLElement | null;
- busy: boolean;
- username: string;
- password: string;
- scope: string;
- message: string;
- isServerReady: boolean;
- providers: {
- id: string;
- title: string;
- loginUrl: string;
- }[] | null;
-}
+type LoginProps = RouteComponentProps;
// todo: ggf. redirect to einbauen
-class LoginComponent extends React.Component<LoginProps, ILoginState> {
+const LoginComponent: FC<LoginProps> = (props) => {
- constructor(props: LoginProps) {
- super(props);
-
- this.state = {
- externalProviderAnchor: null,
- busy: false,
- username: '',
- password: '',
- scope: 'sdn',
- message: '',
- providers: null,
- isServerReady: false
- };
+ const search = useSelectApplicationState(state => state.framework.navigationState.search);
+ const authentication = useSelectApplicationState(state => state.framework.applicationState.authentication);
+ const externalLoginProviders = useSelectApplicationState(state => state.framework.applicationState.externalLoginProviders);
+
+ const dispatch = useApplicationDispatch();
+ const updateExternalProviders = () => dispatch(updateExternalLoginProviderAsyncActionCreator());
+ const updateAuthentication = (token: AuthToken | null) => {
+ const user = token && new User(token) || undefined;
+ dispatch(loginUserAction(user));
+ }
+ const updatePolicies = (policies?: AuthPolicy[]) => {
+ return dispatch(new UpdatePolicies(policies));
}
- async componentDidMount(){
- if (this.props.authentication === "oauth" && (this.props.externalLoginProviders == null || this.props.externalLoginProviders.length === 0)){
- this.props.updateExternalProviders();
+ const [isBusy, setBusy] = useState(false);
+ const [username, setUsername] = useState("");
+ const [password, setPassword] = useState("");
+ const [scope, setScope] = useState("sdn");
+ const [message, setMessage] = useState("");
+ const [isServerReady, setIsServerReady] = useState(false);
+
+ useEffect(()=>{
+ if (authentication === "oauth" && (externalLoginProviders == null || externalLoginProviders.length === 0)){
+ updateExternalProviders();
}
authenticationService.getServerReadyState().then(result =>{
- this.setState({isServerReady: result});
+ setIsServerReady(result);
})
+ },[]);
-
-
- }
-
- private setExternalProviderAnchor = (el: HTMLElement | null) => {
- this.setState({externalProviderAnchor: el })
- }
-
- render(): JSX.Element {
- const { classes } = this.props;
- const areProvidersAvailable = this.props.externalLoginProviders && this.props.externalLoginProviders.length > 0;
- return (
- <>
- <CssBaseline />
- <main className={classes.layout}>
- <Paper className={classes.paper}>
- <Avatar className={classes.avatar}>
- <LockIcon />
- </Avatar>
- <Typography variant="caption">Sign in</Typography>
- <form className={classes.form}>
-
-
- {areProvidersAvailable &&
- <>
- {
- this.props.externalLoginProviders!.map((provider, index) => (
- <Button
- aria-controls="externalLogin"
- aria-label={"external-login-identity-provider-" + (index + 1)}
- aria-haspopup="true"
- fullWidth
- variant="contained"
- color="inherit"
- className={classes.submit} onClick={() => { window.location = provider.loginUrl as any; }}>
- {provider.title}
- </Button>))
- }
-
- <div className={classes.lineContainer}>
- <span className={classes.thirdPartyDivider}>
- OR
- </span>
- </div>
- </>
- }
-
- <FormControl variant="standard" margin="normal" required fullWidth>
- <InputLabel htmlFor="username">Username</InputLabel>
- <Input id="username" name="username" autoComplete="username" autoFocus
- disabled={this.state.busy}
- value={this.state.username}
- onChange={event => { this.setState({ username: event.target.value }) }} />
- </FormControl>
- <FormControl variant="standard" margin="normal" required fullWidth>
- <InputLabel htmlFor="password">Password</InputLabel>
- <Input
- name="password"
- type="password"
- id="password"
- autoComplete="current-password"
- disabled={this.state.busy}
- value={this.state.password}
- onChange={event => { this.setState({ password: event.target.value }) }}
- />
- </FormControl>
- <FormControl variant="standard" margin="normal" required fullWidth>
- <InputLabel htmlFor="password">Domain</InputLabel>
- <Input
- name="scope"
- type="scope"
- id="scope"
- disabled={this.state.busy}
- value={this.state.scope}
- onChange={event => { this.setState({ scope: event.target.value }) }}
- />
- </FormControl>
- <Button
- aria-label="login-button"
- type="submit"
- fullWidth
- variant="contained"
- color="inherit"
- disabled={this.state.busy}
- className={classes.submit}
- onClick={this.onSignIn}
- >
- Sign in
- </Button>
-
- </form>
- {this.state.message && <Alert severity="error">{this.state.message}</Alert>}
- </Paper>
- </main>
- </>
- );
- }
-
- private onSignIn = async (event: React.MouseEvent<HTMLButtonElement>) => {
+ const onSignIn = async (event: React.MouseEvent<HTMLButtonElement>) => {
event.preventDefault();
+
+ setBusy(true);
- this.setState({ busy: true });
-
- const token = this.props.authentication === "oauth"
- ? await authenticationService.authenticateUserOAuth(this.state.username, this.state.password, this.state.scope)
- : await authenticationService.authenticateUserBasicAuth(this.state.username, this.state.password, this.state.scope);
+ const token = authentication === "oauth"
+ ? await authenticationService.authenticateUserOAuth(username, password, scope)
+ : await authenticationService.authenticateUserBasicAuth(username, password, scope);
- this.props.updateAuthentication(token);
- this.setState({ busy: false });
+ updateAuthentication(token);
+ setBusy(false);
if (token) {
- const query = this.props.search && this.props.search.replace(/^\?/, "").split('&').map(e => e.split("="));
+ const query = search && search.replace(/^\?/, "").split('&').map(e => e.split("="));
const returnTo = query && query.find(e => e[0] === "returnTo");
- this.props.history.replace(returnTo && returnTo[1] || "/");
+ props.history.replace(returnTo && returnTo[1] || "/");
}
else {
- if(!this.state.isServerReady){
+ if(!isServerReady){
const ready = await authenticationService.getServerReadyState();
if(ready){
- this.setState({isServerReady: true});
+ setIsServerReady(true);
}else{
- this.setState({message: "Login is currently not possible. Please re-try in a few minutes. If the problem persits, ask your administrator for assistence."});
+ setMessage("Login is currently not possible. Please re-try in a few minutes. If the problem persists, ask your administrator for assistance.");
}
}else{
- this.setState({
- message: "Could not log in. Please check your credentials or ask your administrator for assistence.",
- password: ""
- })
+ setMessage("Could not log in. Please check your credentials or ask your administrator for assistance.");
+ setPassword("");
}
}
}
+
+ const classes = styles();
+ const areProvidersAvailable = externalLoginProviders && externalLoginProviders.length > 0;
+
+ return (
+ <>
+ <CssBaseline />
+ <main className={classes.layout}>
+ <Paper className={classes.paper}>
+ <Avatar className={classes.avatar}>
+ <img src={loginIcon} alt="loginIcon" />
+ </Avatar>
+ <Typography variant="caption">Sign in</Typography>
+ <form className={classes.form}>
+ {areProvidersAvailable &&
+ <>
+ {
+ externalLoginProviders!.map((provider, index) => (
+ <Button
+ aria-controls="externalLogin"
+ aria-label={"external-login-identity-provider-" + (index + 1)}
+ aria-haspopup="true"
+ fullWidth
+ variant="contained"
+ color="inherit"
+ className={classes.submit} onClick={() => { window.location = provider.loginUrl as any; }}>
+ {provider.title}
+ </Button>))
+ }
+ <div className={classes.lineContainer}>
+ <span className={classes.thirdPartyDivider}>
+ OR
+ </span>
+ </div>
+ </>
+ }
+ <FormControl variant="standard" margin="normal" required fullWidth>
+ <InputLabel htmlFor="username">Username</InputLabel>
+ <Input id="username" name="username" autoComplete="username" autoFocus
+ disabled={isBusy}
+ value={username}
+ onChange={event => { setUsername(event.target.value); }} />
+ </FormControl>
+ <FormControl variant="standard" margin="normal" required fullWidth>
+ <InputLabel htmlFor="password">Password</InputLabel>
+ <Input
+ name="password"
+ type="password"
+ id="password"
+ autoComplete="current-password"
+ disabled={isBusy}
+ value={password}
+ onChange={event => { setPassword(event.target.value); }}
+ />
+ </FormControl>
+ <FormControl variant="standard" margin="normal" required fullWidth>
+ <InputLabel htmlFor="password">Domain</InputLabel>
+ <Input
+ name="scope"
+ type="scope"
+ id="scope"
+ disabled={isBusy}
+ value={scope}
+ onChange={event => { setScope(event.target.value); }}
+ />
+ </FormControl>
+ <Button
+ aria-label="login-button"
+ type="submit"
+ fullWidth
+ variant="contained"
+ color="inherit"
+ disabled={isBusy}
+ className={classes.submit}
+ onClick={onSignIn}
+ >
+ Sign in
+ </Button>
+
+ </form>
+ {message && <Alert severity="error">{message}</Alert>}
+ </Paper>
+ </main>
+ </>
+ );
}
-export const Login = withStyles(styles)(withRouter(connect(mapProps, mapDispatch)(LoginComponent)));
+export const Login = withRouter(LoginComponent);
export default Login;
\ No newline at end of file
* ============LICENSE_END==========================================================================
*/
-import * as React from 'react';
-import { IApplicationStoreState } from "../store/applicationStore";
-import connect, { Connect, IDispatcher } from "../flux/connect";
+import React, {FC, useState } from 'react';
+import { useApplicationDispatch } from "../flux/connect";
-import applicationService from '../services/applicationManager';
-import { makeStyles } from '@mui/styles';
import { Divider, List, ListItem, ListItemText, Paper } from '@mui/material';
+import { makeStyles } from '@mui/styles';
+import applicationService from '../services/applicationManager';
-import { GeneralUserSettings } from '../components/settings/general'
import { GoBackAction } from '../actions/navigationActions';
+import { GeneralUserSettings } from '../components/settings/general';
import { toAriaLabel } from '../utilities/yangHelper';
-type props = Connect<typeof mapProps, typeof mapDispatch>;
-
-type SettingsEntry = { name: string, element: JSX.Element }
-
-
-const mapProps = (state: IApplicationStoreState) => ({
-
-});
-
-const mapDispatch = (dispatcher: IDispatcher) => ({
- goBack: () => dispatcher.dispatch(new GoBackAction())
-});
+type SettingsEntry = { name: string, element: JSX.Element };
const styles = makeStyles({
sectionMargin: {
marginBottom: "15px"
},
elementMargin: {
-
marginLeft: "10px"
},
menu: {
}
});
-const UserSettings: React.FunctionComponent<props> = (props) => {
+const UserSettings: FC = (props) => {
- const classes = styles();
- const registrations = applicationService.applications;
+ const dispatch = useApplicationDispatch();
+ const goBack = () => dispatch(new GoBackAction());
+
+ const [selectedIndex, setSelectedIndex] = useState(0);
- const [selectedIndex, setSelectedIndex] = React.useState(0);
+ const registrations = applicationService.applications;
const navigateBack = () => {
- props.goBack();
+ goBack();
}
let settingsArray: SettingsEntry[] = [];
//add all framework specific settings
settingsArray.push({name:"General", element: <GeneralUserSettings onClose={navigateBack} />})
-
//get app settings
let settingsElements : (SettingsEntry) [] = Object.keys(registrations).map(p => {
const application = registrations[p];
setSelectedIndex(newValue);
}
+ const classes = styles();
+
return <div style={{ display: "flex", flexDirection: "row", height: "100%" }}>
<div style={{ display: "flex", flexDirection: "column", height: "100%", width: "15%" }}>
<Paper variant="outlined" style={{ height: "70%" }}>
settingsArray.map((el, index) => {
return (
<>
- <ListItem selected={selectedIndex === index} button onClick={e => { onSelectElement(e, index) }} aria-label={toAriaLabel(el?.name+"-settings")}>
+ <ListItem key={"settings-key-"+index} selected={selectedIndex === index} button onClick={e => { onSelectElement(e, index) }} aria-label={toAriaLabel(el?.name+"-settings")}>
<ListItemText primary={el?.name} style={{ padding: 0 }} />
</ListItem>
<Divider />
}
</List>
</Paper>
-
</div>
<div style={{ height: "100%", width: "80%", marginLeft: 15 }}>
<div style={{ height: "100%" }}>
}
-export default connect(mapProps, mapDispatch)(UserSettings);
+export default UserSettings;
\ No newline at end of file
"faultApp":"##odlux.apps.faultApp.buildno##",
"helpApp":"##odlux.apps.helpApp.buildno##",
"inventoryApp":"##odlux.apps.inventoryApp.buildno##",
+ "linkCalculationApp":"##odlux.apps.linkCalculationApp.buildno##",
"maintenanceApp":"##odlux.apps.maintenanceApp.buildno##",
"mediatorApp":"##odlux.apps.mediatorApp.buildno##",
+ "networkMapApp":"##odlux.apps.networkMapApp.buildno##",
"permanceHistoryApp":"##odlux.apps.permanceHistoryApp.buildno##"
}
~ ============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">
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
-odlux.framework.buildno=166.7b222ec(22/08/26)
-odlux.apps.configurationApp.buildno=165.93e23ca(22/08/12)
-odlux.apps.connectApp.buildno=166.7b222ec(22/08/26)
-odlux.apps.eventLogApp.buildno=142.63ceae1(22/01/31)
-odlux.apps.faultApp.buildno=158.f3ad6e0(22/07/18)
-odlux.apps.helpApp.buildno=166.7b222ec(22/08/26)
-odlux.apps.inventoryApp.buildno=161.f556fbb(22/07/29)
-odlux.apps.maintenanceApp.buildno=142.63ceae1(22/01/31)
-odlux.apps.mediatorApp.buildno=158.f3ad6e0(22/07/18)
+odlux.framework.buildno=172.52348b7c(23/02/16)
+odlux.apps.configurationApp.buildno=172.52348b7c(23/02/16)
+odlux.apps.connectApp.buildno=172.52348b7c(23/02/16)
+odlux.apps.eventLogApp.buildno=172.52348b7c(23/02/16)
+odlux.apps.faultApp.buildno=177.3f75df5a(23/03/06)
+odlux.apps.helpApp.buildno=172.52348b7c(23/02/16)
+odlux.apps.inventoryApp.buildno=178.3bd8a2a9(23/03/16)
+odlux.apps.maintenanceApp.buildno=172.52348b7c(23/02/16)
+odlux.apps.mediatorApp.buildno=172.52348b7c(23/02/16)
odlux.apps.permanceHistoryApp.buildno=81.1c38886(20/12/04)
"react": "17.0.2",
"react-dom": "17.0.2",
"react-router-dom": "5.2.0",
+ "react-split-pane": "0.1.92",
"react-transition-group": "4.3.0"
},
"devDependencies": {
"@babel/preset-react": "7.0.0",
"@octokit/core": "3.0.0",
"@types/jest": "23.3.12",
+ "@typescript-eslint/eslint-plugin": "5.42.0",
+ "@typescript-eslint/parser": "5.42.0",
"autoprefixer": "9.1.5",
"babel-loader": "8.0.4",
"copy-webpack-plugin": "4.5.2",
"css-loader": "1.0.0",
+ "eslint": "8.26.0",
+ "eslint-config-airbnb": "19.0.4",
+ "eslint-config-airbnb-typescript": "17.0.0",
+ "eslint-plugin-import": "2.26.0",
+ "eslint-plugin-jsx-a11y": "6.6.1",
+ "eslint-plugin-react": "7.31.10",
+ "eslint-plugin-react-hooks": "4.6.0",
"extract-text-webpack-plugin": "next",
"file-loader": "2.0.0",
"glob-to-regexp": "0.4.1",
"html-webpack-include-assets-plugin": "1.0.5",
"html-webpack-plugin": "3.2.0",
"jest": "23.6.0",
- "less": "3.8.1",
- "less-loader": "4.1.0",
- "node-sass": "4.12.0",
"postcss-loader": "3.0.0",
"requirejs": "2.3.6",
"requirejs-webpack-plugin": "1.0.5",
"rimraf": "2.6.2",
- "sass-loader": "7.1.0",
"style-loader": "0.23.0",
"terser-webpack-plugin": "1.2.1",
"ts-jest": "23.10.5",
~ ============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>
--- /dev/null
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2021 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==========================================================================
+ */
+
+module.exports = {
+ "/about": {
+ target: "http://sdncweb:8080",
+ secure: false
+ },
+ "/yang-schema/": {
+ target: "http://sdncweb:8080",
+ secure: false
+ },
+ "/oauth/": {
+ target: "http://sdncweb:8080",
+ secure: false
+ },
+ "/database/": {
+ target: "http://sdncweb:8080",
+ secure: false
+ },
+ "/restconf/": {
+ target: "http://sdncweb:8080",
+ secure: false
+ },
+ "/rests/": {
+ target: "http://sdncweb:8080",
+ secure: false
+ },
+ "/userdata": {
+ target: "http://sdncweb:8080",
+ secure: false
+ },
+ "/userdata/": {
+ target: "http://sdncweb:8080",
+ secure: false
+ },
+ "/help/": {
+ target: "http://sdncweb:8080",
+ secure: false
+ },
+ "/about/": {
+ target: "http://sdncweb:8080",
+ secure: false
+ },
+ "/tree/": {
+ target: "http://sdncweb:8080",
+ secure: false
+ },
+ "/sitedoc/": {
+ target: "http://sdncweb:8080",
+ secure: false
+ },
+ "/topology/": {
+ target: "http://sdncweb:8080",
+ secure: false
+ },
+
+ "/websocket": {
+ target: "http://sdncweb:8080",
+ ws: true,
+ changeOrigin: true,
+ secure: false
+ },
+ "/apidoc": {
+ target: "http://sdncweb:8080",
+ ws: true,
+ changeOrigin: true,
+ secure: false
+ },
+ "/tiles/": {
+ target: "http://sdncweb:8080",
+ headers: {
+ "Connection": "keep-alive"
+ },
+ secure: false
+ },
+ "/swagger/": {
+ target: "http://swagger.t1.lab.osn-lab.com",
+ secure: false,
+ pathRewrite(pathname) {
+ return pathname.replace(/^\/swagger/, '/');
+ }
+ },
+ "/electromagnetic-field/": {
+ target: "http://sdncweb:8080",
+ ws: true,
+ changeOrigin: true,
+ secure: false
+ },
+}
+
"@babel/plugin-transform-react-jsx-self" "^7.0.0"
"@babel/plugin-transform-react-jsx-source" "^7.0.0"
+"@babel/runtime-corejs3@^7.10.2":
+ version "7.21.0"
+ resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.21.0.tgz#6e4939d9d9789ff63e2dc58e88f13a3913a24eba"
+ integrity sha512-TDD4UJzos3JJtM+tHX+w2Uc+KWj7GV+VKKFdMVd2Rx8sdA19hcc3P3AHFYd5LVOw+pYuSd5lICC3gm52B6Rwxw==
+ dependencies:
+ core-js-pure "^3.25.1"
+ regenerator-runtime "^0.13.11"
+
"@babel/runtime@^7.1.2", "@babel/runtime@^7.12.1", "@babel/runtime@^7.13.10", "@babel/runtime@^7.16.3", "@babel/runtime@^7.7.2":
version "7.16.3"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.16.3.tgz#b86f0db02a04187a3c17caa77de69840165d42d5"
dependencies:
regenerator-runtime "^0.13.4"
+"@babel/runtime@^7.10.2", "@babel/runtime@^7.18.9":
+ version "7.21.0"
+ resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.21.0.tgz#5b55c9d394e5fcf304909a8b00c07dc217b56673"
+ integrity sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==
+ dependencies:
+ regenerator-runtime "^0.13.11"
+
"@babel/runtime@^7.19.0":
version "7.20.1"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.20.1.tgz#1148bb33ab252b165a06698fde7576092a78b4a9"
resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.3.0.tgz#ea89004119dc42db2e1dba0f97d553f7372f6fcb"
integrity sha512-AHPmaAx+RYfZz0eYu6Gviiagpmiyw98ySSlQvCUhVGDRtDFe4DBS0x1bSjdF3gqUDYOczB+yYvBTtEylYSdRhg==
+"@eslint/eslintrc@^1.3.3":
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.4.1.tgz#af58772019a2d271b7e2d4c23ff4ddcba3ccfb3e"
+ integrity sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA==
+ dependencies:
+ ajv "^6.12.4"
+ debug "^4.3.2"
+ espree "^9.4.0"
+ globals "^13.19.0"
+ ignore "^5.2.0"
+ import-fresh "^3.2.1"
+ js-yaml "^4.1.0"
+ minimatch "^3.1.2"
+ strip-json-comments "^3.1.1"
+
"@evocateur/libnpmaccess@^3.1.2":
version "3.1.2"
resolved "https://registry.yarnpkg.com/@evocateur/libnpmaccess/-/libnpmaccess-3.1.2.tgz#ecf7f6ce6b004e9f942b098d92200be4a4b1c845"
dependencies:
prop-types "^15.7.2"
+"@humanwhocodes/config-array@^0.11.6":
+ version "0.11.8"
+ resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.8.tgz#03595ac2075a4dc0f191cc2131de14fbd7d410b9"
+ integrity sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==
+ dependencies:
+ "@humanwhocodes/object-schema" "^1.2.1"
+ debug "^4.1.1"
+ minimatch "^3.0.5"
+
+"@humanwhocodes/module-importer@^1.0.1":
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c"
+ integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==
+
+"@humanwhocodes/object-schema@^1.2.1":
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45"
+ integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==
+
"@lerna/add@3.21.0":
version "3.21.0"
resolved "https://registry.yarnpkg.com/@lerna/add/-/add-3.21.0.tgz#27007bde71cc7b0a2969ab3c2f0ae41578b4577b"
prop-types "^15.7.2"
react-is "^17.0.2"
+"@nodelib/fs.scandir@2.1.5":
+ version "2.1.5"
+ resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5"
+ integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==
+ dependencies:
+ "@nodelib/fs.stat" "2.0.5"
+ run-parallel "^1.1.9"
+
+"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2":
+ version "2.0.5"
+ resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b"
+ integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==
+
"@nodelib/fs.stat@^1.1.2":
version "1.1.3"
resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b"
integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==
+"@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8":
+ version "1.2.8"
+ resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a"
+ integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==
+ dependencies:
+ "@nodelib/fs.scandir" "2.1.5"
+ fastq "^1.6.0"
+
"@octokit/auth-token@^2.4.0":
version "2.4.5"
resolved "https://registry.yarnpkg.com/@octokit/auth-token/-/auth-token-2.4.5.tgz#568ccfb8cb46f36441fac094ce34f7a875b197f3"
resolved "https://registry.yarnpkg.com/@types/jquery/-/jquery-3.3.10.tgz#d0afaec7ee55f591992e74c607df5dc7cd9c76ab"
integrity sha512-W2bE8pGh9Tsg8mxh+B6BSH8lTG6ZV7K2ZMAlEwSTqKFU1wMI5HShyRKSp3DngnxCmDu35tW3RAC4mxBFYRsTuw==
+"@types/json-schema@^7.0.9":
+ version "7.0.11"
+ resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3"
+ integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==
+
+"@types/json5@^0.0.29":
+ version "0.0.29"
+ resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee"
+ integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==
+
"@types/jsonwebtoken@7.2.8":
version "7.2.8"
resolved "https://registry.yarnpkg.com/@types/jsonwebtoken/-/jsonwebtoken-7.2.8.tgz#8d199dab4ddb5bba3234f8311b804d2027af2b3a"
resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39"
integrity sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==
+"@types/semver@^7.3.12":
+ version "7.3.13"
+ resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.13.tgz#da4bfd73f49bd541d28920ab0e2bf0ee80f71c91"
+ integrity sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==
+
"@types/x2js@^3.1.0":
version "3.1.0"
resolved "https://registry.yarnpkg.com/@types/x2js/-/x2js-3.1.0.tgz#d809ef1ace1a8b55b3e8cb6a1a0b282af66475be"
dependencies:
x2js "*"
+"@typescript-eslint/eslint-plugin@5.42.0":
+ version "5.42.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.42.0.tgz#36a8c0c379870127059889a9cc7e05c260d2aaa5"
+ integrity sha512-5TJh2AgL6+wpL8H/GTSjNb4WrjKoR2rqvFxR/DDTqYNk6uXn8BJMEcncLSpMbf/XV1aS0jAjYwn98uvVCiAywQ==
+ dependencies:
+ "@typescript-eslint/scope-manager" "5.42.0"
+ "@typescript-eslint/type-utils" "5.42.0"
+ "@typescript-eslint/utils" "5.42.0"
+ debug "^4.3.4"
+ ignore "^5.2.0"
+ natural-compare-lite "^1.4.0"
+ regexpp "^3.2.0"
+ semver "^7.3.7"
+ tsutils "^3.21.0"
+
+"@typescript-eslint/parser@5.42.0":
+ version "5.42.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.42.0.tgz#be0ffbe279e1320e3d15e2ef0ad19262f59e9240"
+ integrity sha512-Ixh9qrOTDRctFg3yIwrLkgf33AHyEIn6lhyf5cCfwwiGtkWhNpVKlEZApi3inGQR/barWnY7qY8FbGKBO7p3JA==
+ dependencies:
+ "@typescript-eslint/scope-manager" "5.42.0"
+ "@typescript-eslint/types" "5.42.0"
+ "@typescript-eslint/typescript-estree" "5.42.0"
+ debug "^4.3.4"
+
+"@typescript-eslint/scope-manager@5.42.0":
+ version "5.42.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.42.0.tgz#e1f2bb26d3b2a508421ee2e3ceea5396b192f5ef"
+ integrity sha512-l5/3IBHLH0Bv04y+H+zlcLiEMEMjWGaCX6WyHE5Uk2YkSGAMlgdUPsT/ywTSKgu9D1dmmKMYgYZijObfA39Wow==
+ dependencies:
+ "@typescript-eslint/types" "5.42.0"
+ "@typescript-eslint/visitor-keys" "5.42.0"
+
+"@typescript-eslint/type-utils@5.42.0":
+ version "5.42.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.42.0.tgz#4206d7192d4fe903ddf99d09b41d4ac31b0b7dca"
+ integrity sha512-HW14TXC45dFVZxnVW8rnUGnvYyRC0E/vxXShFCthcC9VhVTmjqOmtqj6H5rm9Zxv+ORxKA/1aLGD7vmlLsdlOg==
+ dependencies:
+ "@typescript-eslint/typescript-estree" "5.42.0"
+ "@typescript-eslint/utils" "5.42.0"
+ debug "^4.3.4"
+ tsutils "^3.21.0"
+
+"@typescript-eslint/types@5.42.0":
+ version "5.42.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.42.0.tgz#5aeff9b5eced48f27d5b8139339bf1ef805bad7a"
+ integrity sha512-t4lzO9ZOAUcHY6bXQYRuu+3SSYdD9TS8ooApZft4WARt4/f2Cj/YpvbTe8A4GuhT4bNW72goDMOy7SW71mZwGw==
+
+"@typescript-eslint/typescript-estree@5.42.0":
+ version "5.42.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.42.0.tgz#2592d24bb5f89bf54a63384ff3494870f95b3fd8"
+ integrity sha512-2O3vSq794x3kZGtV7i4SCWZWCwjEtkWfVqX4m5fbUBomOsEOyd6OAD1qU2lbvV5S8tgy/luJnOYluNyYVeOTTg==
+ dependencies:
+ "@typescript-eslint/types" "5.42.0"
+ "@typescript-eslint/visitor-keys" "5.42.0"
+ debug "^4.3.4"
+ globby "^11.1.0"
+ is-glob "^4.0.3"
+ semver "^7.3.7"
+ tsutils "^3.21.0"
+
+"@typescript-eslint/utils@5.42.0":
+ version "5.42.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.42.0.tgz#f06bd43b9a9a06ed8f29600273240e84a53f2f15"
+ integrity sha512-JZ++3+h1vbeG1NUECXQZE3hg0kias9kOtcQr3+JVQ3whnjvKuMyktJAAIj6743OeNPnGBmjj7KEmiDL7qsdnCQ==
+ dependencies:
+ "@types/json-schema" "^7.0.9"
+ "@types/semver" "^7.3.12"
+ "@typescript-eslint/scope-manager" "5.42.0"
+ "@typescript-eslint/types" "5.42.0"
+ "@typescript-eslint/typescript-estree" "5.42.0"
+ eslint-scope "^5.1.1"
+ eslint-utils "^3.0.0"
+ semver "^7.3.7"
+
+"@typescript-eslint/visitor-keys@5.42.0":
+ version "5.42.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.42.0.tgz#ee8d62d486f41cfe646632fab790fbf0c1db5bb0"
+ integrity sha512-QHbu5Hf/2lOEOwy+IUw0GoSCuAzByTAWWrOTKzTzsotiUnWFpuKnXcAhC9YztAf2EElQ0VvIK+pHJUPkM0q7jg==
+ dependencies:
+ "@typescript-eslint/types" "5.42.0"
+ eslint-visitor-keys "^3.3.0"
+
"@webassemblyjs/ast@1.7.11":
version "1.7.11"
resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.7.11.tgz#b988582cafbb2b095e8b556526f30c90d057cace"
acorn "^6.0.1"
acorn-walk "^6.0.1"
+acorn-jsx@^5.3.2:
+ version "5.3.2"
+ resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937"
+ integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==
+
acorn-walk@^6.0.1:
version "6.2.0"
resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-6.2.0.tgz#123cb8f3b84c2171f1f7fb252615b1c78a6b1a8c"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.2.tgz#35866fd710528e92de10cf06016498e47e39e1e6"
integrity sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==
+acorn@^8.8.0:
+ version "8.8.2"
+ resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.2.tgz#1b2f25db02af965399b9776b0c2c391276d37c4a"
+ integrity sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==
+
agent-base@4, agent-base@^4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee"
resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d"
integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==
-ajv@^6.1.0, ajv@^6.12.3:
+ajv@^6.1.0, ajv@^6.10.0, ajv@^6.12.3, ajv@^6.12.4:
version "6.12.6"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4"
integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==
json-schema-traverse "^0.4.1"
uri-js "^4.2.2"
-amdefine@>=0.0.4:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5"
- integrity sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg==
-
ansi-colors@^3.0.0:
version "3.2.4"
resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.4.tgz#e3a3da4bfbae6c86a9c285625de124a234026fbf"
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997"
integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==
+ansi-regex@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304"
+ integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==
+
ansi-styles@^2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
dependencies:
color-convert "^1.9.0"
+ansi-styles@^4.1.0:
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937"
+ integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==
+ dependencies:
+ color-convert "^2.0.1"
+
any-promise@^1.0.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f"
dependencies:
sprintf-js "~1.0.2"
+argparse@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38"
+ integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==
+
+aria-query@^4.2.2:
+ version "4.2.2"
+ resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-4.2.2.tgz#0d2ca6c9aceb56b8977e9fed6aed7e15bbd2f83b"
+ integrity sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA==
+ dependencies:
+ "@babel/runtime" "^7.10.2"
+ "@babel/runtime-corejs3" "^7.10.2"
+
arr-diff@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf"
resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4"
integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=
+array-buffer-byte-length@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz#fabe8bc193fea865f317fe7807085ee0dee5aead"
+ integrity sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==
+ dependencies:
+ call-bind "^1.0.2"
+ is-array-buffer "^3.0.1"
+
array-differ@^2.0.3:
version "2.1.0"
resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-2.1.0.tgz#4b9c1c3f14b906757082925769e8ab904f4801b1"
resolved "https://registry.yarnpkg.com/array-ify/-/array-ify-1.0.0.tgz#9e528762b4a9066ad163a6962a364418e9626ece"
integrity sha1-nlKHYrSpBmrRY6aWKjZEGOlibs4=
+array-includes@^3.1.4, array-includes@^3.1.5:
+ version "3.1.6"
+ resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.6.tgz#9e9e720e194f198266ba9e18c29e6a9b0e4b225f"
+ integrity sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.1.4"
+ es-abstract "^1.20.4"
+ get-intrinsic "^1.1.3"
+ is-string "^1.0.7"
+
array-union@^1.0.1, array-union@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39"
dependencies:
array-uniq "^1.0.1"
+array-union@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d"
+ integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==
+
array-uniq@^1.0.1:
version "1.0.3"
resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6"
resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428"
integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=
+array.prototype.flat@^1.2.5:
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz#ffc6576a7ca3efc2f46a143b9d1dda9b4b3cf5e2"
+ integrity sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.1.4"
+ es-abstract "^1.20.4"
+ es-shim-unscopables "^1.0.0"
+
+array.prototype.flatmap@^1.3.0:
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz#1aae7903c2100433cb8261cd4ed310aab5c4a183"
+ integrity sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.1.4"
+ es-abstract "^1.20.4"
+ es-shim-unscopables "^1.0.0"
+
arrify@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d"
integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=
-asap@^2.0.0, asap@~2.0.3:
+asap@^2.0.0:
version "2.0.6"
resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46"
integrity sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==
resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367"
integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=
+ast-types-flow@^0.0.7:
+ version "0.0.7"
+ resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad"
+ integrity sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==
+
astral-regex@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9"
resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf"
integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==
-async-foreach@^0.1.3:
- version "0.1.3"
- resolved "https://registry.yarnpkg.com/async-foreach/-/async-foreach-0.1.3.tgz#36121f845c0578172de419a97dbeb1d16ec34542"
- integrity sha512-VUeSMD8nEGBWaZK4lizI1sf3yEC7pnAQ/mrI7pC2fBz2s/tq5jWWEngTwaf0Gruu/OoXRGLGg1XFqpYBiGTYJA==
-
async-limiter@~1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd"
postcss "^7.0.2"
postcss-value-parser "^3.2.3"
+available-typed-arrays@^1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7"
+ integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==
+
aws-sign2@~0.7.0:
version "0.7.0"
resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8"
resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59"
integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==
+axe-core@^4.4.3:
+ version "4.6.3"
+ resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.6.3.tgz#fc0db6fdb65cc7a80ccf85286d91d64ababa3ece"
+ integrity sha512-/BQzOX780JhsxDnPpH4ZiyrJAzcd8AfzFPkv+89veFSr1rcMjuq2JDCwypKaPeB6ljHp9KjXhPpjgCvQlWYuqg==
+
+axobject-query@^2.2.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-2.2.0.tgz#943d47e10c0b704aa42275e20edf3722648989be"
+ integrity sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA==
+
babel-code-frame@^6.22.0, babel-code-frame@^6.26.0:
version "6.26.0"
resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b"
dependencies:
file-uri-to-path "1.0.0"
-block-stream@*:
- version "0.0.9"
- resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a"
- integrity sha512-OorbnJVPII4DuUKbjARAe8u8EfqOmkEEaSFIyoQ7OjTHn6kafxWl0wLgoZ2rXaYd7MyLcDaU4TmhfxtwgcccMQ==
- dependencies:
- inherits "~2.0.0"
-
bluebird@^3.5.1, bluebird@^3.5.3, bluebird@^3.5.5:
version "3.7.2"
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f"
split-string "^3.0.2"
to-regex "^3.0.1"
-braces@~3.0.2:
+braces@^3.0.2, braces@~3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f"
integrity sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=
-camelcase@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a"
- integrity sha512-4nhGqUkc4BqbBBB4Q6zLuD7lzzrHYrjKGeYaEji/3tFR5VdJu9v+LilhGIVe8wxEJPPOeWo7eg8dwY13TZ1BNg==
-
camelcase@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd"
resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=
-chalk@^1.1.1, chalk@^1.1.3:
+chalk@^1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=
escape-string-regexp "^1.0.5"
supports-color "^5.3.0"
+chalk@^4.0.0:
+ version "4.1.2"
+ resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
+ integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
+ dependencies:
+ ansi-styles "^4.1.0"
+ supports-color "^7.1.0"
+
chardet@^0.7.0:
version "0.7.0"
resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e"
resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.1.tgz#b0433d0b4e9c847ef18868a4ef16fd5fc8271c48"
integrity sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==
-cliui@^3.2.0:
- version "3.2.0"
- resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d"
- integrity sha512-0yayqDxWQbqk3ojkYqUKqaAQ6AfNKeKWRNA8kR0WXzAsdHpP4BIaOmMAG87JGuO6qcobyW4GjxHd9PmhEd+T9w==
- dependencies:
- string-width "^1.0.1"
- strip-ansi "^3.0.1"
- wrap-ansi "^2.0.0"
-
cliui@^4.0.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/cliui/-/cliui-4.1.0.tgz#348422dbe82d800b3022eef4f6ac10bf2e4d1b49"
strip-ansi "^5.2.0"
wrap-ansi "^5.1.0"
-clone-deep@^2.0.1:
- version "2.0.2"
- resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-2.0.2.tgz#00db3a1e173656730d1188c3d6aced6d7ea97713"
- integrity sha512-SZegPTKjCgpQH63E+eN6mVEEPdQBOUzjyJm5Pora4lrwWRFS8I0QAxV/KD6vV/i0WuijHZWQC1fMsPEdxfdVCQ==
- dependencies:
- for-own "^1.0.0"
- is-plain-object "^2.0.4"
- kind-of "^6.0.0"
- shallow-clone "^1.0.0"
-
clone-deep@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387"
resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e"
integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4=
-clone@^2.1.1, clone@^2.1.2:
- version "2.1.2"
- resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f"
- integrity sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==
-
clsx@^1.1.0, clsx@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.1.1.tgz#98b3134f9abbdf23b2663491ace13c5c03a73188"
dependencies:
color-name "1.1.3"
+color-convert@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3"
+ integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==
+ dependencies:
+ color-name "~1.1.4"
+
color-name@1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=
-color-name@^1.0.0:
+color-name@^1.0.0, color-name@~1.1.4:
version "1.1.4"
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
ini "^1.3.4"
proto-list "~1.2.1"
+confusing-browser-globals@^1.0.10:
+ version "1.0.11"
+ resolved "https://registry.yarnpkg.com/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz#ae40e9b57cdd3915408a2805ebd3a5585608dc81"
+ integrity sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==
+
connect-history-api-fallback@^1.3.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz#8b32089359308d111115d81cad3fceab888f97bc"
p-limit "^1.0.0"
serialize-javascript "^1.4.0"
+core-js-pure@^3.25.1:
+ version "3.29.1"
+ resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.29.1.tgz#1be6ca2b8772f6b4df7fc4621743286e676c6162"
+ integrity sha512-4En6zYVi0i0XlXHVz/bi6l1XDjCqkKRq765NXuX+SnaIatlE96Odt5lMLjdxUiNI1v9OXI5DSLWYPlmTfkTktg==
+
core-js@^2.4.0, core-js@^2.5.0, core-js@^2.5.7, core-js@^2.6.5:
version "2.6.12"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec"
safe-buffer "^5.0.1"
sha.js "^2.4.8"
-cross-spawn@^3.0.0:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-3.0.1.tgz#1256037ecb9f0c5f79e3d6ef135e30770184b982"
- integrity sha512-eZ+m1WNhSZutOa/uRblAc9Ut5MQfukFrFMtPSm3bZCA888NmMd5AWXWdgRZ80zd+pTk1P2JrGjg9pUPTvl2PWQ==
- dependencies:
- lru-cache "^4.0.1"
- which "^1.2.9"
-
cross-spawn@^6.0.0, cross-spawn@^6.0.5:
version "6.0.5"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
shebang-command "^1.2.0"
which "^1.2.9"
+cross-spawn@^7.0.2:
+ version "7.0.3"
+ resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
+ integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==
+ dependencies:
+ path-key "^3.1.0"
+ shebang-command "^2.0.0"
+ which "^2.0.1"
+
crypto-browserify@^3.11.0:
version "3.12.0"
resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec"
resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9"
integrity sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=
+damerau-levenshtein@^1.0.8:
+ version "1.0.8"
+ resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz#b43d286ccbd36bc5b2f7ed41caf2d0aba1f8a6e7"
+ integrity sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==
+
dargs@^4.0.1:
version "4.1.0"
resolved "https://registry.yarnpkg.com/dargs/-/dargs-4.1.0.tgz#03a9dbb4b5c2f139bf14ae53f0b8a2a6a86f4e17"
dependencies:
ms "2.0.0"
-debug@^3.1.0, debug@^3.1.1, debug@^3.2.5:
+debug@^3.1.0, debug@^3.1.1, debug@^3.2.5, debug@^3.2.7:
version "3.2.7"
resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a"
integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==
dependencies:
ms "2.1.2"
+debug@^4.1.1, debug@^4.3.2, debug@^4.3.4:
+ version "4.3.4"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
+ integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
+ dependencies:
+ ms "2.1.2"
+
debuglog@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492"
object-keys "^1.1.1"
regexp.prototype.flags "^1.2.0"
+deep-is@^0.1.3:
+ version "0.1.4"
+ resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831"
+ integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==
+
deep-is@~0.1.3:
version "0.1.3"
resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
dependencies:
object-keys "^1.0.12"
+define-properties@^1.1.4:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.0.tgz#52988570670c9eacedd8064f4a990f2405849bd5"
+ integrity sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==
+ dependencies:
+ has-property-descriptors "^1.0.0"
+ object-keys "^1.1.1"
+
define-property@^0.2.5:
version "0.2.5"
resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116"
dependencies:
path-type "^3.0.0"
+dir-glob@^3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f"
+ integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==
+ dependencies:
+ path-type "^4.0.0"
+
dns-equal@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/dns-equal/-/dns-equal-1.0.0.tgz#b39e7f1da6eb0a75ba9c17324b34753c47e0654d"
esutils "^1.1.6"
isarray "0.0.1"
+doctrine@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d"
+ integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==
+ dependencies:
+ esutils "^2.0.2"
+
+doctrine@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961"
+ integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==
+ dependencies:
+ esutils "^2.0.2"
+
dom-converter@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/dom-converter/-/dom-converter-0.2.0.tgz#6721a9daee2e293682955b6afe416771627bb768"
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156"
integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==
+emoji-regex@^9.2.2:
+ version "9.2.2"
+ resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72"
+ integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==
+
emojis-list@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389"
resolved "https://registry.yarnpkg.com/err-code/-/err-code-1.1.2.tgz#06e0116d3028f6aef4806849eb0ea6a748ae6960"
integrity sha1-BuARbTAo9q70gGhJ6w6mp0iuaWA=
-errno@^0.1.1, errno@^0.1.3, errno@~0.1.7:
+errno@^0.1.3, errno@~0.1.7:
version "0.1.8"
resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.8.tgz#8bb3e9c7d463be4976ff888f76b4809ebc2e811f"
integrity sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==
string.prototype.trimstart "^1.0.4"
unbox-primitive "^1.0.1"
+es-abstract@^1.19.0, es-abstract@^1.20.4:
+ version "1.21.2"
+ resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.21.2.tgz#a56b9695322c8a185dc25975aa3b8ec31d0e7eff"
+ integrity sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==
+ dependencies:
+ array-buffer-byte-length "^1.0.0"
+ available-typed-arrays "^1.0.5"
+ call-bind "^1.0.2"
+ es-set-tostringtag "^2.0.1"
+ es-to-primitive "^1.2.1"
+ function.prototype.name "^1.1.5"
+ get-intrinsic "^1.2.0"
+ get-symbol-description "^1.0.0"
+ globalthis "^1.0.3"
+ gopd "^1.0.1"
+ has "^1.0.3"
+ has-property-descriptors "^1.0.0"
+ has-proto "^1.0.1"
+ has-symbols "^1.0.3"
+ internal-slot "^1.0.5"
+ is-array-buffer "^3.0.2"
+ is-callable "^1.2.7"
+ is-negative-zero "^2.0.2"
+ is-regex "^1.1.4"
+ is-shared-array-buffer "^1.0.2"
+ is-string "^1.0.7"
+ is-typed-array "^1.1.10"
+ is-weakref "^1.0.2"
+ object-inspect "^1.12.3"
+ object-keys "^1.1.1"
+ object.assign "^4.1.4"
+ regexp.prototype.flags "^1.4.3"
+ safe-regex-test "^1.0.0"
+ string.prototype.trim "^1.2.7"
+ string.prototype.trimend "^1.0.6"
+ string.prototype.trimstart "^1.0.6"
+ typed-array-length "^1.0.4"
+ unbox-primitive "^1.0.2"
+ which-typed-array "^1.1.9"
+
+es-set-tostringtag@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz#338d502f6f674301d710b80c8592de8a15f09cd8"
+ integrity sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==
+ dependencies:
+ get-intrinsic "^1.1.3"
+ has "^1.0.3"
+ has-tostringtag "^1.0.0"
+
+es-shim-unscopables@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz#702e632193201e3edf8713635d083d378e510241"
+ integrity sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==
+ dependencies:
+ has "^1.0.3"
+
es-to-primitive@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a"
optionalDependencies:
source-map "~0.6.1"
+eslint-config-airbnb-base@^15.0.0:
+ version "15.0.0"
+ resolved "https://registry.yarnpkg.com/eslint-config-airbnb-base/-/eslint-config-airbnb-base-15.0.0.tgz#6b09add90ac79c2f8d723a2580e07f3925afd236"
+ integrity sha512-xaX3z4ZZIcFLvh2oUNvcX5oEofXda7giYmuplVxoOg5A7EXJMrUyqRgR+mhDhPK8LZ4PttFOBvCYDbX3sUoUig==
+ dependencies:
+ confusing-browser-globals "^1.0.10"
+ object.assign "^4.1.2"
+ object.entries "^1.1.5"
+ semver "^6.3.0"
+
+eslint-config-airbnb-typescript@17.0.0:
+ version "17.0.0"
+ resolved "https://registry.yarnpkg.com/eslint-config-airbnb-typescript/-/eslint-config-airbnb-typescript-17.0.0.tgz#360dbcf810b26bbcf2ff716198465775f1c49a07"
+ integrity sha512-elNiuzD0kPAPTXjFWg+lE24nMdHMtuxgYoD30OyMD6yrW1AhFZPAg27VX7d3tzOErw+dgJTNWfRSDqEcXb4V0g==
+ dependencies:
+ eslint-config-airbnb-base "^15.0.0"
+
+eslint-config-airbnb@19.0.4:
+ version "19.0.4"
+ resolved "https://registry.yarnpkg.com/eslint-config-airbnb/-/eslint-config-airbnb-19.0.4.tgz#84d4c3490ad70a0ffa571138ebcdea6ab085fdc3"
+ integrity sha512-T75QYQVQX57jiNgpF9r1KegMICE94VYwoFQyMGhrvc+lB8YF2E/M/PYDaQe1AJcWaEgqLE+ErXV1Og/+6Vyzew==
+ dependencies:
+ eslint-config-airbnb-base "^15.0.0"
+ object.assign "^4.1.2"
+ object.entries "^1.1.5"
+
+eslint-import-resolver-node@^0.3.6:
+ version "0.3.7"
+ resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.7.tgz#83b375187d412324a1963d84fa664377a23eb4d7"
+ integrity sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA==
+ dependencies:
+ debug "^3.2.7"
+ is-core-module "^2.11.0"
+ resolve "^1.22.1"
+
+eslint-module-utils@^2.7.3:
+ version "2.7.4"
+ resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.7.4.tgz#4f3e41116aaf13a20792261e61d3a2e7e0583974"
+ integrity sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==
+ dependencies:
+ debug "^3.2.7"
+
+eslint-plugin-import@2.26.0:
+ version "2.26.0"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.26.0.tgz#f812dc47be4f2b72b478a021605a59fc6fe8b88b"
+ integrity sha512-hYfi3FXaM8WPLf4S1cikh/r4IxnO6zrhZbEGz2b660EJRbuxgpDS5gkCuYgGWg2xxh2rBuIr4Pvhve/7c31koA==
+ dependencies:
+ array-includes "^3.1.4"
+ array.prototype.flat "^1.2.5"
+ debug "^2.6.9"
+ doctrine "^2.1.0"
+ eslint-import-resolver-node "^0.3.6"
+ eslint-module-utils "^2.7.3"
+ has "^1.0.3"
+ is-core-module "^2.8.1"
+ is-glob "^4.0.3"
+ minimatch "^3.1.2"
+ object.values "^1.1.5"
+ resolve "^1.22.0"
+ tsconfig-paths "^3.14.1"
+
+eslint-plugin-jsx-a11y@6.6.1:
+ version "6.6.1"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.6.1.tgz#93736fc91b83fdc38cc8d115deedfc3091aef1ff"
+ integrity sha512-sXgFVNHiWffBq23uiS/JaP6eVR622DqwB4yTzKvGZGcPq6/yZ3WmOZfuBks/vHWo9GaFOqC2ZK4i6+C35knx7Q==
+ dependencies:
+ "@babel/runtime" "^7.18.9"
+ aria-query "^4.2.2"
+ array-includes "^3.1.5"
+ ast-types-flow "^0.0.7"
+ axe-core "^4.4.3"
+ axobject-query "^2.2.0"
+ damerau-levenshtein "^1.0.8"
+ emoji-regex "^9.2.2"
+ has "^1.0.3"
+ jsx-ast-utils "^3.3.2"
+ language-tags "^1.0.5"
+ minimatch "^3.1.2"
+ semver "^6.3.0"
+
+eslint-plugin-react-hooks@4.6.0:
+ version "4.6.0"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz#4c3e697ad95b77e93f8646aaa1630c1ba607edd3"
+ integrity sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==
+
+eslint-plugin-react@7.31.10:
+ version "7.31.10"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.31.10.tgz#6782c2c7fe91c09e715d536067644bbb9491419a"
+ integrity sha512-e4N/nc6AAlg4UKW/mXeYWd3R++qUano5/o+t+wnWxIf+bLsOaH3a4q74kX3nDjYym3VBN4HyO9nEn1GcAqgQOA==
+ dependencies:
+ array-includes "^3.1.5"
+ array.prototype.flatmap "^1.3.0"
+ doctrine "^2.1.0"
+ estraverse "^5.3.0"
+ jsx-ast-utils "^2.4.1 || ^3.0.0"
+ minimatch "^3.1.2"
+ object.entries "^1.1.5"
+ object.fromentries "^2.0.5"
+ object.hasown "^1.1.1"
+ object.values "^1.1.5"
+ prop-types "^15.8.1"
+ resolve "^2.0.0-next.3"
+ semver "^6.3.0"
+ string.prototype.matchall "^4.0.7"
+
eslint-scope@^4.0.0:
version "4.0.3"
resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848"
esrecurse "^4.1.0"
estraverse "^4.1.1"
+eslint-scope@^5.1.1:
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c"
+ integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==
+ dependencies:
+ esrecurse "^4.3.0"
+ estraverse "^4.1.1"
+
+eslint-scope@^7.1.1:
+ version "7.1.1"
+ resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.1.1.tgz#fff34894c2f65e5226d3041ac480b4513a163642"
+ integrity sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==
+ dependencies:
+ esrecurse "^4.3.0"
+ estraverse "^5.2.0"
+
+eslint-utils@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-3.0.0.tgz#8aebaface7345bb33559db0a1f13a1d2d48c3672"
+ integrity sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==
+ dependencies:
+ eslint-visitor-keys "^2.0.0"
+
+eslint-visitor-keys@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303"
+ integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==
+
+eslint-visitor-keys@^3.3.0:
+ version "3.3.0"
+ resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826"
+ integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==
+
+eslint@8.26.0:
+ version "8.26.0"
+ resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.26.0.tgz#2bcc8836e6c424c4ac26a5674a70d44d84f2181d"
+ integrity sha512-kzJkpaw1Bfwheq4VXUezFriD1GxszX6dUekM7Z3aC2o4hju+tsR/XyTC3RcoSD7jmy9VkPU3+N6YjVU2e96Oyg==
+ dependencies:
+ "@eslint/eslintrc" "^1.3.3"
+ "@humanwhocodes/config-array" "^0.11.6"
+ "@humanwhocodes/module-importer" "^1.0.1"
+ "@nodelib/fs.walk" "^1.2.8"
+ ajv "^6.10.0"
+ chalk "^4.0.0"
+ cross-spawn "^7.0.2"
+ debug "^4.3.2"
+ doctrine "^3.0.0"
+ escape-string-regexp "^4.0.0"
+ eslint-scope "^7.1.1"
+ eslint-utils "^3.0.0"
+ eslint-visitor-keys "^3.3.0"
+ espree "^9.4.0"
+ esquery "^1.4.0"
+ esutils "^2.0.2"
+ fast-deep-equal "^3.1.3"
+ file-entry-cache "^6.0.1"
+ find-up "^5.0.0"
+ glob-parent "^6.0.2"
+ globals "^13.15.0"
+ grapheme-splitter "^1.0.4"
+ ignore "^5.2.0"
+ import-fresh "^3.0.0"
+ imurmurhash "^0.1.4"
+ is-glob "^4.0.0"
+ is-path-inside "^3.0.3"
+ js-sdsl "^4.1.4"
+ js-yaml "^4.1.0"
+ json-stable-stringify-without-jsonify "^1.0.1"
+ levn "^0.4.1"
+ lodash.merge "^4.6.2"
+ minimatch "^3.1.2"
+ natural-compare "^1.4.0"
+ optionator "^0.9.1"
+ regexpp "^3.2.0"
+ strip-ansi "^6.0.1"
+ strip-json-comments "^3.1.0"
+ text-table "^0.2.0"
+
+espree@^9.4.0:
+ version "9.5.0"
+ resolved "https://registry.yarnpkg.com/espree/-/espree-9.5.0.tgz#3646d4e3f58907464edba852fa047e6a27bdf113"
+ integrity sha512-JPbJGhKc47++oo4JkEoTe2wjy4fmMwvFpgJT9cQzmfXKp22Dr6Hf1tdCteLz1h0P3t+mGvWZ+4Uankvh8+c6zw==
+ dependencies:
+ acorn "^8.8.0"
+ acorn-jsx "^5.3.2"
+ eslint-visitor-keys "^3.3.0"
+
esprima@^4.0.0, esprima@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71"
integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==
-esrecurse@^4.1.0:
+esquery@^1.4.0:
+ version "1.5.0"
+ resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b"
+ integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==
+ dependencies:
+ estraverse "^5.1.0"
+
+esrecurse@^4.1.0, esrecurse@^4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921"
integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==
resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d"
integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==
+estraverse@^5.1.0, estraverse@^5.3.0:
+ version "5.3.0"
+ resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123"
+ integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==
+
estraverse@^5.2.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.2.0.tgz#307df42547e6cc7324d3cf03c155d5cdb8c53880"
resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f"
integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8=
-fast-deep-equal@^3.1.1:
+fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3:
version "3.1.3"
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
merge2 "^1.2.3"
micromatch "^3.1.10"
+fast-glob@^3.2.9:
+ version "3.2.12"
+ resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80"
+ integrity sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==
+ dependencies:
+ "@nodelib/fs.stat" "^2.0.2"
+ "@nodelib/fs.walk" "^1.2.3"
+ glob-parent "^5.1.2"
+ merge2 "^1.3.0"
+ micromatch "^4.0.4"
+
fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633"
integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==
-fast-levenshtein@~2.0.6:
+fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6:
version "2.0.6"
resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
- integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=
+ integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==
fastparse@^1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/fastparse/-/fastparse-1.1.2.tgz#91728c5a5942eced8531283c79441ee4122c35a9"
integrity sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==
+fastq@^1.6.0:
+ version "1.15.0"
+ resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.15.0.tgz#d04d07c6a2a68fe4599fea8d2e103a937fae6b3a"
+ integrity sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==
+ dependencies:
+ reusify "^1.0.4"
+
faye-websocket@^0.10.0:
version "0.10.0"
resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.10.0.tgz#4e492f8d04dfb6f89003507f6edbf2d501e7c6f4"
dependencies:
escape-string-regexp "^1.0.5"
+file-entry-cache@^6.0.1:
+ version "6.0.1"
+ resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027"
+ integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==
+ dependencies:
+ flat-cache "^3.0.4"
+
file-loader@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-2.0.0.tgz#39749c82f020b9e85901dcff98e8004e6401cfde"
locate-path "^5.0.0"
path-exists "^4.0.0"
+find-up@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc"
+ integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==
+ dependencies:
+ locate-path "^6.0.0"
+ path-exists "^4.0.0"
+
findup-sync@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-2.0.0.tgz#9326b1488c22d1a6088650a86901b2d9a90a2cbc"
micromatch "^3.0.4"
resolve-dir "^1.0.1"
+flat-cache@^3.0.4:
+ version "3.0.4"
+ resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11"
+ integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==
+ dependencies:
+ flatted "^3.1.0"
+ rimraf "^3.0.2"
+
+flatted@^3.1.0:
+ version "3.2.7"
+ resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.7.tgz#609f39207cb614b89d0765b477cb2d437fbf9787"
+ integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==
+
flush-write-stream@^1.0.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.1.1.tgz#8dd7d873a1babc207d94ead0c2e0e44276ebf2e8"
dependencies:
is-callable "^1.1.3"
-for-in@^0.1.3:
- version "0.1.8"
- resolved "https://registry.yarnpkg.com/for-in/-/for-in-0.1.8.tgz#d8773908e31256109952b1fdb9b3fa867d2775e1"
- integrity sha512-F0to7vbBSHP8E3l6dCjxNOLuSFAACIxFy3UehTUlG7svlXi37HHsDkyVcHo0Pq8QwrE+pXvWSVX3ZT1T9wAZ9g==
-
for-in@^1.0.1, for-in@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80"
dependencies:
for-in "^1.0.1"
-for-own@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/for-own/-/for-own-1.0.0.tgz#c63332f415cedc4b04dbfe70cf836494c53cb44b"
- integrity sha512-0OABksIGrxKK8K4kynWkQ7y1zounQxP+CWnyclVwj81KW3vlLlGUx57DKGcP/LH216GzqnstnPocF16Nxs0Ycg==
- dependencies:
- for-in "^1.0.1"
-
forever-agent@~0.6.1:
version "0.6.1"
resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
-fstream@^1.0.0, fstream@^1.0.12:
- version "1.0.12"
- resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.12.tgz#4e8ba8ee2d48be4f7d0de505455548eae5932045"
- integrity sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==
- dependencies:
- graceful-fs "^4.1.2"
- inherits "~2.0.0"
- mkdirp ">=0.5 0"
- rimraf "2"
-
function-bind@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
+function.prototype.name@^1.1.5:
+ version "1.1.5"
+ resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.5.tgz#cce0505fe1ffb80503e6f9e46cc64e46a12a9621"
+ integrity sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.1.3"
+ es-abstract "^1.19.0"
+ functions-have-names "^1.2.2"
+
+functions-have-names@^1.2.2:
+ version "1.2.3"
+ resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834"
+ integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==
+
gauge@~2.7.3:
version "2.7.4"
resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7"
strip-ansi "^3.0.1"
wide-align "^1.1.0"
-gaze@^1.0.0:
- version "1.1.3"
- resolved "https://registry.yarnpkg.com/gaze/-/gaze-1.1.3.tgz#c441733e13b927ac8c0ff0b4c3b033f28812924a"
- integrity sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==
- dependencies:
- globule "^1.0.0"
-
genfun@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/genfun/-/genfun-5.0.0.tgz#9dd9710a06900a5c4a5bf57aca5da4e52fe76537"
has "^1.0.3"
has-symbols "^1.0.1"
+get-intrinsic@^1.1.3, get-intrinsic@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.0.tgz#7ad1dc0535f3a2904bba075772763e5051f6d05f"
+ integrity sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==
+ dependencies:
+ function-bind "^1.1.1"
+ has "^1.0.3"
+ has-symbols "^1.0.3"
+
get-pkg-repo@^1.0.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/get-pkg-repo/-/get-pkg-repo-1.4.0.tgz#c73b489c06d80cc5536c2c853f9e05232056972d"
dependencies:
pump "^3.0.0"
+get-symbol-description@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6"
+ integrity sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==
+ dependencies:
+ call-bind "^1.0.2"
+ get-intrinsic "^1.1.1"
+
get-value@^2.0.3, get-value@^2.0.6:
version "2.0.6"
resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28"
is-glob "^3.1.0"
path-dirname "^1.0.0"
-glob-parent@^5.0.0, glob-parent@~5.1.2:
+glob-parent@^5.0.0, glob-parent@^5.1.2, glob-parent@~5.1.2:
version "5.1.2"
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
dependencies:
is-glob "^4.0.1"
+glob-parent@^6.0.2:
+ version "6.0.2"
+ resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3"
+ integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==
+ dependencies:
+ is-glob "^4.0.3"
+
glob-to-regexp@0.4.1:
version "0.4.1"
resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e"
resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab"
integrity sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs=
-glob@^7.0.0:
- version "7.2.3"
- resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b"
- integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==
- dependencies:
- fs.realpath "^1.0.0"
- inflight "^1.0.4"
- inherits "2"
- minimatch "^3.1.1"
- once "^1.3.0"
- path-is-absolute "^1.0.0"
-
-glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@~7.1.1:
+glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4:
version "7.1.7"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90"
integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==
resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e"
integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==
+globals@^13.15.0, globals@^13.19.0:
+ version "13.20.0"
+ resolved "https://registry.yarnpkg.com/globals/-/globals-13.20.0.tgz#ea276a1e508ffd4f1612888f9d1bad1e2717bf82"
+ integrity sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==
+ dependencies:
+ type-fest "^0.20.2"
+
globals@^9.18.0:
version "9.18.0"
resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a"
integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==
+globalthis@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.3.tgz#5852882a52b80dc301b0660273e1ed082f0b6ccf"
+ integrity sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==
+ dependencies:
+ define-properties "^1.1.3"
+
+globby@^11.1.0:
+ version "11.1.0"
+ resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b"
+ integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==
+ dependencies:
+ array-union "^2.1.0"
+ dir-glob "^3.0.1"
+ fast-glob "^3.2.9"
+ ignore "^5.2.0"
+ merge2 "^1.4.1"
+ slash "^3.0.0"
+
globby@^6.1.0:
version "6.1.0"
resolved "https://registry.yarnpkg.com/globby/-/globby-6.1.0.tgz#f5a6d70e8395e21c858fb0489d64df02424d506c"
pify "^4.0.1"
slash "^2.0.0"
-globule@^1.0.0:
- version "1.3.4"
- resolved "https://registry.yarnpkg.com/globule/-/globule-1.3.4.tgz#7c11c43056055a75a6e68294453c17f2796170fb"
- integrity sha512-OPTIfhMBh7JbBYDpa5b+Q5ptmMWKwcNcFSR/0c6t8V4f3ZAVBEsKNY37QdVqmLRYSMhOUGYrY0QhSoEpzGr/Eg==
+gopd@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c"
+ integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==
dependencies:
- glob "~7.1.1"
- lodash "^4.17.21"
- minimatch "~3.0.2"
+ get-intrinsic "^1.1.3"
graceful-fs@4.1.4:
version "4.1.4"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.6.tgz#ff040b2b0853b23c3d31027523706f1885d76bee"
integrity sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==
+grapheme-splitter@^1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz#9cf3a665c6247479896834af35cf1dbb4400767e"
+ integrity sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==
+
growly@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081"
resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.1.tgz#64fe6acb020673e3b78db035a5af69aa9d07b113"
integrity sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==
+has-bigints@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa"
+ integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==
+
has-flag@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa"
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0=
-has-symbols@^1.0.1, has-symbols@^1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.2.tgz#165d3070c00309752a1236a479331e3ac56f1423"
+has-flag@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
+ integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
+
+has-property-descriptors@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz#610708600606d36961ed04c196193b6a607fa861"
+ integrity sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==
+ dependencies:
+ get-intrinsic "^1.1.1"
+
+has-proto@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0"
+ integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==
+
+has-symbols@^1.0.1, has-symbols@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.2.tgz#165d3070c00309752a1236a479331e3ac56f1423"
integrity sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==
+has-symbols@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8"
+ integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==
+
+has-tostringtag@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25"
+ integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==
+ dependencies:
+ has-symbols "^1.0.2"
+
has-unicode@^2.0.0, has-unicode@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9"
resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc"
integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==
-image-size@~0.5.0:
- version "0.5.5"
- resolved "https://registry.yarnpkg.com/image-size/-/image-size-0.5.5.tgz#09dfd4ab9d20e29eb1c3e80b8990378df9e3cb9c"
- integrity sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==
+ignore@^5.2.0:
+ version "5.2.4"
+ resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324"
+ integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==
import-cwd@^2.0.0:
version "2.1.0"
caller-path "^2.0.0"
resolve-from "^3.0.0"
-import-fresh@^3.1.0:
+import-fresh@^3.0.0, import-fresh@^3.1.0, import-fresh@^3.2.1:
version "3.3.0"
resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b"
integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==
resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
integrity sha1-khi5srkoojixPcT7a21XbyMUU+o=
-in-publish@^2.0.0:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/in-publish/-/in-publish-2.0.1.tgz#948b1a535c8030561cea522f73f78f4be357e00c"
- integrity sha512-oDM0kUSNFC31ShNxHKUyfZKy8ZeXZBWMjMdZHKLOk13uvT27VTL/QzRGfRUcevJhpkZAvlhPYuXkF7eNWrtyxQ==
-
indent-string@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-2.1.0.tgz#8e2d48348742121b4a8218b7a137e9a52049dc80"
once "^1.3.0"
wrappy "1"
-inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3:
+inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3:
version "2.0.4"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
default-gateway "^2.6.0"
ipaddr.js "^1.5.2"
+internal-slot@^1.0.3, internal-slot@^1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.5.tgz#f2a2ee21f668f8627a4667f309dc0f4fb6674986"
+ integrity sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==
+ dependencies:
+ get-intrinsic "^1.2.0"
+ has "^1.0.3"
+ side-channel "^1.0.4"
+
interpret@^1.1.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e"
resolved "https://registry.yarnpkg.com/inversify/-/inversify-5.1.1.tgz#6fbd668c591337404e005a1946bfe0d802c08730"
integrity sha512-j8grHGDzv1v+8T1sAQ+3boTCntFPfvxLCkNcxB1J8qA0lUN+fAlSyYd+RXKvaPRL4AGyPxViutBEJHNXOyUdFQ==
-invert-kv@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6"
- integrity sha512-xgs2NH9AE66ucSq4cNG1nhSFghr5l6tdL15Pk+jl46bmmBapgoaY/AacXyaDznAqmGL99TiLSQgO/XazFSKYeQ==
-
invert-kv@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-2.0.0.tgz#7393f5afa59ec9ff5f67a27620d11c226e3eec02"
dependencies:
call-bind "^1.0.0"
+is-array-buffer@^3.0.1, is-array-buffer@^3.0.2:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.2.tgz#f2653ced8412081638ecb0ebbd0c41c6e0aecbbe"
+ integrity sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==
+ dependencies:
+ call-bind "^1.0.2"
+ get-intrinsic "^1.2.0"
+ is-typed-array "^1.1.10"
+
is-arrayish@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.3.tgz#8b1e0500b73a1d76c70487636f368e519de8db8e"
integrity sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==
+is-callable@^1.2.7:
+ version "1.2.7"
+ resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055"
+ integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==
+
is-ci@^1.0.10:
version "1.2.1"
resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-1.2.1.tgz#e3779c8ee17fccf428488f6e281187f2e632841c"
dependencies:
ci-info "^2.0.0"
+is-core-module@^2.11.0, is-core-module@^2.8.1, is-core-module@^2.9.0:
+ version "2.11.0"
+ resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.11.0.tgz#ad4cb3e3863e814523c96f3f58d26cc570ff0144"
+ integrity sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==
+ dependencies:
+ has "^1.0.3"
+
is-core-module@^2.2.0:
version "2.4.0"
resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.4.0.tgz#8e9fc8e15027b011418026e98f0e6f4d86305cc1"
dependencies:
is-extglob "^2.1.1"
+is-glob@^4.0.3:
+ version "4.0.3"
+ resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084"
+ integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==
+ dependencies:
+ is-extglob "^2.1.1"
+
is-in-browser@^1.0.2, is-in-browser@^1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/is-in-browser/-/is-in-browser-1.1.3.tgz#56ff4db683a078c6082eb95dad7dc62e1d04f835"
resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.1.tgz#3de746c18dda2319241a53675908d8f766f11c24"
integrity sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==
+is-negative-zero@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150"
+ integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==
+
is-number-object@^1.0.4:
version "1.0.5"
resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.5.tgz#6edfaeed7950cff19afedce9fbfca9ee6dd289eb"
dependencies:
path-is-inside "^1.0.1"
+is-path-inside@^3.0.3:
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283"
+ integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==
+
is-plain-obj@^1.0.0, is-plain-obj@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e"
call-bind "^1.0.2"
has-symbols "^1.0.2"
+is-regex@^1.1.4:
+ version "1.1.4"
+ resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958"
+ integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==
+ dependencies:
+ call-bind "^1.0.2"
+ has-tostringtag "^1.0.0"
+
+is-shared-array-buffer@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz#8f259c573b60b6a32d4058a1a07430c0a7344c79"
+ integrity sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==
+ dependencies:
+ call-bind "^1.0.2"
+
is-ssh@^1.3.0:
version "1.3.3"
resolved "https://registry.yarnpkg.com/is-ssh/-/is-ssh-1.3.3.tgz#7f133285ccd7f2c2c7fc897b771b53d95a2b2c7e"
resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.6.tgz#3fe5d5992fb0d93404f32584d4b0179a71b54a5f"
integrity sha512-2gdzbKUuqtQ3lYNrUTQYoClPhm7oQu4UdpSZMp1/DGgkHBT8E2Z1l0yMdb6D4zNAxwDiMv8MdulKROJGNl0Q0w==
+is-string@^1.0.7:
+ version "1.0.7"
+ resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd"
+ integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==
+ dependencies:
+ has-tostringtag "^1.0.0"
+
is-symbol@^1.0.2, is-symbol@^1.0.3:
version "1.0.4"
resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c"
dependencies:
text-extensions "^1.0.0"
+is-typed-array@^1.1.10, is-typed-array@^1.1.9:
+ version "1.1.10"
+ resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.10.tgz#36a5b5cb4189b575d1a3e4b08536bfb485801e3f"
+ integrity sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==
+ dependencies:
+ available-typed-arrays "^1.0.5"
+ call-bind "^1.0.2"
+ for-each "^0.3.3"
+ gopd "^1.0.1"
+ has-tostringtag "^1.0.0"
+
is-typedarray@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72"
integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=
+is-weakref@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2"
+ integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==
+ dependencies:
+ call-bind "^1.0.2"
+
is-windows@^1.0.0, is-windows@^1.0.1, is-windows@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d"
resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.3.1.tgz#958ce29e81c9790f31be7792df5d4d95fc57fbca"
integrity sha512-Ubldcmxp5np52/ENotGxlLe6aGMvmF4R8S6tZjsP6Knsaxd/xp3Zrh50cG93lR6nPXyUFwzN3ZSOQI0wRJNdGg==
-js-base64@^2.1.8:
- version "2.6.4"
- resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.6.4.tgz#f4e686c5de1ea1f867dbcad3d46d969428df98c4"
- integrity sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==
-
js-levenshtein@^1.1.3:
version "1.1.6"
resolved "https://registry.yarnpkg.com/js-levenshtein/-/js-levenshtein-1.1.6.tgz#c6cee58eb3550372df8deb85fad5ce66ce01d59d"
integrity sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==
+js-sdsl@^4.1.4:
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/js-sdsl/-/js-sdsl-4.3.0.tgz#aeefe32a451f7af88425b11fdb5f58c90ae1d711"
+ integrity sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==
+
"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
argparse "^1.0.7"
esprima "^4.0.0"
+js-yaml@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602"
+ integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==
+ dependencies:
+ argparse "^2.0.1"
+
jsbn@~0.1.0:
version "0.1.1"
resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13"
integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=
+json-stable-stringify-without-jsonify@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651"
+ integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==
+
json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
dependencies:
minimist "^1.2.0"
+json5@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593"
+ integrity sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==
+ dependencies:
+ minimist "^1.2.0"
+
jsonfile@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb"
is-in-browser "^1.1.3"
tiny-warning "^1.0.2"
+"jsx-ast-utils@^2.4.1 || ^3.0.0", jsx-ast-utils@^3.3.2:
+ version "3.3.3"
+ resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.3.3.tgz#76b3e6e6cece5c69d49a5792c3d01bd1a0cdc7ea"
+ integrity sha512-fYQHZTZ8jSfmWZ0iyzfwiU4WDX4HpHbMCZ3gPlWYiCl3BoeOTsqKBqnTVfH2rYT7eP5c3sVbeSPHnnJOaTrWiw==
+ dependencies:
+ array-includes "^3.1.5"
+ object.assign "^4.1.3"
+
jwa@^1.4.1:
version "1.4.1"
resolved "https://registry.yarnpkg.com/jwa/-/jwa-1.4.1.tgz#743c32985cb9e98655530d53641b66c8645b039a"
resolved "https://registry.yarnpkg.com/kleur/-/kleur-2.0.2.tgz#b704f4944d95e255d038f0cb05fb8a602c55a300"
integrity sha512-77XF9iTllATmG9lSlIv0qdQ2BQ/h9t0bJllHlbvsQ0zUWfU7Yi0S8L5JXzPZgkefIiajLmBJJ4BsMJmqcf7oxQ==
-lcid@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835"
- integrity sha512-YiGkH6EnGrDGqLMITnGjXtGmNtjoXw9SVUzcaos8RBi7Ps0VBylkq+vOcY9QE5poLasPCR849ucFUkl0UzUyOw==
+language-subtag-registry@^0.3.20:
+ version "0.3.22"
+ resolved "https://registry.yarnpkg.com/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz#2e1500861b2e457eba7e7ae86877cbd08fa1fd1d"
+ integrity sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==
+
+language-tags@^1.0.5:
+ version "1.0.8"
+ resolved "https://registry.yarnpkg.com/language-tags/-/language-tags-1.0.8.tgz#042b4bdb0d4e771a9f8cc2fdc9bb26a52a367312"
+ integrity sha512-aWAZwgPLS8hJ20lNPm9HNVs4inexz6S2sQa3wx/+ycuutMNE5/IfYxiWYBbi+9UWCQVaXYCOPUl6gFrPR7+jGg==
dependencies:
- invert-kv "^1.0.0"
+ language-subtag-registry "^0.3.20"
lcid@^2.0.0:
version "2.0.0"
import-local "^2.0.0"
npmlog "^4.1.2"
-less-loader@4.1.0:
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/less-loader/-/less-loader-4.1.0.tgz#2c1352c5b09a4f84101490274fd51674de41363e"
- integrity sha512-KNTsgCE9tMOM70+ddxp9yyt9iHqgmSs0yTZc5XH5Wo+g80RWRIYNqE58QJKm/yMud5wZEvz50ugRDuzVIkyahg==
- dependencies:
- clone "^2.1.1"
- loader-utils "^1.1.0"
- pify "^3.0.0"
-
-less@3.8.1:
- version "3.8.1"
- resolved "https://registry.yarnpkg.com/less/-/less-3.8.1.tgz#f31758598ef5a1930dd4caefa9e4340641e71e1d"
- integrity sha512-8HFGuWmL3FhQR0aH89escFNBQH/nEiYPP2ltDFdQw2chE28Yx2E3lhAIq9Y2saYwLSwa699s4dBVEfCY8Drf7Q==
- dependencies:
- clone "^2.1.2"
- optionalDependencies:
- errno "^0.1.1"
- graceful-fs "^4.1.2"
- image-size "~0.5.0"
- mime "^1.4.1"
- mkdirp "^0.5.0"
- promise "^7.1.1"
- request "^2.83.0"
- source-map "~0.6.0"
-
leven@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/leven/-/leven-2.1.0.tgz#c2e7a9f772094dee9d34202ae8acce4687875580"
integrity sha1-wuep93IJTe6dNCAq6KzORoeHVYA=
+levn@^0.4.1:
+ version "0.4.1"
+ resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade"
+ integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==
+ dependencies:
+ prelude-ls "^1.2.1"
+ type-check "~0.4.0"
+
levn@~0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee"
json5 "^0.5.0"
object-assign "^4.0.1"
-loader-utils@^1.0.1:
- version "1.4.2"
- resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.2.tgz#29a957f3a63973883eb684f10ffd3d151fec01a3"
- integrity sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==
- dependencies:
- big.js "^5.2.2"
- emojis-list "^3.0.0"
- json5 "^1.0.1"
-
loader-utils@^1.0.2, loader-utils@^1.1.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613"
dependencies:
p-locate "^4.1.0"
+locate-path@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286"
+ integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==
+ dependencies:
+ p-locate "^5.0.0"
+
lodash._reinterpolate@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d"
resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451"
integrity sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=
+lodash.merge@^4.6.2:
+ version "4.6.2"
+ resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
+ integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==
+
lodash.once@^4.0.0:
version "4.1.1"
resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac"
resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438"
integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=
-lodash.tail@^4.1.1:
- version "4.1.1"
- resolved "https://registry.yarnpkg.com/lodash.tail/-/lodash.tail-4.1.1.tgz#d2333a36d9e7717c8ad2f7cacafec7c32b444664"
- integrity sha512-+7y6zfkH4TqgS5DYKIqJuxmL5xT3WUUumVMZVRpDUo0UqJREwZqKmGo9wluj12FbPGl1UjRf2TnAImbw/bKtdw==
-
lodash.template@^4.0.2, lodash.template@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-4.5.0.tgz#f976195cf3f347d0d5f52483569fe8031ccce8ab"
resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=
-lodash@^4.0.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.3, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.1:
+lodash@^4.17.10, lodash@^4.17.12, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.3, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.1:
version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-1.1.4.tgz#9a2cabd1b9e8e0ae993a4bf7d5875c39c42e8eac"
integrity sha1-miyr0bno4K6ZOkv31YdcOcQujqw=
-lru-cache@^4.0.1, lru-cache@^4.1.1:
+lru-cache@^4.1.1:
version "4.1.5"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd"
integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==
errno "^0.1.3"
readable-stream "^2.0.1"
-meow@^3.3.0, meow@^3.7.0:
+meow@^3.3.0:
version "3.7.0"
resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb"
integrity sha512-TNdwZs0skRlpPpCUK25StC4VH+tP5GgeY1HQOOGP+lQ2xtdkN2VtT/5tiX9k3IWpkBPV9b3LsAWXn4GGi/PrSA==
dependencies:
readable-stream "^2.0.1"
-merge2@^1.2.3:
+merge2@^1.2.3, merge2@^1.3.0, merge2@^1.4.1:
version "1.4.1"
resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae"
integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==
snapdragon "^0.8.1"
to-regex "^3.0.2"
+micromatch@^4.0.4:
+ version "4.0.5"
+ resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6"
+ integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==
+ dependencies:
+ braces "^3.0.2"
+ picomatch "^2.3.1"
+
miller-rabin@^4.0.0:
version "4.0.1"
resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d"
dependencies:
mime-db "1.48.0"
-mime@1.6.0, mime@^1.4.1, mime@^1.6.0:
+mime@1.6.0, mime@^1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==
dependencies:
brace-expansion "^1.1.7"
-minimatch@^3.1.1:
+minimatch@^3.0.5, minimatch@^3.1.2:
version "3.1.2"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
dependencies:
brace-expansion "^1.1.7"
-minimatch@~3.0.2:
- version "3.0.8"
- resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.8.tgz#5e6a59bd11e2ab0de1cfb843eb2d82e546c321c1"
- integrity sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==
- dependencies:
- brace-expansion "^1.1.7"
-
minimist-options@4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-4.1.0.tgz#c0655713c53a8a2ebd77ffa247d342c40f010619"
for-in "^1.0.2"
is-extendable "^1.0.1"
-mixin-object@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/mixin-object/-/mixin-object-2.0.1.tgz#4fb949441dab182540f1fe035ba60e1947a5e57e"
- integrity sha512-ALGF1Jt9ouehcaXaHhn6t1yGWRqGaHkPFndtFVHfZXOvkIZ/yoGaSi0AHVTafb3ZBGg4dr/bDwnaEKqCXzchMA==
- dependencies:
- for-in "^0.1.3"
- is-extendable "^0.1.1"
-
mkdirp-promise@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/mkdirp-promise/-/mkdirp-promise-5.0.1.tgz#e9b8f68e552c68a9c1713b84883f7a1dd039b8a1"
dependencies:
minimist "^1.2.5"
-"mkdirp@>=0.5 0":
- version "0.5.6"
- resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6"
- integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==
- dependencies:
- minimist "^1.2.6"
-
modify-values@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/modify-values/-/modify-values-1.0.1.tgz#b3939fa605546474e3e3e3c63d64bd43b4ee6022"
resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.2.tgz#f5376400695168f4cc694ac9393d0c9585eeea19"
integrity sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==
-nan@^2.13.2:
- version "2.17.0"
- resolved "https://registry.yarnpkg.com/nan/-/nan-2.17.0.tgz#c0150a2368a182f033e9aa5195ec76ea41a199cb"
- integrity sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==
-
nanomatch@^1.2.9:
version "1.2.13"
resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119"
snapdragon "^0.8.1"
to-regex "^3.0.1"
+natural-compare-lite@^1.4.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz#17b09581988979fddafe0201e931ba933c96cbb4"
+ integrity sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==
+
natural-compare@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.10.0.tgz#32dea2afb3e9926f02ee5ce8794902691a676bf3"
integrity sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==
-node-gyp@^3.8.0:
- version "3.8.0"
- resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-3.8.0.tgz#540304261c330e80d0d5edce253a68cb3964218c"
- integrity sha512-3g8lYefrRRzvGeSowdJKAKyks8oUpLEd/DyPV4eMhVlhJ0aNaZqIrNUIPuEWWTAoPqyFkfGrM67MC69baqn6vA==
- dependencies:
- fstream "^1.0.0"
- glob "^7.0.3"
- graceful-fs "^4.1.2"
- mkdirp "^0.5.0"
- nopt "2 || 3"
- npmlog "0 || 1 || 2 || 3 || 4"
- osenv "0"
- request "^2.87.0"
- rimraf "2"
- semver "~5.3.0"
- tar "^2.0.0"
- which "1"
-
node-gyp@^5.0.2:
version "5.1.1"
resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-5.1.1.tgz#eb915f7b631c937d282e33aed44cb7a025f62a3e"
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.73.tgz#dd4e81ddd5277ff846b80b52bb40c49edf7a7b20"
integrity sha512-uW7fodD6pyW2FZNZnp/Z3hvWKeEW1Y8R1+1CnErE8cXFXzl5blBOoVB41CvMer6P6Q0S5FXDwcHgFd1Wj0U9zg==
-node-sass@4.12.0:
- version "4.12.0"
- resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.12.0.tgz#0914f531932380114a30cc5fa4fa63233a25f017"
- integrity sha512-A1Iv4oN+Iel6EPv77/HddXErL2a+gZ4uBeZUy+a8O35CFYTXhgA8MgLCWBtwpGZdCvTvQ9d+bQxX/QC36GDPpQ==
- dependencies:
- async-foreach "^0.1.3"
- chalk "^1.1.1"
- cross-spawn "^3.0.0"
- gaze "^1.0.0"
- get-stdin "^4.0.1"
- glob "^7.0.3"
- in-publish "^2.0.0"
- lodash "^4.17.11"
- meow "^3.7.0"
- mkdirp "^0.5.1"
- nan "^2.13.2"
- node-gyp "^3.8.0"
- npmlog "^4.0.0"
- request "^2.88.0"
- sass-graph "^2.2.4"
- stdout-stream "^1.4.0"
- "true-case-path" "^1.0.2"
-
-"nopt@2 || 3":
- version "3.0.6"
- resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9"
- integrity sha512-4GUt3kSEYmk4ITxzB/b9vaIDfUVWN/Ml1Fwl11IlnIG2iaJ9O6WXZ9SrYM9NLI8OCBieN2Y8SWC2oJV0RQ7qYg==
- dependencies:
- abbrev "1"
-
nopt@^4.0.1:
version "4.0.3"
resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.3.tgz#a375cad9d02fd921278d954c2254d5aa57e15e48"
dependencies:
path-key "^2.0.0"
-"npmlog@0 || 1 || 2 || 3 || 4", npmlog@^4.0.0, npmlog@^4.1.2:
+npmlog@^4.1.2:
version "4.1.2"
resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b"
integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.10.3.tgz#c2aa7d2d09f50c99375704f7a0adf24c5782d369"
integrity sha512-e5mCJlSH7poANfC8z8S9s9S2IN5/4Zb3aZ33f5s8YqoazCFzNLloLU8r5VCG+G7WoqLvAAZoVMcy3tp/3X0Plw==
+object-inspect@^1.12.3:
+ version "1.12.3"
+ resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.3.tgz#ba62dffd67ee256c8c086dfae69e016cd1f198b9"
+ integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==
+
object-is@^1.0.1:
version "1.1.5"
resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac"
has-symbols "^1.0.1"
object-keys "^1.1.1"
+object.assign@^4.1.3, object.assign@^4.1.4:
+ version "4.1.4"
+ resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.4.tgz#9673c7c7c351ab8c4d0b516f4343ebf4dfb7799f"
+ integrity sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.1.4"
+ has-symbols "^1.0.3"
+ object-keys "^1.1.1"
+
+object.entries@^1.1.5:
+ version "1.1.6"
+ resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.6.tgz#9737d0e5b8291edd340a3e3264bb8a3b00d5fa23"
+ integrity sha512-leTPzo4Zvg3pmbQ3rDK69Rl8GQvIqMWubrkxONG9/ojtFE2rD9fjMKfSI5BxW3osRH1m6VdzmqK8oAY9aT4x5w==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.1.4"
+ es-abstract "^1.20.4"
+
+object.fromentries@^2.0.5:
+ version "2.0.6"
+ resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.6.tgz#cdb04da08c539cffa912dcd368b886e0904bfa73"
+ integrity sha512-VciD13dswC4j1Xt5394WR4MzmAQmlgN72phd/riNp9vtD7tp4QQWJ0R4wvclXcafgcYK8veHRed2W6XeGBvcfg==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.1.4"
+ es-abstract "^1.20.4"
+
object.getownpropertydescriptors@^2.0.3, object.getownpropertydescriptors@^2.1.1:
version "2.1.2"
resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.2.tgz#1bd63aeacf0d5d2d2f31b5e393b03a7c601a23f7"
define-properties "^1.1.3"
es-abstract "^1.18.0-next.2"
+object.hasown@^1.1.1:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/object.hasown/-/object.hasown-1.1.2.tgz#f919e21fad4eb38a57bc6345b3afd496515c3f92"
+ integrity sha512-B5UIT3J1W+WuWIU55h0mjlwaqxiE5vYENJXIXZ4VFe05pNYrkKuK0U/6aFcb0pKywYJh7IhfoqUfKVmrJJHZHw==
+ dependencies:
+ define-properties "^1.1.4"
+ es-abstract "^1.20.4"
+
object.omit@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa"
dependencies:
isobject "^3.0.1"
+object.values@^1.1.5:
+ version "1.1.6"
+ resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.6.tgz#4abbaa71eba47d63589d402856f908243eea9b1d"
+ integrity sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.1.4"
+ es-abstract "^1.20.4"
+
obuf@^1.0.0, obuf@^1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e"
type-check "~0.3.2"
word-wrap "~1.2.3"
+optionator@^0.9.1:
+ version "0.9.1"
+ resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499"
+ integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==
+ dependencies:
+ deep-is "^0.1.3"
+ fast-levenshtein "^2.0.6"
+ levn "^0.4.1"
+ prelude-ls "^1.2.1"
+ type-check "^0.4.0"
+ word-wrap "^1.2.3"
+
original@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/original/-/original-1.0.2.tgz#e442a61cffe1c5fd20a65f3261c26663b303f25f"
resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3"
integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M=
-os-locale@^1.4.0:
- version "1.4.0"
- resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9"
- integrity sha512-PRT7ZORmwu2MEFt4/fv3Q+mEfN4zetKxufQrkShY2oGvUms9r8otu5HfdyIFHkYXjO7laNsoVGmM2MANfuTA8g==
- dependencies:
- lcid "^1.0.0"
-
os-locale@^3.0.0, os-locale@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-3.1.0.tgz#a802a6ee17f24c10483ab9935719cef4ed16bf1a"
resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=
-osenv@0, osenv@^0.1.4, osenv@^0.1.5:
+osenv@^0.1.4, osenv@^0.1.5:
version "0.1.5"
resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410"
integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==
dependencies:
p-try "^2.0.0"
+p-limit@^3.0.2:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b"
+ integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==
+ dependencies:
+ yocto-queue "^0.1.0"
+
p-locate@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43"
dependencies:
p-limit "^2.2.0"
+p-locate@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834"
+ integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==
+ dependencies:
+ p-limit "^3.0.2"
+
p-map-series@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/p-map-series/-/p-map-series-1.0.0.tgz#bf98fe575705658a9e1351befb85ae4c1f07bdca"
resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40"
integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=
-path-parse@^1.0.5, path-parse@^1.0.6:
+path-key@^3.1.0:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375"
+ integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==
+
+path-parse@^1.0.5, path-parse@^1.0.6, path-parse@^1.0.7:
version "1.0.7"
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972"
integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==
+picomatch@^2.3.1:
+ version "2.3.1"
+ resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
+ integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
+
pify@^2.0.0, pify@^2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
source-map "^0.6.1"
supports-color "^6.1.0"
+prelude-ls@^1.2.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396"
+ integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==
+
prelude-ls@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
err-code "^1.0.0"
retry "^0.10.0"
-promise@^7.1.1:
- version "7.3.1"
- resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf"
- integrity sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==
- dependencies:
- asap "~2.0.3"
-
prompts@^0.1.9:
version "0.1.14"
resolved "https://registry.yarnpkg.com/prompts/-/prompts-0.1.14.tgz#a8e15c612c5c9ec8f8111847df3337c9cbd443b2"
object-assign "^4.1.1"
react-is "^16.8.1"
-prop-types@^15.8.1:
+prop-types@^15.5.4, prop-types@^15.8.1:
version "15.8.1"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5"
integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==
resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6"
integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==
+queue-microtask@^1.2.2:
+ version "1.2.3"
+ resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243"
+ integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==
+
quick-lru@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-1.1.0.tgz#4360b17c61136ad38078397ff11416e186dcfbb8"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b"
integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==
+react-lifecycles-compat@^3.0.4:
+ version "3.0.4"
+ resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362"
+ integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==
+
react-router-dom@5.2.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-5.2.0.tgz#9e65a4d0c45e13289e66c7b17c7e175d0ea15662"
tiny-invariant "^1.0.2"
tiny-warning "^1.0.0"
+react-split-pane@0.1.92:
+ version "0.1.92"
+ resolved "https://registry.yarnpkg.com/react-split-pane/-/react-split-pane-0.1.92.tgz#68242f72138aed95dd5910eeb9d99822c4fc3a41"
+ integrity sha512-GfXP1xSzLMcLJI5BM36Vh7GgZBpy+U/X0no+VM3fxayv+p1Jly5HpMofZJraeaMl73b3hvlr+N9zJKvLB/uz9w==
+ dependencies:
+ prop-types "^15.7.2"
+ react-lifecycles-compat "^3.0.4"
+ react-style-proptype "^3.2.2"
+
+react-style-proptype@^3.2.2:
+ version "3.2.2"
+ resolved "https://registry.yarnpkg.com/react-style-proptype/-/react-style-proptype-3.2.2.tgz#d8e998e62ce79ec35b087252b90f19f1c33968a0"
+ integrity sha512-ywYLSjNkxKHiZOqNlso9PZByNEY+FTyh3C+7uuziK0xFXu9xzdyfHwg4S9iyiRRoPCR4k2LqaBBsWVmSBwCWYQ==
+ dependencies:
+ prop-types "^15.5.4"
+
react-transition-group@4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.3.0.tgz#fea832e386cf8796c58b61874a3319704f5ce683"
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.10.tgz#ed07b19616bcbec5da6274ebc75ae95634bfc2ee"
integrity sha512-KepLsg4dU12hryUO7bp/axHAKvwGOCV0sGloQtpagJ12ai+ojVDqkeGSiRX1zlq+kjIMZ1t7gpze+26QqtdGqw==
+regenerator-runtime@^0.13.11:
+ version "0.13.11"
+ resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9"
+ integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==
+
regenerator-runtime@^0.13.4:
version "0.13.7"
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz#cac2dacc8a1ea675feaabaeb8ae833898ae46f55"
call-bind "^1.0.2"
define-properties "^1.1.3"
+regexp.prototype.flags@^1.4.3:
+ version "1.4.3"
+ resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz#87cab30f80f66660181a3bb7bf5981a872b367ac"
+ integrity sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.1.3"
+ functions-have-names "^1.2.2"
+
+regexpp@^3.2.0:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2"
+ integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==
+
regexpu-core@^4.7.1:
version "4.7.1"
resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.7.1.tgz#2dea5a9a07233298fbf0db91fa9abc4c6e0f8ad6"
stealthy-require "^1.1.1"
tough-cookie "^2.3.3"
-request@^2.83.0, request@^2.87.0, request@^2.88.0:
+request@^2.87.0, request@^2.88.0:
version "2.88.2"
resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3"
integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==
is-core-module "^2.2.0"
path-parse "^1.0.6"
+resolve@^1.22.0, resolve@^1.22.1:
+ version "1.22.1"
+ resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177"
+ integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==
+ dependencies:
+ is-core-module "^2.9.0"
+ path-parse "^1.0.7"
+ supports-preserve-symlinks-flag "^1.0.0"
+
+resolve@^2.0.0-next.3:
+ version "2.0.0-next.4"
+ resolved "https://registry.yarnpkg.com/resolve/-/resolve-2.0.0-next.4.tgz#3d37a113d6429f496ec4752d2a2e58efb1fd4660"
+ integrity sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ==
+ dependencies:
+ is-core-module "^2.9.0"
+ path-parse "^1.0.7"
+ supports-preserve-symlinks-flag "^1.0.0"
+
restore-cursor@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf"
resolved "https://registry.yarnpkg.com/retry/-/retry-0.10.1.tgz#e76388d217992c252750241d3d3956fed98d8ff4"
integrity sha1-52OI0heZLCUnUCQdPTlW/tmNj/Q=
-rimraf@2, rimraf@^2.2.8, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2, rimraf@^2.6.3:
- version "2.7.1"
- resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec"
- integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==
- dependencies:
- glob "^7.1.3"
+reusify@^1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
+ integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==
rimraf@2.6.2:
version "2.6.2"
dependencies:
glob "^7.0.5"
+rimraf@^2.2.8, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2, rimraf@^2.6.3:
+ version "2.7.1"
+ resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec"
+ integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==
+ dependencies:
+ glob "^7.1.3"
+
+rimraf@^3.0.2:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a"
+ integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==
+ dependencies:
+ glob "^7.1.3"
+
ripemd160@^2.0.0, ripemd160@^2.0.1:
version "2.0.2"
resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c"
resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455"
integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==
+run-parallel@^1.1.9:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee"
+ integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==
+ dependencies:
+ queue-microtask "^1.2.2"
+
run-queue@^1.0.0, run-queue@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/run-queue/-/run-queue-1.0.3.tgz#e848396f057d223f24386924618e25694161ec47"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
+safe-regex-test@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.0.tgz#793b874d524eb3640d1873aad03596db2d4f2295"
+ integrity sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==
+ dependencies:
+ call-bind "^1.0.2"
+ get-intrinsic "^1.1.3"
+ is-regex "^1.1.4"
+
safe-regex@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e"
optionalDependencies:
fsevents "^1.2.3"
-sass-graph@^2.2.4:
- version "2.2.6"
- resolved "https://registry.yarnpkg.com/sass-graph/-/sass-graph-2.2.6.tgz#09fda0e4287480e3e4967b72a2d133ba09b8d827"
- integrity sha512-MKuEYXFSGuRSi8FZ3A7imN1CeVn9Gpw0/SFJKdL1ejXJneI9a5rwlEZrKejhEFAA3O6yr3eIyl/WuvASvlT36g==
- dependencies:
- glob "^7.0.0"
- lodash "^4.0.0"
- scss-tokenizer "^0.2.3"
- yargs "^7.0.0"
-
-sass-loader@7.1.0:
- version "7.1.0"
- resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-7.1.0.tgz#16fd5138cb8b424bf8a759528a1972d72aad069d"
- integrity sha512-+G+BKGglmZM2GUSfT9TLuEp6tzehHPjAMoRRItOojWIqIGPloVCMhNIQuG639eJ+y033PaGTSjLaTHts8Kw79w==
- dependencies:
- clone-deep "^2.0.1"
- loader-utils "^1.0.1"
- lodash.tail "^4.1.1"
- neo-async "^2.5.0"
- pify "^3.0.0"
- semver "^5.5.0"
-
sax@^1.2.4:
version "1.2.4"
resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
ajv-errors "^1.0.0"
ajv-keywords "^3.1.0"
-scss-tokenizer@^0.2.3:
- version "0.2.3"
- resolved "https://registry.yarnpkg.com/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz#8eb06db9a9723333824d3f5530641149847ce5d1"
- integrity sha512-dYE8LhncfBUar6POCxMTm0Ln+erjeczqEvCJib5/7XNkdw1FkUGgwMPY360FY0FgPWQxHWCx29Jl3oejyGLM9Q==
- dependencies:
- js-base64 "^2.1.8"
- source-map "^0.4.2"
-
select-hose@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca"
dependencies:
lru-cache "^6.0.0"
-semver@~5.3.0:
- version "5.3.0"
- resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f"
- integrity sha512-mfmm3/H9+67MCVix1h+IXTpDwL6710LyHuk7+cWC9T1mE0qz4iHhh6r4hU2wrIT9iTsAAC2XQRvfblL028cpLw==
+semver@^7.3.7:
+ version "7.3.8"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.8.tgz#07a78feafb3f7b32347d725e33de7e2a2df67798"
+ integrity sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==
+ dependencies:
+ lru-cache "^6.0.0"
send@0.17.1:
version "0.17.1"
inherits "^2.0.1"
safe-buffer "^5.0.1"
-shallow-clone@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-1.0.0.tgz#4480cd06e882ef68b2ad88a3ea54832e2c48b571"
- integrity sha512-oeXreoKR/SyNJtRJMAKPDSvd28OqEwG4eR/xc856cRGBII7gX9lvAqDxusPm0846z/w/hWYjI1NpKwJ00NHzRA==
- dependencies:
- is-extendable "^0.1.1"
- kind-of "^5.0.0"
- mixin-object "^2.0.1"
-
shallow-clone@^3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3"
dependencies:
shebang-regex "^1.0.0"
+shebang-command@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea"
+ integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==
+ dependencies:
+ shebang-regex "^3.0.0"
+
shebang-regex@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3"
integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=
+shebang-regex@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172"
+ integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==
+
shellwords@^0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b"
resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44"
integrity sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==
+slash@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634"
+ integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==
+
slide@^1.1.6:
version "1.1.6"
resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707"
resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.1.tgz#0af66605a745a5a2f91cf1bbf8a7afbc283dec56"
integrity sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==
-source-map@^0.4.2:
- version "0.4.4"
- resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b"
- integrity sha512-Y8nIfcb1s/7DcobUz1yOO1GSp7gyL+D9zLHDehT7iRESqGSxjJ448Sg7rvfgsRJCnKLdSl11uGf0s9X80cH0/A==
- dependencies:
- amdefine ">=0.0.4"
-
source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7:
version "0.5.7"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=
-stdout-stream@^1.4.0:
- version "1.4.1"
- resolved "https://registry.yarnpkg.com/stdout-stream/-/stdout-stream-1.4.1.tgz#5ac174cdd5cd726104aa0c0b2bd83815d8d535de"
- integrity sha512-j4emi03KXqJWcIeF8eIXkjMFN1Cmb8gUlDYGeBALLPo5qdyTfA9bOtl8m33lRoC+vFMkP3gl0WsDr6+gzxbbTA==
- dependencies:
- readable-stream "^2.0.1"
-
stealthy-require@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b"
astral-regex "^1.0.0"
strip-ansi "^4.0.0"
-string-width@^1.0.1, string-width@^1.0.2:
+string-width@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3"
integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=
is-fullwidth-code-point "^2.0.0"
strip-ansi "^5.1.0"
+string.prototype.matchall@^4.0.7:
+ version "4.0.8"
+ resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.8.tgz#3bf85722021816dcd1bf38bb714915887ca79fd3"
+ integrity sha512-6zOCOcJ+RJAQshcTvXPHoxoQGONa3e/Lqx90wUA+wEzX78sg5Bo+1tQo4N0pohS0erG9qtCqJDjNCQBjeWVxyg==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.1.4"
+ es-abstract "^1.20.4"
+ get-intrinsic "^1.1.3"
+ has-symbols "^1.0.3"
+ internal-slot "^1.0.3"
+ regexp.prototype.flags "^1.4.3"
+ side-channel "^1.0.4"
+
+string.prototype.trim@^1.2.7:
+ version "1.2.7"
+ resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz#a68352740859f6893f14ce3ef1bb3037f7a90533"
+ integrity sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.1.4"
+ es-abstract "^1.20.4"
+
string.prototype.trimend@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz#e75ae90c2942c63504686c18b287b4a0b1a45f80"
call-bind "^1.0.2"
define-properties "^1.1.3"
+string.prototype.trimend@^1.0.6:
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz#c4a27fa026d979d79c04f17397f250a462944533"
+ integrity sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.1.4"
+ es-abstract "^1.20.4"
+
string.prototype.trimstart@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz#b36399af4ab2999b4c9c648bd7a3fb2bb26feeed"
call-bind "^1.0.2"
define-properties "^1.1.3"
+string.prototype.trimstart@^1.0.6:
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz#e90ab66aa8e4007d92ef591bbf3cd422c56bdcf4"
+ integrity sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.1.4"
+ es-abstract "^1.20.4"
+
string_decoder@^1.0.0, string_decoder@^1.1.1:
version "1.3.0"
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e"
dependencies:
ansi-regex "^4.1.0"
+strip-ansi@^6.0.1:
+ version "6.0.1"
+ resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
+ integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
+ dependencies:
+ ansi-regex "^5.0.1"
+
strip-bom@3.0.0, strip-bom@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3"
dependencies:
min-indent "^1.0.0"
+strip-json-comments@^3.1.0, strip-json-comments@^3.1.1:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006"
+ integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==
+
strong-log-transformer@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/strong-log-transformer/-/strong-log-transformer-2.1.0.tgz#0f5ed78d325e0421ac6f90f7f10e691d6ae3ae10"
dependencies:
has-flag "^3.0.0"
+supports-color@^7.1.0:
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da"
+ integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==
+ dependencies:
+ has-flag "^4.0.0"
+
+supports-preserve-symlinks-flag@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09"
+ integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==
+
symbol-tree@^3.2.2:
version "3.2.4"
resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2"
resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2"
integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==
-tar@^2.0.0:
- version "2.2.2"
- resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.2.tgz#0ca8848562c7299b8b446ff6a4d60cdbb23edc40"
- integrity sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==
- dependencies:
- block-stream "*"
- fstream "^1.0.12"
- inherits "2"
-
tar@^4.4.10, tar@^4.4.12, tar@^4.4.8:
version "4.4.13"
resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.13.tgz#43b364bc52888d555298637b10d60790254ab525"
resolved "https://registry.yarnpkg.com/text-extensions/-/text-extensions-1.9.0.tgz#1853e45fee39c945ce6f6c36b2d659b5aabc2a26"
integrity sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==
+text-table@^0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
+ integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==
+
thenify-all@^1.0.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/thenify-all/-/thenify-all-1.6.0.tgz#1a1918d402d8fc3f98fbf234db0bcc8cc10e9726"
resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003"
integrity sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=
-"true-case-path@^1.0.2":
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/true-case-path/-/true-case-path-1.0.3.tgz#f813b5a8c86b40da59606722b144e3225799f47d"
- integrity sha512-m6s2OdQe5wgpFMC+pAJ+q9djG82O2jcHPOI6RNg1yy9rCYR+WD6Nbpl32fDpfC56nirdRy+opFa/Vk7HYhqaew==
- dependencies:
- glob "^7.1.2"
-
ts-jest@23.10.5:
version "23.10.5"
resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-23.10.5.tgz#cdb550df4466a30489bf70ba867615799f388dd5"
micromatch "^3.1.4"
semver "^5.0.1"
+tsconfig-paths@^3.14.1:
+ version "3.14.2"
+ resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz#6e32f1f79412decd261f92d633a9dc1cfa99f088"
+ integrity sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==
+ dependencies:
+ "@types/json5" "^0.0.29"
+ json5 "^1.0.2"
+ minimist "^1.2.6"
+ strip-bom "^3.0.0"
+
tslib@1.9.0:
version "1.9.0"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.0.tgz#e37a86fda8cbbaf23a057f473c9f4dc64e5fc2e8"
dependencies:
tslib "^1.8.1"
-tsutils@^3.0.0, tsutils@^3.5.0:
+tsutils@^3.0.0, tsutils@^3.21.0, tsutils@^3.5.0:
version "3.21.0"
resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623"
integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==
resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=
+type-check@^0.4.0, type-check@~0.4.0:
+ version "0.4.0"
+ resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1"
+ integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==
+ dependencies:
+ prelude-ls "^1.2.1"
+
type-check@~0.3.2:
version "0.3.2"
resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72"
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.18.1.tgz#db4bc151a4a2cf4eebf9add5db75508db6cc841f"
integrity sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==
+type-fest@^0.20.2:
+ version "0.20.2"
+ resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4"
+ integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==
+
type-fest@^0.3.0:
version "0.3.1"
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.3.1.tgz#63d00d204e059474fe5e1b7c011112bbd1dc29e1"
media-typer "0.3.0"
mime-types "~2.1.24"
+typed-array-length@^1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.4.tgz#89d83785e5c4098bec72e08b319651f0eac9c1bb"
+ integrity sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==
+ dependencies:
+ call-bind "^1.0.2"
+ for-each "^0.3.3"
+ is-typed-array "^1.1.9"
+
typedarray@^0.0.6:
version "0.0.6"
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
has-symbols "^1.0.2"
which-boxed-primitive "^1.0.2"
+unbox-primitive@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e"
+ integrity sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==
+ dependencies:
+ call-bind "^1.0.2"
+ has-bigints "^1.0.2"
+ has-symbols "^1.0.3"
+ which-boxed-primitive "^1.0.2"
+
unicode-canonical-property-names-ecmascript@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz#2619800c4c825800efdd8343af7dd9933cbe2818"
is-string "^1.0.5"
is-symbol "^1.0.3"
-which-module@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f"
- integrity sha512-F6+WgncZi/mJDrammbTuHe1q0R5hOXv/mBaiNA2TCNT/LTHusX0V+CJnj9XT8ki5ln2UZyyddDgHfCzyrOH7MQ==
-
which-module@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a"
integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=
-which@1, which@^1.2.12, which@^1.2.14, which@^1.2.9, which@^1.3.0, which@^1.3.1:
+which-typed-array@^1.1.9:
+ version "1.1.9"
+ resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.9.tgz#307cf898025848cf995e795e8423c7f337efbde6"
+ integrity sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==
+ dependencies:
+ available-typed-arrays "^1.0.5"
+ call-bind "^1.0.2"
+ for-each "^0.3.3"
+ gopd "^1.0.1"
+ has-tostringtag "^1.0.0"
+ is-typed-array "^1.1.10"
+
+which@^1.2.12, which@^1.2.14, which@^1.2.9, which@^1.3.0, which@^1.3.1:
version "1.3.1"
resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==
dependencies:
isexe "^2.0.0"
+which@^2.0.1:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1"
+ integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==
+ dependencies:
+ isexe "^2.0.0"
+
wide-align@^1.1.0:
version "1.1.3"
resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457"
dependencies:
execa "^1.0.0"
-word-wrap@~1.2.3:
+word-wrap@^1.2.3, word-wrap@~1.2.3:
version "1.2.3"
resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c"
integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee"
integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==
-yargs-parser@^5.0.1:
- version "5.0.1"
- resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-5.0.1.tgz#7ede329c1d8cdbbe209bd25cdb990e9b1ebbb394"
- integrity sha512-wpav5XYiddjXxirPoCTUPbqM0PXvJ9hiBMvuJgInvo4/lAOTZzUprArw17q2O1P2+GHhbBr18/iQwjL5Z9BqfA==
- dependencies:
- camelcase "^3.0.0"
- object.assign "^4.1.0"
-
yargs-parser@^9.0.2:
version "9.0.2"
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-9.0.2.tgz#9ccf6a43460fe4ed40a9bb68f48d43b8a68cc077"
y18n "^4.0.0"
yargs-parser "^15.0.1"
-yargs@^7.0.0:
- version "7.1.2"
- resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.2.tgz#63a0a5d42143879fdbb30370741374e0641d55db"
- integrity sha512-ZEjj/dQYQy0Zx0lgLMLR8QuaqTihnxirir7EwUHp1Axq4e3+k8jXU5K0VLbNvedv1f4EWtBonDIZm0NUr+jCcA==
- dependencies:
- camelcase "^3.0.0"
- cliui "^3.2.0"
- decamelize "^1.1.1"
- get-caller-file "^1.0.1"
- os-locale "^1.4.0"
- read-pkg-up "^1.0.1"
- require-directory "^2.1.1"
- require-main-filename "^1.0.1"
- set-blocking "^2.0.0"
- string-width "^1.0.2"
- which-module "^1.0.0"
- y18n "^3.2.1"
- yargs-parser "^5.0.1"
+yocto-queue@^0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
+ integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==