summaryrefslogtreecommitdiffstats
path: root/sdnr/wt/odlux/apps
diff options
context:
space:
mode:
authorAijana Schumann <aijana.schumann@highstreet-technologies.com>2021-08-04 11:59:18 +0200
committerAijana Schumann <aijana.schumann@highstreet-technologies.com>2021-08-04 16:06:05 +0200
commit437f67407aece6f7aed8e989638b0d64075f0c0a (patch)
tree53e9e336cd8544edf8a06c889e33f5b9c98fe083 /sdnr/wt/odlux/apps
parent1c4995eb199437e9c86336efff9972f2049e1532 (diff)
Update ODLUX
Add various updates and bugfixes to NetworkMap, Configuration, LinkCalculation and ConnectApp Issue-ID: CCSDK-3414 Signed-off-by: Aijana Schumann <aijana.schumann@highstreet-technologies.com> Change-Id: I6ea5c3a9d6ccbe9c450da43220654a53fd2f262b Signed-off-by: Aijana Schumann <aijana.schumann@highstreet-technologies.com>
Diffstat (limited to 'sdnr/wt/odlux/apps')
-rw-r--r--sdnr/wt/odlux/apps/apiDemo/package.json4
-rw-r--r--sdnr/wt/odlux/apps/apiDemo/pom.xml4
-rw-r--r--sdnr/wt/odlux/apps/configurationApp/package.json4
-rw-r--r--sdnr/wt/odlux/apps/configurationApp/pom.xml4
-rw-r--r--sdnr/wt/odlux/apps/configurationApp/src/actions/deviceActions.ts26
-rw-r--r--sdnr/wt/odlux/apps/configurationApp/src/index.html6
-rw-r--r--sdnr/wt/odlux/apps/configurationApp/src/models/yang.ts4
-rw-r--r--sdnr/wt/odlux/apps/configurationApp/src/pluginConfiguration.tsx2
-rw-r--r--sdnr/wt/odlux/apps/configurationApp/src/services/restServices.ts123
-rw-r--r--sdnr/wt/odlux/apps/configurationApp/src/views/configurationApplication.tsx14
-rw-r--r--sdnr/wt/odlux/apps/configurationApp/src/yang/yangParser.ts47
-rw-r--r--sdnr/wt/odlux/apps/connectApp/package.json4
-rw-r--r--sdnr/wt/odlux/apps/connectApp/pom.xml4
-rw-r--r--sdnr/wt/odlux/apps/connectApp/src/actions/tlsKeyActions.ts60
-rw-r--r--sdnr/wt/odlux/apps/connectApp/src/components/connectionStatusLog.tsx2
-rw-r--r--sdnr/wt/odlux/apps/connectApp/src/components/editNetworkElementDialog.tsx131
-rw-r--r--sdnr/wt/odlux/apps/connectApp/src/components/networkElements.tsx47
-rw-r--r--sdnr/wt/odlux/apps/connectApp/src/handlers/connectAppRootHandler.ts5
-rw-r--r--sdnr/wt/odlux/apps/connectApp/src/handlers/tlsKeyHandler.ts55
-rw-r--r--sdnr/wt/odlux/apps/connectApp/src/index.html2
-rw-r--r--sdnr/wt/odlux/apps/connectApp/src/models/networkElementConnection.ts7
-rw-r--r--sdnr/wt/odlux/apps/connectApp/src/pluginConnect.tsx4
-rw-r--r--sdnr/wt/odlux/apps/connectApp/src/services/connectService.ts522
-rw-r--r--sdnr/wt/odlux/apps/demoApp/package.json4
-rw-r--r--sdnr/wt/odlux/apps/demoApp/pom.xml4
-rw-r--r--sdnr/wt/odlux/apps/eventLogApp/package.json4
-rw-r--r--sdnr/wt/odlux/apps/eventLogApp/pom.xml4
-rw-r--r--sdnr/wt/odlux/apps/faultApp/package.json4
-rw-r--r--sdnr/wt/odlux/apps/faultApp/pom.xml4
-rw-r--r--sdnr/wt/odlux/apps/helpApp/package.json4
-rw-r--r--sdnr/wt/odlux/apps/helpApp/pom.xml4
-rw-r--r--sdnr/wt/odlux/apps/inventoryApp/package.json4
-rw-r--r--sdnr/wt/odlux/apps/inventoryApp/pom.xml4
-rw-r--r--sdnr/wt/odlux/apps/linkCalculationApp/package.json4
-rw-r--r--sdnr/wt/odlux/apps/linkCalculationApp/pom.xml4
-rw-r--r--sdnr/wt/odlux/apps/linkCalculationApp/src/actions/commonLinkCalculationActions.ts141
-rw-r--r--sdnr/wt/odlux/apps/linkCalculationApp/src/handlers/linkCalculationAppRootHandler.ts51
-rw-r--r--sdnr/wt/odlux/apps/linkCalculationApp/src/views/Style.scss143
-rw-r--r--sdnr/wt/odlux/apps/linkCalculationApp/src/views/linkCalculationComponent.tsx662
-rw-r--r--sdnr/wt/odlux/apps/maintenanceApp/package.json4
-rw-r--r--sdnr/wt/odlux/apps/maintenanceApp/pom.xml4
-rw-r--r--sdnr/wt/odlux/apps/mediatorApp/package.json4
-rw-r--r--sdnr/wt/odlux/apps/mediatorApp/pom.xml4
-rw-r--r--sdnr/wt/odlux/apps/minimumApp/package.json4
-rw-r--r--sdnr/wt/odlux/apps/minimumApp/pom.xml4
-rw-r--r--sdnr/wt/odlux/apps/networkMapApp/icons/README.md2
-rw-r--r--sdnr/wt/odlux/apps/networkMapApp/icons/apartment.png.d.ts18
-rw-r--r--sdnr/wt/odlux/apps/networkMapApp/icons/customize.png.d.ts18
-rw-r--r--sdnr/wt/odlux/apps/networkMapApp/icons/datacenter.png.d.ts18
-rw-r--r--sdnr/wt/odlux/apps/networkMapApp/icons/datacenterred.png.d.ts18
-rw-r--r--sdnr/wt/odlux/apps/networkMapApp/icons/factory.png.d.ts18
-rw-r--r--sdnr/wt/odlux/apps/networkMapApp/icons/factoryred.png.d.ts18
-rw-r--r--sdnr/wt/odlux/apps/networkMapApp/icons/lamp.png.d.ts18
-rw-r--r--sdnr/wt/odlux/apps/networkMapApp/icons/lampred.png.d.ts18
-rw-r--r--sdnr/wt/odlux/apps/networkMapApp/package.json4
-rw-r--r--sdnr/wt/odlux/apps/networkMapApp/pom.xml4
-rw-r--r--sdnr/wt/odlux/apps/networkMapApp/src/actions/detailsAction.ts21
-rw-r--r--sdnr/wt/odlux/apps/networkMapApp/src/components/denseTable.tsx15
-rw-r--r--sdnr/wt/odlux/apps/networkMapApp/src/components/details/linkDetails.tsx34
-rw-r--r--sdnr/wt/odlux/apps/networkMapApp/src/components/details/siteDetails.tsx77
-rw-r--r--sdnr/wt/odlux/apps/networkMapApp/src/components/details/stadokDetailsPopup.tsx274
-rw-r--r--sdnr/wt/odlux/apps/networkMapApp/src/components/map/connectionInfo.tsx2
-rw-r--r--sdnr/wt/odlux/apps/networkMapApp/src/components/map/iconSwitch.tsx4
-rw-r--r--sdnr/wt/odlux/apps/networkMapApp/src/components/map/map.tsx204
-rw-r--r--sdnr/wt/odlux/apps/networkMapApp/src/components/map/searchBar.tsx1
-rw-r--r--sdnr/wt/odlux/apps/networkMapApp/src/components/map/statistics.tsx2
-rw-r--r--sdnr/wt/odlux/apps/networkMapApp/src/config.ts1
-rw-r--r--sdnr/wt/odlux/apps/networkMapApp/src/handlers/detailsReducer.ts10
-rw-r--r--sdnr/wt/odlux/apps/networkMapApp/src/index.html5
-rw-r--r--sdnr/wt/odlux/apps/networkMapApp/src/model/link.ts10
-rw-r--r--sdnr/wt/odlux/apps/networkMapApp/src/model/site.ts3
-rw-r--r--sdnr/wt/odlux/apps/networkMapApp/src/model/stadokOrder.ts56
-rw-r--r--sdnr/wt/odlux/apps/networkMapApp/src/model/stadokSite.ts54
-rw-r--r--sdnr/wt/odlux/apps/networkMapApp/src/pluginTransport.tsx7
-rw-r--r--sdnr/wt/odlux/apps/networkMapApp/src/utils/mapLayers.ts2
-rw-r--r--sdnr/wt/odlux/apps/networkMapApp/webpack.config.js13
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/package.json4
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/pom.xml4
78 files changed, 2044 insertions, 1063 deletions
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 @@
<!-- optional: default phase is "generate-resources" -->
<phase>initialize</phase>
<configuration>
- <nodeVersion>v10.16.3</nodeVersion>
- <yarnVersion>v1.19.0</yarnVersion>
+ <nodeVersion>v12.13.0</nodeVersion>
+ <yarnVersion>v1.22.10</yarnVersion>
</configuration>
</execution>
<execution>
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 @@
<!-- optional: default phase is "generate-resources" -->
<phase>initialize</phase>
<configuration>
- <nodeVersion>v10.16.3</nodeVersion>
- <yarnVersion>v1.19.0</yarnVersion>
+ <nodeVersion>v12.13.0</nodeVersion>
+ <yarnVersion>v1.22.10</yarnVersion>
</configuration>
</execution>
<execution>
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 @@
<script type="text/javascript" src="./config.js"></script>
<script>
// run the application
- require(["app", "connectApp", "maintenanceApp", "configurationApp"], function (app, connectApp, maintenanceApp, configurationApp) {
+ require(["app", "connectApp", "maintenanceApp", "configurationApp", "faultApp"], function (app, connectApp, maintenanceApp, configurationApp, faultApp) {
connectApp.register();
configurationApp.register();
maintenanceApp.register();
- app("./app.tsx").configureApplication({ authentication:"oauth", enablePolicy: true,});
+ faultApp.register();
+ // app("./app.tsx").configureApplication({ authentication:"oauth", enablePolicy: true,});
+ app("./app.tsx").configureApplication({ authentication:"basic", enablePolicy: false,});
app("./app.tsx").runApplication();
});
</script>
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<CapabilityAnswer> {
+ 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 importOnlyModules = importOnlyResult
+ ? 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 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<any>(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<any>(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<any>(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<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;
+
+ return { availableCapabilities, unavailableCapabilities, importOnlyModules };
}
public async getMountedNetworkElementByMountId(nodeId: string): Promise<NetworkElementConnection | null> {
@@ -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<ConfigurationApp
private renderUIViewList(listSpecification: ViewSpecification, dataPath: string, listKeyProperty: string, apiDocPath: string, listData: { [key: string]: any }[]) {
const listElements = listSpecification.elements;
- const apiDocPathCreate = apiDocPath ? `${location.origin}${apiDocPath
+ const apiDocPathCreate = apiDocPath ? `${location.origin}${apiDocPath
.replace("$$$standard$$$", "topology-netconfnode%20resources%20-%20RestConf%20RFC%208040")
- .replace("$$$action$$$", "put")}_${listKeyProperty.replace(/[\/=\-\:]/g, '_')}_` : undefined;
+ .replace("$$$action$$$", "put")}${listKeyProperty ? `_${listKeyProperty.replace(/[\/=\-\:]/g, '_')}_` : '' }` : undefined;
+
+ const config = listSpecification.config && listKeyProperty; // We can not configure a list with no key.
const navigate = (path: string) => {
this.props.history.push(`${this.props.match.url}${path}`);
@@ -593,7 +595,7 @@ class ConfigurationApplicationComponent extends React.Component<ConfigurationApp
onClick: () => {
navigate("[]"); // empty key means new element
},
- disabled: !listSpecification.config,
+ disabled: !config,
};
const addWithApiDocElementAction = {
@@ -603,7 +605,7 @@ class ConfigurationApplicationComponent extends React.Component<ConfigurationApp
onClick: () => {
window.open(apiDocPathCreate, '_blank');
},
- disabled: !listSpecification.config,
+ disabled: !config,
};
const { classes, removeElement } = this.props;
@@ -650,13 +652,13 @@ class ConfigurationApplicationComponent extends React.Component<ConfigurationApp
}, []).concat([{
property: "Actions", disableFilter: true, disableSorting: true, type: ColumnType.custom, customControl: (({ rowData }) => {
return (
- <DeleteIconWithConfirmation disabled={!listSpecification.config} rowData={rowData} onReload={() => this.props.vPath && this.props.reloadView(this.props.vPath)} />
+ <DeleteIconWithConfirmation disabled={!config} rowData={rowData} onReload={() => 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.
}} ></SelectElementTable>
);
}
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 @@
<!-- optional: default phase is "generate-resources" -->
<phase>initialize</phase>
<configuration>
- <nodeVersion>v10.16.3</nodeVersion>
- <yarnVersion>v1.19.0</yarnVersion>
+ <nodeVersion>v12.13.0</nodeVersion>
+ <yarnVersion>v1.22.10</yarnVersion>
</configuration>
</execution>
<execution>
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<ConnectionStatusLogCo
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
});
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<UpdateNetworkElement>("id");
const isRequiredProperty = propertyOf<UpdateNetworkElement>("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<undefined, typeof mapDispa
mode: EditNetworkElementDialogMode;
initialNetworkElement: NetworkElementConnection;
onClose: () => 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<EditNetworkElementDialogComponentProps, EditNetworkElementDialogComponentState> {
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 (
<Dialog open={this.props.mode !== EditNetworkElementDialogMode.None}>
<DialogTitle id="form-dialog-title" aria-label={`${setting.dialogTitle.replace(/ /g, "-").toLowerCase()}-dialog`}>{setting.dialogTitle}</DialogTitle>
@@ -187,9 +226,39 @@ class EditNetworkElementDialogComponent extends React.Component<EditNetworkEleme
{!this.state.isNameValid && <Typography variant="body1" color="error">Name cannot be empty.</Typography>}
<TextField disabled={!setting.enableMountIdEditor} spellCheck={false} margin="dense" id="ipaddress" label="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">IP Adress cannot be empty.</Typography>}
+
<TextField 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 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 && <TextField disabled={!setting.enableUsernameEditor} spellCheck={false} margin="dense" id="password" label="Password" aria-label="password" type="password" fullWidth value={this.state.password} onChange={(event) => { this.setState({ password: event.target.value }); }} /> || null}
+
+ {setting.enableUsernameEditor &&
+ <RadioGroup row aria-label="password-tls-key" name="password-tls-key" value={radioSelected}
+ onChange={this.handleRadioChange} >
+ <FormControlLabel value='password' control={<Radio />} label="Password" onChange={this.onRadioSelect} />
+ <FormControlLabel value='tlsKey' control={<Radio />} label="TlsKey" onChange={this.onRadioSelect} />
+ </RadioGroup> || null}
+
+ {setting.enableUsernameEditor && showPasswordTextField &&
+ <TextField disabled={!setting.enableUsernameEditor || !showPasswordTextField} spellCheck={false} margin="dense"
+ id="password" aria-label="password" type="password" fullWidth value={this.state.password}
+ onChange={(event) => { this.setState({ password: event.target.value }); }}
+ /> || null}
+
+ <FormControl fullWidth disabled={!setting.enableUsernameEditor}>
+ {setting.enableUsernameEditor && showTlsDropdown &&
+ <div>
+ <InputLabel htmlFor="pass">--Select tls-key--</InputLabel>
+ <Select disabled={!setting.enableUsernameEditor || !showTlsDropdown}
+ 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>
+ {tlsKeysList.map(tlsKey =>
+ (<MenuItem value={tlsKey.key} key={tlsKey.key} aria-label={tlsKey.key} >{tlsKey.key}</MenuItem>))}
+ </Select>
+ </div>
+ }
+ </FormControl>
+
<FormControl fullWidth disabled={!setting.enableUsernameEditor}>
<InputLabel htmlFor="active">Required</InputLabel>
<Select aria-label="required-selection" value={this.state.isRequired || false} onChange={(event) => {
@@ -212,6 +281,7 @@ class EditNetworkElementDialogComponent extends React.Component<EditNetworkEleme
port: this.state.port,
username: this.state.username,
password: this.state.password,
+ tlsKey: this.state.tlsKey
});
}
event.preventDefault();
@@ -227,14 +297,44 @@ class EditNetworkElementDialogComponent extends React.Component<EditNetworkEleme
)
}
+ public renderTlsKeys = () => {
+ try {
+ this.props.getAvailableTlsKeys();
+ } catch (err) {
+ console.log(err);
+ }
+ }
+
+ public componentDidMount() {
+ this.renderTlsKeys();
+ }
+
+ public onRadioSelect = (e: any) => {
+ if (e.target.value == 'password') {
+ this.setState({ isPasswordSelected: true, isTlsSelected: false })
+ } else if (e.target.value == 'tlsKey') {
+ this.setState({ isPasswordSelected: false, isTlsSelected: true })
+ }
+ };
+
private onApply = (element: NetworkElementConnection) => {
this.props.onClose && this.props.onClose();
let updateElement: UpdateNetworkElement = {
id: this.state.nodeId
}
+ if (this.state.isPasswordSelected) {
+ element.tlsKey = ''
+ }
+ else if (this.state.isTlsSelected) { //check here
+ element.password = ''
+ }
+
switch (this.props.mode) {
case EditNetworkElementDialogMode.AddNewNetworkElement:
element && this.props.addNewNetworkElement(element);
+ this.setState({
+ radioSelected: ''
+ });
break;
case EditNetworkElementDialogMode.MountNetworkElement:
element && this.props.mountNetworkElement(element);
@@ -247,22 +347,31 @@ class EditNetworkElementDialogComponent extends React.Component<EditNetworkEleme
updateElement.isRequired = this.state.isRequired;
if (this.props.initialNetworkElement.username !== this.state.username)
updateElement.username = this.state.username;
- if (this.props.initialNetworkElement.password !== this.state.password)
+ if (this.props.initialNetworkElement.password !== this.state.password && this.state.isPasswordSelected) {
updateElement.password = this.state.password;
+ updateElement.tlsKey = '';
+ }
+ if (this.props.initialNetworkElement.tlsKey !== this.state.tlsKey && this.state.isTlsSelected) {
+ updateElement.tlsKey = this.state.tlsKey;
+ updateElement.password = '';
+ }
element && this.props.editNetworkElement(updateElement, element);
+ this.setState({
+ radioSelected: ''
+ });
break;
case EditNetworkElementDialogMode.RemoveNetworkElement:
element && this.props.removeNetworkElement(updateElement);
break;
}
- this.setState({ password: '', username: '' });
+ this.setState({ password: '', username: '', tlsKey: '' });
this.resetRequieredFields();
};
private onCancel = () => {
this.props.onClose && this.props.onClose();
- this.setState({ password: '', username: '' });
+ this.setState({ password: '', username: '', tlsKey: '', radioSelected: '' });
this.resetRequieredFields();
}
diff --git a/sdnr/wt/odlux/apps/connectApp/src/components/networkElements.tsx b/sdnr/wt/odlux/apps/connectApp/src/components/networkElements.tsx
index 73706f678..5d0757ab2 100644
--- a/sdnr/wt/odlux/apps/connectApp/src/components/networkElements.tsx
+++ b/sdnr/wt/odlux/apps/connectApp/src/components/networkElements.tsx
@@ -19,7 +19,7 @@ import * as React from 'react';
import { Theme, createStyles, withStyles, WithStyles } from '@material-ui/core/styles';
import AddIcon from '@material-ui/icons/Add';
-import Refresh from '@material-ui/icons/Refresh';
+import Refresh from '@material-ui/icons/Refresh';
import LinkIcon from '@material-ui/icons/Link';
import LinkOffIcon from '@material-ui/icons/LinkOff';
import RemoveIcon from '@material-ui/icons/RemoveCircleOutline';
@@ -68,18 +68,18 @@ const styles = (theme: Theme) => createStyles({
});
type GetStatelessComponentProps<T> = T extends (props: infer P & { children?: React.ReactNode }) => any ? P : any
-const MenuItemExt : React.FC<GetStatelessComponentProps<typeof MenuItem>> = (props) => {
+const MenuItemExt: React.FC<GetStatelessComponentProps<typeof MenuItem>> = (props) => {
const [disabled, setDisabled] = React.useState(true);
const onMouseDown = (ev: React.MouseEvent<HTMLElement>) => {
- if (ev.button ===1){
- setDisabled(!disabled);
- ev.preventDefault();
- }
+ if (ev.button === 1) {
+ setDisabled(!disabled);
+ ev.preventDefault();
+ }
};
return (
<div onMouseDown={onMouseDown} >
- <MenuItem {...{...props, disabled: props.disabled && disabled }} />
- </div>
+ <MenuItem {...{ ...props, disabled: props.disabled && disabled }} />
+ </div>
);
};
@@ -119,17 +119,17 @@ export class NetworkElementsListComponent extends React.Component<NetworkElement
networkElementEditorMode: EditNetworkElementDialogMode.None,
refreshNetworkElementsEditorMode: RefreshNetworkElementsDialogMode.None,
elementInfo: null,
- elementInfoFeature:null,
+ elementInfoFeature: null,
infoNetworkElementEditorMode: InfoNetworkElementDialogMode.None
};
}
-
+
getContextMenu(rowData: NetworkElementConnection): JSX.Element[] {
const mountUri = rowData.id && connectService.getNetworkElementUri(rowData.id);
const mountPolicy = mountUri && getAccessPolicyByUrl(mountUri);
- const canMount = mountPolicy && mountPolicy.POST || false;
-
- const { configuration} = this.props.applicationState as any;
+ const canMount = mountPolicy && mountPolicy.POST || false;
+
+ 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>,
@@ -160,6 +160,12 @@ export class NetworkElementsListComponent extends React.Component<NetworkElement
render(): JSX.Element {
const { classes } = this.props;
const { networkElementToEdit } = this.state;
+ let savedRadio = "password";
+ if (this.state.networkElementToEdit.password && this.state.networkElementToEdit.password.length > 0) {
+ savedRadio = 'password'
+ } else if (this.state.networkElementToEdit.tlsKey && this.state.networkElementToEdit.tlsKey.length > 0) {
+ savedRadio = 'tlsKey'
+ }
// const mountUri = rowData.id && connectService.getNetworkElementUri(rowData.id);
// const mountPolicy = mountUri && getAccessPolicyByUrl(mountUri);
@@ -167,7 +173,7 @@ export class NetworkElementsListComponent extends React.Component<NetworkElement
const canAdd = true;
const addRequireNetworkElementAction = {
- icon: AddIcon, tooltip: 'Add', ariaLabel:"add-element", onClick: () => {
+ icon: AddIcon, tooltip: 'Add', ariaLabel: "add-element", onClick: () => {
this.setState({
networkElementEditorMode: EditNetworkElementDialogMode.AddNewNetworkElement,
networkElementToEdit: emptyRequireNetworkElement,
@@ -176,16 +182,16 @@ export class NetworkElementsListComponent extends React.Component<NetworkElement
};
const refreshNetworkElementsAction = {
- icon: Refresh, tooltip: 'Refresh Network Elements table', ariaLabel:'refresh', onClick: () => {
+ icon: Refresh, tooltip: 'Refresh Network Elements table', ariaLabel: 'refresh', onClick: () => {
this.setState({
refreshNetworkElementsEditorMode: RefreshNetworkElementsDialogMode.RefreshNetworkElementsTable
});
}
};
-
+
return (
<>
- <NetworkElementTable stickyHeader tableId="network-element-table" customActionButtons={[refreshNetworkElementsAction, ...canAdd ? [addRequireNetworkElementAction]: []]} columns={[
+ <NetworkElementTable stickyHeader tableId="network-element-table" customActionButtons={[refreshNetworkElementsAction, ...canAdd ? [addRequireNetworkElementAction] : []]} columns={[
{ property: "nodeId", title: "Node Name", type: ColumnType.text },
{ property: "isRequired", title: "Required", type: ColumnType.boolean },
{ property: "status", title: "Connection Status", type: ColumnType.text },
@@ -202,6 +208,7 @@ export class NetworkElementsListComponent extends React.Component<NetworkElement
initialNetworkElement={networkElementToEdit}
mode={this.state.networkElementEditorMode}
onClose={this.onCloseEditNetworkElementDialog}
+ radioChecked={savedRadio}
/>
<RefreshNetworkElementsDialog
mode={this.state.refreshNetworkElementsEditorMode}
@@ -240,6 +247,11 @@ export class NetworkElementsListComponent extends React.Component<NetworkElement
}
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'
this.setState({
networkElementToEdit: {
nodeId: element.nodeId,
@@ -248,6 +260,7 @@ export class NetworkElementsListComponent extends React.Component<NetworkElement
port: element.port,
username: element.username,
password: element.password,
+ tlsKey: element.tlsKey
},
networkElementEditorMode: EditNetworkElementDialogMode.EditNetworkElement
});
diff --git a/sdnr/wt/odlux/apps/connectApp/src/handlers/connectAppRootHandler.ts b/sdnr/wt/odlux/apps/connectApp/src/handlers/connectAppRootHandler.ts
index 81ee97a0a..dbb9b2c04 100644
--- a/sdnr/wt/odlux/apps/connectApp/src/handlers/connectAppRootHandler.ts
+++ b/sdnr/wt/odlux/apps/connectApp/src/handlers/connectAppRootHandler.ts
@@ -25,6 +25,7 @@ import { SetPanelAction, AddWebUriList, RemoveWebUri, SetWeburiSearchBusy } from
import { PanelId } from '../models/panelId';
import { guiCutThrough } from '../models/guiCutTrough';
import { connectionStatusCountHandler, IConnectionStatusCount } from './connectionStatusCountHandler';
+import { availableTlsKeysActionHandler, IAvailableTlsKeysState } from './tlsKeyHandler';
export interface IConnectAppStoreState {
networkElements: INetworkElementsState;
@@ -34,6 +35,7 @@ export interface IConnectAppStoreState {
elementFeatureInfo: IInfoNetworkElementFeaturesState;
guiCutThrough: guiCutThroughState;
connectionStatusCount: IConnectionStatusCount;
+ availableTlsKeys: IAvailableTlsKeysState
}
const currentOpenPanelHandler: IActionHandler<PanelId> = (state = null, action) => {
@@ -92,7 +94,8 @@ const actionHandlers = {
elementInfo: infoNetworkElementsActionHandler,
elementFeatureInfo: infoNetworkElementFeaturesActionHandler,
guiCutThrough: guiCutThroughHandler,
- connectionStatusCount: connectionStatusCountHandler
+ connectionStatusCount: connectionStatusCountHandler,
+ availableTlsKeys: availableTlsKeysActionHandler
};
export const connectAppRootHandler = combineActionHandler<IConnectAppStoreState>(actionHandlers);
diff --git a/sdnr/wt/odlux/apps/connectApp/src/handlers/tlsKeyHandler.ts b/sdnr/wt/odlux/apps/connectApp/src/handlers/tlsKeyHandler.ts
new file mode 100644
index 000000000..326b3cc8e
--- /dev/null
+++ b/sdnr/wt/odlux/apps/connectApp/src/handlers/tlsKeyHandler.ts
@@ -0,0 +1,55 @@
+/**
+ * ============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 { IActionHandler } from '../../../../framework/src/flux/action';
+
+import { AllTlsKeyListLoadedAction, LoadAllTlsKeyListAction } from '../actions/tlsKeyActions';
+import { TlsKeys } from '../models/networkElementConnection';
+
+export interface IAvailableTlsKeysState {
+ tlsKeysList: TlsKeys[];
+ busy: boolean;
+}
+
+const tlsKeysStateInit: IAvailableTlsKeysState = {
+ tlsKeysList: [],
+ busy: false,
+};
+
+export const availableTlsKeysActionHandler: IActionHandler<IAvailableTlsKeysState> = (state = tlsKeysStateInit, action) => {
+ if (action instanceof LoadAllTlsKeyListAction) {
+ state = {
+ ...state,
+ busy: true
+ };
+
+ } else if (action instanceof AllTlsKeyListLoadedAction) {
+ if (!action.error && action.tlsList) {
+ state = {
+ ...state,
+ tlsKeysList: action.tlsList,
+ busy: false,
+ };
+ } else {
+ state = {
+ ...state,
+ busy: false
+ };
+ }
+ }
+ return state;
+}; \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/connectApp/src/index.html b/sdnr/wt/odlux/apps/connectApp/src/index.html
index 6f44c25f7..35dbdf71d 100644
--- a/sdnr/wt/odlux/apps/connectApp/src/index.html
+++ b/sdnr/wt/odlux/apps/connectApp/src/index.html
@@ -19,7 +19,7 @@
connectApp.register();
faultApp.register();
inventoryApp.register();
- app("./app.tsx").configureApplication({ authentication:"basic", enablePolicy: false,});
+ app("./app.tsx").configureApplication({ authentication:"oauth", enablePolicy: false, transportpceUrl:"http://test.de"});
app("./app.tsx").runApplication();
});
</script>
diff --git a/sdnr/wt/odlux/apps/connectApp/src/models/networkElementConnection.ts b/sdnr/wt/odlux/apps/connectApp/src/models/networkElementConnection.ts
index 71eddc808..89070ab39 100644
--- a/sdnr/wt/odlux/apps/connectApp/src/models/networkElementConnection.ts
+++ b/sdnr/wt/odlux/apps/connectApp/src/models/networkElementConnection.ts
@@ -24,6 +24,7 @@ export type NetworkElementConnection = {
port: number;
username?: string;
password?: string;
+ tlsKey?: string;
weburi?: string;
isWebUriUnreachable?: boolean;
status?: "Connected" | "mounted" | "unmounted" | "Connecting" | "Disconnected" | "idle";
@@ -47,12 +48,18 @@ export type UpdateNetworkElement = {
isRequired?: boolean;
username?: string;
password?: string;
+ tlsKey?: string;
}
export type ConnectionStatus = {
status: string
}
+export type TlsKeys = {
+ key: string
+}
+
+
/**
* Checks if a object has a given propertyname, if yes, the name is returned as string.
* @throws at compile time if property is not available
diff --git a/sdnr/wt/odlux/apps/connectApp/src/pluginConnect.tsx b/sdnr/wt/odlux/apps/connectApp/src/pluginConnect.tsx
index 461e14023..1990cc03d 100644
--- a/sdnr/wt/odlux/apps/connectApp/src/pluginConnect.tsx
+++ b/sdnr/wt/odlux/apps/connectApp/src/pluginConnect.tsx
@@ -88,9 +88,9 @@ export function register() {
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) {
- store.dispatch(new AddSnackbarNotification({ message: `Adding network element [${msg['node-id']}]`, options: { variant: 'info' } }));
+ store.dispatch(new AddSnackbarNotification({ message: `Adding network element [${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) {
- store.dispatch(new AddSnackbarNotification({ message: `Updating network element [${msg['node-id']}]`, options: { variant: 'info' } }));
+ store.dispatch(new AddSnackbarNotification({ message: `Updating network element [${msg.data['object-id-ref']}]`, options: { variant: 'info' } }));
}
if (store) {
store.dispatch(updateCurrentViewAsyncAction() as any).then(() => {
diff --git a/sdnr/wt/odlux/apps/connectApp/src/services/connectService.ts b/sdnr/wt/odlux/apps/connectApp/src/services/connectService.ts
index ed8b0f67d..427acd3ec 100644
--- a/sdnr/wt/odlux/apps/connectApp/src/services/connectService.ts
+++ b/sdnr/wt/odlux/apps/connectApp/src/services/connectService.ts
@@ -16,243 +16,289 @@
* ============LICENSE_END==========================================================================
*/
- import { requestRest } from '../../../../framework/src/services/restService';
- import { NetworkElementConnection, ConnectionStatus, UpdateNetworkElement } from '../models/networkElementConnection';
- import { convertPropertyNames, replaceUpperCase } from '../../../../framework/src/utilities/yangHelper';
- import { Result } from '../../../../framework/src/models/elasticSearch';
-
- import { FeatureTopology, Topology, TopologyNode, Module } from '../models/topologyNetconf';
- import { guiCutThrough } from '../models/guiCutTrough';
-
- /**
- * Represents a web api accessor service for all Network Elements actions.
- */
- 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 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'
-
- /**
- * Inserts a network elements.
- */
- public async createNetworkElement(element: NetworkElementConnection): Promise<NetworkElementConnection | null> {
- const path = this.getNetworkElementConnectDataProviderUri("create") ;
- const result = await requestRest<NetworkElementConnection>(path, {
- method: "POST", body: JSON.stringify(convertPropertyNames({ "data-provider:input": element }, replaceUpperCase))
- });
- return result || null;
- }
-
- /**
- * Updates a network element.
+import { requestRest } from '../../../../framework/src/services/restService';
+import { NetworkElementConnection, ConnectionStatus, UpdateNetworkElement } from '../models/networkElementConnection';
+import { TlsKeys } from '../models/networkElementConnection'
+import { convertPropertyNames, replaceUpperCase } from '../../../../framework/src/utilities/yangHelper';
+import { Result } from '../../../../framework/src/models/elasticSearch';
+
+import { FeatureTopology, Topology, TopologyNode, Module } from '../models/topologyNetconf';
+import { guiCutThrough } from '../models/guiCutTrough';
+
+/**
+* Represents a web api accessor service for all Network Elements actions.
+*/
+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 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'
+
+ /**
+ * Inserts a network elements.
*/
- public async updateNetworkElement(element: UpdateNetworkElement): Promise<NetworkElementConnection | null> {
- const path = this.getNetworkElementConnectDataProviderUri("update");
- const result = await requestRest<NetworkElementConnection>(path, {
- method: "POST", body: JSON.stringify(convertPropertyNames({ "data-provider:input": element }, replaceUpperCase))
- });
- return result || null;
- }
-
- /**
- * Deletes a network element.
- */
- public async deleteNetworkElement(element: UpdateNetworkElement): Promise<NetworkElementConnection | null> {
- const query = {
- "id": element.id
- };
- const path = this.getNetworkElementConnectDataProviderUri("delete");
- const result = await requestRest<NetworkElementConnection>(path, {
- method: "POST", body: JSON.stringify(convertPropertyNames({ "data-provider:input": query }, replaceUpperCase))
- });
- return result || null;
- }
-
- /** Mounts network element. */
- public async mountNetworkElement(networkElement: NetworkElementConnection): Promise<boolean> {
- const path = this.getNetworkElementUri(networkElement.nodeId);
- const mountXml = [
- '<node xmlns="urn:TBD:params:xml:ns:yang:network-topology">',
- `<node-id>${networkElement.nodeId}</node-id>`,
- `<host xmlns="urn:opendaylight:netconf-node-topology">${networkElement.host}</host>`,
- `<port xmlns="urn:opendaylight:netconf-node-topology">${networkElement.port}</port>`,
- `<username xmlns="urn:opendaylight:netconf-node-topology">${networkElement.username}</username>`,
- `<password xmlns="urn:opendaylight:netconf-node-topology">${networkElement.password}</password>`,
- ' <tcp-only xmlns="urn:opendaylight:netconf-node-topology">false</tcp-only>',
-
- ' <!-- non-mandatory fields with default values, you can safely remove these if you do not wish to override any of these values-->',
- ' <reconnect-on-changed-schema xmlns="urn:opendaylight:netconf-node-topology">false</reconnect-on-changed-schema>',
- ' <connection-timeout-millis xmlns="urn:opendaylight:netconf-node-topology">20000</connection-timeout-millis>',
- ' <max-connection-attempts xmlns="urn:opendaylight:netconf-node-topology">100</max-connection-attempts>',
- ' <between-attempts-timeout-millis xmlns="urn:opendaylight:netconf-node-topology">2000</between-attempts-timeout-millis>',
- ' <sleep-factor xmlns="urn:opendaylight:netconf-node-topology">1.5</sleep-factor>',
-
- ' <!-- keepalive-delay set to 0 turns off keepalives-->',
- ' <keepalive-delay xmlns="urn:opendaylight:netconf-node-topology">120</keepalive-delay>',
- '</node>'].join('');
-
- try {
- const result = await requestRest<string>(path, {
- method: 'PUT',
- headers: {
- 'Content-Type': 'application/xml',
- 'Accept': 'application/xml'
- },
- body: mountXml
- });
- // expect an empty answer
- return result !== null;
- } catch {
- return false;
- }
- };
-
- /** Unmounts a network element by its id. */
- public async unmountNetworkElement(nodeId: string): Promise<boolean> {
- const path = this.getNetworkElementUri(nodeId);
-
- try {
- const result = await requestRest<string>(path, {
- method: 'DELETE',
- headers: {
- 'Content-Type': 'application/xml',
- 'Accept': 'application/xml'
- },
- });
- // expect an empty answer
- return result !== null;
-
- } catch {
- return false;
- }
- };
-
- /** Yang capabilities of the selected network elements. */
- public async infoNetworkElement(nodeId: string): Promise<TopologyNode | null> {
- const path = this.getNetworkElementUri(nodeId);
- const topologyRequestPomise = requestRest<Topology>(path, { method: "GET" });
-
- return topologyRequestPomise && topologyRequestPomise.then(result => {
- return result && result["network-topology:node"] && result["network-topology:node"][0] || null;
- });
- }
-
-
- /** Yang features of the selected network element module. */
- public async infoNetworkElementFeatures(nodeId: string): Promise<Module[] | null | undefined> {
- const path = this.getNetworkElementYangLibraryFeature(nodeId);
- 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;
- return resultFinal;
- });
- }
-
-
-
- /**
- * Get the connection state of the network element.
+ public async createNetworkElement(element: NetworkElementConnection): Promise<NetworkElementConnection | null> {
+ const path = this.getNetworkElementConnectDataProviderUri("create");
+ const result = await requestRest<NetworkElementConnection>(path, {
+ method: "POST", body: JSON.stringify(convertPropertyNames({ "data-provider:input": element }, replaceUpperCase))
+ });
+ return result || null;
+ }
+
+ /**
+ * Updates a network element.
+ */
+ public async updateNetworkElement(element: UpdateNetworkElement): Promise<NetworkElementConnection | null> {
+ const path = this.getNetworkElementConnectDataProviderUri("update");
+ const result = await requestRest<NetworkElementConnection>(path, {
+ method: "POST", body: JSON.stringify(convertPropertyNames({ "data-provider:input": element }, replaceUpperCase))
+ });
+ return result || null;
+ }
+
+ /**
+ * Deletes a network element.
*/
- public async getNetworkElementConnectionStatus(element: string): Promise<(ConnectionStatus)[] | null> {
- const path = `/rests/operations/data-provider:read-network-element-connection-list`;
- const query = {
- "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
- })) || null;
- }
-
- public async getAllWebUriExtensionsForNetworkElementListAsync(neList: string[]): Promise<(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
- }],
- "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;
- neList.forEach(nodeId => {
- let entryNotFound = true;
- if (resultData) {
- const BreakException = {};
- try {
- resultData.forEach(entry => {
- if (entry.id == nodeId) {
- entryNotFound = false;
- if (entry.weburi) {
- webUriList.push({ id: nodeId, weburi: entry.weburi });
- } else {
- webUriList.push({ id: nodeId, weburi: undefined });
- }
- throw BreakException;
- }
- });
- } catch (e) {}
- }
- if (entryNotFound)
- webUriList.push({ id: nodeId, weburi: undefined });
- });
- return webUriList;
- }
-
- // public async getAllWebUriExtensionsForNetworkElementListAsync(ne: string[]): Promise<(guiCutThrough)[] | null> {
-
- // let promises: any[] = [];
- // let webUris: guiCutThrough[] = []
-
- // ne.forEach(nodeId => {
- // const path = this.getAllWebUriExtensionsForNetworkElementListUri(nodeId);
-
- // // add search request to array
- // promises.push(requestRest<any>(path, { method: "GET" })
- // .then(result => {
- // if (result != null && result['core-model:network-element'] && result['core-model:network-element'].extension) {
- // const webUri = result['core-model:network-element'].extension.find((item: any) => item['value-name'] === "webUri")
- // if (webUri) {
- // webUris.push({ weburi: webUri.value, id: nodeId });
- // } else {
- // webUris.push({ weburi: undefined, id: nodeId });
- // }
- // } else {
- // webUris.push({ weburi: undefined, id: nodeId });
- // }
- // })
- // .catch(error => {
- // webUris.push({ weburi: undefined, id: nodeId });
- // }))
- // })
- // // wait until all promises are done and return weburis
- // return Promise.all(promises).then(result => { return webUris });
- // }
-
- }
-
-
-
- export const connectService = new ConnectService();
- \ No newline at end of file
+ public async deleteNetworkElement(element: UpdateNetworkElement): Promise<NetworkElementConnection | null> {
+ const query = {
+ "id": element.id
+ };
+ const path = this.getNetworkElementConnectDataProviderUri("delete");
+ const result = await requestRest<NetworkElementConnection>(path, {
+ method: "POST", body: JSON.stringify(convertPropertyNames({ "data-provider:input": query }, replaceUpperCase))
+ });
+ return result || null;
+ }
+
+ /** Mounts network element. */
+ public async mountNetworkElement(networkElement: NetworkElementConnection): Promise<boolean> {
+ const path = this.getNetworkElementUri(networkElement.nodeId);
+ const mountXml = [
+ '<node xmlns="urn:TBD:params:xml:ns:yang:network-topology">',
+ `<node-id>${networkElement.nodeId}</node-id>`,
+ `<host xmlns="urn:opendaylight:netconf-node-topology">${networkElement.host}</host>`,
+ `<port xmlns="urn:opendaylight:netconf-node-topology">${networkElement.port}</port>`,
+ `<username xmlns="urn:opendaylight:netconf-node-topology">${networkElement.username}</username>`,
+ `<password xmlns="urn:opendaylight:netconf-node-topology">${networkElement.password}</password>`,
+ ' <tcp-only xmlns="urn:opendaylight:netconf-node-topology">false</tcp-only>',
+
+ ' <!-- non-mandatory fields with default values, you can safely remove these if you do not wish to override any of these values-->',
+ ' <reconnect-on-changed-schema xmlns="urn:opendaylight:netconf-node-topology">false</reconnect-on-changed-schema>',
+ ' <connection-timeout-millis xmlns="urn:opendaylight:netconf-node-topology">20000</connection-timeout-millis>',
+ ' <max-connection-attempts xmlns="urn:opendaylight:netconf-node-topology">100</max-connection-attempts>',
+ ' <between-attempts-timeout-millis xmlns="urn:opendaylight:netconf-node-topology">2000</between-attempts-timeout-millis>',
+ ' <sleep-factor xmlns="urn:opendaylight:netconf-node-topology">1.5</sleep-factor>',
+
+ ' <!-- keepalive-delay set to 0 turns off keepalives-->',
+ ' <keepalive-delay xmlns="urn:opendaylight:netconf-node-topology">120</keepalive-delay>',
+ '</node>'].join('');
+
+ const tlsXml = [
+ '<node xmlns="urn:TBD:params:xml:ns:yang:network-topology">',
+ `<node-id>${networkElement.nodeId}</node-id>`,
+ '<key-based xmlns="urn:opendaylight:netconf-node-topology">',
+ `<key-id xmlns="urn:opendaylight:netconf-node-topology">${networkElement.tlsKey}</key-id>`,
+ `<username xmlns="urn:opendaylight:netconf-node-topology">${networkElement.username}</username>`,
+ '</key-based>',
+ `<host xmlns="urn:opendaylight:netconf-node-topology">${networkElement.host}</host>`,
+ `<port xmlns="urn:opendaylight:netconf-node-topology">${networkElement.port}</port>`,
+ '<tcp-only xmlns="urn:opendaylight:netconf-node-topology">false</tcp-only>',
+ '<protocol xmlns="urn:opendaylight:netconf-node-topology">',
+ '<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('')
+ let bodyXml;
+ if (networkElement.password) {
+ bodyXml = mountXml
+ }
+ else {
+ bodyXml = tlsXml
+ }
+
+ try {
+ const result = await requestRest<string>(path, {
+ method: 'PUT',
+ headers: {
+ 'Content-Type': 'application/xml',
+ 'Accept': 'application/xml'
+ },
+ 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> {
+ const path = this.getNetworkElementUri(nodeId);
+
+ try {
+ const result = await requestRest<string>(path, {
+ method: 'DELETE',
+ headers: {
+ 'Content-Type': 'application/xml',
+ 'Accept': 'application/xml'
+ },
+ });
+ // expect an empty answer
+ return result !== null;
+
+ } catch {
+ return false;
+ }
+ };
+
+ /** Yang capabilities of the selected network elements. */
+ public async infoNetworkElement(nodeId: string): Promise<TopologyNode | null> {
+ const path = this.getNetworkElementUri(nodeId);
+ const topologyRequestPomise = requestRest<Topology>(path, { method: "GET" });
+
+ return topologyRequestPomise && topologyRequestPomise.then(result => {
+ return result && result["network-topology:node"] && result["network-topology:node"][0] || null;
+ });
+ }
+
+
+ /** Yang features of the selected network element module. */
+ public async infoNetworkElementFeatures(nodeId: string): Promise<Module[] | null | undefined> {
+ const path = this.getNetworkElementYangLibraryFeature(nodeId);
+ 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;
+ return resultFinal;
+ });
+ }
+
+
+
+ /**
+ * Get the connection state of the network element.
+ */
+ public async getNetworkElementConnectionStatus(element: string): Promise<(ConnectionStatus)[] | null> {
+ const path = `/rests/operations/data-provider:read-network-element-connection-list`;
+ const query = {
+ "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
+ })) || null;
+ }
+
+ /**
+ * Gets all available tlsKeys.
+ */
+
+ 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
+ }
+ }
+ };
+
+ 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 query = {
+ "data-provider:input": {
+ "filter": [{
+ "property": "id",
+ "filtervalues": neList
+ }],
+ "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;
+ neList.forEach(nodeId => {
+ let entryNotFound = true;
+ if (resultData) {
+ const BreakException = {};
+ try {
+ resultData.forEach(entry => {
+ if (entry.id == nodeId) {
+ entryNotFound = false;
+ if (entry.weburi) {
+ webUriList.push({ id: nodeId, weburi: entry.weburi });
+ } else {
+ webUriList.push({ id: nodeId, weburi: undefined });
+ }
+ throw BreakException;
+ }
+ });
+ } catch (e) { }
+ }
+ if (entryNotFound)
+ webUriList.push({ id: nodeId, weburi: undefined });
+ });
+ return webUriList;
+ }
+
+ // public async getAllWebUriExtensionsForNetworkElementListAsync(ne: string[]): Promise<(guiCutThrough)[] | null> {
+
+ // let promises: any[] = [];
+ // let webUris: guiCutThrough[] = []
+
+ // ne.forEach(nodeId => {
+ // const path = this.getAllWebUriExtensionsForNetworkElementListUri(nodeId);
+
+ // // add search request to array
+ // promises.push(requestRest<any>(path, { method: "GET" })
+ // .then(result => {
+ // if (result != null && result['core-model:network-element'] && result['core-model:network-element'].extension) {
+ // const webUri = result['core-model:network-element'].extension.find((item: any) => item['value-name'] === "webUri")
+ // if (webUri) {
+ // webUris.push({ weburi: webUri.value, id: nodeId });
+ // } else {
+ // webUris.push({ weburi: undefined, id: nodeId });
+ // }
+ // } else {
+ // webUris.push({ weburi: undefined, id: nodeId });
+ // }
+ // })
+ // .catch(error => {
+ // webUris.push({ weburi: undefined, id: nodeId });
+ // }))
+ // })
+ // // wait until all promises are done and return weburis
+ // return Promise.all(promises).then(result => { return webUris });
+ // }
+
+}
+
+
+
+export const connectService = new ConnectService();
diff --git a/sdnr/wt/odlux/apps/demoApp/package.json b/sdnr/wt/odlux/apps/demoApp/package.json
index 7756fe328..d52383719 100644
--- a/sdnr/wt/odlux/apps/demoApp/package.json
+++ b/sdnr/wt/odlux/apps/demoApp/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/demoApp/pom.xml b/sdnr/wt/odlux/apps/demoApp/pom.xml
index e3f27d5c9..7c95fc3b5 100644
--- a/sdnr/wt/odlux/apps/demoApp/pom.xml
+++ b/sdnr/wt/odlux/apps/demoApp/pom.xml
@@ -140,8 +140,8 @@
<!-- optional: default phase is "generate-resources" -->
<phase>initialize</phase>
<configuration>
- <nodeVersion>v10.16.3</nodeVersion>
- <yarnVersion>v1.19.0</yarnVersion>
+ <nodeVersion>v12.13.0</nodeVersion>
+ <yarnVersion>v1.22.10</yarnVersion>
</configuration>
</execution>
<execution>
diff --git a/sdnr/wt/odlux/apps/eventLogApp/package.json b/sdnr/wt/odlux/apps/eventLogApp/package.json
index dfcebfe63..52c49b328 100644
--- a/sdnr/wt/odlux/apps/eventLogApp/package.json
+++ b/sdnr/wt/odlux/apps/eventLogApp/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/eventLogApp/pom.xml b/sdnr/wt/odlux/apps/eventLogApp/pom.xml
index 0b061a5b9..2cc6234da 100644
--- a/sdnr/wt/odlux/apps/eventLogApp/pom.xml
+++ b/sdnr/wt/odlux/apps/eventLogApp/pom.xml
@@ -140,8 +140,8 @@
<!-- optional: default phase is "generate-resources" -->
<phase>initialize</phase>
<configuration>
- <nodeVersion>v10.16.3</nodeVersion>
- <yarnVersion>v1.19.0</yarnVersion>
+ <nodeVersion>v12.13.0</nodeVersion>
+ <yarnVersion>v1.22.10</yarnVersion>
</configuration>
</execution>
<execution>
diff --git a/sdnr/wt/odlux/apps/faultApp/package.json b/sdnr/wt/odlux/apps/faultApp/package.json
index 5d1439b85..cb03e49d9 100644
--- a/sdnr/wt/odlux/apps/faultApp/package.json
+++ b/sdnr/wt/odlux/apps/faultApp/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/faultApp/pom.xml b/sdnr/wt/odlux/apps/faultApp/pom.xml
index 63236dab4..fec425892 100644
--- a/sdnr/wt/odlux/apps/faultApp/pom.xml
+++ b/sdnr/wt/odlux/apps/faultApp/pom.xml
@@ -140,8 +140,8 @@
<!-- optional: default phase is "generate-resources" -->
<phase>initialize</phase>
<configuration>
- <nodeVersion>v10.16.3</nodeVersion>
- <yarnVersion>v1.19.0</yarnVersion>
+ <nodeVersion>v12.13.0</nodeVersion>
+ <yarnVersion>v1.22.10</yarnVersion>
</configuration>
</execution>
<execution>
diff --git a/sdnr/wt/odlux/apps/helpApp/package.json b/sdnr/wt/odlux/apps/helpApp/package.json
index 58e68dd03..51e383b11 100644
--- a/sdnr/wt/odlux/apps/helpApp/package.json
+++ b/sdnr/wt/odlux/apps/helpApp/package.json
@@ -32,8 +32,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/helpApp/pom.xml b/sdnr/wt/odlux/apps/helpApp/pom.xml
index da49a7850..6bea827e5 100644
--- a/sdnr/wt/odlux/apps/helpApp/pom.xml
+++ b/sdnr/wt/odlux/apps/helpApp/pom.xml
@@ -140,8 +140,8 @@
<!-- optional: default phase is "generate-resources" -->
<phase>initialize</phase>
<configuration>
- <nodeVersion>v10.16.3</nodeVersion>
- <yarnVersion>v1.19.0</yarnVersion>
+ <nodeVersion>v12.13.0</nodeVersion>
+ <yarnVersion>v1.22.10</yarnVersion>
</configuration>
</execution>
<execution>
diff --git a/sdnr/wt/odlux/apps/inventoryApp/package.json b/sdnr/wt/odlux/apps/inventoryApp/package.json
index 0f6b40379..e78f3ac82 100644
--- a/sdnr/wt/odlux/apps/inventoryApp/package.json
+++ b/sdnr/wt/odlux/apps/inventoryApp/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/inventoryApp/pom.xml b/sdnr/wt/odlux/apps/inventoryApp/pom.xml
index 2701e04ed..377446edc 100644
--- a/sdnr/wt/odlux/apps/inventoryApp/pom.xml
+++ b/sdnr/wt/odlux/apps/inventoryApp/pom.xml
@@ -140,8 +140,8 @@
<!-- optional: default phase is "generate-resources" -->
<phase>initialize</phase>
<configuration>
- <nodeVersion>v10.16.3</nodeVersion>
- <yarnVersion>v1.19.0</yarnVersion>
+ <nodeVersion>v12.13.0</nodeVersion>
+ <yarnVersion>v1.22.10</yarnVersion>
</configuration>
</execution>
<execution>
diff --git a/sdnr/wt/odlux/apps/linkCalculationApp/package.json b/sdnr/wt/odlux/apps/linkCalculationApp/package.json
index 171770603..c03afe19b 100644
--- a/sdnr/wt/odlux/apps/linkCalculationApp/package.json
+++ b/sdnr/wt/odlux/apps/linkCalculationApp/package.json
@@ -29,8 +29,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/linkCalculationApp/pom.xml b/sdnr/wt/odlux/apps/linkCalculationApp/pom.xml
index 5467c8b5d..c5d8c3617 100644
--- a/sdnr/wt/odlux/apps/linkCalculationApp/pom.xml
+++ b/sdnr/wt/odlux/apps/linkCalculationApp/pom.xml
@@ -140,8 +140,8 @@
<!-- optional: default phase is "generate-resources" -->
<phase>initialize</phase>
<configuration>
- <nodeVersion>v10.16.3</nodeVersion>
- <yarnVersion>v1.19.0</yarnVersion>
+ <nodeVersion>v12.13.0</nodeVersion>
+ <yarnVersion>v1.22.10</yarnVersion>
</configuration>
</execution>
<execution>
diff --git a/sdnr/wt/odlux/apps/linkCalculationApp/src/actions/commonLinkCalculationActions.ts b/sdnr/wt/odlux/apps/linkCalculationApp/src/actions/commonLinkCalculationActions.ts
index e7427e4cc..0849058dc 100644
--- a/sdnr/wt/odlux/apps/linkCalculationApp/src/actions/commonLinkCalculationActions.ts
+++ b/sdnr/wt/odlux/apps/linkCalculationApp/src/actions/commonLinkCalculationActions.ts
@@ -21,98 +21,155 @@ import { Dispatch } from "../../../../framework/src/flux/store";
import { IApplicationStoreState } from "../../../../framework/src/store/applicationStore";
-export class UpdateLinkIdAction extends Action{
- constructor(public linkId: string){
+export class UpdateLinkIdAction extends Action {
+ constructor(public linkId: string) {
super();
}
}
-export class UpdateFrequencyAction extends Action{
- constructor(public frequency: number){
+export class UpdateFrequencyAction extends Action {
+ constructor(public frequency: number) {
super();
}
}
-export class UpdateSiteAction extends Action{
+export class UpdateSiteAction extends Action {
constructor(
public siteA?: any,
public siteB?: any
- ){
+ ) {
super();
}
}
-export class UpdateRainAttAction extends Action{
-
- constructor(public rainAtt: number){
+export class UpdateRainAttAction extends Action {
+
+ constructor(public rainAtt: number) {
super();
}
}
-export class UpdateRainValAction extends Action{
- constructor(public rainVal: number){
+export class UpdateRainValAction extends Action {
+ constructor(public rainVal: number) {
super();
}
}
-export class updateHideForm extends Action{
- constructor(public formView: boolean){
+export class updateHideForm extends Action {
+ constructor(public formView: boolean) {
super();
}
}
-export class UpdateDistanceAction extends Action{
- constructor(public distance: number){
+export class UpdateDistanceAction extends Action {
+ constructor(public distance: number) {
super();
}
}
-export class UpdateFslCalculation extends Action{
- constructor(public fsl: number){
+export class UpdateFslCalculation extends Action {
+ constructor(public fsl: number) {
super();
}
}
-export class UpdateLatLonAction extends Action{
+export class UpdateLatLonAction extends Action {
constructor(
public Lat1: number,
- public Lon1:number,
- public Lat2: number,
+ public Lon1: number,
+ public Lat2: number,
public Lon2: number
- ){
+ ) {
+ super();
+
+ }
+}
+export class UpdatePolAction extends Action {
+ constructor(public polarization: string) {
super();
-
}
}
-export class UpdatePolAction extends Action{
- constructor(public polarization: string){
+export class isCalculationServerReachableAction extends Action {
+ constructor(public reachable: boolean) {
super();
}
}
-export class isCalculationServerReachableAction extends Action{
- constructor(public reachable: boolean){
+export class updateAltitudeAction extends Action {
+ constructor(
+ public amslA: number,
+ public aglA: number,
+ public amslB: number,
+ public aglB: number
+ ) {
super();
}
}
-export class updateAltitudeAction extends Action{
+export class UpdateAbsorptionLossAction extends Action {
constructor(
- public amslA:number,
- public aglA:number,
- public amslB:number,
- public aglB:number
- ){
+ public absorptionOxygen: number,
+ public absorptionWater: number,
+
+ ) {
+ super();
+ }
+}
+export class UpdateWorstMonthRainAction extends Action {
+ constructor(public month: string) {
+ super();
+ }
+}
+
+export class UpdateEIRPAction extends Action {
+ constructor(public eirpA: number,public eirpB: number) {
+ super();
+ }
+}
+export class UpdateAntennaGainAction extends Action {
+ constructor(public antennaGainList: string[]) {
+ super();
+ }
+}
+export class UpdateAntennaListAction extends Action {
+ constructor(public antennaList: string[]) {
+ super();
+ }
+}
+export class UpdateAntennaAction extends Action {
+ constructor(public antennaA: string | null, public antennaB : string | null) {
+ super();
+ }
+}
+export class UpdateRadioAttributesAction extends Action {
+ constructor(public som: number , public eirpA : number, public eirpB : number) {
super();
}
}
-export class UpdateAbsorptionLossAction extends Action{
- constructor(
- public absorptionOxygen:number,
- public absorptionWater:number,
-
- ){
- super();
- }
+export class UpdateTxPowerAction extends Action {
+ constructor(public txPowerA: string | null , public txPowerB : string | null) {
+ super();
+ }
}
-export class UpdateWorstMonthRainAction extends Action{
- constructor(public month: string){
+export class UpdateRxSensitivityAction extends Action {
+ constructor(public rxSensitivityA: string | null , public rxSensitivityB : string | null) {
super();
}
}
+
+export const updateAntennaList = (frequency: number) => async (dispatcher: Dispatch, getState: () => IApplicationStoreState) => {
+ let antennaList: string[] = []
+ let antennaDiameterList: string[] = []
+ let antennaGainList :string[] =[]
+ //switch case here frequency = 26? antennaList.push
+ switch (frequency) {
+ case 7: antennaList.push('ANDREW VHLPX2.5-7W', 'ANDREW VHLPX3-7W', 'ANDREW VHLPX4-7W', 'ANDREW VHLPX6-7W' ), antennaDiameterList.push('0.6','0.9','1.2','1.8'), antennaGainList.push('33.90','35.50','37.30','40.61'); break
+ case 11: antennaList.push('ANDREW VHLPX2-11W', 'ANDREW VHLPX3-11W', 'ANDREW VHLPX4-11W'), antennaDiameterList.push('0.6','0.9','1.2'), antennaGainList.push('34.50','38.4','40.70');break
+ case 15: antennaList.push('ANDREW VHLPX1-15', 'ANDREW VHLPX2-15', 'ANDREW VHLPX3-15', 'ANDREW VHLPX4-15'), antennaDiameterList.push('0.3','0.6','0.9','1.2'), antennaGainList.push('32.00','36.80','41.11','42.90');break
+ case 23: antennaList.push('ANDREW VHLPX1-23', 'ANDREW VHLPX2-23', 'ANDREW VHLPX3-23', 'ANDREW VHLPX4-23'), antennaDiameterList.push('0.3','0.6','0.9','1.2'), antennaGainList.push('35.30','40.21','44.80','46.71');break
+ case 26: antennaList.push('ANDREW VHLPX1-26', 'ANDREW VHLPX2-26', 'ANDREW VHLPX3-26'), antennaDiameterList.push('0.3','0.6','0.9'), antennaGainList.push('36.61','40.21','41.21','45.80');break
+ case 28: antennaList.push('ANDREW VHLPX1-28', 'ANDREW VHLPX2-28'), antennaDiameterList.push('0.3','0.6'), antennaGainList.push('38.11','42.21');break
+ case 38: antennaList.push('ANDREW VHLPX1-38', 'ANDREW VHLPX2-38'), antennaDiameterList.push('0.3','0.6'), antennaGainList.push('40.11','45.21');break
+ case 42: antennaList.push('ANDREW VHLPX1-42-XXX/D', 'ANDREW VHLPX2-42-XXX/A'), antennaDiameterList.push('0.3','0.6'), antennaGainList.push('40.80','46.00');break
+ case 80: antennaList.push('Radio Waves HPCPE-80', 'Radio Waves HPLP2-80'), antennaDiameterList.push('0.3','0.6'), antennaGainList.push('43.80','50.80');break
+ }
+ dispatcher(new UpdateAntennaListAction(antennaList))
+ dispatcher(new UpdateAntennaGainAction(antennaGainList))
+}
+
diff --git a/sdnr/wt/odlux/apps/linkCalculationApp/src/handlers/linkCalculationAppRootHandler.ts b/sdnr/wt/odlux/apps/linkCalculationApp/src/handlers/linkCalculationAppRootHandler.ts
index 608367072..edfad052a 100644
--- a/sdnr/wt/odlux/apps/linkCalculationApp/src/handlers/linkCalculationAppRootHandler.ts
+++ b/sdnr/wt/odlux/apps/linkCalculationApp/src/handlers/linkCalculationAppRootHandler.ts
@@ -21,7 +21,7 @@ import { combineActionHandler } from '../../../../framework/src/flux/middleware'
// ** do not remove **
import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
import { IActionHandler } from '../../../../framework/src/flux/action';;
-import { UpdateLinkIdAction, UpdateFrequencyAction , UpdateLatLonAction, UpdateRainAttAction, UpdateRainValAction, updateHideForm, UpdateFslCalculation, UpdateSiteAction, UpdateDistanceAction, isCalculationServerReachableAction, UpdatePolAction, updateAltitudeAction, UpdateAbsorptionLossAction, UpdateWorstMonthRainAction} from '../actions/commonLinkCalculationActions';
+import { UpdateLinkIdAction, UpdateFrequencyAction , UpdateLatLonAction, UpdateRainAttAction, UpdateRainValAction, updateHideForm, UpdateFslCalculation, UpdateSiteAction, UpdateDistanceAction, isCalculationServerReachableAction, UpdatePolAction, updateAltitudeAction, UpdateAbsorptionLossAction, UpdateWorstMonthRainAction, UpdateEIRPAction, UpdateAntennaAction, UpdateAntennaListAction, UpdateAntennaGainAction, UpdateTxPowerAction, UpdateRxSensitivityAction} from '../actions/commonLinkCalculationActions';
declare module '../../../../framework/src/store/applicationStore' {
interface IApplicationStoreState {
@@ -55,7 +55,20 @@ export type ILinkCalculationAppStateState= {
aglB:number,
absorptionWater:number,
absorptionOxygen: number,
- month: string
+ month: string,
+ eirpA: number,
+ eirpB: number,
+ antennaGainA: number,
+ antennaGainB :number,
+ antennaList:string[],
+ antennaGainList:string[],
+ antennaA: string,
+ antennaB:string,
+ systemOperatingMargin : number,
+ txPowerA : string,
+ txPowerB: string,
+ rxSensitivityA : string,
+ rxSensitivityB: string
}
const initialState: ILinkCalculationAppStateState ={
@@ -80,7 +93,20 @@ const initialState: ILinkCalculationAppStateState ={
aglB:0,
absorptionWater:0,
absorptionOxygen: 0,
- month: ''
+ month: '',
+ eirpA: 0,
+ eirpB: 0,
+ antennaGainA :0,
+ antennaGainB :0,
+ antennaList:[],
+ antennaGainList:[],
+ antennaA: '0',
+ antennaB:'0',
+ systemOperatingMargin : 0,
+ txPowerA : '0',
+ txPowerB: '0',
+ rxSensitivityA: '0',
+ rxSensitivityB: '0'
}
@@ -130,6 +156,25 @@ export const LinkCalculationHandler: IActionHandler<ILinkCalculationAppStateStat
else if (action instanceof UpdateWorstMonthRainAction){
state = Object.assign({}, state, {month:action.month})
}
+ else if (action instanceof UpdateEIRPAction){
+ state = Object.assign({}, state, {eirpA:action.eirpA, eirpB:action.eirpB})
+ }
+ else if (action instanceof UpdateAntennaGainAction){
+ state = Object.assign({}, state, {antennaGainList:action.antennaGainList})
+ }
+ else if (action instanceof UpdateAntennaListAction){
+ state = Object.assign({}, state, {antennaList:action.antennaList})
+ }
+ else if (action instanceof UpdateAntennaAction){
+ state = Object.assign({}, state, {antennaA:action.antennaA == null ? state.antennaA : action.antennaA , antennaB: action.antennaB == null? state.antennaB : action.antennaB})
+ }
+ else if (action instanceof UpdateTxPowerAction){
+ state = Object.assign({}, state, {txPowerA:action.txPowerA == null ? state.txPowerA : action.txPowerA , txPowerB: action.txPowerB == null? state.txPowerB : action.txPowerB})
+ }
+ else if (action instanceof UpdateRxSensitivityAction){
+ state = Object.assign({}, state, {rxSensitivityA:action.rxSensitivityA == null ? state.rxSensitivityA : action.rxSensitivityA , rxSensitivityB: action.rxSensitivityB == null? state.rxSensitivityB : action.rxSensitivityB})
+ }
+
return state
}
diff --git a/sdnr/wt/odlux/apps/linkCalculationApp/src/views/Style.scss b/sdnr/wt/odlux/apps/linkCalculationApp/src/views/Style.scss
index 35a9b9702..e4b0c7797 100644
--- a/sdnr/wt/odlux/apps/linkCalculationApp/src/views/Style.scss
+++ b/sdnr/wt/odlux/apps/linkCalculationApp/src/views/Style.scss
@@ -1,11 +1,11 @@
-.parent{
+// .parent{
- display: flex;
- justify-content: space-evenly;
- margin: auto;
+// display: flex;
+// justify-content: space-evenly;
+// margin: auto;
-}
+//}
.input {
width: 150px;
box-sizing: border-box;
@@ -18,56 +18,99 @@
box-sizing: border-box;
}
+.container1{
+ margin-bottom: 15px;
-.container-1 {
- height: 50vh;
- width: 80%;
- justify-content: center;
- align-items: baseline;;
- display: flex;
- flex-direction: row;
- align-content: space-between;
- padding: 20px 40px;
- border-radius: 10px;
- // box-shadow: 0px 10px 50px #555;
- background-color: #ffffff;
- // padding-top: 10px;
-
}
- .column1 {
- flex-direction: column;
- width: 30%;
- align-items: flex-end;;
- // padding: 2em;
+.container1 div{
+ display:flex;
+ flex-direction: row;
+
+ width:100%;
+ padding-top: 2px;
+}
+
+.container1 div div{
+ width:50%;
+ border-bottom-style: solid;
+ border-bottom-width: thin;
+ border-color: silver;
+}
+
+.firstBox div:first-child{
+ margin-left: 33.5%;
+}
+
+// .container-1 {
+// width: 80%;
+// justify-content: center;
+// align-items: baseline;;
+// display: flex;
+// flex-direction: row;
+// align-content: space-between;
+// padding: 20px 40px;
+// border-radius: 10px;
+// // box-shadow: 0px 10px 50px #555;
+// background-color: #ffffff;
+// // padding-top: 10px;
+
+// }
+
+ // .column1 {
+ // flex-direction: column;
+ // width: 30%;
+ // align-items: flex-end;;
+ // // padding: 2em;
- }
- .column1 div {
- margin-top: 10px;
- // align-items: space-between;
- // flex-wrap: wrap;
- border-bottom-style: solid;
- border-bottom-width: thin;
- border-color: silver;
- }
- .middlecolumn{
+ // }
+ // .column1 div {
+ // margin-top: 10px;
+ // // align-items: space-between;
+ // // flex-wrap: wrap;
+ // border-bottom-style: solid;
+ // border-bottom-width: thin;
+ // border-color: silver;
+ // }
+ // .middlecolumn{
- flex-direction: column;
- flex-grow: 1;
- // padding: 10px 10px;
- }
+ // flex-direction: column;
+ // flex-grow: 1;
+ // // padding: 10px 10px;
+ // }
- .middlecolumn div{
- margin-top: 10px;
- border-bottom-style: solid;
- border-bottom-width: thin;
- border-color: silver;
- }
+ // .middlecolumn div{
+ // margin-top: 10px;
+ // border-bottom-style: solid;
+ // border-bottom-width: thin;
+ // border-color: silver;
+ // }
- .column2 {
- margin-left: 200px;
- }
- .column2 div{
- margin-top: 10px;
+ // .column2 {
+ // margin-left: 200px;
+ // }
+ // .column2 div{
+ // margin-top: 10px;
- } \ No newline at end of file
+ // }
+
+ .antennaContainer{
+ margin-bottom: 15px;
+ background-color: rgb(184, 181, 181);
+
+ }
+ .antennaContainer div {
+ display:flex;
+ flex-direction: row;
+
+ width:100%;
+ padding-top: 2px;
+}
+.antennaContainer div div{
+
+ width:50%;
+
+}
+.antennaFont{
+ font-family: "Lucida Console";
+} \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/linkCalculationApp/src/views/linkCalculationComponent.tsx b/sdnr/wt/odlux/apps/linkCalculationApp/src/views/linkCalculationComponent.tsx
index 61a700c71..063926269 100644
--- a/sdnr/wt/odlux/apps/linkCalculationApp/src/views/linkCalculationComponent.tsx
+++ b/sdnr/wt/odlux/apps/linkCalculationApp/src/views/linkCalculationComponent.tsx
@@ -24,10 +24,11 @@ import { TextField, Tabs, Tab, Typography, AppBar, Button, Tooltip, Checkbox, Ta
import './Style.scss'
import { IApplicationStoreState } from "../../../../framework/src/store/applicationStore";
-import { UpdateFrequencyAction, UpdateLatLonAction, UpdateRainAttAction, UpdateRainValAction, UpdateFslCalculation, isCalculationServerReachableAction, UpdatePolAction, UpdateDistanceAction, updateAltitudeAction, UpdateAbsorptionLossAction, UpdateWorstMonthRainAction } from "../actions/commonLinkCalculationActions";
+import { UpdateFrequencyAction, UpdateLatLonAction, UpdateRainAttAction, UpdateRainValAction, UpdateFslCalculation, isCalculationServerReachableAction, UpdatePolAction, UpdateDistanceAction, updateAltitudeAction, UpdateAbsorptionLossAction, UpdateWorstMonthRainAction, updateAntennaList, UpdateAntennaAction, UpdateRadioAttributesAction, UpdateTxPowerAction, UpdateRxSensitivityAction } from "../actions/commonLinkCalculationActions";
import { faPlaneArrival, faAlignCenter } from "@fortawesome/free-solid-svg-icons";
import ConnectionInfo from '../components/connectionInfo'
import { red } from "@material-ui/core/colors";
+import { Dvr } from "@material-ui/icons";
@@ -41,33 +42,44 @@ const mapProps = (state: IApplicationStoreState) => ({
rainAtt: state.linkCalculation.calculations.rainAtt,
rainVal: state.linkCalculation.calculations.rainVal,
formView: state.linkCalculation.calculations.formView,
- fsl:state.linkCalculation.calculations.fsl,
+ fsl: state.linkCalculation.calculations.fsl,
siteA: state.linkCalculation.calculations.siteA,
siteB: state.linkCalculation.calculations.siteB,
distance: state.linkCalculation.calculations.distance,
- reachable :state.linkCalculation.calculations.reachable,
- polarization:state.linkCalculation.calculations.polarization,
- amslA:state.linkCalculation.calculations.amslA,
- amslB:state.linkCalculation.calculations.amslB,
- aglA:state.linkCalculation.calculations.aglA,
- aglB:state.linkCalculation.calculations.aglB,
- absorptionOxygen : state.linkCalculation.calculations.absorptionOxygen,
- absorptionWater : state.linkCalculation.calculations.absorptionWater,
- month : state.linkCalculation.calculations.month
+ reachable: state.linkCalculation.calculations.reachable,
+ polarization: state.linkCalculation.calculations.polarization,
+ amslA: state.linkCalculation.calculations.amslA,
+ amslB: state.linkCalculation.calculations.amslB,
+ aglA: state.linkCalculation.calculations.aglA,
+ aglB: state.linkCalculation.calculations.aglB,
+ absorptionOxygen: state.linkCalculation.calculations.absorptionOxygen,
+ absorptionWater: state.linkCalculation.calculations.absorptionWater,
+ month: state.linkCalculation.calculations.month,
+ eirpSiteA: state.linkCalculation.calculations.eirpA,
+ eirpSiteB: state.linkCalculation.calculations.eirpB,
+ antennaGainA: state.linkCalculation.calculations.antennaGainA,
+ antennaGainB: state.linkCalculation.calculations.antennaGainB,
+ antennaList: state.linkCalculation.calculations.antennaList,
+ antennaGainList: state.linkCalculation.calculations.antennaGainList,
+ antennaA: state.linkCalculation.calculations.antennaA,
+ antennaB: state.linkCalculation.calculations.antennaB,
+ systemOperatingMargin : state.linkCalculation.calculations.systemOperatingMargin
+
});
-const BASE_URL="/topology/linkcalculator"
+const BASE_URL = "/topology/linkcalculator"
const mapDispatch = (dispatcher: IDispatcher) => ({
updateFrequency: (frequency: number) => {
- dispatcher.dispatch(new UpdateFrequencyAction(frequency))
+ dispatcher.dispatch(new UpdateFrequencyAction(frequency))
+ dispatcher.dispatch(updateAntennaList(frequency))
},
updateLatLon: (Lat1: number, Lon1: number, Lat2: number, Lon2: number) => {
dispatcher.dispatch(new UpdateLatLonAction(Lat1, Lon1, Lat2, Lon2))
},
-
+
updateRainValue: (rainVal: number) => {
dispatcher.dispatch(new UpdateRainValAction(rainVal))
},
@@ -80,53 +92,59 @@ const mapDispatch = (dispatcher: IDispatcher) => ({
dispatcher.dispatch(new UpdateRainAttAction(rainAtt))
},
-
- FSL :(free:number)=> {
- dispatcher.dispatch(new UpdateFslCalculation (free))
- },
- UpdateConectivity : (reachable:boolean) => {
- dispatcher.dispatch (new isCalculationServerReachableAction (reachable))
+ FSL: (free: number) => {
+ dispatcher.dispatch(new UpdateFslCalculation(free))
},
- updatePolarization :(polarization:any)=>{
- dispatcher.dispatch (new UpdatePolAction(polarization))
+ UpdateConectivity: (reachable: boolean) => {
+ dispatcher.dispatch(new isCalculationServerReachableAction(reachable))
},
- updateAutoDistance : (distance:number)=>{
- dispatcher.dispatch (new UpdateDistanceAction(distance))
+ updatePolarization: (polarization: any) => {
+ dispatcher.dispatch(new UpdatePolAction(polarization))
},
- UpdateAbsorption : (OxLoss:number , WaterLoss:number) => {
- dispatcher.dispatch (new UpdateAbsorptionLossAction (OxLoss, WaterLoss))
+ updateAutoDistance: (distance: number) => {
+ dispatcher.dispatch(new UpdateDistanceAction(distance))
},
- // UpdateWorstMonth : (worstmonth:boolean) => {
- // dispatcher.dispatch (new UpdateWorstMonthAction(worstmonth))
- // },
-
- UpdateWorstMonthRain : (month:string) => {
- dispatcher.dispatch (new UpdateWorstMonthRainAction(month))
- }
+ UpdateAbsorption: (OxLoss: number, WaterLoss: number) => {
+ dispatcher.dispatch(new UpdateAbsorptionLossAction(OxLoss, WaterLoss))
+ },
+ UpdateWorstMonthRain: (month: string) => {
+ dispatcher.dispatch(new UpdateWorstMonthRainAction(month))
+ },
+ UpdateAntenas: (antennaA: string | null, antennaB: string | null) => {
+ dispatcher.dispatch(new UpdateAntennaAction(antennaA, antennaB))
+ },
+ UpdateRadioAttributes :(som: number, eirpA: number, eirpB: number)=>{
+ dispatcher.dispatch(new UpdateRadioAttributesAction(som,eirpA, eirpB))
+ },
+ UpdateTxPower :(txPowerA: string | null, txPowerB: string | null)=>{
+ dispatcher.dispatch(new UpdateTxPowerAction(txPowerA, txPowerB))
+ },
+ UpdateRxSensitivity :(rxSensitivityA : string | null, rxSensitivityB : string | null)=>{
+ dispatcher.dispatch(new UpdateRxSensitivityAction(rxSensitivityA, rxSensitivityB))
+ }
});
type linkCalculationProps = Connect<typeof mapProps, typeof mapDispatch>;
interface initialState {
- rainMethodDisplay: boolean,
- absorptionMethod : string;
+ rainMethodDisplay: boolean,
+ absorptionMethod: string;
horizontalBoxChecked: boolean,
- latitude1Error: string,
- longitude1Error:string
- latitude2Error: string,
- longitude2Error:string,
- frequencyError: string,
- rainMethodError: string,
- attenuationMethodError : string,
- worstmonth : boolean,
- showWM : string
-
-
+ latitude1Error: string,
+ longitude1Error: string
+ latitude2Error: string,
+ longitude2Error: string,
+ frequencyError: string,
+ rainMethodError: string,
+ antennaTypeError: string,
+ attenuationMethodError: string,
+ worstmonth: boolean,
+ showWM: string,
}
class LinkCalculation extends React.Component<linkCalculationProps, initialState> {
@@ -135,40 +153,41 @@ class LinkCalculation extends React.Component<linkCalculationProps, initialState
this.state = {
rainMethodDisplay: false,
horizontalBoxChecked: true,
- absorptionMethod : '0',
+ absorptionMethod: '0',
latitude1Error: '',
- longitude1Error:'',
+ longitude1Error: '',
latitude2Error: '',
- longitude2Error:'',
+ longitude2Error: '',
frequencyError: '',
rainMethodError: '',
- attenuationMethodError : '',
- worstmonth : false,
- showWM: ''
- };
- }
-
- updateAutoDistance = async (lat1: number, lon1: number, lat2: number, lon2: number)=>{
- const result = await fetch(BASE_URL+'/distance/' + lat1 + ',' + lon1 + ',' + lat2 + ',' + lon2)
- const json = await result.json()
- return json.distanceInKm
- }
+ attenuationMethodError: '',
+ antennaTypeError: '',
+ worstmonth: false,
+ showWM: '',
+ };
+ }
+
+ updateAutoDistance = async (lat1: number, lon1: number, lat2: number, lon2: number) => {
+ const result = await fetch(BASE_URL + '/distance/' + lat1 + ',' + lon1 + ',' + lat2 + ',' + lon2)
+ const json = await result.json()
+ return json.distanceInKm
+ }
+
+ updateLatLon = (e: any) => {
+
+ e.target.id == 'Lat1' ? this.props.updateLatLon(e.target.value, this.props.lon1, this.props.lat2, this.props.lon2) : null
+ e.target.id == 'Lon1' ? this.props.updateLatLon(this.props.lat1, e.target.value, this.props.lat2, this.props.lon2) : null
+ e.target.id == 'Lat2' ? this.props.updateLatLon(this.props.lat1, this.props.lon1, e.target.value, this.props.lon2) : null
+ e.target.id == 'Lon2' ? this.props.updateLatLon(this.props.lat1, e.target.value, this.props.lat2, e.target.value) : null
- updateLatLon = (e:any) => {
-
- e.target.id== 'Lat1'? this.props.updateLatLon(e.target.value, this.props.lon1, this.props.lat2, this.props.lon2) : null
- e.target.id== 'Lon1'? this.props.updateLatLon(this.props.lat1, e.target.value, this.props.lat2, this.props.lon2) : null
- e.target.id== 'Lat2'? this.props.updateLatLon(this.props.lat1, this.props.lon1, e.target.value, this.props.lon2) : null
- e.target.id== 'Lon2'? this.props.updateLatLon(this.props.lat1, e.target.value, this.props.lat2, e.target.value) : null
-
}
- updatePoli = (val: string) =>{
+ updatePoli = (val: string) => {
- this.setState({horizontalBoxChecked: !this.state.horizontalBoxChecked});
+ this.setState({ horizontalBoxChecked: !this.state.horizontalBoxChecked });
this.props.updatePolarization(val);
-
+
}
LatLonToDMS = (value: number, isLon: boolean = false) => {
@@ -187,266 +206,359 @@ class LinkCalculation extends React.Component<linkCalculationProps, initialState
}
}
- rainAttCal = (lat1: any, lon1: any, lat2: any, lon2: any, frequency: any, distance: number, polarization : string, worstmonth:boolean) => {
- if(!worstmonth){
- fetch(BASE_URL+'/rain/annual/' + lat1 + ',' + lon1 + ',' + lat2 + ',' + lon2 + '/' + frequency+ '/'+ distance + '/' + polarization.toUpperCase())
- .then(res => res.json())
- .then(result => { this.props.UpdateRainAtt(result.rainAttenuation) ; this.props.updateRainValue(result.rainFall.rainrate)})
+ rainAttCal = (lat1: any, lon1: any, lat2: any, lon2: any, frequency: any, distance: number, polarization: string, worstmonth: boolean) => {
+ if (!worstmonth) {
+ fetch(BASE_URL + '/rain/annual/' + lat1 + ',' + lon1 + ',' + lat2 + ',' + lon2 + '/' + frequency + '/' + distance + '/' + polarization.toUpperCase())
+ .then(res => res.json())
+ .then(result => { this.props.UpdateRainAtt(result.rainAttenuation); this.props.updateRainValue(result.rainFall.rainrate) })
}
else {
- fetch(BASE_URL+'/rain/worstmonth/' + lat1 + ',' + lon1 + ',' + lat2 + ',' + lon2 + '/' + frequency+ '/'+ distance + '/' + polarization.toUpperCase())
- .then(res => res.json())
- .then(result => { this.props.UpdateRainAtt(result.rainAttenuation) ; this.props.updateRainValue(result.rainFall.rainrate); this.props.UpdateWorstMonthRain (result.rainFall.period); this.setState({showWM: '- Wm is : '})})
+ fetch(BASE_URL + '/rain/worstmonth/' + lat1 + ',' + lon1 + ',' + lat2 + ',' + lon2 + '/' + frequency + '/' + distance + '/' + polarization.toUpperCase())
+ .then(res => res.json())
+ .then(result => { this.props.UpdateRainAtt(result.rainAttenuation); this.props.updateRainValue(result.rainFall.rainrate); this.props.UpdateWorstMonthRain(result.rainFall.period); this.setState({ showWM: '- Wm is : ' }) })
}
}
- manualRain = (rainfall: number, frequency: number, distance:number, polarization : string) => {
- fetch(BASE_URL+'/rain/' + rainfall + '/' + frequency + '/' + distance+ '/' + polarization.toUpperCase())
+ manualRain = (rainfall: number, frequency: number, distance: number, polarization: string) => {
+ fetch(BASE_URL + '/rain/' + rainfall + '/' + frequency + '/' + distance + '/' + polarization.toUpperCase())
.then(res => res.json())
.then(result => { this.props.specificRain(result.rainAttenuation) })
- }
+ }
+
+ FSL = (distance: number, frequency: number) => {
+ fetch(BASE_URL + '/fsl/' + distance + '/' + frequency)
+ .then(res => res.json())
+ .then(result => { this.props.FSL(result.fspl) })
+ }
- FSL = (distance:number, frequency:number) => {
- fetch(BASE_URL+'/fsl/' + distance + '/' + frequency)
- .then(res=>res.json())
- .then (result => {this.props.FSL(result.fspl)})
+ AbsorptionAtt = (lat1: number, lon1: number, lat2: number, lon2: number, distance: number, frequency: number, worstmonth: boolean, absorptionMethod: string) => {
+ if (!worstmonth) {
+ fetch(BASE_URL + '/absorption/annual/' + lat1 + ',' + lon1 + ',' + lat2 + ',' + lon2 + '/' + distance + '/' + frequency + '/' + absorptionMethod)
+ .then(res => res.json())
+ .then(result => { this.props.UpdateAbsorption(result.oxygenLoss, result.waterLoss) })
}
-
- AbsorptionAtt =(lat1: number, lon1: number, lat2: number, lon2: number, distance:number, frequency:number, worstmonth:boolean, absorptionMethod : string) => {
- if(!worstmonth)
- {
- fetch(BASE_URL+'/absorption/annual/' +lat1 + ',' + lon1 + ',' + lat2 + ',' + lon2 + '/' + distance + '/' + frequency + '/' +absorptionMethod)
- .then(res=>res.json())
- .then (result => {this.props.UpdateAbsorption(result.oxygenLoss, result.waterLoss)})
- }
- else {
- fetch(BASE_URL+'/absorption/annual/' +lat1 + ',' + lon1 + ',' + lat2 + ',' + lon2 + '/' + distance + '/' + frequency + '/' +absorptionMethod)
- .then(res=>res.json())
- .then (result => {this.props.UpdateAbsorption(result.oxygenLoss, result.waterLoss)})
- }
+ else {
+ fetch(BASE_URL + '/absorption/annual/' + lat1 + ',' + lon1 + ',' + lat2 + ',' + lon2 + '/' + distance + '/' + frequency + '/' + absorptionMethod)
+ .then(res => res.json())
+ .then(result => { this.props.UpdateAbsorption(result.oxygenLoss, result.waterLoss) })
}
+ }
+
+ linkBudget = (antennaA: string, antennaB: string, transmissionPowerA: number, transmissionPowerB: number) => {
+ fetch(BASE_URL + '/linkbudget/' + antennaA + '/' + antennaB + '/' + transmissionPowerA + '/' + transmissionPowerB)
+ .then(res=>res.json())
+ .then(result => {this.props.UpdateRadioAttributes(result.systemOperatingMargin, result.eirpA, result.eirpB)})
+ }
+
+ formValid = () => {
+
+ this.props.lat1 === 0 ? this.setState({ latitude1Error: 'Enter a number between -90 to 90' }) : null
+ this.props.lat2 === 0 ? this.setState({ latitude2Error: 'Enter a number between -90 to 90' }) : null
+ this.props.lon1 === 0 ? this.setState({ longitude1Error: 'Enter a number between -180 to 180' }) : null
+ this.props.lon2 === 0 ? this.setState({ longitude2Error: 'Enter a number between -180 to 180' }) : null
+ this.props.frequency === 0 ? this.setState({ frequencyError: 'Select a frequency' }) : this.setState({ frequencyError: '' })
+
+ this.state.rainMethodDisplay === null && this.props.rainVal === 0 ? this.setState({ rainMethodError: 'Select the rain method' }) : this.setState({ rainMethodError: '' })
+ this.state.absorptionMethod === '0' ? this.setState({ attenuationMethodError: 'Select the attenuation method' }) : this.setState({ attenuationMethodError: '' })
+ console.log(this.state);
+ console.log(this.props.lat1 !== 0 && this.props.lat2 !== 0 && this.props.lon1 !== 0 && this.props.lon2 !== 0 && this.props.frequency !== 0 && this.state.rainMethodError === '' && this.state.attenuationMethodError === '');
+
+ return this.props.lat1 !== 0 && this.props.lat2 !== 0 && this.props.lon1 !== 0 && this.props.lon2 !== 0 && this.props.frequency !== 0 && this.state.rainMethodError === '' && this.state.attenuationMethodError === '';
+
+ }
+
+
- formValid = () => {
-
- this.props.lat1 === 0 ? this.setState({latitude1Error: 'Enter a number between -90 to 90'}) : null
- this.props.lat2 === 0 ? this.setState({latitude2Error: 'Enter a number between -90 to 90'}) : null
- this.props.lon1 === 0 ? this.setState({longitude1Error: 'Enter a number between -180 to 180' }) : null
- this.props.lon2 === 0 ? this.setState({longitude2Error: 'Enter a number between -180 to 180' }) : null
- this.props.frequency === 0 ? this.setState({frequencyError: 'Select a frequency' }) : this.setState({frequencyError: ''})
-
- this.state.rainMethodDisplay === null && this.props.rainVal === 0 ? this.setState({rainMethodError: 'Select the rain method'}) : this.setState({rainMethodError: ''})
- this.state.absorptionMethod === '0' ? this.setState({attenuationMethodError: 'Select the attenuation method'}) : this.setState({attenuationMethodError: ''})
- console.log(this.state);
- console.log(this.props.lat1 !== 0 && this.props.lat2 !== 0 && this.props.lon1 !== 0 && this.props.lon2 !==0 && this.props.frequency!==0 && this.state.rainMethodError==='' && this.state.attenuationMethodError=== '');
-
- return this.props.lat1 !== 0 && this.props.lat2 !== 0 && this.props.lon1 !== 0 && this.props.lon2 !==0 && this.props.frequency!==0 && this.state.rainMethodError==='' && this.state.attenuationMethodError=== '';
-
- }
-
-
-
buttonHandler = async () => {
-
- if (this.formValid()) {
+
+ if (this.formValid()) {
this.props.updateAutoDistance(await this.updateAutoDistance(this.props.lat1, this.props.lon1, this.props.lat2, this.props.lon2))
this.FSL(this.props.distance, this.props.frequency)
- if (this.state.worstmonth===false) {
- this.setState({showWM : ' '})
+ if (this.state.worstmonth === false) {
+ this.setState({ showWM: ' ' })
this.props.UpdateWorstMonthRain('')
- this.AbsorptionAtt (this.props.lat1, this.props.lon1, this.props.lat2, this.props.lon2, this.props.distance, this.props.frequency, this.state.worstmonth, this.state.absorptionMethod)
+ this.AbsorptionAtt(this.props.lat1, this.props.lon1, this.props.lat2, this.props.lon2, this.props.distance, this.props.frequency, this.state.worstmonth, this.state.absorptionMethod)
- if (this.state.rainMethodDisplay === true){
+ if (this.state.rainMethodDisplay === true) {
- this.manualRain(this.props.rainVal, this.props.frequency, this.props.distance, this.props.polarization!);
+ this.manualRain(this.props.rainVal, this.props.frequency, this.props.distance, this.props.polarization!);
}
else {
// this.updateRainValue(this.props.lat1, this.props.lon1, this.props.lat2, this.props.lon2, this.state.worstmonth)
this.rainAttCal(this.props.lat1, this.props.lon1, this.props.lat2, this.props.lon2, this.props.frequency, this.props.distance, this.props.polarization!, this.state.worstmonth);
}
- }
- else {
- this.AbsorptionAtt (this.props.lat1, this.props.lon1, this.props.lat2, this.props.lon2, this.props.distance, this.props.frequency, this.state.worstmonth, this.state.absorptionMethod)
+ }
+ else {
+ this.AbsorptionAtt(this.props.lat1, this.props.lon1, this.props.lat2, this.props.lon2, this.props.distance, this.props.frequency, this.state.worstmonth, this.state.absorptionMethod)
- // this.updateRainValue(this.props.lat1, this.props.lon1, this.props.lat2, this.props.lon2, this.state.worstmonth)
+ // this.updateRainValue(this.props.lat1, this.props.lon1, this.props.lat2, this.props.lon2, this.state.worstmonth)
- this.rainAttCal(this.props.lat1, this.props.lon1, this.props.lat2, this.props.lon2, this.props.frequency, this.props.distance, this.props.polarization!, this.state.worstmonth);
+ this.rainAttCal(this.props.lat1, this.props.lon1, this.props.lat2, this.props.lon2, this.props.frequency, this.props.distance, this.props.polarization!, this.state.worstmonth);
}
}
- else console.log('form is not valid')
+ else console.log('form is not valid')
}
componentDidMount = () => {
- fetch (BASE_URL+'/fsl/1/1')
- .then(res => {if (res.ok) { this.props.UpdateConectivity(true)}else {this.props.UpdateConectivity(false)} })
- .catch (res => {this.props.UpdateConectivity(false)} )
+ fetch(BASE_URL + '/fsl/1/1')
+ .then(res => { if (res.ok) { this.props.UpdateConectivity(true) } else { this.props.UpdateConectivity(false) } })
+ .catch(res => { this.props.UpdateConectivity(false) })
}
- handleChange =(e:any) => {
-
- switch (e.target.id){
- case 'Lat1' : if ( e.target.value >90 || e.target.value<-90 )
- { this.setState({latitude1Error: 'Enter a number between -90 to 90'})}
- else {this.updateLatLon(e)
- this.setState({latitude1Error: ''}) }
- break;
- case 'Lat2' : if ( e.target.value >90 || e.target.value<-90 )
- { this.setState({latitude2Error: 'Enter a number between -90 to 90'})}
- else {this.updateLatLon(e)
- this.setState({latitude2Error: ''}) }
- break;
- case 'Lon1' : if ( e.target.value >180 || e.target.value<-180 )
- { this.setState({longitude1Error: 'Enter a number between -180 to 180'})}
- else {this.updateLatLon(e)
- this.setState({longitude1Error: ''}) }
- break;
- case 'Lon2' : if ( e.target.value >180 || e.target.value<-180 )
- { this.setState({longitude2Error: 'Enter a number between -180 to 180'})}
- else {this.updateLatLon(e)
- this.setState({longitude2Error: ''}) }
- break;
-
+ handleChange = (e: any) => {
+
+ switch (e.target.id) {
+ case 'Lat1': if (e.target.value > 90 || e.target.value < -90) { this.setState({ latitude1Error: 'Enter a number between -90 to 90' }) }
+ else {
+ this.updateLatLon(e)
+ this.setState({ latitude1Error: '' })
+ }
+ break;
+ case 'Lat2': if (e.target.value > 90 || e.target.value < -90) { this.setState({ latitude2Error: 'Enter a number between -90 to 90' }) }
+ else {
+ this.updateLatLon(e)
+ this.setState({ latitude2Error: '' })
+ }
+ break;
+ case 'Lon1': if (e.target.value > 180 || e.target.value < -180) { this.setState({ longitude1Error: 'Enter a number between -180 to 180' }) }
+ else {
+ this.updateLatLon(e)
+ this.setState({ longitude1Error: '' })
+ }
+ break;
+ case 'Lon2': if (e.target.value > 180 || e.target.value < -180) { this.setState({ longitude2Error: 'Enter a number between -180 to 180' }) }
+ else {
+ this.updateLatLon(e)
+ this.setState({ longitude2Error: '' })
+ }
+ break;
+
}
}
- render() {
+ render() {
return (
-
- <div >
-
- {!this.props.formView &&
-
- <div className = 'parent'>
-
- <div >Site A
- <form >
- <label>Latitude: <input aria-label="site-a-latitude-input" className={this.state.latitude1Error.length>0 ? 'error' : 'input'} id='Lat1' type='number' onChange={(e: any) => {this.handleChange(e)} }/></label>
- <div style={{fontSize:12, color:'red'}}> {this.state.latitude1Error} </div></form>
- <form><label>Longitude: <input aria-label="site-a-longitude-input" className={this.state.longitude1Error.length>0 ? 'error' : 'input'} id='Lon1' type='number' onChange={(e: any) => this.handleChange(e) } /></label><div style={{fontSize:12, color:'red'}}> {this.state.longitude1Error} </div>
- </form>
- </div>
-
- <div>Site B
- <form>
- <label>Latitude: <input aria-label="site-b-latitude-input" className={this.state.latitude2Error.length>0 ? 'error' : 'input'} id='Lat2' type='number' onChange={(e: any) => {this.handleChange(e) }} /></label><div style={{fontSize:12, color:'red'}}> {this.state.latitude2Error} </div></form>
- <form><label>Longitude: <input aria-label="site-b-longitude-input" className={this.state.longitude2Error.length>0 ? 'error' : 'input'} id='Lon2' type='number' onChange={(e: any) => {this.handleChange(e) } }/></label><div style={{fontSize:12, color:'red'}}> {this.state.longitude2Error} </div></form>
- </div>
-
+
+ <div >
+
+ {!this.props.formView &&
+
+ <div className='container1'>
+ <div className='firstBox'>
+ <div>SiteA</div>
+ <div>SiteB</div>
+ </div>
+
+ <div className='firstBox'>
+ <div>
+ <form >
+ <label>Latitude: <input aria-label="site-a-latitude-input" className={this.state.latitude1Error.length > 0 ? 'error' : 'input'} id='Lat1' type='number' onChange={(e: any) => { this.handleChange(e) }} /></label>
+ <div style={{ fontSize: 12, color: 'red' }}> {this.state.latitude1Error} </div>
+ </form></div>
+ <div>
+ <form>
+ <label>Latitude: <input aria-label="site-b-latitude-input" className={this.state.latitude2Error.length > 0 ? 'error' : 'input'} id='Lat2' type='number' onChange={(e: any) => { this.handleChange(e) }} /></label><div style={{ fontSize: 12, color: 'red' }}> {this.state.latitude2Error} </div>
+ </form></div>
+ </div>
+
+ <div className='firstBox'>
+ <div>
+ <form><label>Longitude: <input aria-label="site-a-longitude-input" className={this.state.longitude1Error.length > 0 ? 'error' : 'input'} id='Lon1' type='number' onChange={(e: any) => this.handleChange(e)} /></label><div style={{ fontSize: 12, color: 'red' }}> {this.state.longitude1Error} </div>
+ </form></div>
+ <div>
+ <form><label>Longitude: <input aria-label="site-b-longitude-input" className={this.state.longitude2Error.length > 0 ? 'error' : 'input'} id='Lon2' type='number' onChange={(e: any) => { this.handleChange(e) }} /></label><div style={{ fontSize: 12, color: 'red' }}> {this.state.longitude2Error} </div></form>
+ </div>
+ </div>
+
+
+
</div>
}
- <div className='container-1'>
- <div>{<form><input aria-label="annual" type='checkbox' id='Annual' value ="Annual" checked= {this.state.worstmonth===false} onClick= {(e: any) => this.setState ({worstmonth: false})}></input>Annual
- <input aria-label="worst-month" style={{marginLeft:10}} type='checkbox' id='Worst Month' value ="Worst" checked= {this.state.worstmonth===true} onClick= {(e:any)=>this.setState ({worstmonth: true})}></input>WM</form>}</div>
-
-
- <div className='column1'>
- <div>&nbsp;</div>
- {(this.props.siteA.length>0 || this.props.siteB.length>0) && <div >Site Name</div>}
- <div>Latitude</div>
- <div>Longitude</div>
- <div>Azimuth</div>
- <div>Average Mean Sea Level</div>
- <div>Antenna Height Above Ground</div>
- <div>Distance</div>
- <div style={{marginTop:20}}>Polarization</div>
- <div style={{marginTop:20}}>Frequency</div>
- <div>Free Space Loss</div>
- <div style={{marginTop:10}}>Rain Model</div>
- <div style={{marginTop:20}}>Rainfall Rate</div>
- <div>Rain Loss</div>
- <div style={{marginTop:18}}>Absorption Model</div>
- <div>Oxygen Specific Attenuation</div>
- <div>Water Vapor Specific Attenuation</div>
+ <div className='container1'>
+ <div >{<form><input aria-label="annual" type='checkbox' id='Annual' value="Annual" checked={this.state.worstmonth === false} onClick={(e: any) => this.setState({ worstmonth: false })}></input>Annual
+ <input aria-label="worst-month" style={{ marginLeft: 10 }} type='checkbox' id='Worst Month' value="Worst" checked={this.state.worstmonth === true} onClick={(e: any) => this.setState({ worstmonth: true })}></input>WM</form>}
</div>
-
-
- <div className='middlecolumn'>
- <div >Site A</div>
- {this.props.siteA.length>0 &&<div> {this.props.siteA }</div>}
- <div aria-label="site-a-latitude-dms"> {this.props.lat1 && this.LatLonToDMS(this.props.lat1)}</div>
- <div aria-label="site-a-longitude-dms">{this.props.lon1 && this.LatLonToDMS(this.props.lon1)}</div>
- <div>0</div>
- <div aria-label="site-a-amsl">{this.props.amslA.toFixed(2)} m</div>
- <div aria-label="site-a-antenna-amsl">{this.props.aglA.toFixed(2)} m</div>
-
-
- <div className='column2'>
- <div aria-label="distance-between-sites">{this.props.distance?.toFixed(3)} km</div>
- <div>{<form><input aria-label="polarization-horizontal" type='checkbox' id='Horizontal' value ="Horizontal" checked= {this.props.polarization==='Horizontal'} onClick= {(e: any) => this.props.updatePolarization(e.target.value)}></input>Horizontal
- <input aria-label="polarization-vertical" style={{marginLeft:10}} type='checkbox' id='Vertical' value ="Vertical" checked= {this.props.polarization==='Vertical'} onClick= {(e:any)=>{this.props.updatePolarization(e.target.value)}}></input>Vertical</form>}</div>
-
- <div> {<select aria-label="select-frequency-in-ghz" className={this.state.frequencyError.length>0 ? 'error' : 'input'} onChange={(e) => { this.props.updateFrequency(Number(e.target.value)); e.target.value==='0'? this.setState({frequencyError: 'select a frequency'}): this.setState({frequencyError:''})}}>
-
- <option value='0' aria-label="none-value" >Select Freq</option>
- <option value='7' aria-label="7" >7 GHz</option>
- <option value='11' aria-label="11" >11 GHz</option>
- <option value='15' aria-label="15" >15 GHz</option>
- <option value='23' aria-label="23">23 GHz</option>
- <option value='26' aria-label="26">26 GHz</option>
- <option value='28' aria-label="28">28 GHz</option>
- <option value='38' aria-label="38">38 GHz</option>
- <option value='42' aria-label="42">42 GHz</option>
- <option value='80' aria-label="80">80 GHz</option>
- </select>} <div style={{fontSize:12, color:'red'}}> {this.state.frequencyError} </div> </div>
-
- <div aria-label="fspl-value">{this.props.fsl.toFixed(3)} dB</div>
-
- <div> {<select aria-label="select-rain-method" className={this.state.rainMethodError.length>0 ? 'error' : 'input'} onChange = {(e) => {e.target.value === 'itu' ? this.setState({ rainMethodDisplay: false}):this.setState({ rainMethodDisplay: true}); e.target.value==='0'? this.setState({rainMethodError: 'select a Rain model'}): this.setState({rainMethodError:''}) }}>
- <option value='0' aria-label="none-value" >Select Rain Method</option>
- <option value='itu' aria-label="itur8377">ITU-R P.837-7</option>
- <option value='manual' aria-label="manual-entry">Specific Rain</option>
- </select>} <div style={{fontSize:12,color:'red'}}>{this.state.rainMethodError}</div>
- </div>
+ <div className='firstBox'>
+ <div>Site A</div>
+ <div>Site B</div>
+ </div>
+ {/* <div>&nbsp;</div> */}
+ <div>
+ {(this.props.siteA.length > 0 || this.props.siteB.length > 0) && <div >Site Name</div>}
+ <div> {this.props.siteA}</div>
+ <div> {this.props.siteB}</div>
+ </div>
+ <div>
+ <div>Latitude</div>
+ <div aria-label="site-a-latitude-dms"> {this.props.lat1 && this.LatLonToDMS(this.props.lat1)}</div>
+ <div aria-label="site-b-latitude-dms"> {this.props.lat2 && this.LatLonToDMS(this.props.lat2)}</div>
+
+ </div>
+ <div>
+ <div>Longitude</div>
+ <div aria-label="site-a-longitude-dms">{this.props.lon1 && this.LatLonToDMS(this.props.lon1)}</div>
+ <div aria-label="site-b-longitude-dms">{this.props.lon2 && this.LatLonToDMS(this.props.lon2)}</div>
+ </div>
+ <div>
+ <div>Azimuth</div>
+ <div>0</div>
+ <div>0</div>
+ </div>
+ <div>
+ <div>Average Mean Sea Level</div>
+ <div aria-label="site-a-amsl">{this.props.amslA.toFixed(2)} m</div>
+ <div aria-label="site-b-amsl">{this.props.amslB.toFixed(2)} m</div>
+ </div>
+ <div>
+ <div>Antenna Height Above Ground</div>
+ <div aria-label="site-a-antenna-amsl">{this.props.aglA.toFixed(2)} m</div>
+ <div aria-label="site-b-antenna-amsl">{this.props.aglB.toFixed(2)} m</div>
+ </div>
+ <div>
+ <div >Distance</div>
+ <div aria-label="distance-between-sites">{this.props.distance?.toFixed(3)} km</div>
+ </div>
+ <div>
+ <div >Polarization</div>
+ <div >{<form><input aria-label="polarization-horizontal" type='checkbox' id='Horizontal' value="Horizontal" checked={this.props.polarization === 'Horizontal'} onClick={(e: any) => this.props.updatePolarization(e.target.value)}></input>Horizontal
+ <input aria-label="polarization-vertical" style={{ marginLeft: 10 }} type='checkbox' id='Vertical' value="Vertical" checked={this.props.polarization === 'Vertical'} onClick={(e: any) => { this.props.updatePolarization(e.target.value) }}></input>Vertical</form>}</div>
+ </div>
+ <div>
+ <div style={{ marginTop: 5 }}>Frequency</div>
+ <div style={{ marginTop: 5 }}> {<select aria-label="select-frequency-in-ghz" className={this.state.frequencyError.length > 0 ? 'error' : 'input'} onChange={(e) => { this.props.updateFrequency(Number(e.target.value)); e.target.value === '0' ? this.setState({ frequencyError: 'select a frequency' }) : this.setState({ frequencyError: '' }); this.props.UpdateAntenas('0', '0') }}>
+
+ <option value='0' aria-label="none-value" >Select Freq</option>
+ <option value='7' aria-label="7" >7 GHz</option>
+ <option value='11' aria-label="11" >11 GHz</option>
+ <option value='15' aria-label="15" >15 GHz</option>
+ <option value='23' aria-label="23">23 GHz</option>
+ <option value='26' aria-label="26">26 GHz</option>
+ <option value='28' aria-label="28">28 GHz</option>
+ <option value='38' aria-label="38">38 GHz</option>
+ <option value='42' aria-label="42">42 GHz</option>
+ <option value='80' aria-label="80">80 GHz</option>
+ </select>} <div style={{ fontSize: 12, color: 'red' }}> {this.state.frequencyError} </div> </div>
+ </div>
+ <div>
+ <div>Free Space Loss</div>
+ <div aria-label="fspl-value">{this.props.fsl.toFixed(3)} dB</div>
+ </div>
+ <div>
+ <div>Rain Model</div>
+ <div> {<select aria-label="select-rain-method" className={this.state.rainMethodError.length > 0 ? 'error' : 'input'} onChange={(e) => { e.target.value === 'itu' ? this.setState({ rainMethodDisplay: false }) : this.setState({ rainMethodDisplay: true }); e.target.value === '0' ? this.setState({ rainMethodError: 'select a Rain model' }) : this.setState({ rainMethodError: '' }) }}>
+ <option value='0' aria-label="none-value" >Select Rain Method</option>
+ <option value='itu' aria-label="itur8377">ITU-R P.837-7</option>
+ <option value='manual' aria-label="manual-entry">Specific Rain</option>
+ </select>} <div style={{ fontSize: 12, color: 'red' }}>{this.state.rainMethodError}</div>
+ </div>
+ </div>
+ <div>
+ <div>Rainfall Rate</div>
<div> {<form><input aria-label="rain-value" type="number" style={{ width: 70, height: 15, fontSize: 14 }} onChange={(e) => { this.props.updateRainValue(Number(e.target.value)) }}
- value={this.props.rainVal} disabled={this.state.rainMethodDisplay === false ? true : false}>
- </input> mm/hr {this.state.showWM} {this.props.month}</form> } </div>
- <div aria-label="rain-attenuation-value">{this.props.rainAtt.toFixed(3)} dB</div>
-
- <div> {<select aria-label="select-absorption-method" className={this.state.attenuationMethodError.length>0 ? 'error' : 'input'} onChange = {(e) => { if (e.target.value!== ''){ this.setState({absorptionMethod : e.target.value}); this.setState({attenuationMethodError:''}) }}}>
- <option value='0' aria-label="none-value" >Select Absorption Method</option>
- <option value='ITURP67612' aria-label="iturp67612" >ITU-R P.676-12</option>
- <option value='ITURP67611' aria-label="iturp67611" >ITU-R P.676-11</option>
- <option value='ITURP67610' aria-label="iturp67610" >ITU-R P.676-10</option>
- </select>} <div style={{fontSize:12,color:'red'}}>{this.state.attenuationMethodError}</div>
- </div>
- <div aria-label="absorption-oxygen-value">{this.props.absorptionOxygen.toFixed(3)} dB</div>
- <div aria-label="absorption-water-value">{this.props.absorptionWater.toFixed(3)} dB</div>
- <div>{<button aria-label="calculate-button" style={{color: '#222', fontFamily:'Arial', boxAlign: 'center', display:'inline-block', insetInlineStart: '20' , alignSelf:'center' }}
- onClick = {(e) => this.buttonHandler()} >Calculate</button>} </div>
+ value={this.props.rainVal} disabled={this.state.rainMethodDisplay === false ? true : false}>
+ </input> mm/hr {this.state.showWM} {this.props.month}</form>} </div>
+ </div>
+ <div>
+ <div>Rain Loss</div>
+ <div aria-label="rain-attenuation-value">{this.props.rainAtt.toFixed(3)} dB</div>
+ </div>
+ <div>
+ <div>Absorption Model</div>
+ <div> {<select aria-label="select-absorption-method" className={this.state.attenuationMethodError.length > 0 ? 'error' : 'input'} onChange={(e) => { if (e.target.value !== '') { this.setState({ absorptionMethod: e.target.value }); this.setState({ attenuationMethodError: '' }) } }}>
+ <option value='0' aria-label="none-value" >Select Absorption Method</option>
+ <option value='ITURP67612' aria-label="iturp67612" >ITU-R P.676-12</option>
+ <option value='ITURP67611' aria-label="iturp67611" >ITU-R P.676-11</option>
+ <option value='ITURP67610' aria-label="iturp67610" >ITU-R P.676-10</option>
+ </select>} <div style={{ fontSize: 12, color: 'red' }}>{this.state.attenuationMethodError}</div>
+ </div>
+ </div>
+ <div>
+ <div>Oxygen Specific Attenuation</div>
+ <div aria-label="absorption-oxygen-value">{this.props.absorptionOxygen.toFixed(3)} dB</div>
+ </div>
+ <div>
+ <div>Water Vapor Specific Attenuation</div>
+ <div aria-label="absorption-water-value">{this.props.absorptionWater.toFixed(3)} dB</div>
+ </div>
+ <div>
+ <div>System Operating Margin</div>
+ <div aria-label="system-operating-margin">{this.props.systemOperatingMargin} dB</div>
+ </div>
+ <div>
+ <div>Radio Transmitted Power</div>
+ <div> {<form><input aria-label="site-a-transmitted-power" type="number" style={{ width: 70, height: 15, fontSize: 14 }} onChange={(e) => {if (e.target.value !== '') this.props.UpdateTxPower(e.target.value,null) }}
+ >
+ </input> dBm </form>} </div>
+ <div> {<form><input aria-label="site-b-transmitted-power" type="number" style={{ width: 70, height: 15, fontSize: 14 }} onChange={(e) => { if (e.target.value !== '') this.props.UpdateTxPower(null,e.target.value) }}
+ >
+ </input> dBm </form>} </div>
+ </div>
+ <div>
+ <div>RF Receiver Sensitivity</div>
+ <div> {<form><input aria-label="site-a-receiver-sensitivity" type="number" style={{ width: 70, height: 15, fontSize: 14 }} onChange={(e) => { if (e.target.value !== '') this.props.UpdateRxSensitivity(e.target.value, null) }}
+ >
+ </input> dBm </form>} </div>
+ <div> {<form><input aria-label="site-b-receiver-sensitivity" type="number" style={{ width: 70, height: 15, fontSize: 14 }} onChange={(e) => { if (e.target.value !== '') this.props.UpdateRxSensitivity(null, e.target.value) }}
+ >
+ </input> dBm </form>} </div>
+ </div>
+ </div>
+ <div className='antennaContainer'>
+ <div>
+ <div></div>
+ <div className='antennaFont'>Antenna Settings</div>
+ </div>
+ <div>
+ <div>Antenna</div>
+
+ <div> {<select aria-label="site-a-select-antenna" value={this.props.antennaA} style={{ width: 160, height: 22, fontSize: 13 }} className={this.state.antennaTypeError.length > 0 ? 'error' : 'input'} onChange={(e) => { if (e.target.value !== '') { this.props.UpdateAntenas(e.target.value, null); this.setState({ antennaTypeError: '' }) } }}>
+ <option value='0' aria-label="none-value" >Select Antenna</option>
+ {this.props.antennaList.map(antenna => <option value={antenna}>{antenna}</option>)}
+ </select>} <div style={{ fontSize: 12, color: 'red' }}>{this.state.antennaTypeError}</div>
+ </div>
+ <div> {<select aria-label="site-b-select-antenna" value={this.props.antennaB} style={{ width: 160, height: 22, fontSize: 13 }} className={this.state.antennaTypeError.length > 0 ? 'error' : 'input'} onChange={(e) => { if (e.target.value !== '') { this.props.UpdateAntenas(null, e.target.value); this.setState({ antennaTypeError: '' }) } }}>
+ <option value='0' aria-label="none-value" >Select Antenna</option>
+ {this.props.antennaList.map(antenna => <option value={antenna}>{antenna}</option>)}
+ </select>} <div style={{ fontSize: 12, color: 'red' }}>{this.state.antennaTypeError}</div>
+ </div>
</div>
+ <div>
+ <div>EIRP</div>
+ <div aria-label="site-a-effective-isotropic-radiated-power">{this.props.eirpSiteA} dBm</div>
+ <div aria-label="site-b-effective-isotropic-radiated-power">{this.props.eirpSiteB} dBm</div>
</div>
- <div className= 'middlecolumn'>
- <div >Site B</div>
- {this.props.siteB.length>0 &&<div> {this.props.siteB}</div>}
- <div aria-label="site-b-latitude-dms"> {this.props.lat2 && this.LatLonToDMS(this.props.lat2)}</div>
- <div aria-label="site-b-longitude-dms">{this.props.lon2 && this.LatLonToDMS(this.props.lon2)}</div>
- <div>0</div>
- <div aria-label="site-b-asml">{this.props.amslB.toFixed(2)} m</div>
- <div aria-label="site-b-antenna-asml">{this.props.aglB.toFixed(2)} m</div>
-
- </div>
-
+ <div>
+ <div>Gain</div>
+ <div aria-label="site-a-antenna-gain" > {this.props.antennaGainList[this.props.antennaList.indexOf(this.props.antennaA)]} dBi</div>
+ <div aria-label="site-b-antenna-gain">{this.props.antennaGainList[this.props.antennaList.indexOf(this.props.antennaB)]} dBi</div>
+ </div>
+ <div>
+ <div></div>
+ <div>{<button aria-label="calculate-button" style={{ color: '#222', fontFamily: 'Arial', boxAlign: 'center', display: 'inline-block', insetInlineStart: '20', alignSelf: 'center' }}
+ onClick={(e) => this.buttonHandler()} >Calculate</button>} </div>
+ </div>
</div>
-
+
<ConnectionInfo />
-
-
-
- </div>
- )
- }
-
+
+
+ </div>
+
+ )
}
+}
+
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 @@
<!-- optional: default phase is "generate-resources" -->
<phase>initialize</phase>
<configuration>
- <nodeVersion>v10.16.3</nodeVersion>
- <yarnVersion>v1.19.0</yarnVersion>
+ <nodeVersion>v12.13.0</nodeVersion>
+ <yarnVersion>v1.22.10</yarnVersion>
</configuration>
</execution>
<execution>
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 @@
<!-- optional: default phase is "generate-resources" -->
<phase>initialize</phase>
<configuration>
- <nodeVersion>v10.16.3</nodeVersion>
- <yarnVersion>v1.19.0</yarnVersion>
+ <nodeVersion>v12.13.0</nodeVersion>
+ <yarnVersion>v1.22.10</yarnVersion>
</configuration>
</execution>
<execution>
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 @@
<!-- optional: default phase is "generate-resources" -->
<phase>initialize</phase>
<configuration>
- <nodeVersion>v10.16.3</nodeVersion>
- <yarnVersion>v1.19.0</yarnVersion>
+ <nodeVersion>v12.13.0</nodeVersion>
+ <yarnVersion>v1.22.10</yarnVersion>
</configuration>
</execution>
<execution>
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 @@
<!-- optional: default phase is "generate-resources" -->
<phase>initialize</phase>
<configuration>
- <nodeVersion>v10.16.3</nodeVersion>
- <yarnVersion>v1.19.0</yarnVersion>
+ <nodeVersion>v12.13.0</nodeVersion>
+ <yarnVersion>v1.22.10</yarnVersion>
</configuration>
</execution>
<execution>
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<any>(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> = (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 <TableCell aria-label={ariaLabel}>{data}</TableCell>
} else {
@@ -93,7 +102,7 @@ const DenseTable: React.FunctionComponent<props> = (props) => {
if (i === 0) {
return <TableCell>{data}</TableCell>
} else {
- const ariaLabel = props.ariaLabelColumn[index];
+ const ariaLabel = props.ariaLabelColumn === undefined ? props.headers[index].toLowerCase() : props.ariaLabelColumn[index];
return <TableCell aria-label={ariaLabel}>{data}</TableCell>
}
}
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> = (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> = (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<HTMLButtonElement, 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) => {
</AppBar>
<DenseTable ariaLabelRow="site-information-table-entry" ariaLabelColumn={["site-name", "latitude", "longitude", "azimuth"]} verticalTable height={height} hover={false} headers={["", "Site A", "Site B"]} data={data} />
{
- props.link.type==="microwave" && <Button style={{marginTop:20}} fullWidth variant="contained" color="primary" onClick={onCalculateLinkClick}>Calculate link</Button>
+ props.link.type==="microwave" &&<>
+ <Button style={{marginTop:20}} fullWidth variant="contained" color="primary" onClick={onCalculateLinkClick}>Calculate link</Button>
+ <Button style={{marginTop:20}} fullWidth variant="contained" color="primary" onClick={onLineofSightClick}>Line of Sight</Button>
+
+ </>
}
</div>)
}
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<siteDetailProps> = (props) => {
const [value, setValue] = React.useState<panelId>("links");
const [height, setHeight] = React.useState(330);
+ const [openPopup, setOpenPopup] = React.useState(false);
+ const [staSite, setStaSite] = React.useState<StadokSite|null>(null);
const handleResize = () =>{
const el = document.getElementById('site-details-panel')?.getBoundingClientRect();
@@ -82,35 +87,55 @@ const SiteDetails: React.FunctionComponent<siteDetailProps> = (props) => {
setValue(newValue);
}
+ const getFurtherInformation = (url: string) =>{
+
+ const request = requestRest<StadokSite>(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<siteDetailProps> = (props) => {
value === "links" &&
<>
{
- props.site.links.length === 0 &&
+ props.site.links==null &&
<Typography aria-label="no-links-available" variant="body1" style={{ marginTop: '10px' }}>No links available.</Typography>
}
{
- props.site.links.length > 0 &&
+ props.site.links?.length > 0 &&
<DenseTable ariaLabelRow="available-links-table" ariaLabelColumn={["link-name", "azimuth"]} height={height} hover={true} headers={linkTableHeader} data={linkRows} onClick={props.onLinkClick} ></DenseTable>
}
@@ -178,6 +203,15 @@ const SiteDetails: React.FunctionComponent<siteDetailProps> = (props) => {
}
</>
}
+ {
+ props.isSitedocReachable && props.site.furtherInformation!==null && props.site.furtherInformation.length>0 &&
+ <Button style={{marginTop:20}} fullWidth variant="contained" color="primary" onClick={e => getFurtherInformation(props.site.furtherInformation) }>Further information available</Button>
+ }
+
+ {
+ staSite !== null && openPopup && <StadokDetailsPopup site={staSite} onClose={closePopup} open={true} />
+ }
+
</div>
)
}
@@ -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> = (props) => {
+ const classes = useStyles();
+
+ const [open, setOpen] = React.useState(props.open);
+ const [value, setValue] = React.useState("devices");
+ const [orders, setOrders] = React.useState<OrderToDisplay[]|null>(null);
+
+ const DialogTitle = withStyles(styles)((props: any) => {
+ const { children, classes, onClose, ...other } = props;
+ return (
+ <MuiDialogTitle disableTypography className={classes.root} {...other}>
+ <Typography variant="h6">{children}</Typography>
+ {onClose ? (
+ <IconButton aria-label="close" style={{position: 'absolute', top:0, right:0, color: 'black'}} onClick={onClose}>
+ <CloseIcon />
+ </IconButton>
+ ) : null}
+ </MuiDialogTitle>
+ );
+ });
+
+ 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<StadokOrder[]>(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 (<div style={{ height: 300 }}>
+ <Typography variant="body1" style={{ marginTop: '10px' }}>
+ Loading orders
+ </Typography>
+ </div>)
+ } else if (orders.length === 0) {
+ return (<div style={{ height: 300 }}>
+ <Typography variant="body1" style={{ marginTop: '10px' }}>
+ No orders available
+ </Typography>
+ </div>)
+ } else {
+ return <DenseTable data={orders} height={300} headers={["Person", "State", "Current Task"]} hover={false} ariaLabelRow="activity-log-table" />
+ }
+ }
+
+ 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")
+ }
+ <div style={{ display: 'flex', flexDirection: 'row', flexWrap:'wrap' }}>
+
+ {
+ 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")
+ )
+ }
+
+ </>
+ }
+ </div>
+ </>
+ }
+
+ }
+
+ 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 <img className={className} src={url} onClick={e => window.open(url)} />
+
+ }
+
+
+ return (<Dialog onClose={onClose} fullWidth maxWidth="md" aria-labelledby="customized-dialog-title" open={open}>
+ <DialogTitle id="customized-dialog-title" onClose={onClose}>
+ {props.site.siteId}
+ </DialogTitle>
+ <DialogContent style={{minWidth:'900px'}} dividers>
+ <div style={{ display: 'flex', flexDirection: 'row', flexGrow: 1 }}>
+ <div style={{ width: '60%', display:'flex', flexDirection: 'column' }}>
+
+ <TextField inputProps={{ 'aria-label': 'type' }} disabled={true} value={props.site.updatedOn} label="Updated on" style={{ marginTop: "5px" }} />
+
+
+ {
+ props.site.type !== undefined && props.site.type.length > 0 &&
+ <TextField inputProps={{ 'aria-label': 'type' }} disabled={true} value={props.site.type} label="Type" style={{ marginTop: "5px" }} />
+ }
+
+
+ <TextField inputProps={{ 'aria-label': 'adress' }} disabled={true} value={`${props.site.address.streetAndNr}, ${props.site.address.zipCode !== null ? props.site.address.zipCode : ''} ${props.site.address.city}`} label="Address" style={{ marginTop: "5px" }} />
+
+
+ <TextField inputProps={{ 'aria-label': 'latitude' }} style={{ marginTop: "5px" }} disabled={true} value={LatLonToDMS(props.site.location.lat)} label="Latitude" />
+ <TextField inputProps={{ 'aria-label': 'longitude' }} style={{ marginTop: "5px" }} disabled={true} value={LatLonToDMS(props.site.location.lon, true)} label="Longitude" />
+ <AppBar position="static" style={{ marginTop: "5px", background: '#2E3B55' }}>
+ <Tabs id="site-tabs" variant="scrollable" scrollButtons="on" value={value} onChange={onHandleTabChange} aria-label="simple tabs example">
+ <Tab label="Devices" value="devices" />
+ <Tab label="Contacts" value="contacts" />
+ <Tab label="Saftey" value="safteyInfo" />
+ <Tab label="Logs" value="logs" />
+ <Tab label="Orders" value="orders" />
+ </Tabs>
+ </AppBar>
+ {
+ value == "devices" && (props.site.devices?.length>0 ?
+ <DenseTable data={props.site.devices} height={300} headers={["Device", "Antenna"]} hover={false} ariaLabelRow="devices-table" />
+ :
+ <div style={{height:300}}>
+ <Typography variant="body1" style={{ marginTop: '10px' }}>
+ No devices available
+ </Typography>
+ </div>)
+ }
+ {
+ value == "contacts" && (contacts.length>0 ?
+ <DenseTable data={contacts} height={300} headers={["Person", "Firstname", "Lastname", "Email", "Phone No."]} hover={false} ariaLabelRow="contacts-table" ariaLabelColumn={["person", "firstname", "lastname", "email", "phoneno"]} />
+ :
+ <div style={{height:300}}>
+ <Typography variant="body1" style={{ marginTop: '10px' }}>
+ No contacts available
+ </Typography>
+ </div>)
+ }
+ {
+ value == "safteyInfo" && (props.site.safteyNotices.length>0 ?
+ <DenseTable data={props.site.safteyNotices} height={300} headers={["Note"]} hover={false} ariaLabelRow="saftey-info-table" />
+ :
+ <div style={{height:300}}>
+ <Typography variant="body1" style={{ marginTop: '10px' }}>
+ No saftey notices applicable
+ </Typography>
+ </div>)
+ }
+ {
+ value == "logs" && (props.site.logs.length>0 ?
+ <DenseTable data={props.site.logs} height={300} headers={["Date","Person", "Activity"]} hover={false} ariaLabelRow="activity-log-table" />
+ :
+ <div style={{height:300}}>
+ <Typography variant="body1" style={{ marginTop: '10px' }}>
+ No activity log available
+ </Typography>
+ </div>)
+ }
+
+ {
+ value ==="orders" && createOrderInfo()
+ }
+
+ </div>
+ <div style={{padding: '10px', display: 'flex', alignItems:'center', flexDirection:'column', justifyContent: 'start', width:'40%'}}>
+ {
+ props.site.images.length == 0 ?
+ <Typography variant="body1" style={{ marginTop: '10px' }}>
+ No images available
+ </Typography>
+ : displayImages()
+ }
+ </div>
+ </div>
+
+ </DialogContent>
+ </Dialog>)
+
+}
+
+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<typeof mapStateToProps, typeof mapDispatchToProps>;
const ConnectionInfo: React.FunctionComponent<props> = (props) => {
- return ((props.isTopoServerReachable === false || props.isTileServerReachable === false )? <Paper style={{padding:5, position: 'absolute', top: 160, width: 230, left:"40%"}}>
+ return ((props.isTopoServerReachable === false || props.isTileServerReachable === false )? <Paper style={{padding:5, position: 'absolute', top: 160, width: 230, left:"40%", zIndex:1}}>
<div style={{display: 'flex', flexDirection: 'column'}}>
<div style={{'alignSelf': 'center', marginBottom:5}}> <Typography> <FontAwesomeIcon icon={faExclamationTriangle} /> Connection Error</Typography></div>
{props.isTileServerReachable === false && <Typography> Tile data can't be loaded.</Typography>}
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> = (props) =>{
return (
props.visible ?
- <FormControlLabel style={{ padding:5, position: 'absolute',top: 190}}
+ <FormControlLabel style={{ padding:5, position: 'absolute',top: 190, zIndex:1}}
value="end"
- control={<Switch color="secondary" checked={props.areIconsEnabled} onChange={toggleChecked} />}
+ control={<Switch color="secondary" style={{zIndex:1}} checked={props.areIconsEnabled} onChange={toggleChecked} />}
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<HTMLDivElement>();
+import 'mapbox-gl/dist/mapbox-gl.css';
class Map extends React.Component<mapProps, { isPopupOpen: boolean }> {
@@ -158,7 +159,7 @@ class Map extends React.Component<mapProps, { isPopupOpen: boolean }> {
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<mapProps, { isPopupOpen: boolean }> {
}
})
.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<mapProps, { isPopupOpen: boolean }> {
//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<mapProps, { isPopupOpen: boolean }> {
}
}
}
+ }
}
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<mapProps, { isPopupOpen: boolean }> {
<ConnectionInfo />
<Button
disabled={!this.props.isTopoServerReachable}
- style={{'position': 'absolute', 'right':5, top:5, backgroundColor:'white'}}
+ style={{'position': 'absolute', 'right':5, top:5, backgroundColor:'white', zIndex:1}}
onClick={e => this.props.navigateToApplication("network", "customize")} >
<img src={customize} />
</Button>
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: props) =>{
const reachabe = props.isTopoServerReachable && props.isTileServerReachable;
- return (<Paper style={{ padding: 5, position: 'absolute', display: 'flex', flexDirection: "column", top: 70, width: 200, marginLeft: 5 }}>
+ return (<Paper style={{ padding: 5, position: 'absolute', display: 'flex', flexDirection: "column", top: 70, width: 200, marginLeft: 5, zIndex:1 }}>
<div style={{ display: 'flex', flexDirection: "row" }}>
<Typography style={{ fontWeight: "bold", flex: "1", color: reachabe ? "black" : "lightgrey" }} >Statistics</Typography>
<Tooltip style={{ alignSelf: "flex-end" }} title="Gets updated when the map stops moving.">
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<DetailsStoreState>=(state = initialState, action)=>{
@@ -63,6 +65,8 @@ export const DetailsReducer:IActionHandler<DetailsStoreState>=(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 @@
<div id="app"></div>
<script type="text/javascript" src="./require.js"></script>
<script type="text/javascript" src="./config.js"></script>
- <link href='https://api.tiles.mapbox.com/mapbox-gl-js/v1.8.1/mapbox-gl.css' rel='stylesheet' />
<script>
// run the application
require(["app","connectApp","faultApp", "networkMapApp", "configurationApp", "linkCalculationApp"], function (app, connectApp, faultApp, networkMapApp, configurationApp, linkCalculationApp) {
connectApp.register();
- //faultApp.register();
+ faultApp.register();
//configurationApp.register();
- //linkCalculationApp.register();
+ linkCalculationApp.register();
networkMapApp.register();
app("./app.tsx").runApplication();
});
diff --git a/sdnr/wt/odlux/apps/networkMapApp/src/model/link.ts b/sdnr/wt/odlux/apps/networkMapApp/src/model/link.ts
index d992c66db..c1612098d 100644
--- a/sdnr/wt/odlux/apps/networkMapApp/src/model/link.ts
+++ b/sdnr/wt/odlux/apps/networkMapApp/src/model/link.ts
@@ -16,6 +16,12 @@
* ============LICENSE_END==========================================================================
*/
+type Antenna = {
+ name:string,
+ waveguideLossIndB: number,
+ gain: number
+}
+
export type link = {id: string,
name: string,
length: number,
@@ -25,6 +31,6 @@ export type link = {id: string,
siteB: string,
azimuthA: number | null,
azimuthB: number | null,
- locationA: { lon: number, lat: number, amsl:number | null, antennaHeight: number | null },
- locationB: { lon: number, lat: number, amsl:number | null, antennaHeight: number | null },
+ locationA: { lon: number, lat: number, amsl:number | null, antennaHeight: number | null, antenna: Antenna |null },
+ locationB: { lon: number, lat: number, amsl:number | null, antennaHeight: number | null, antenna: Antenna |null },
}; \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/networkMapApp/src/model/site.ts b/sdnr/wt/odlux/apps/networkMapApp/src/model/site.ts
index b9102e871..13a7361f6 100644
--- a/sdnr/wt/odlux/apps/networkMapApp/src/model/site.ts
+++ b/sdnr/wt/odlux/apps/networkMapApp/src/model/site.ts
@@ -28,7 +28,8 @@ export type Site = {
operator: string,
location:{lon: number, lat: number},
devices: Device[],
- links: link[]
+ links: link[],
+ furtherInformation:string
}
export type Address={
diff --git a/sdnr/wt/odlux/apps/networkMapApp/src/model/stadokOrder.ts b/sdnr/wt/odlux/apps/networkMapApp/src/model/stadokOrder.ts
new file mode 100644
index 000000000..1aad3aa97
--- /dev/null
+++ b/sdnr/wt/odlux/apps/networkMapApp/src/model/stadokOrder.ts
@@ -0,0 +1,56 @@
+/**
+ * ============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==========================================================================
+ */
+
+export type StadokOrder = {
+ date: Date,
+ assignedUser: string,
+ state: string, //todo: type restrict
+ tasks: Task[],
+
+
+};
+
+export class OrderToDisplay {
+
+ static parse = (stadokOrder: StadokOrder) =>{
+ let order = new OrderToDisplay();
+ order.assignedUser=stadokOrder.assignedUser;
+ order.state=stadokOrder.state;
+
+ const firstOpenTask = stadokOrder.tasks.find(task => !task.status);
+
+ if(firstOpenTask){
+ order.currentTask=firstOpenTask.description;
+ }else{
+ order.currentTask="No task description available";
+ }
+
+ return order;
+ }
+
+ state: string;
+ assignedUser: string;
+ currentTask: string;
+
+};
+
+type Task = {
+ type: string,
+ description: string,
+ status: boolean
+} \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/networkMapApp/src/model/stadokSite.ts b/sdnr/wt/odlux/apps/networkMapApp/src/model/stadokSite.ts
new file mode 100644
index 000000000..ed0ca397f
--- /dev/null
+++ b/sdnr/wt/odlux/apps/networkMapApp/src/model/stadokSite.ts
@@ -0,0 +1,54 @@
+/**
+ * ============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 { Address } from "./site";
+
+type StadokSite = {
+
+ siteId: string;
+ createdBy: Contact;
+ updatedOn: Date;
+ location: { lat: number, lon: number },
+ address: Address;
+ contacts: { manager: Contact, owner: Contact };
+ safteyNotices: string[];
+ images: string[];
+ type: string;
+ devices: Device[];
+ logs: Log[];
+
+};
+
+type Contact = {
+ firstName: string;
+ lastName: string;
+ email: string;
+ telephoneNumber: string;
+};
+type Log = {
+ date: Date, //string?
+ person: string;
+ entry: string;
+};
+
+type Device = {
+ "device": string,
+ "antenna": string
+};
+
+export default StadokSite; \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/networkMapApp/src/pluginTransport.tsx b/sdnr/wt/odlux/apps/networkMapApp/src/pluginTransport.tsx
index e93368524..24a46994a 100644
--- a/sdnr/wt/odlux/apps/networkMapApp/src/pluginTransport.tsx
+++ b/sdnr/wt/odlux/apps/networkMapApp/src/pluginTransport.tsx
@@ -27,7 +27,7 @@ import { networkmapRootHandler } from './handlers/rootReducer';
import MainView from "./App";
import { subscribe, IFormatedMessage } from "../../../framework/src/services/notificationService";
import applicationApi from "../../../framework/src/services/applicationApi";
-import { UpdateDetailsView } from "./actions/detailsAction";
+import { checkSitedockReachablity, IsSitedocReachableAction, UpdateDetailsView } from "./actions/detailsAction";
import { findSiteToAlarm } from "./actions/mapActions";
import { URL_BASEPATH } from "./config";
import { Redirect, Route, RouteComponentProps, Switch, withRouter } from "react-router-dom";
@@ -40,7 +40,8 @@ const mapProps = (state: IApplicationStoreState) => ({
});
const mapDisp = (dispatcher: IDispatcher) => ({
- getSettings: () => dispatcher.dispatch(getSettings())
+ getSettings: () => dispatcher.dispatch(getSettings()),
+ tryReachSitedoc: () => dispatcher.dispatch(checkSitedockReachablity())
});
@@ -51,6 +52,8 @@ const NetworkRouterApp = withRouter(connect(mapProps, mapDisp)((props: RouteComp
(async function waitFor() {
await props.getSettings();
})();
+
+ props.tryReachSitedoc();
}, []);
diff --git a/sdnr/wt/odlux/apps/networkMapApp/src/utils/mapLayers.ts b/sdnr/wt/odlux/apps/networkMapApp/src/utils/mapLayers.ts
index 6dfd7983a..7ce4bfa92 100644
--- a/sdnr/wt/odlux/apps/networkMapApp/src/utils/mapLayers.ts
+++ b/sdnr/wt/odlux/apps/networkMapApp/src/utils/mapLayers.ts
@@ -141,6 +141,8 @@ class MapLayerService {
public addBaseLayers = (map: mapboxgl.Map, themesettings?: ThemeElement) => {
const theme = !themesettings ? this.pickTheme() : themesettings;
+ console.log("user selected theme: " + this.selectedTheme)
+ console.log("found theme:" + theme);
this.addCommonLayers(map);
diff --git a/sdnr/wt/odlux/apps/networkMapApp/webpack.config.js b/sdnr/wt/odlux/apps/networkMapApp/webpack.config.js
index 3e80514f5..5684040b7 100644
--- a/sdnr/wt/odlux/apps/networkMapApp/webpack.config.js
+++ b/sdnr/wt/odlux/apps/networkMapApp/webpack.config.js
@@ -67,6 +67,10 @@ module.exports = (env) => {
name: './icons/[hash].[ext]'
}
}]
+ },
+ {
+ test: /\.css$/i,
+ use: ["style-loader", "css-loader"],
}]
},
@@ -168,8 +172,15 @@ module.exports = (env) => {
target: "http://localhost:3002",
secure: false
},
+ "/sitedoc/": {
+ target: "http://localhost:3002",
+ secure: false,
+ pathRewrite(pathname) {
+ return pathname.replace(/^\/sitedoc/, '/topology/stadok')
+ }
+ },
"/tiles/": {
- target: "http://www.openstreetmap.org",
+ target: "http://tile.openstreetmap.org",
secure: false
},
"/help/": {
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/package.json b/sdnr/wt/odlux/apps/performanceHistoryApp/package.json
index 305fc07f4..af38fb116 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/package.json
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/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/performanceHistoryApp/pom.xml b/sdnr/wt/odlux/apps/performanceHistoryApp/pom.xml
index cb4cfefde..2fe758114 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/pom.xml
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/pom.xml
@@ -140,8 +140,8 @@
<!-- optional: default phase is "generate-resources" -->
<phase>initialize</phase>
<configuration>
- <nodeVersion>v10.16.3</nodeVersion>
- <yarnVersion>v1.19.0</yarnVersion>
+ <nodeVersion>v12.13.0</nodeVersion>
+ <yarnVersion>v1.22.10</yarnVersion>
</configuration>
</execution>
<execution>