From 437f67407aece6f7aed8e989638b0d64075f0c0a Mon Sep 17 00:00:00 2001 From: Aijana Schumann Date: Wed, 4 Aug 2021 11:59:18 +0200 Subject: Update ODLUX Add various updates and bugfixes to NetworkMap, Configuration, LinkCalculation and ConnectApp Issue-ID: CCSDK-3414 Signed-off-by: Aijana Schumann Change-Id: I6ea5c3a9d6ccbe9c450da43220654a53fd2f262b Signed-off-by: Aijana Schumann --- sdnr/wt/odlux/apps/apiDemo/package.json | 4 +- sdnr/wt/odlux/apps/apiDemo/pom.xml | 4 +- sdnr/wt/odlux/apps/configurationApp/package.json | 4 +- sdnr/wt/odlux/apps/configurationApp/pom.xml | 4 +- .../configurationApp/src/actions/deviceActions.ts | 26 +- sdnr/wt/odlux/apps/configurationApp/src/index.html | 6 +- .../odlux/apps/configurationApp/src/models/yang.ts | 4 +- .../configurationApp/src/pluginConfiguration.tsx | 2 +- .../configurationApp/src/services/restServices.ts | 123 +- .../src/views/configurationApplication.tsx | 14 +- .../apps/configurationApp/src/yang/yangParser.ts | 47 +- sdnr/wt/odlux/apps/connectApp/package.json | 4 +- sdnr/wt/odlux/apps/connectApp/pom.xml | 4 +- .../apps/connectApp/src/actions/tlsKeyActions.ts | 60 + .../src/components/connectionStatusLog.tsx | 2 +- .../src/components/editNetworkElementDialog.tsx | 131 +- .../connectApp/src/components/networkElements.tsx | 47 +- .../src/handlers/connectAppRootHandler.ts | 5 +- .../apps/connectApp/src/handlers/tlsKeyHandler.ts | 55 + sdnr/wt/odlux/apps/connectApp/src/index.html | 2 +- .../src/models/networkElementConnection.ts | 7 + .../wt/odlux/apps/connectApp/src/pluginConnect.tsx | 4 +- .../apps/connectApp/src/services/connectService.ts | 522 +++-- sdnr/wt/odlux/apps/demoApp/package.json | 4 +- sdnr/wt/odlux/apps/demoApp/pom.xml | 4 +- sdnr/wt/odlux/apps/eventLogApp/package.json | 4 +- sdnr/wt/odlux/apps/eventLogApp/pom.xml | 4 +- sdnr/wt/odlux/apps/faultApp/package.json | 4 +- sdnr/wt/odlux/apps/faultApp/pom.xml | 4 +- sdnr/wt/odlux/apps/helpApp/package.json | 4 +- sdnr/wt/odlux/apps/helpApp/pom.xml | 4 +- sdnr/wt/odlux/apps/inventoryApp/package.json | 4 +- sdnr/wt/odlux/apps/inventoryApp/pom.xml | 4 +- sdnr/wt/odlux/apps/linkCalculationApp/package.json | 4 +- sdnr/wt/odlux/apps/linkCalculationApp/pom.xml | 4 +- .../src/actions/commonLinkCalculationActions.ts | 141 +- .../src/handlers/linkCalculationAppRootHandler.ts | 51 +- .../apps/linkCalculationApp/src/views/Style.scss | 143 +- .../src/views/linkCalculationComponent.tsx | 662 +++--- sdnr/wt/odlux/apps/maintenanceApp/package.json | 4 +- sdnr/wt/odlux/apps/maintenanceApp/pom.xml | 4 +- sdnr/wt/odlux/apps/mediatorApp/package.json | 4 +- sdnr/wt/odlux/apps/mediatorApp/pom.xml | 4 +- sdnr/wt/odlux/apps/minimumApp/package.json | 4 +- sdnr/wt/odlux/apps/minimumApp/pom.xml | 4 +- sdnr/wt/odlux/apps/networkMapApp/icons/README.md | 2 +- .../apps/networkMapApp/icons/apartment.png.d.ts | 18 - .../apps/networkMapApp/icons/customize.png.d.ts | 18 - .../apps/networkMapApp/icons/datacenter.png.d.ts | 18 - .../networkMapApp/icons/datacenterred.png.d.ts | 18 - .../apps/networkMapApp/icons/factory.png.d.ts | 18 - .../apps/networkMapApp/icons/factoryred.png.d.ts | 18 - .../odlux/apps/networkMapApp/icons/lamp.png.d.ts | 18 - .../apps/networkMapApp/icons/lampred.png.d.ts | 18 - sdnr/wt/odlux/apps/networkMapApp/package.json | 4 +- sdnr/wt/odlux/apps/networkMapApp/pom.xml | 4 +- .../networkMapApp/src/actions/detailsAction.ts | 21 + .../networkMapApp/src/components/denseTable.tsx | 15 +- .../src/components/details/linkDetails.tsx | 34 +- .../src/components/details/siteDetails.tsx | 77 +- .../src/components/details/stadokDetailsPopup.tsx | 274 +++ .../src/components/map/connectionInfo.tsx | 2 +- .../src/components/map/iconSwitch.tsx | 4 +- .../apps/networkMapApp/src/components/map/map.tsx | 204 +- .../networkMapApp/src/components/map/searchBar.tsx | 1 + .../src/components/map/statistics.tsx | 2 +- sdnr/wt/odlux/apps/networkMapApp/src/config.ts | 1 + .../networkMapApp/src/handlers/detailsReducer.ts | 10 +- sdnr/wt/odlux/apps/networkMapApp/src/index.html | 5 +- sdnr/wt/odlux/apps/networkMapApp/src/model/link.ts | 10 +- sdnr/wt/odlux/apps/networkMapApp/src/model/site.ts | 3 +- .../apps/networkMapApp/src/model/stadokOrder.ts | 56 + .../apps/networkMapApp/src/model/stadokSite.ts | 54 + .../apps/networkMapApp/src/pluginTransport.tsx | 7 +- .../apps/networkMapApp/src/utils/mapLayers.ts | 2 + sdnr/wt/odlux/apps/networkMapApp/webpack.config.js | 13 +- .../odlux/apps/performanceHistoryApp/package.json | 4 +- sdnr/wt/odlux/apps/performanceHistoryApp/pom.xml | 4 +- sdnr/wt/odlux/core/features/pom.xml | 5 - sdnr/wt/odlux/core/installer/pom.xml | 4 +- sdnr/wt/odlux/core/model/pom.xml | 2 + .../opensymphony/xwork2/util/ClassLoaderUtil.java | 2 +- sdnr/wt/odlux/core/provider/pom.xml | 15 +- .../features/sdnr/wt/odlux/IndexOdluxBundle.java | 15 +- .../features/sdnr/wt/odlux/ResFilesServlet.java | 1 + sdnr/wt/odlux/framework/package.json | 6 +- sdnr/wt/odlux/framework/pom.xml | 4 +- sdnr/wt/odlux/installer/pom.xml | 11 +- sdnr/wt/odlux/odlux.properties | 20 +- sdnr/wt/odlux/package.json | 10 +- sdnr/wt/odlux/yarn.lock | 2455 ++++++++++---------- 91 files changed, 3339 insertions(+), 2318 deletions(-) create mode 100644 sdnr/wt/odlux/apps/connectApp/src/actions/tlsKeyActions.ts create mode 100644 sdnr/wt/odlux/apps/connectApp/src/handlers/tlsKeyHandler.ts create mode 100644 sdnr/wt/odlux/apps/networkMapApp/src/components/details/stadokDetailsPopup.tsx create mode 100644 sdnr/wt/odlux/apps/networkMapApp/src/model/stadokOrder.ts create mode 100644 sdnr/wt/odlux/apps/networkMapApp/src/model/stadokSite.ts (limited to 'sdnr') diff --git a/sdnr/wt/odlux/apps/apiDemo/package.json b/sdnr/wt/odlux/apps/apiDemo/package.json index 3805c020e..af47a025e 100644 --- a/sdnr/wt/odlux/apps/apiDemo/package.json +++ b/sdnr/wt/odlux/apps/apiDemo/package.json @@ -27,8 +27,8 @@ "@types/react": "17.0.3", "@types/react-dom": "17.0.2", "@types/react-router-dom": "5.1.7", - "@material-ui/core": "4.11.0", - "@material-ui/icons": "4.9.1", + "@material-ui/core": "4.11.4", + "@material-ui/icons": "4.11.2", "@types/classnames": "2.2.6", "@types/flux": "3.1.8", "@types/jquery": "3.3.10", diff --git a/sdnr/wt/odlux/apps/apiDemo/pom.xml b/sdnr/wt/odlux/apps/apiDemo/pom.xml index 2e9da77fb..6c181cc09 100644 --- a/sdnr/wt/odlux/apps/apiDemo/pom.xml +++ b/sdnr/wt/odlux/apps/apiDemo/pom.xml @@ -140,8 +140,8 @@ initialize - v10.16.3 - v1.19.0 + v12.13.0 + v1.22.10 diff --git a/sdnr/wt/odlux/apps/configurationApp/package.json b/sdnr/wt/odlux/apps/configurationApp/package.json index 16588cd18..8dd2d041f 100644 --- a/sdnr/wt/odlux/apps/configurationApp/package.json +++ b/sdnr/wt/odlux/apps/configurationApp/package.json @@ -27,8 +27,8 @@ "@types/react": "17.0.3", "@types/react-dom": "17.0.2", "@types/react-router-dom": "5.1.7", - "@material-ui/core": "4.11.0", - "@material-ui/icons": "4.9.1", + "@material-ui/core": "4.11.4", + "@material-ui/icons": "4.11.2", "@types/classnames": "2.2.6", "@types/flux": "3.1.8", "@types/jquery": "3.3.10", diff --git a/sdnr/wt/odlux/apps/configurationApp/pom.xml b/sdnr/wt/odlux/apps/configurationApp/pom.xml index bc6bb5da4..43802970f 100644 --- a/sdnr/wt/odlux/apps/configurationApp/pom.xml +++ b/sdnr/wt/odlux/apps/configurationApp/pom.xml @@ -140,8 +140,8 @@ initialize - v10.16.3 - v1.19.0 + v12.13.0 + v1.22.10 diff --git a/sdnr/wt/odlux/apps/configurationApp/src/actions/deviceActions.ts b/sdnr/wt/odlux/apps/configurationApp/src/actions/deviceActions.ts index f80fbfc4d..b5dd310bc 100644 --- a/sdnr/wt/odlux/apps/configurationApp/src/actions/deviceActions.ts +++ b/sdnr/wt/odlux/apps/configurationApp/src/actions/deviceActions.ts @@ -52,26 +52,20 @@ export const updateNodeIdAsyncActionCreator = (nodeId: string) => async (dispatc dispatch(new UpdateDeviceDescription("", {}, [])); dispatch(new SetCollectingSelectionData(true)); - const { avaliableCapabilities, unavaliableCapabilities } = await restService.getCapabilitiesByMoutId(nodeId); - - if (!avaliableCapabilities || avaliableCapabilities.length <= 0) { + const { availableCapabilities, unavailableCapabilities, importOnlyModules } = await restService.getCapabilitiesByMountId(nodeId); + + if (!availableCapabilities || availableCapabilities.length <= 0) { throw new Error(`NetworkElement : [${nodeId}] has no capabilities.`); } - - const capParser = /^\(.*\?revision=(\d{4}-\d{2}-\d{2})\)(\S+)$/i; - - const parser = new YangParser(unavaliableCapabilities?.map(cap => { - const capMatch = cap && capParser.exec(cap.capability); - return { capability:capMatch && capMatch[2] || '', failureReason: cap.failureReason }; - }) || undefined); - - for (let i = 0; i < avaliableCapabilities.length; ++i){ - const capRaw = avaliableCapabilities[i]; - const capMatch = capRaw && capParser.exec(capRaw.capability); + + const parser = new YangParser(unavailableCapabilities || undefined, importOnlyModules || undefined); + + for (let i = 0; i < availableCapabilities.length; ++i){ + const capRaw = availableCapabilities[i]; try { - capMatch && await parser.addCapability(capMatch[2], capMatch[1]); + await parser.addCapability(capRaw.capability, capRaw.version); } catch (err) { - console.error(`Error in ${capMatch && capMatch[2]} ${capMatch && capMatch[1]}`, err); + console.error(`Error in ${capRaw.capability} ${capRaw.version}`, err); } } diff --git a/sdnr/wt/odlux/apps/configurationApp/src/index.html b/sdnr/wt/odlux/apps/configurationApp/src/index.html index 78fff78c5..4a0496bff 100644 --- a/sdnr/wt/odlux/apps/configurationApp/src/index.html +++ b/sdnr/wt/odlux/apps/configurationApp/src/index.html @@ -15,11 +15,13 @@ diff --git a/sdnr/wt/odlux/apps/configurationApp/src/models/yang.ts b/sdnr/wt/odlux/apps/configurationApp/src/models/yang.ts index e4ab6f59f..10f538c2e 100644 --- a/sdnr/wt/odlux/apps/configurationApp/src/models/yang.ts +++ b/sdnr/wt/odlux/apps/configurationApp/src/models/yang.ts @@ -17,12 +17,12 @@ */ import { ViewElement, ViewSpecification } from "./uiModels"; -import { StepLabel } from "@material-ui/core"; export enum ModuleState { stable, instable, - unabaliabe, + importOnly, + unavailable, } export type Token = { diff --git a/sdnr/wt/odlux/apps/configurationApp/src/pluginConfiguration.tsx b/sdnr/wt/odlux/apps/configurationApp/src/pluginConfiguration.tsx index 3bc0e3968..3b9baa657 100644 --- a/sdnr/wt/odlux/apps/configurationApp/src/pluginConfiguration.tsx +++ b/sdnr/wt/odlux/apps/configurationApp/src/pluginConfiguration.tsx @@ -88,7 +88,7 @@ const ConfigurationApplicationRouteAdapter = connect(undefined, mapDisp)((props: // 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.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.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`; switch (elm.uiType) { diff --git a/sdnr/wt/odlux/apps/configurationApp/src/services/restServices.ts b/sdnr/wt/odlux/apps/configurationApp/src/services/restServices.ts index bdef64cf2..02060ef12 100644 --- a/sdnr/wt/odlux/apps/configurationApp/src/services/restServices.ts +++ b/sdnr/wt/odlux/apps/configurationApp/src/services/restServices.ts @@ -21,52 +21,101 @@ import { convertPropertyNames, replaceHyphen } from "../../../../framework/src/u import { NetworkElementConnection } from "../models/networkElementConnection"; +type ImportOnlyResponse = { + "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 = { - avaliableCapabilities: { - capabilityOrigin: string, - capability: string - }[] | null , - unavaliableCapabilities: { - failureReason: string, - capability: string - }[] | null , +type CapabilityAnswer = { + availableCapabilities: { + capabilityOrigin: string, + capability: string, + version: string, + }[] | null, + unavailableCapabilities: { + failureReason: string, + capability: string, + version: string, + }[] | null, + importOnlyModules: { + 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 getCapabilitiesByMoutId(nodeId: string): Promise { + 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(path, { method: "GET" }); + const importOnlyModules = importOnlyResult + ? importOnlyResult["ietf-yang-library:yang-library"]["module-set"][0]["import-only-module"] + : []; + return importOnlyModules; + } + + public async getCapabilitiesByMountId(nodeId: string): Promise { const path = this.getNetworkElementUri(nodeId); const capabilitiesResult = await requestRest(path, { method: "GET" }); - const avaliableCapabilities = 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(obj => convertPropertyNames(obj, replaceHyphen)) || []; - - const unavaliableCapabilities = 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(obj => convertPropertyNames(obj, replaceHyphen)) || [] - - return { avaliableCapabilities, unavaliableCapabilities }; + 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(obj => convertPropertyNames(obj, replaceHyphen)) || []) + .map(cap => { + const capMatch = cap && capParser.exec(cap.capability); + return capMatch ? { + capabilityOrigin: cap.capabilityOrigin, + capability: capMatch && capMatch[2] || '', + version: capMatch && capMatch[1] || '', + } : null ; + }).filter((cap) => cap != null) || [] as any; + + const unavailableCapabilities = capabilitiesResult && capabilitiesResult["network-topology:node"] && capabilitiesResult["network-topology:node"].length > 0 && + (capabilitiesResult["network-topology:node"][0]["netconf-node-topology:unavailable-capabilities"] && + capabilitiesResult["network-topology:node"][0]["netconf-node-topology:unavailable-capabilities"]["unavailable-capability"] && + capabilitiesResult["network-topology:node"][0]["netconf-node-topology:unavailable-capabilities"]["unavailable-capability"].map(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; + + return { availableCapabilities, unavailableCapabilities, importOnlyModules }; } public async getMountedNetworkElementByMountId(nodeId: string): Promise { @@ -80,7 +129,7 @@ class RestService { 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. * @param path The restconf path to be used for read. * @returns The data. diff --git a/sdnr/wt/odlux/apps/configurationApp/src/views/configurationApplication.tsx b/sdnr/wt/odlux/apps/configurationApp/src/views/configurationApplication.tsx index db426e814..8d0e19246 100644 --- a/sdnr/wt/odlux/apps/configurationApp/src/views/configurationApplication.tsx +++ b/sdnr/wt/odlux/apps/configurationApp/src/views/configurationApplication.tsx @@ -578,9 +578,11 @@ class ConfigurationApplicationComponent extends React.Component { this.props.history.push(`${this.props.match.url}${path}`); @@ -593,7 +595,7 @@ class ConfigurationApplicationComponent extends React.Component { navigate("[]"); // empty key means new element }, - disabled: !listSpecification.config, + disabled: !config, }; const addWithApiDocElementAction = { @@ -603,7 +605,7 @@ class ConfigurationApplicationComponent extends React.Component { window.open(apiDocPathCreate, '_blank'); }, - disabled: !listSpecification.config, + disabled: !config, }; const { classes, removeElement } = this.props; @@ -650,13 +652,13 @@ class ConfigurationApplicationComponent extends React.Component { return ( - this.props.vPath && this.props.reloadView(this.props.vPath)} /> + this.props.vPath && this.props.reloadView(this.props.vPath)} /> ); }) }]) } onHandleClick={(ev, row) => { ev.preventDefault(); - navigate(`[${encodeURIComponent(row[listKeyProperty])}]`); + listKeyProperty && navigate(`[${encodeURIComponent(row[listKeyProperty])}]`); // Do not navigate without key. }} > ); } diff --git a/sdnr/wt/odlux/apps/configurationApp/src/yang/yangParser.ts b/sdnr/wt/odlux/apps/configurationApp/src/yang/yangParser.ts index 2d38976d5..c80bd4c84 100644 --- a/sdnr/wt/odlux/apps/configurationApp/src/yang/yangParser.ts +++ b/sdnr/wt/odlux/apps/configurationApp/src/yang/yangParser.ts @@ -286,7 +286,7 @@ export class YangParser { public static ResolveStack = Symbol("ResolveStack"); - constructor(private _unavailableCapabilities: { failureReason: string; capability: string; }[] = []) { + constructor(private _unavailableCapabilities: { failureReason: string; capability: string; }[] = [], private _importOnlyModules: { name: string; revision: string; }[] = []) { } @@ -298,16 +298,16 @@ export class YangParser { return this._views; } - public async addCapability(capability: string, version?: string) { + public async addCapability(capability: string, version?: string, parentImportOnlyModule?: boolean) { // do not add twice if (this._modules[capability]) { - // console.warn(`Skipped capability: ${capability} since allready contained.` ); + // console.warn(`Skipped capability: ${capability} since already contained.` ); return; } - // // do not add unavaliabe capabilities + // // do not add unavailable capabilities // if (this._unavailableCapabilities.some(c => c.capability === capability)) { - // // console.warn(`Skipped capability: ${capability} since it is marked as unavaliable.` ); + // // console.warn(`Skipped capability: ${capability} since it is marked as unavailable.` ); // return; // } @@ -325,7 +325,8 @@ export class YangParser { throw new Error(`Root element capability ${rootStatement.arg} does not requested ${capability}.`); } - const isUnavaliabe = this._unavailableCapabilities.some(c => c.capability === capability); + const isUnavailable = this._unavailableCapabilities.some(c => c.capability === capability); + const isImportOnly = parentImportOnlyModule === true || this._importOnlyModules.some(c => c.name === capability); const module = this._modules[capability] = { name: rootStatement.arg, @@ -338,9 +339,11 @@ export class YangParser { typedefs: {}, views: {}, elements: {}, - state: isUnavaliabe - ? ModuleState.unabaliabe - : ModuleState.stable, + state: isUnavailable + ? ModuleState.unavailable + : isImportOnly + ? ModuleState.importOnly + : ModuleState.stable, }; await this.handleModule(module, rootStatement, capability); @@ -406,7 +409,7 @@ export class YangParser { // import all required files and set module state if (imports) for (let ind = 0; ind < imports.length; ++ind) { const moduleName = imports[ind].arg!; - await this.addCapability(moduleName); + await this.addCapability(moduleName, undefined, 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); @@ -415,7 +418,7 @@ export class YangParser { this.extractTypeDefinitions(rootStatement, module, ""); - this.extractIdentites(rootStatement, 0, module, ""); + this.extractIdentities(rootStatement, 0, module, ""); const groupings = this.extractGroupings(rootStatement, 0, module, ""); this._views.push(...groupings); @@ -440,8 +443,8 @@ export class YangParser { module.views[key] = this._views[viewIdIndex]; } - // add only the UI View if the module is avliable - if (module.state !== ModuleState.unabaliabe) this._views[0].elements[key] = module.elements[key]; + // 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]; }); }); return module; @@ -449,7 +452,7 @@ export class YangParser { public postProcess() { - // execute all post processes like resolving in propper order + // execute all post processes like resolving in proper order this._unionsToResolve.forEach(cb => { try { cb(); } catch (error) { console.warn(error.message); @@ -463,7 +466,7 @@ export class YangParser { } }); - // process all augmentations / sort by namespace changes to ensure propper order + // process all augmentations / sort by namespace changes to ensure proper order Object.keys(this.modules).forEach(modKey => { const module = this.modules[modKey]; const augmentKeysWithCounter = Object.keys(module.augments).map((key) => { @@ -517,7 +520,7 @@ export class YangParser { return result; } - const baseIdentites: Identity[] = []; + const baseIdentities: Identity[] = []; Object.keys(this.modules).forEach(modKey => { const module = this.modules[modKey]; Object.keys(module.identities).forEach(idKey => { @@ -526,11 +529,11 @@ export class YangParser { const base = this.resolveIdentity(identity.base, module); base.children?.push(identity); } else { - baseIdentites.push(identity); + baseIdentities.push(identity); } }); }); - baseIdentites.forEach(identity => { + baseIdentities.forEach(identity => { identity.values = identity.children && traverseIdentity(identity.children) || []; }); @@ -598,7 +601,7 @@ export class YangParser { }); } - /** Handles Goupings like named Container */ + /** 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"); @@ -620,7 +623,7 @@ export class YangParser { return subViews; } - /** Handles Augmants also like named Container */ + /** 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"); @@ -645,8 +648,8 @@ export class YangParser { return subViews; } - /** Handles Identities */ - private extractIdentites(statement: Statement, parentId: number, module: Module, currentPath: string) { + /** Handles identities */ + private extractIdentities(statement: Statement, parentId: number, module: Module, currentPath: string) { const identities = this.extractNodes(statement, "identity"); module.identities = identities.reduce<{ [name: string]: Identity }>((acc, cur) => { if (!cur.arg) { diff --git a/sdnr/wt/odlux/apps/connectApp/package.json b/sdnr/wt/odlux/apps/connectApp/package.json index 4fae39ccb..a6b23df84 100644 --- a/sdnr/wt/odlux/apps/connectApp/package.json +++ b/sdnr/wt/odlux/apps/connectApp/package.json @@ -27,8 +27,8 @@ "@types/react": "17.0.3", "@types/react-dom": "17.0.2", "@types/react-router-dom": "5.1.7", - "@material-ui/core": "4.11.0", - "@material-ui/icons": "4.9.1", + "@material-ui/core": "4.11.4", + "@material-ui/icons": "4.11.2", "@types/classnames": "2.2.6", "@types/flux": "3.1.8", "@types/jquery": "3.3.10", diff --git a/sdnr/wt/odlux/apps/connectApp/pom.xml b/sdnr/wt/odlux/apps/connectApp/pom.xml index e3ca9dd4d..117a374c4 100644 --- a/sdnr/wt/odlux/apps/connectApp/pom.xml +++ b/sdnr/wt/odlux/apps/connectApp/pom.xml @@ -140,8 +140,8 @@ initialize - v10.16.3 - v1.19.0 + v12.13.0 + v1.22.10 diff --git a/sdnr/wt/odlux/apps/connectApp/src/actions/tlsKeyActions.ts b/sdnr/wt/odlux/apps/connectApp/src/actions/tlsKeyActions.ts new file mode 100644 index 000000000..1da16d9ad --- /dev/null +++ b/sdnr/wt/odlux/apps/connectApp/src/actions/tlsKeyActions.ts @@ -0,0 +1,60 @@ +/** + * ============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========================================================================== + */ +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 the base action. + */ +export class BaseAction extends Action { } + +/** + * Represents an action causing the store to load all TLS Keys. + */ +export class LoadAllTlsKeyListAction extends BaseAction { } + +/** + * 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(); + } +} + +/** + * Represents an asynchronous thunk action to load all tlsKeys + */ + +export const loadAllTlsKeyListAsync = () => async (dispatch: Dispatch) => { + dispatch(new LoadAllTlsKeyListAction()); + connectService.getTlsKeys().then(TlsKeyList => { + dispatch(new AllTlsKeyListLoadedAction(TlsKeyList)); + }).catch(error => { + dispatch(new AllTlsKeyListLoadedAction(null, error)); + }); +}; diff --git a/sdnr/wt/odlux/apps/connectApp/src/components/connectionStatusLog.tsx b/sdnr/wt/odlux/apps/connectApp/src/components/connectionStatusLog.tsx index 7d2f96af3..5a5ebcc45 100644 --- a/sdnr/wt/odlux/apps/connectApp/src/components/connectionStatusLog.tsx +++ b/sdnr/wt/odlux/apps/connectApp/src/components/connectionStatusLog.tsx @@ -54,7 +54,7 @@ class ConnectionStatusLogComponent extends React.Component { + icon: Refresh, tooltip: 'Refresh Connection Status Log Table',ariaLabel:'refresh', onClick: () => { this.setState({ refreshConnectionStatusLogEditorMode: RefreshConnectionStatusLogDialogMode.RefreshConnectionStatusLogTable }); diff --git a/sdnr/wt/odlux/apps/connectApp/src/components/editNetworkElementDialog.tsx b/sdnr/wt/odlux/apps/connectApp/src/components/editNetworkElementDialog.tsx index 97e6647cf..df265c23d 100644 --- a/sdnr/wt/odlux/apps/connectApp/src/components/editNetworkElementDialog.tsx +++ b/sdnr/wt/odlux/apps/connectApp/src/components/editNetworkElementDialog.tsx @@ -24,7 +24,9 @@ import DialogActions from '@material-ui/core/DialogActions'; import DialogContent from '@material-ui/core/DialogContent'; import DialogContentText from '@material-ui/core/DialogContentText'; import DialogTitle from '@material-ui/core/DialogTitle'; -import { FormControl, InputLabel, Select, MenuItem, Typography } from '@material-ui/core'; +import { FormControl, InputLabel, Select, MenuItem, Typography, Radio, RadioGroup, Options, FormLabel, FormControlLabel } from '@material-ui/core'; +import { loadAllTlsKeyListAsync } from '../actions/tlsKeyActions'; +import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore'; import { IDispatcher, connect, Connect } from '../../../../framework/src/flux/connect'; @@ -67,13 +69,13 @@ const mapDispatch = (dispatcher: IDispatcher) => ({ //make sure properties are there in case they get renamed const idProperty = propertyOf("id"); const isRequiredProperty = propertyOf("isRequired"); - + if (values.length === 2 && values.includes(idProperty as string) && values.includes(isRequiredProperty as string)) { // do not mount network element, if only isRequired is changed await dispatcher.dispatch(editNetworkElementAsyncActionCreator(element)); - } else if(!(values.length===1 &&values.includes(idProperty as string))) { //do not edit or mount element, if only id was saved into object (no changes made!) + } else if (!(values.length === 1 && values.includes(idProperty as string))) { //do not edit or mount element, if only id was saved into object (no changes made!) await dispatcher.dispatch(editNetworkElementAsyncActionCreator(element)); await dispatcher.dispatch(mountNetworkElementAsyncActionCreator(mountElement)); } @@ -81,7 +83,8 @@ const mapDispatch = (dispatcher: IDispatcher) => ({ removeNetworkElement: async (element: UpdateNetworkElement) => { await dispatcher.dispatch(removeNetworkElementAsyncActionCreator(element)); dispatcher.dispatch(removeWebUriAction(element.id)); - } + }, + getAvailableTlsKeys: async () => await dispatcher.dispatch(loadAllTlsKeyListAsync()), }); type DialogSettings = { @@ -156,26 +159,62 @@ type EditNetworkElementDialogComponentProps = Connect void; + radioChecked: string }; -type EditNetworkElementDialogComponentState = NetworkElementConnection & { isNameValid: boolean, isHostSet: boolean }; +type EditNetworkElementDialogComponentState = NetworkElementConnection & { + isNameValid: boolean, + isHostSet: boolean, + isPasswordSelected: boolean, + isTlsSelected: boolean, + radioSelected: string, + showPasswordTextField: boolean, + showTlsDropdown: boolean +}; class EditNetworkElementDialogComponent extends React.Component { constructor(props: EditNetworkElementDialogComponentProps) { super(props); - + this.handleRadioChange = this.handleRadioChange.bind(this); this.state = { nodeId: this.props.initialNetworkElement.nodeId, isRequired: false, host: this.props.initialNetworkElement.host, port: this.props.initialNetworkElement.port, isNameValid: true, - isHostSet: true + isHostSet: true, + isPasswordSelected: true, + isTlsSelected: false, + radioSelected: '', + showPasswordTextField: true, + showTlsDropdown: false }; } + public handleRadioChange = (event: any) => { + this.setState({ + radioSelected: event.target.value, + showPasswordTextField: event.target.value === 'password', + showTlsDropdown: event.target.value === 'tlsKey' + }); + } render(): JSX.Element { const setting = settings[this.props.mode]; + let { showPasswordTextField, showTlsDropdown, radioSelected } = this.state; + radioSelected = this.state.radioSelected.length > 0 ? this.state.radioSelected : this.props.radioChecked; + + if (radioSelected === 'password') { + radioSelected = 'password'; + showPasswordTextField = true; + showTlsDropdown = false; + } else if (radioSelected === 'tlsKey') { + radioSelected = 'tlsKey'; + showPasswordTextField = false; + showTlsDropdown = true; + } + + let tlsKeysList = this.props.state.connect.availableTlsKeys ? this.props.state.connect.availableTlsKeys.tlsKeysList ? this.props.state.connect.availableTlsKeys.tlsKeysList : [] : [] + return ( {setting.dialogTitle} @@ -187,9 +226,39 @@ class EditNetworkElementDialogComponent extends React.ComponentName cannot be empty.} { this.setState({ host: event.target.value }); }} /> {!this.state.isHostSet && IP Adress cannot be empty.} + { this.setState({ port: +event.target.value }); }} /> {setting.enableUsernameEditor && { this.setState({ username: event.target.value }); }} /> || null} - {setting.enableUsernameEditor && { this.setState({ password: event.target.value }); }} /> || null} + + {setting.enableUsernameEditor && + + } label="Password" onChange={this.onRadioSelect} /> + } label="TlsKey" onChange={this.onRadioSelect} /> + || null} + + {setting.enableUsernameEditor && showPasswordTextField && + { this.setState({ password: event.target.value }); }} + /> || null} + + + {setting.enableUsernameEditor && showTlsDropdown && +
+ --Select tls-key-- + +
+ } +
+ Required 0 ? 'error' : 'input'} id='Lat1' type='number' onChange={(e: any) => {this.handleChange(e)} }/> -
{this.state.latitude1Error}
-
{this.state.longitude1Error}
-
- - -
Site B -
-
{this.state.latitude2Error}
-
{this.state.longitude2Error}
-
- + +
+ + {!this.props.formView && + +
+
+
SiteA
+
SiteB
+
+ +
+
+
+ +
{this.state.latitude1Error}
+
+
+
+
{this.state.latitude2Error}
+
+
+ +
+
+
{this.state.longitude1Error}
+
+
+
{this.state.longitude2Error}
+
+
+ + +
} -
-
{
this.setState ({worstmonth: false})}>Annual - this.setState ({worstmonth: true})}>WM
}
- - -
-
 
- {(this.props.siteA.length>0 || this.props.siteB.length>0) &&
Site Name
} -
Latitude
-
Longitude
-
Azimuth
-
Average Mean Sea Level
-
Antenna Height Above Ground
-
Distance
-
Polarization
-
Frequency
-
Free Space Loss
-
Rain Model
-
Rainfall Rate
-
Rain Loss
-
Absorption Model
-
Oxygen Specific Attenuation
-
Water Vapor Specific Attenuation
+
+
{
this.setState({ worstmonth: false })}>Annual + this.setState({ worstmonth: true })}>WM
}
- - -
-
Site A
- {this.props.siteA.length>0 &&
{this.props.siteA }
} -
{this.props.lat1 && this.LatLonToDMS(this.props.lat1)}
-
{this.props.lon1 && this.LatLonToDMS(this.props.lon1)}
-
0
-
{this.props.amslA.toFixed(2)} m
-
{this.props.aglA.toFixed(2)} m
- - -
-
{this.props.distance?.toFixed(3)} km
-
{
this.props.updatePolarization(e.target.value)}>Horizontal - {this.props.updatePolarization(e.target.value)}}>Vertical
}
- -
{}
{this.state.frequencyError}
- -
{this.props.fsl.toFixed(3)} dB
- -
{}
{this.state.rainMethodError}
-
+
+
Site A
+
Site B
+
+ {/*
 
*/} +
+ {(this.props.siteA.length > 0 || this.props.siteB.length > 0) &&
Site Name
} +
{this.props.siteA}
+
{this.props.siteB}
+
+
+
Latitude
+
{this.props.lat1 && this.LatLonToDMS(this.props.lat1)}
+
{this.props.lat2 && this.LatLonToDMS(this.props.lat2)}
+ +
+
+
Longitude
+
{this.props.lon1 && this.LatLonToDMS(this.props.lon1)}
+
{this.props.lon2 && this.LatLonToDMS(this.props.lon2)}
+
+
+
Azimuth
+
0
+
0
+
+
+
Average Mean Sea Level
+
{this.props.amslA.toFixed(2)} m
+
{this.props.amslB.toFixed(2)} m
+
+
+
Antenna Height Above Ground
+
{this.props.aglA.toFixed(2)} m
+
{this.props.aglB.toFixed(2)} m
+
+
+
Distance
+
{this.props.distance?.toFixed(3)} km
+
+
+
Polarization
+
{
this.props.updatePolarization(e.target.value)}>Horizontal + { this.props.updatePolarization(e.target.value) }}>Vertical
}
+
+
+
Frequency
+
{}
{this.state.frequencyError}
+
+
+
Free Space Loss
+
{this.props.fsl.toFixed(3)} dB
+
+
+
Rain Model
+
{}
{this.state.rainMethodError}
+
+
+
+
Rainfall Rate
{
{ this.props.updateRainValue(Number(e.target.value)) }} - value={this.props.rainVal} disabled={this.state.rainMethodDisplay === false ? true : false}> - mm/hr {this.state.showWM} {this.props.month}
}
-
{this.props.rainAtt.toFixed(3)} dB
- -
{}
{this.state.attenuationMethodError}
-
-
{this.props.absorptionOxygen.toFixed(3)} dB
-
{this.props.absorptionWater.toFixed(3)} dB
-
{}
+ value={this.props.rainVal} disabled={this.state.rainMethodDisplay === false ? true : false}> + mm/hr {this.state.showWM} {this.props.month}}
+
+
+
Rain Loss
+
{this.props.rainAtt.toFixed(3)} dB
+
+
+
Absorption Model
+
{}
{this.state.attenuationMethodError}
+
+
+
+
Oxygen Specific Attenuation
+
{this.props.absorptionOxygen.toFixed(3)} dB
+
+
+
Water Vapor Specific Attenuation
+
{this.props.absorptionWater.toFixed(3)} dB
+
+
+
System Operating Margin
+
{this.props.systemOperatingMargin} dB
+
+
+
Radio Transmitted Power
+
{
{if (e.target.value !== '') this.props.UpdateTxPower(e.target.value,null) }} + > + dBm
}
+
{
{ if (e.target.value !== '') this.props.UpdateTxPower(null,e.target.value) }} + > + dBm
}
+
+
+
RF Receiver Sensitivity
+
{
{ if (e.target.value !== '') this.props.UpdateRxSensitivity(e.target.value, null) }} + > + dBm
}
+
{
{ if (e.target.value !== '') this.props.UpdateRxSensitivity(null, e.target.value) }} + > + dBm
}
+
+
+
+
+
+
Antenna Settings
+
+
+
Antenna
+ +
{}
{this.state.antennaTypeError}
+
+
{}
{this.state.antennaTypeError}
+
+
+
EIRP
+
{this.props.eirpSiteA} dBm
+
{this.props.eirpSiteB} dBm
-
-
Site B
- {this.props.siteB.length>0 &&
{this.props.siteB}
} -
{this.props.lat2 && this.LatLonToDMS(this.props.lat2)}
-
{this.props.lon2 && this.LatLonToDMS(this.props.lon2)}
-
0
-
{this.props.amslB.toFixed(2)} m
-
{this.props.aglB.toFixed(2)} m
- -
- +
+
Gain
+
{this.props.antennaGainList[this.props.antennaList.indexOf(this.props.antennaA)]} dBi
+
{this.props.antennaGainList[this.props.antennaList.indexOf(this.props.antennaB)]} dBi
+
+
+
+
{}
+
- + - - - -
- ) - } - + + +
+ + ) } +} + export default connect(mapProps, mapDispatch)(LinkCalculation); diff --git a/sdnr/wt/odlux/apps/maintenanceApp/package.json b/sdnr/wt/odlux/apps/maintenanceApp/package.json index d2980f1dc..939044e20 100644 --- a/sdnr/wt/odlux/apps/maintenanceApp/package.json +++ b/sdnr/wt/odlux/apps/maintenanceApp/package.json @@ -28,8 +28,8 @@ "@types/react": "17.0.3", "@types/react-dom": "17.0.2", "@types/react-router-dom": "5.1.7", - "@material-ui/core": "4.11.0", - "@material-ui/icons": "4.9.1", + "@material-ui/core": "4.11.4", + "@material-ui/icons": "4.11.2", "@types/classnames": "2.2.6", "@types/flux": "3.1.8", "@types/jquery": "3.3.10", diff --git a/sdnr/wt/odlux/apps/maintenanceApp/pom.xml b/sdnr/wt/odlux/apps/maintenanceApp/pom.xml index 29eec4bed..e510d2a3b 100644 --- a/sdnr/wt/odlux/apps/maintenanceApp/pom.xml +++ b/sdnr/wt/odlux/apps/maintenanceApp/pom.xml @@ -140,8 +140,8 @@ initialize - v10.16.3 - v1.19.0 + v12.13.0 + v1.22.10 diff --git a/sdnr/wt/odlux/apps/mediatorApp/package.json b/sdnr/wt/odlux/apps/mediatorApp/package.json index 0f0e74673..74fdd33ac 100644 --- a/sdnr/wt/odlux/apps/mediatorApp/package.json +++ b/sdnr/wt/odlux/apps/mediatorApp/package.json @@ -28,8 +28,8 @@ "@types/react": "17.0.3", "@types/react-dom": "17.0.2", "@types/react-router-dom": "5.1.7", - "@material-ui/core": "4.11.0", - "@material-ui/icons": "4.9.1", + "@material-ui/core": "4.11.4", + "@material-ui/icons": "4.11.2", "@types/classnames": "2.2.6", "@types/flux": "3.1.8", "@types/jquery": "3.3.10", diff --git a/sdnr/wt/odlux/apps/mediatorApp/pom.xml b/sdnr/wt/odlux/apps/mediatorApp/pom.xml index 9d593dc90..ffc09ca38 100644 --- a/sdnr/wt/odlux/apps/mediatorApp/pom.xml +++ b/sdnr/wt/odlux/apps/mediatorApp/pom.xml @@ -140,8 +140,8 @@ initialize - v10.16.3 - v1.19.0 + v12.13.0 + v1.22.10 diff --git a/sdnr/wt/odlux/apps/minimumApp/package.json b/sdnr/wt/odlux/apps/minimumApp/package.json index bcda2fb58..6c4193310 100644 --- a/sdnr/wt/odlux/apps/minimumApp/package.json +++ b/sdnr/wt/odlux/apps/minimumApp/package.json @@ -27,8 +27,8 @@ "@types/react": "17.0.3", "@types/react-dom": "17.0.2", "@types/react-router-dom": "5.1.7", - "@material-ui/core": "4.11.0", - "@material-ui/icons": "4.9.1", + "@material-ui/core": "4.11.4", + "@material-ui/icons": "4.11.2", "@types/classnames": "2.2.6", "@types/flux": "3.1.8", "@types/jquery": "3.3.10", diff --git a/sdnr/wt/odlux/apps/minimumApp/pom.xml b/sdnr/wt/odlux/apps/minimumApp/pom.xml index dd9504be1..02a0a8dac 100644 --- a/sdnr/wt/odlux/apps/minimumApp/pom.xml +++ b/sdnr/wt/odlux/apps/minimumApp/pom.xml @@ -140,8 +140,8 @@ initialize - v10.16.3 - v1.19.0 + v12.13.0 + v1.22.10 diff --git a/sdnr/wt/odlux/apps/networkMapApp/icons/README.md b/sdnr/wt/odlux/apps/networkMapApp/icons/README.md index 85c75c4e9..b26fbc29b 100644 --- a/sdnr/wt/odlux/apps/networkMapApp/icons/README.md +++ b/sdnr/wt/odlux/apps/networkMapApp/icons/README.md @@ -19,7 +19,7 @@ Copyright of icons is as followes: */ --> -datacenter.png, lamp.png and customize.png with all variations (different colors) +datacenter.png and lamp.png Taken from MS Word diff --git a/sdnr/wt/odlux/apps/networkMapApp/icons/apartment.png.d.ts b/sdnr/wt/odlux/apps/networkMapApp/icons/apartment.png.d.ts index 9f956f813..bf398f5a4 100644 --- a/sdnr/wt/odlux/apps/networkMapApp/icons/apartment.png.d.ts +++ b/sdnr/wt/odlux/apps/networkMapApp/icons/apartment.png.d.ts @@ -1,20 +1,2 @@ -/** - * ============LICENSE_START======================================================================== - * ONAP : ccsdk feature sdnr wt odlux - * ================================================================================================= - * Copyright (C) 2020 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========================================================================== - */ - declare const apartment: string; export default apartment; \ No newline at end of file diff --git a/sdnr/wt/odlux/apps/networkMapApp/icons/customize.png.d.ts b/sdnr/wt/odlux/apps/networkMapApp/icons/customize.png.d.ts index 16327f5af..7bcffb2ca 100644 --- a/sdnr/wt/odlux/apps/networkMapApp/icons/customize.png.d.ts +++ b/sdnr/wt/odlux/apps/networkMapApp/icons/customize.png.d.ts @@ -1,20 +1,2 @@ -/** - * ============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========================================================================== - */ - declare const customize: string; export default customize; \ No newline at end of file diff --git a/sdnr/wt/odlux/apps/networkMapApp/icons/datacenter.png.d.ts b/sdnr/wt/odlux/apps/networkMapApp/icons/datacenter.png.d.ts index dc7019766..a58a9f5af 100644 --- a/sdnr/wt/odlux/apps/networkMapApp/icons/datacenter.png.d.ts +++ b/sdnr/wt/odlux/apps/networkMapApp/icons/datacenter.png.d.ts @@ -1,20 +1,2 @@ -/** - * ============LICENSE_START======================================================================== - * ONAP : ccsdk feature sdnr wt odlux - * ================================================================================================= - * Copyright (C) 2020 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========================================================================== - */ - declare const datacenter: string; export default datacenter; \ No newline at end of file diff --git a/sdnr/wt/odlux/apps/networkMapApp/icons/datacenterred.png.d.ts b/sdnr/wt/odlux/apps/networkMapApp/icons/datacenterred.png.d.ts index 74836be8d..33f3061e2 100644 --- a/sdnr/wt/odlux/apps/networkMapApp/icons/datacenterred.png.d.ts +++ b/sdnr/wt/odlux/apps/networkMapApp/icons/datacenterred.png.d.ts @@ -1,20 +1,2 @@ -/** - * ============LICENSE_START======================================================================== - * ONAP : ccsdk feature sdnr wt odlux - * ================================================================================================= - * Copyright (C) 2020 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========================================================================== - */ - declare const datacenterred: string; export default datacenterred; \ No newline at end of file diff --git a/sdnr/wt/odlux/apps/networkMapApp/icons/factory.png.d.ts b/sdnr/wt/odlux/apps/networkMapApp/icons/factory.png.d.ts index e341c5f95..b5c4f19d9 100644 --- a/sdnr/wt/odlux/apps/networkMapApp/icons/factory.png.d.ts +++ b/sdnr/wt/odlux/apps/networkMapApp/icons/factory.png.d.ts @@ -1,20 +1,2 @@ -/** - * ============LICENSE_START======================================================================== - * ONAP : ccsdk feature sdnr wt odlux - * ================================================================================================= - * Copyright (C) 2020 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========================================================================== - */ - declare const factory: string; export default factory; \ No newline at end of file diff --git a/sdnr/wt/odlux/apps/networkMapApp/icons/factoryred.png.d.ts b/sdnr/wt/odlux/apps/networkMapApp/icons/factoryred.png.d.ts index 317ff7e85..1fac0a943 100644 --- a/sdnr/wt/odlux/apps/networkMapApp/icons/factoryred.png.d.ts +++ b/sdnr/wt/odlux/apps/networkMapApp/icons/factoryred.png.d.ts @@ -1,20 +1,2 @@ -/** - * ============LICENSE_START======================================================================== - * ONAP : ccsdk feature sdnr wt odlux - * ================================================================================================= - * Copyright (C) 2020 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========================================================================== - */ - declare const factoryRed: string; export default factoryRed; \ No newline at end of file diff --git a/sdnr/wt/odlux/apps/networkMapApp/icons/lamp.png.d.ts b/sdnr/wt/odlux/apps/networkMapApp/icons/lamp.png.d.ts index eeedc7fcd..9634b1275 100644 --- a/sdnr/wt/odlux/apps/networkMapApp/icons/lamp.png.d.ts +++ b/sdnr/wt/odlux/apps/networkMapApp/icons/lamp.png.d.ts @@ -1,20 +1,2 @@ -/** - * ============LICENSE_START======================================================================== - * ONAP : ccsdk feature sdnr wt odlux - * ================================================================================================= - * Copyright (C) 2020 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========================================================================== - */ - declare const lamp: string; export default lamp; \ No newline at end of file diff --git a/sdnr/wt/odlux/apps/networkMapApp/icons/lampred.png.d.ts b/sdnr/wt/odlux/apps/networkMapApp/icons/lampred.png.d.ts index b053df0b8..12a8f91cb 100644 --- a/sdnr/wt/odlux/apps/networkMapApp/icons/lampred.png.d.ts +++ b/sdnr/wt/odlux/apps/networkMapApp/icons/lampred.png.d.ts @@ -1,20 +1,2 @@ -/** - * ============LICENSE_START======================================================================== - * ONAP : ccsdk feature sdnr wt odlux - * ================================================================================================= - * Copyright (C) 2020 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========================================================================== - */ - declare const lampred: string; export default lampred; \ No newline at end of file diff --git a/sdnr/wt/odlux/apps/networkMapApp/package.json b/sdnr/wt/odlux/apps/networkMapApp/package.json index cde312ce3..160537045 100644 --- a/sdnr/wt/odlux/apps/networkMapApp/package.json +++ b/sdnr/wt/odlux/apps/networkMapApp/package.json @@ -30,8 +30,8 @@ "@types/react": "17.0.3", "@types/react-dom": "17.0.2", "@types/react-router-dom": "5.1.7", - "@material-ui/core": "4.11.0", - "@material-ui/icons": "4.9.1", + "@material-ui/core": "4.11.4", + "@material-ui/icons": "4.11.2", "@types/classnames": "2.2.6", "@types/flux": "3.1.8", "@types/jquery": "3.3.10", diff --git a/sdnr/wt/odlux/apps/networkMapApp/pom.xml b/sdnr/wt/odlux/apps/networkMapApp/pom.xml index 8284149e0..76da05dc1 100644 --- a/sdnr/wt/odlux/apps/networkMapApp/pom.xml +++ b/sdnr/wt/odlux/apps/networkMapApp/pom.xml @@ -140,8 +140,8 @@ initialize - v10.16.3 - v1.19.0 + v12.13.0 + v1.22.10 diff --git a/sdnr/wt/odlux/apps/networkMapApp/src/actions/detailsAction.ts b/sdnr/wt/odlux/apps/networkMapApp/src/actions/detailsAction.ts index 34cf10915..a9bea4fc2 100644 --- a/sdnr/wt/odlux/apps/networkMapApp/src/actions/detailsAction.ts +++ b/sdnr/wt/odlux/apps/networkMapApp/src/actions/detailsAction.ts @@ -25,6 +25,7 @@ import { link } from '../model/link'; import { HistoryEntry } from "../model/historyEntry"; import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore'; import { Dispatch } from '../../../../framework/src/flux/store'; +import { SITEDOC_URL } from '../config'; export class SelectSiteAction extends Action { constructor(public site: Site){ @@ -80,6 +81,12 @@ export class InitializeLoadedDevicesAction extends Action{ } } +export class IsSitedocReachableAction extends Action{ + constructor(public isReachable: boolean){ + super(); + } +} + let running=false; export const UpdateDetailsView = (nodeId: string) =>(dispatcher: Dispatch, getState: () => IApplicationStoreState) =>{ @@ -137,4 +144,18 @@ running=true; dispatcher(new IsBusyCheckingDeviceListAction(false)); }); +} + +export const checkSitedockReachablity = () => async (dispatcher: Dispatch, getState: () => IApplicationStoreState) =>{ + console.log("searching for sitedoc server...") + requestRest(SITEDOC_URL+'/app/versioninfo').then(response =>{ + console.log(response); + if(response){ + + dispatcher(new IsSitedocReachableAction(true)); + + }else{ + dispatcher(new IsSitedocReachableAction(false)); + } + }) } \ No newline at end of file diff --git a/sdnr/wt/odlux/apps/networkMapApp/src/components/denseTable.tsx b/sdnr/wt/odlux/apps/networkMapApp/src/components/denseTable.tsx index 7e378b81e..e04fda547 100644 --- a/sdnr/wt/odlux/apps/networkMapApp/src/components/denseTable.tsx +++ b/sdnr/wt/odlux/apps/networkMapApp/src/components/denseTable.tsx @@ -26,7 +26,16 @@ import TableRow from '@material-ui/core/TableRow'; import Paper from '@material-ui/core/Paper'; import { makeStyles, Button, Tooltip } from '@material-ui/core'; -type props = { headers: string[], height: number, navigate?(applicationName: string, path?: string): void, onLinkClick?(id: string): void, data: any[], hover: boolean, ariaLabelRow: string, ariaLabelColumn: string[], verticalTable?: boolean, onClick?(id: string): void, actions?: boolean }; +type props = { headers: string[], + height: number, + navigate?(applicationName: string, path?: string): void, + onLinkClick?(id: string): void, data: any[], + hover: boolean, + ariaLabelRow: string, + ariaLabelColumn?: string[], + verticalTable?: boolean, + onClick?(id: string): void, + actions?: boolean }; const styles = makeStyles({ @@ -81,7 +90,7 @@ const DenseTable: React.FunctionComponent = (props) => { if (data !== undefined) { if (!props.verticalTable) { - const ariaLabel = props.ariaLabelColumn[i]; + const ariaLabel = props.ariaLabelColumn === undefined ? props.headers[i].toLowerCase() : props.ariaLabelColumn[i]; if (ariaLabel.length > 0) { return {data} } else { @@ -93,7 +102,7 @@ const DenseTable: React.FunctionComponent = (props) => { if (i === 0) { return {data} } else { - const ariaLabel = props.ariaLabelColumn[index]; + const ariaLabel = props.ariaLabelColumn === undefined ? props.headers[index].toLowerCase() : props.ariaLabelColumn[index]; return {data} } } diff --git a/sdnr/wt/odlux/apps/networkMapApp/src/components/details/linkDetails.tsx b/sdnr/wt/odlux/apps/networkMapApp/src/components/details/linkDetails.tsx index 57091aebf..96727cc0d 100644 --- a/sdnr/wt/odlux/apps/networkMapApp/src/components/details/linkDetails.tsx +++ b/sdnr/wt/odlux/apps/networkMapApp/src/components/details/linkDetails.tsx @@ -37,7 +37,7 @@ const LinkDetails: React.FunctionComponent = (props) => { if(el && el2){ if(props.link.type==="microwave") - setHeight(el!.height - el2!.y -30); + setHeight(el!.height - el2!.y -50); else setHeight(el!.height - el2!.y +20); @@ -68,10 +68,34 @@ const LinkDetails: React.FunctionComponent = (props) => { const distance = props.link.length > 0 ? props.link.length : props.link.calculatedLength; const azimuthA = props.link.azimuthA; const azimuthB = props.link.azimuthB; + const antennaA = props.link.locationA.antenna; + const antennaB = props.link.locationB.antenna; + + + let antennaData = ""; + if(antennaA!==null && antennaB!==null){ + antennaData = `&antennaNameA=${antennaA.name}&antennaGainA=${antennaA.gain}&waveguideLossA=${antennaA.waveguideLossIndB}&antennaNameB=${antennaB.name}&antennaGainB=${antennaB.gain}&waveguideLossB=${antennaB.waveguideLossIndB}`; + } + + const baseUrl = window.location.pathname.split('#')[0]; - window.open(`${baseUrl}#/linkCalculation?lat1=${siteA.lat}&lon1=${siteA.lon}&lat2=${siteB.lat}&lon2=${siteB.lon}&siteA=${nameA}&siteB=${nameB}&azimuthA=${azimuthA}&azimuthB=${azimuthB}&distance=${distance}&amslSiteA=${siteA.amsl}&AGLsiteA=${siteA.antennaHeight}&amslSiteB=${siteB.amsl}&AGLsiteB=${siteB.antennaHeight}`) + window.open(`${baseUrl}#/linkCalculation?lat1=${siteA.lat}&lon1=${siteA.lon}&lat2=${siteB.lat}&lon2=${siteB.lon}&siteA=${nameA}&siteB=${nameB}&azimuthA=${azimuthA}&azimuthB=${azimuthB}&distance=${distance}&amslSiteA=${siteA.amsl}&AGLsiteA=${siteA.antennaHeight}&amslSiteB=${siteB.amsl}&AGLsiteB=${siteB.antennaHeight}${antennaData}`) + + } + + const onLineofSightClick = (e: React.MouseEvent) =>{ + e.preventDefault(); + + const siteA= props.link.locationA; + const siteB =props.link.locationB; + + //TODO: add check if available + let heightPart = `&amslA=${siteA.amsl}&antennaHeightA=${siteA.antennaHeight}&amslB=${siteB.amsl}&antennaHeightB=${siteB.antennaHeight}`; + + const baseUrl = window.location.pathname.split('#')[0]; + window.open(`${baseUrl}#/lineofsight/los?lat1=${siteA.lat}&lon1=${siteA.lon}&lat2=${siteB.lat}&lon2=${siteB.lon}${heightPart}`); } const data = [ @@ -94,7 +118,11 @@ const LinkDetails: React.FunctionComponent = (props) => { { - props.link.type==="microwave" && + props.link.type==="microwave" &&<> + + + + }
) } diff --git a/sdnr/wt/odlux/apps/networkMapApp/src/components/details/siteDetails.tsx b/sdnr/wt/odlux/apps/networkMapApp/src/components/details/siteDetails.tsx index 3aa35c348..7f0c1c926 100644 --- a/sdnr/wt/odlux/apps/networkMapApp/src/components/details/siteDetails.tsx +++ b/sdnr/wt/odlux/apps/networkMapApp/src/components/details/siteDetails.tsx @@ -30,6 +30,9 @@ import { CheckDeviceList, InitializeLoadedDevicesAction } from '../../actions/de import { NavigateToApplication } from '../../../../../framework/src/actions/navigationActions'; import connect, { Connect, IDispatcher } from '../../../../../framework/src/flux/connect'; import { IApplicationStoreState } from '../../../../../framework/src/store/applicationStore'; +import StadokSite from '../../model/stadokSite'; +import { requestRest } from '../../../../../framework/src/services/restService'; +import StadokDetailsPopup from './stadokDetailsPopup'; type linkRow = { name: string, azimuth?: string} type deviceRow = { id: string;type: string,name: string,manufacturer: string,owner: string,status?: string,port: number[]} @@ -48,6 +51,8 @@ const SiteDetails: React.FunctionComponent = (props) => { const [value, setValue] = React.useState("links"); const [height, setHeight] = React.useState(330); + const [openPopup, setOpenPopup] = React.useState(false); + const [staSite, setStaSite] = React.useState(null); const handleResize = () =>{ const el = document.getElementById('site-details-panel')?.getBoundingClientRect(); @@ -82,35 +87,55 @@ const SiteDetails: React.FunctionComponent = (props) => { setValue(newValue); } + const getFurtherInformation = (url: string) =>{ + + const request = requestRest(url, { method: "GET"}); + + request.then(result =>{ + if(result){ + setStaSite(result); + setOpenPopup(true); + }else{ + console.error(result); + } + + + }); + } + + const closePopup = () =>{ + setOpenPopup(false); + } + //prepare link table let hasAzimuth = false; - const linkRows: linkRow[] = props.site.links.map(link=> + const linkRows: linkRow[] = props.site.links?.map(link=> { if(link.azimuthB!==null){ hasAzimuth=true; - return {name: link.name, azimuth: link.azimuthB.toFixed(2) } + return {name: link.name, azimuth: link.azimuthB.toFixed(2) } - }else{ - return {name: link.name } - } - - }); + }else{ + return {name: link.name } + } + }); const linkTableHeader = hasAzimuth ? ["Link Name", "Azimuth in °"] : ["Link Name"]; //prepare device table - const deviceRows : deviceRow[] = props.updatedDevices.map(device=>{ - return{ - id: device.id, - name: device.name, - type: device.type, - status: device.status, - manufacturer: device.manufacturer, - owner: device.owner, - port: device.port - } - }); + const deviceRows : deviceRow[] = props.updatedDevices?.map(device=>{ + return{ + id: device.id, + name: device.name, + type: device.type, + status: device.status, + manufacturer: device.manufacturer, + owner: device.owner, + port: device.port + } + }); + const adressString = props.site.address == null ? null : buildAdress(props.site.address); @@ -152,12 +177,12 @@ const SiteDetails: React.FunctionComponent = (props) => { value === "links" && <> { - props.site.links.length === 0 && + props.site.links==null && No links available. } { - props.site.links.length > 0 && + props.site.links?.length > 0 && } @@ -178,6 +203,15 @@ const SiteDetails: React.FunctionComponent = (props) => { } } + { + props.isSitedocReachable && props.site.furtherInformation!==null && props.site.furtherInformation.length>0 && + + } + + { + staSite !== null && openPopup && + } +
) } @@ -200,7 +234,8 @@ const buildAdress = (adress: Address) =>{ } const mapStateToProps = (state: IApplicationStoreState) => ({ - updatedDevices: state.network.details.checkedDevices + updatedDevices: state.network.details.checkedDevices, + isSitedocReachable: state.network.details.isSitedocReachable }); const mapDispatchToProps = (dispatcher: IDispatcher) => ({ diff --git a/sdnr/wt/odlux/apps/networkMapApp/src/components/details/stadokDetailsPopup.tsx b/sdnr/wt/odlux/apps/networkMapApp/src/components/details/stadokDetailsPopup.tsx new file mode 100644 index 000000000..4f3235db7 --- /dev/null +++ b/sdnr/wt/odlux/apps/networkMapApp/src/components/details/stadokDetailsPopup.tsx @@ -0,0 +1,274 @@ +/** + * ============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========================================================================== + */ + +import * as React from 'react'; + +import MuiDialogTitle from '@material-ui/core/DialogTitle'; +import { AppBar, Dialog, DialogContent, IconButton, Tab, Tabs, TextField, Typography } from '@material-ui/core'; +import CloseIcon from '@material-ui/icons/Close'; +import { withStyles, WithStyles, createStyles, Theme, makeStyles } from '@material-ui/core/styles'; + + +import StadokSite from '../../model/stadokSite'; +import { LatLonToDMS } from '../../utils/mapUtils'; +import DenseTable from '../../components/denseTable'; +import { requestRest } from '../../../../../framework/src/services/restService'; +import { OrderToDisplay, StadokOrder } from '../../model/stadokOrder'; +import { CSSProperties } from '@material-ui/core/styles/withStyles'; +import { SITEDOC_URL } from '../../config'; + + +type props = { site: StadokSite; onClose(): void; open:boolean }; + +const styles = (theme: Theme) => createStyles({ + root: { + margin: 0, + padding: theme.spacing(2), + }, + closeButton: { + position: 'absolute', + right: theme.spacing(1), + top: theme.spacing(1), + color: theme.palette.grey[500], + }, +}); + +const useStyles = makeStyles({ + largeImage:{cursor:'pointer', width:300}, + smallImage:{cursor:'pointer', width: 50, marginTop:'10px', marginLeft:'10px'} +}); + +const StadokDetailsPopup: React.FunctionComponent = (props) => { + const classes = useStyles(); + + const [open, setOpen] = React.useState(props.open); + const [value, setValue] = React.useState("devices"); + const [orders, setOrders] = React.useState(null); + + const DialogTitle = withStyles(styles)((props: any) => { + const { children, classes, onClose, ...other } = props; + return ( + + {children} + {onClose ? ( + + + + ) : null} + + ); + }); + + const getContacts = (site: StadokSite) =>{ + const contacts = []; + + if(site.createdBy){ + contacts.push({h: "Site Creator",col1: site.createdBy.firstName, col2: site.createdBy.lastName, col3: site.createdBy.email, col4: site.createdBy.telephoneNumber }); + } + + if(site.contacts.manager){ + contacts.push({h: "Manager",col1: site.contacts.manager.firstName, col2: site.contacts.manager.lastName, col3: site.contacts.manager.email, col4: site.contacts.manager.telephoneNumber }); + } + + if(site.contacts.owner){ + contacts.push({h: "Owner",col1: site.contacts.owner.firstName, col2: site.contacts.owner.lastName, col3: site.contacts.owner.email, col4: site.contacts.owner.telephoneNumber }); + } + return contacts; + } + + const onClose = () =>{ + // setOpen(false); + props.onClose() + } + + //todo: use a set 'panelId' -> which values are allowed + const onHandleTabChange = (event: React.ChangeEvent<{}>, newValue: string) => { + setValue(newValue); +} +console.log(props.site) + const contacts = getContacts(props.site); + + const orderUrl=`${SITEDOC_URL}/site/${props.site.siteId}/orders`; + + if(orders==null){ + requestRest(orderUrl,{ method: "GET"}).then(result =>{ + if(result){ + const orderList = result.map(order =>{ + return OrderToDisplay.parse(order); + }); + setOrders(orderList); + + }else{ + setOrders([]); + } + }); + } + + const createOrderInfo = () => { + + if (orders === null) { + return (
+ + Loading orders + +
) + } else if (orders.length === 0) { + return (
+ + No orders available + +
) + } else { + return + } + } + + const displayImages = () => { + + if (props.site.images.length === 1) { + return stadokImage(props.site.siteId, props.site.images[0],"large") + } else { + return <> + { + stadokImage(props.site.siteId, props.site.images[0], "large") + } +
+ + { + props.site.images.length<=9 ? + props.site.images.slice(1, props.site.images.length).map(image => + stadokImage(props.site.siteId, image, "small") + ) + : + <> + { + props.site.images.slice(1, 9).map(image => + stadokImage(props.site.siteId, image, "small") + ) + } + + + } +
+ + } + + } + + const stadokImage = (siteId: string, imagename: string, size: 'large' | 'small') => { + const url = `${SITEDOC_URL}/site/${siteId}/files/${imagename}`; + const className = size === "small" ? classes.smallImage : classes.largeImage; + return window.open(url)} /> + + } + + + return ( + + {props.site.siteId} + + +
+
+ + + + + { + props.site.type !== undefined && props.site.type.length > 0 && + + } + + + + + + + + + + + + + + + + + { + value == "devices" && (props.site.devices?.length>0 ? + + : +
+ + No devices available + +
) + } + { + value == "contacts" && (contacts.length>0 ? + + : +
+ + No contacts available + +
) + } + { + value == "safteyInfo" && (props.site.safteyNotices.length>0 ? + + : +
+ + No saftey notices applicable + +
) + } + { + value == "logs" && (props.site.logs.length>0 ? + + : +
+ + No activity log available + +
) + } + + { + value ==="orders" && createOrderInfo() + } + +
+
+ { + props.site.images.length == 0 ? + + No images available + + : displayImages() + } +
+
+ +
+
) + +} + +export default StadokDetailsPopup; \ No newline at end of file diff --git a/sdnr/wt/odlux/apps/networkMapApp/src/components/map/connectionInfo.tsx b/sdnr/wt/odlux/apps/networkMapApp/src/components/map/connectionInfo.tsx index c1fdccfb8..3b5a15ce5 100644 --- a/sdnr/wt/odlux/apps/networkMapApp/src/components/map/connectionInfo.tsx +++ b/sdnr/wt/odlux/apps/networkMapApp/src/components/map/connectionInfo.tsx @@ -29,7 +29,7 @@ type props = Connect; const ConnectionInfo: React.FunctionComponent = (props) => { - return ((props.isTopoServerReachable === false || props.isTileServerReachable === false )? + return ((props.isTopoServerReachable === false || props.isTileServerReachable === false )?
Connection Error
{props.isTileServerReachable === false && Tile data can't be loaded.} diff --git a/sdnr/wt/odlux/apps/networkMapApp/src/components/map/iconSwitch.tsx b/sdnr/wt/odlux/apps/networkMapApp/src/components/map/iconSwitch.tsx index bb98cb467..221e7dab8 100644 --- a/sdnr/wt/odlux/apps/networkMapApp/src/components/map/iconSwitch.tsx +++ b/sdnr/wt/odlux/apps/networkMapApp/src/components/map/iconSwitch.tsx @@ -32,9 +32,9 @@ const IconSwitch: React.FunctionComponent = (props) =>{ return ( props.visible ? - } + control={} label="Show icons" labelPlacement="end" />: null) diff --git a/sdnr/wt/odlux/apps/networkMapApp/src/components/map/map.tsx b/sdnr/wt/odlux/apps/networkMapApp/src/components/map/map.tsx index 9637d745e..1314edbba 100644 --- a/sdnr/wt/odlux/apps/networkMapApp/src/components/map/map.tsx +++ b/sdnr/wt/odlux/apps/networkMapApp/src/components/map/map.tsx @@ -54,6 +54,7 @@ let notLoadedBoundingBoxes: mapboxgl.LngLatBounds[] = []; let lastBoundingBox: mapboxgl.LngLatBounds | null = null; let myRef = React.createRef(); +import 'mapbox-gl/dist/mapbox-gl.css'; class Map extends React.Component { @@ -158,7 +159,7 @@ class Map extends React.Component { mapLayerService.addBaseSources(map, this.props.selectedSite, this.props.selectedLink); addImages(map, (result: boolean)=>{ - if(map.getZoom()>11) + if(map.getZoom()>11 && this.props.showIcons) { mapLayerService.addIconLayers(map, this.props.selectedSite?.properties.id) }else{ @@ -190,134 +191,142 @@ class Map extends React.Component { } }) .catch(error => this.props.handleConnectionError(error)); + + map.on('click', this.mapClick); + map.on('moveend', this.mapMoveEnd); + map.on('move', this.mapMove); + }); + } - map.on('click', (e: any) => { + mapMove = () => { + + const mapZoom = map.getZoom(); - if (map.getLayer('points')) { // data is shown as points + const boundingBox = map.getBounds(); + + this.loadNetworkData(boundingBox); + if (mapZoom > 9) { - var clickedLines = getUniqueFeatures(map.queryRenderedFeatures([[e.point.x - 5, e.point.y - 5], - [e.point.x + 5, e.point.y + 5]], { - layers: ['microwave-lines', 'fibre-lines'] - }), "id"); + if (map.getLayer('points')) { + map.setLayoutProperty('selectedPoints', 'visibility', 'visible'); + map.setPaintProperty('points', 'circle-radius', 7); + } + } else { - const clickedPoints = getUniqueFeatures(map.queryRenderedFeatures(e.point, { layers: ['points'] }), "id"); - const alarmedSites = getUniqueFeatures(map.queryRenderedFeatures(e.point, { layers: ['alarmedPoints'] }), "id"); + // reduce size of points / lines if zoomed out + map.setPaintProperty('points', 'circle-radius', 2); + map.setLayoutProperty('selectedPoints', 'visibility', 'none'); - if (clickedPoints.length != 0) { + if (mapZoom <= 4) { + map.setPaintProperty('fibre-lines', 'line-width', 1); + map.setPaintProperty('microwave-lines', 'line-width', 1); + + } else { + map.setPaintProperty('fibre-lines', 'line-width', 2); + map.setPaintProperty('microwave-lines', 'line-width', 2); + } + } + }; + mapClick = (e: any) => { - if (alarmedSites.length > 0) { - alarmedSites.forEach(alarm => { - const index = clickedPoints.findIndex(item => item.properties!.id === alarm.properties!.id); + + if (map.getLayer('points')) { // data is shown as points - if (index !== -1) { - clickedPoints[index].properties!.alarmed = true; - clickedPoints[index].properties!.type = "alarmed"; - } - }); - } + var clickedLines = getUniqueFeatures(map.queryRenderedFeatures([[e.point.x - 5, e.point.y - 5], + [e.point.x + 5, e.point.y + 5]], { + layers: ['microwave-lines', 'fibre-lines'] + }), "id"); - this.showSitePopup(clickedPoints, e.point.x, e.point.y); - } else if (clickedLines.length != 0) { - this.showLinkPopup(clickedLines, e.point.x, e.point.y); - } + const clickedPoints = getUniqueFeatures(map.queryRenderedFeatures(e.point, { layers: ['points'] }), "id"); + const alarmedSites = getUniqueFeatures(map.queryRenderedFeatures(e.point, { layers: ['alarmedPoints'] }), "id"); + if (clickedPoints.length != 0) { - } else { // data is shown as icons - const clickedSites = getUniqueFeatures(map.queryRenderedFeatures(e.point, { layers: ['point-lamps', 'point-building', 'point-data-center', 'point-factory', 'point-remaining'] }), "id"); - const clickedLines = getUniqueFeatures(map.queryRenderedFeatures([[e.point.x - 5, e.point.y - 5], - [e.point.x + 5, e.point.y + 5]], { - layers: ['microwave-lines', 'fibre-lines'] - }), "id"); + if (alarmedSites.length > 0) { + alarmedSites.forEach(alarm => { + const index = clickedPoints.findIndex(item => item.properties!.id === alarm.properties!.id); - if (clickedSites.length > 0) - this.showSitePopup(clickedSites, e.point.x, e.point.y); - else if (clickedLines.length != 0) { - this.showLinkPopup(clickedLines, e.point.x, e.point.y); + if (index !== -1) { + clickedPoints[index].properties!.alarmed = true; + clickedPoints[index].properties!.type = "alarmed"; + } + }); } - } - }); + this.showSitePopup(clickedPoints, e.point.x, e.point.y); + } else if (clickedLines.length != 0) { + this.showLinkPopup(clickedLines, e.point.x, e.point.y); + } - map.on('moveend', () => { - const mapZoom = Number(map.getZoom().toFixed(2)); - const lat = Number(map.getCenter().lat.toFixed(4)); - const lon = Number(map.getCenter().lng.toFixed(4)); + } else { // data is shown as icons + const clickedSites = getUniqueFeatures(map.queryRenderedFeatures(e.point, { layers: ['point-lamps', 'point-building', 'point-data-center', 'point-factory', 'point-remaining'] }), "id"); + const clickedLines = getUniqueFeatures(map.queryRenderedFeatures([[e.point.x - 5, e.point.y - 5], + [e.point.x + 5, e.point.y + 5]], { + layers: ['microwave-lines', 'fibre-lines'] + }), "id"); - if (this.props.lat !== lat || this.props.lon !== lon || this.props.zoom !== mapZoom) { - this.props.updateMapPosition(lat, lon, mapZoom) + if (clickedSites.length > 0) + this.showSitePopup(clickedSites, e.point.x, e.point.y); + else if (clickedLines.length != 0) { + this.showLinkPopup(clickedLines, e.point.x, e.point.y); } + } + }; - // update the url to current lat,lon,zoom values + mapMoveEnd = () => { - const currentUrl = window.location.href; - const parts = currentUrl.split(URL_BASEPATH); - if(parts.length>0){ + const mapZoom = Number(map.getZoom().toFixed(2)); + const lat = Number(map.getCenter().lat.toFixed(4)); + const lon = Number(map.getCenter().lng.toFixed(4)); - const detailsPath = parts[1].split("/details/"); - if (detailsPath[1] !== undefined && detailsPath[1].length > 0) { - this.props.history.replace(`/${URL_BASEPATH}/${map.getCenter().lat.toFixed(4)},${map.getCenter().lng.toFixed(4)},${mapZoom.toFixed(2)}/details/${detailsPath[1]}`) - } - else { - this.props.history.replace(`/${URL_BASEPATH}/${map.getCenter().lat.toFixed(4)},${map.getCenter().lng.toFixed(4)},${mapZoom.toFixed(2)}`) - } - } - - - //switch icon layers if applicable - mapLayerService.showIconLayers(map, this.props.showIcons, this.props.selectedSite?.properties.id); + if (this.props.lat !== lat || this.props.lon !== lon || this.props.zoom !== mapZoom) { + this.props.updateMapPosition(lat, lon, mapZoom) + } - //update statistics - const boundingBox = map.getBounds(); + // update the url to current lat,lon,zoom values - fetch(`${URL_API}/info/count/${boundingBox.getWest()},${boundingBox.getSouth()},${boundingBox.getEast()},${boundingBox.getNorth()}`) - .then(result => verifyResponse(result)) - .then(res => res.json()) - .then(result => { - if (result.links !== this.props.linkCount || result.sites !== this.props.siteCount) { - this.props.setStatistics(result.links, result.sites); - } - }) - .catch(error => this.props.handleConnectionError(error));; - }) + const currentUrl = window.location.href; + const parts = currentUrl.split(URL_BASEPATH); + if (parts.length > 0) { - map.on('move', () => { - const mapZoom = map.getZoom(); + const detailsPath = parts[1].split("/details/"); - const boundingBox = map.getBounds(); + if (detailsPath[1] !== undefined && detailsPath[1].length > 0) { + this.props.history.replace(`/${URL_BASEPATH}/${map.getCenter().lat.toFixed(4)},${map.getCenter().lng.toFixed(4)},${mapZoom.toFixed(2)}/details/${detailsPath[1]}`) + } + else { + this.props.history.replace(`/${URL_BASEPATH}/${map.getCenter().lat.toFixed(4)},${map.getCenter().lng.toFixed(4)},${mapZoom.toFixed(2)}`) + } + } - this.loadNetworkData(boundingBox); - if (mapZoom > 9) { - if (map.getLayer('points')) { - map.setLayoutProperty('selectedPoints', 'visibility', 'visible'); - map.setPaintProperty('points', 'circle-radius', 7); - } - } else { + //switch icon layers if applicable - // reduce size of points / lines if zoomed out - map.setPaintProperty('points', 'circle-radius', 2); - map.setLayoutProperty('selectedPoints', 'visibility', 'none'); + mapLayerService.showIconLayers(map, this.props.showIcons, this.props.selectedSite?.properties.id); - if (mapZoom <= 4) { - map.setPaintProperty('fibre-lines', 'line-width', 1); - map.setPaintProperty('microwave-lines', 'line-width', 1); + //update statistics + const boundingBox = map.getBounds(); - } else { - map.setPaintProperty('fibre-lines', 'line-width', 2); - map.setPaintProperty('microwave-lines', 'line-width', 2); + fetch(`${URL_API}/info/count/${boundingBox.getWest()},${boundingBox.getSouth()},${boundingBox.getEast()},${boundingBox.getNorth()}`) + .then(result => verifyResponse(result)) + .then(res => res.json()) + .then(result => { + if (result.links !== this.props.linkCount || result.sites !== this.props.siteCount) { + this.props.setStatistics(result.links, result.sites); } - } - }); + }) + .catch(error => this.props.handleConnectionError(error));; } componentDidUpdate(prevProps: mapProps, prevState: {}) { + if(prevProps !== this.props){ //(load map) //triggered if either settings were done loading or tile/topology server connectivity checked if(prevProps.settings !== this.props.settings || this.props.isConnectivityCheckBusy !== prevProps.isConnectivityCheckBusy){ @@ -329,6 +338,7 @@ class Map extends React.Component { //if everything done loading/reachable, load map if(!this.props.isConnectivityCheckBusy && this.props.isTileServerReachable && !this.props.settings.isLoadingData && (prevProps.settings.isLoadingData !==this.props.settings.isLoadingData || prevProps.isConnectivityCheckBusy !== this.props.isConnectivityCheckBusy)){ + if(map == undefined){ this.setupMap(); } @@ -443,12 +453,22 @@ class Map extends React.Component { } } } + } } componentWillUnmount(){ + + //unregister events window.removeEventListener("menu-resized", this.handleResize); - lastBoundingBox=null; + + if(map){ + map.off('click', this.mapClick); + map.off('moveend', this.mapMoveEnd); + map.off('move', this.mapMove); + } + lastBoundingBox=null; + // will be checked again on next load this.props.setConnectivityCheck(true); } @@ -624,7 +644,7 @@ class Map extends React.Component { diff --git a/sdnr/wt/odlux/apps/networkMapApp/src/components/map/searchBar.tsx b/sdnr/wt/odlux/apps/networkMapApp/src/components/map/searchBar.tsx index 45bc6092d..307c5d203 100644 --- a/sdnr/wt/odlux/apps/networkMapApp/src/components/map/searchBar.tsx +++ b/sdnr/wt/odlux/apps/networkMapApp/src/components/map/searchBar.tsx @@ -46,6 +46,7 @@ const styles = makeStyles({ top: 15, marginLeft: 5, width: 400, + zIndex:1 }, input: { flex: 1, diff --git a/sdnr/wt/odlux/apps/networkMapApp/src/components/map/statistics.tsx b/sdnr/wt/odlux/apps/networkMapApp/src/components/map/statistics.tsx index 116b789d7..562689198 100644 --- a/sdnr/wt/odlux/apps/networkMapApp/src/components/map/statistics.tsx +++ b/sdnr/wt/odlux/apps/networkMapApp/src/components/map/statistics.tsx @@ -41,7 +41,7 @@ const Statistics: React.FunctionComponent = (props: props) =>{ const reachabe = props.isTopoServerReachable && props.isTileServerReachable; - return ( + return (
Statistics diff --git a/sdnr/wt/odlux/apps/networkMapApp/src/config.ts b/sdnr/wt/odlux/apps/networkMapApp/src/config.ts index 633bd3732..bdb7d15e6 100644 --- a/sdnr/wt/odlux/apps/networkMapApp/src/config.ts +++ b/sdnr/wt/odlux/apps/networkMapApp/src/config.ts @@ -17,6 +17,7 @@ */ export const URL_API="/topology/network" +export const SITEDOC_URL="/sitedoc"; export const URL_TILE_API = '/tiles'; // http://tile.openstreetmap.org can be used for local testing, never commit with tile url changed! /tiles diff --git a/sdnr/wt/odlux/apps/networkMapApp/src/handlers/detailsReducer.ts b/sdnr/wt/odlux/apps/networkMapApp/src/handlers/detailsReducer.ts index 67e10e629..8a7fc6ada 100644 --- a/sdnr/wt/odlux/apps/networkMapApp/src/handlers/detailsReducer.ts +++ b/sdnr/wt/odlux/apps/networkMapApp/src/handlers/detailsReducer.ts @@ -20,13 +20,14 @@ import { IActionHandler } from '../../../../framework/src/flux/action'; import { link } from "../model/link"; import { Site, Device } from "../model/site"; import { HistoryEntry } from "../model/historyEntry"; -import { SelectSiteAction, SelectLinkAction, AddToHistoryAction, ClearHistoryAction, IsBusyCheckingDeviceListAction, FinishedLoadingDeviceListAction, ClearLoadedDevicesAction, ClearDetailsAction, InitializeLoadedDevicesAction } from '../actions/detailsAction'; +import { SelectSiteAction, SelectLinkAction, AddToHistoryAction, ClearHistoryAction, IsBusyCheckingDeviceListAction, FinishedLoadingDeviceListAction, ClearLoadedDevicesAction, ClearDetailsAction, InitializeLoadedDevicesAction, IsSitedocReachableAction } from '../actions/detailsAction'; export type DetailsStoreState={ data: Site | link | null, history: HistoryEntry[], isBusyCheckingDeviceList: boolean, - checkedDevices: Device[] + checkedDevices: Device[], + isSitedocReachable: boolean } @@ -34,7 +35,8 @@ const initialState: DetailsStoreState = { data: null, history:[], isBusyCheckingDeviceList: false, - checkedDevices: [] + checkedDevices: [], + isSitedocReachable: false } export const DetailsReducer:IActionHandler=(state = initialState, action)=>{ @@ -63,6 +65,8 @@ export const DetailsReducer:IActionHandler=(state = initialSt }else if(action instanceof InitializeLoadedDevicesAction){ state = Object.assign({}, state, {checkedDevices: action.devices}); + }else if(action instanceof IsSitedocReachableAction){ + state = Object.assign({}, state, {isSitedocReachable: action.isReachable}); } diff --git a/sdnr/wt/odlux/apps/networkMapApp/src/index.html b/sdnr/wt/odlux/apps/networkMapApp/src/index.html index e64c08c1e..f70571152 100644 --- a/sdnr/wt/odlux/apps/networkMapApp/src/index.html +++ b/sdnr/wt/odlux/apps/networkMapApp/src/index.html @@ -13,15 +13,14 @@
-