SDN-R add updated odlux
Updates all odlux framework and app components.
Issue-ID: SDNC-1032
Signed-off-by: herbert <herbert.eiselt@highstreet-technologies.com>
Change-Id: I13c520489fd40d05b7fd5215f5941af6238e9cae
diff --git a/sdnr/wt/odlux/README.md b/sdnr/wt/odlux/README.md
index 6e02db0..6e5d596 100644
--- a/sdnr/wt/odlux/README.md
+++ b/sdnr/wt/odlux/README.md
@@ -1,15 +1,22 @@
# Developing a ODLUX application
+## Introduction
+
+ODLUX bundle contains the Browser based Grapical User Interface for SDN-R.
+ODLUX is available as OSGi bundle that is running in Opendaylight Karaf environment, using the configured jetty server of Opendaylight.
+Since ONAP Frankfurt a second WEB Server setup "sdncweb" is available, that extracts the JavaScrip files.
+
## Prerequisites
-* Node: 8.10 or higher
-* Yarn: 1.12.3 or higher
-* Lerna: 3.10.7 or higher
+Actual version in framework pom.xml in the frontend-maven-plugin definition.
+ * Node
+ * Yarn
+ * Lerna
You can install these globally or let it be installed by maven due "mvn clean install"
* Maven: 3 or higher
-* Java: 8 or higher
+* Java: 8
## Dev-Environment Installation
@@ -25,7 +32,7 @@
|-framework
```
- * go to features/sdnr/wt/odlux/apps and create your app:
+ * go to features/sdnr/wt/odlux/apps and create your app:
```
mvn archetype:generate -DarchetypeGroupId=org.onap.ccsdk.features.sdnr.wt \
-DarchetypeArtifactId=odlux-app-archetype \
@@ -40,7 +47,7 @@
* with ```yarn start``` you can run your application due runtime in your application folder
* by default this will run on http://localhost:3100/index.html
* if you have added new dependencies you have to run ```lerna bootstrap``` in odlux/
- * build your app for development version you can use ```yarn run build``` or ```yarn run build:dev```
+ * build your app for development version you can use ```yarn run build``` or ```yarn run build:dev```
* build for karaf with ```mvn clean install```
@@ -63,19 +70,19 @@
### Default menu positions
* from 0 for top to 999 for bottom.
-
+
```
-0 Connect
-10 Fault
-20 Maintenance
-30 Configuration
-40 Protection
-50 Performance
-60 Security
-70 Inventory
-80 Topology
-90 Mediator
-100 Help
+0 Connect
+10 Fault
+20 Maintenance
+30 Configuration
+40 Protection
+50 Performance
+60 Security
+70 Inventory
+80 Topology
+90 Mediator
+100 Help
```
### blueprint.xml
@@ -99,162 +106,6 @@
### pom.xml
-```
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-
- <parent>
- <groupId>org.onap.ccsdk.parent</groupId>
- <artifactId>odlparent</artifactId>
- <version>1.2.1-SNAPSHOT</version>
- <relativePath />
- </parent>
- <modelVersion>4.0.0</modelVersion>
- <groupId>org.onap.ccsdk.features.sdnr.wt</groupId>
- <artifactId>sdnr-wt-odlux-app-demoApp</artifactId>
- <version>0.4.1-SNAPSHOT</version>
- <packaging>bundle</packaging>
- <name>sdnr-wt-odlux-app-demoApp</name>
- <licenses>
- <license>
- <name>Apache License, Version 2.0</name>
- <url>http://www.apache.org/licenses/LICENSE-2.0</url>
- </license>
- </licenses>
- <dependencies>
- <dependency>
- <groupId>${project.groupId}</groupId>
- <artifactId>sdnr-wt-odlux-core-model</artifactId>
- <version>${project.version}</version>
- </dependency>
- <dependency>
- <groupId>${project.groupId}</groupId>
- <artifactId>sdnr-wt-odlux-core-provider</artifactId>
- <version>${project.version}</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <scope>test</scope>
- </dependency>
- </dependencies>
- <build>
- <sourceDirectory>src2/main/java</sourceDirectory>
- <plugins>
- <plugin>
- <artifactId>maven-clean-plugin</artifactId>
- <configuration>
- <filesets>
- <fileset>
- <directory>dist</directory>
- <followSymlinks>false</followSymlinks>
- </fileset>
- <fileset>
- <directory>node</directory>
- <followSymlinks>false</followSymlinks>
- </fileset>
- <fileset>
- <directory>node_modules</directory>
- <followSymlinks>false</followSymlinks>
- </fileset>
- <fileset>
- <directory>../node_modules</directory>
- <followSymlinks>false</followSymlinks>
- </fileset>
- </filesets>
- </configuration>
- </plugin>
- <plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>build-helper-maven-plugin</artifactId>
- <executions>
- <execution>
- <id>add-test-source</id>
- <phase>generate-test-sources</phase>
- <goals>
- <goal>add-test-source</goal>
- </goals>
- <configuration>
- <sources>
- <source>src2/test/java</source>
- </sources>
- </configuration>
- </execution>
- </executions>
- </plugin>
- <plugin>
- <groupId>com.github.eirslett</groupId>
- <artifactId>frontend-maven-plugin</artifactId>
- <version>1.8-SNAPSHOT</version>
- <executions>
- <execution>
- <id>install node and yarn</id>
- <goals>
- <goal>install-node-and-yarn</goal>
- </goals>
- <!-- optional: default phase is "generate-resources" -->
- <phase>initialize</phase>
- <configuration>
- <nodeVersion>v8.10.0</nodeVersion>
- <yarnVersion>v1.12.3</yarnVersion>
- </configuration>
- </execution>
- <execution>
- <id>yarn build</id>
- <goals>
- <goal>yarn</goal>
- </goals>
- <configuration>
- <arguments>run build</arguments>
- </configuration>
- </execution>
- </executions>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-jar-plugin</artifactId>
- </plugin>
- <plugin>
- <groupId>org.apache.felix</groupId>
- <artifactId>maven-bundle-plugin</artifactId>
- <extensions>true</extensions>
- <configuration>
- <instructions>
- <Import-Package>org.onap.ccsdk.features.sdnr.wt.odlux.model.*,com.opensymphony.*</Import-Package>
- <Private-Package></Private-Package>
- </instructions>
- </configuration>
- </plugin>
- </plugins>
- <resources>
- <resource>
- <directory>dist</directory>
- <targetPath>odlux</targetPath>
- </resource>
- <resource>
- <directory>src2/main/resources</directory>
- </resource>
- <resource>
- <directory>src2/test/resources</directory>
- </resource>
- </resources>
- </build>
- <pluginRepositories>
- <pluginRepository>
- <id>highstreet repo</id>
- <url>https://cloud-highstreet-technologies.com/mvn/</url>
- <snapshots>
- <enabled>true</enabled>
- <updatePolicy>always</updatePolicy>
- </snapshots>
- </pluginRepository>
- </pluginRepositories>
-</project>
-your
-```
-
-* a modified frontend-maven-plugin installs node, yarn and (optionally lerna) to compile the typescript sources to javascript. These will be build into the dist folder.
-
+ * The pom.xml in the framework subdirectory is the reference for ODLUX creation. [framework pom](framework/pom.xml)
+ * The node and yarn versions are specified
+ * A specific variant of "frontend-maven-plugin" is used to create the environment to compile to javascript. This modified frontend-maven-plugin installs node, yarn and (optionally lerna) to compile the typescript sources to javascript. These will be build into the dist folder.
diff --git a/sdnr/wt/odlux/apps/apiDemo/pom.xml b/sdnr/wt/odlux/apps/apiDemo/pom.xml
index c59a842..5b6cfa3 100644
--- a/sdnr/wt/odlux/apps/apiDemo/pom.xml
+++ b/sdnr/wt/odlux/apps/apiDemo/pom.xml
@@ -14,7 +14,7 @@
<version>0.7.1-SNAPSHOT</version>
<packaging>bundle</packaging>
- <name>ccsdk-features :: ${project.artifactId}</name>
+ <name>sdnr-wt-odlux-app-apiDemo</name>
<licenses>
<license>
<name>Apache License, Version 2.0</name>
@@ -111,10 +111,10 @@
</executions>
</plugin>
<plugin>
- <groupId>de.jacks-it-lab</groupId>
- <artifactId>frontend-maven-plugin</artifactId>
- <version>1.7.2</version>
- <executions>
+ <groupId>de.jacks-it-lab</groupId>
+ <artifactId>frontend-maven-plugin</artifactId>
+ <version>1.7.2</version>
+ <executions>
<execution>
<id>install node and yarn</id>
<goals>
diff --git a/sdnr/wt/odlux/apps/app-feature/pom.xml b/sdnr/wt/odlux/apps/app-feature/pom.xml
index 8888a75..d951016 100644
--- a/sdnr/wt/odlux/apps/app-feature/pom.xml
+++ b/sdnr/wt/odlux/apps/app-feature/pom.xml
@@ -26,7 +26,7 @@
<version>0.7.1-SNAPSHOT</version>
<packaging>feature</packaging>
- <name>ccsdk-features :: ${project.artifactId}</name>
+ <name>ccsdk-features :: ${project.artifactId} :: feature</name>
<licenses>
<license>
<name>Apache License, Version 2.0</name>
diff --git a/sdnr/wt/odlux/apps/configurationApp/pom.xml b/sdnr/wt/odlux/apps/configurationApp/pom.xml
index 305630d..9681555 100644
--- a/sdnr/wt/odlux/apps/configurationApp/pom.xml
+++ b/sdnr/wt/odlux/apps/configurationApp/pom.xml
@@ -14,7 +14,7 @@
<version>0.7.1-SNAPSHOT</version>
<packaging>bundle</packaging>
- <name>ccsdk-features :: ${project.artifactId}</name>
+ <name>sdnr-wt-odlux-app-configurationApp</name>
<licenses>
<license>
<name>Apache License, Version 2.0</name>
@@ -103,10 +103,10 @@
</executions>
</plugin>
<plugin>
- <groupId>de.jacks-it-lab</groupId>
- <artifactId>frontend-maven-plugin</artifactId>
- <version>1.7.2</version>
- <executions>
+ <groupId>de.jacks-it-lab</groupId>
+ <artifactId>frontend-maven-plugin</artifactId>
+ <version>1.7.2</version>
+ <executions>
<execution>
<id>install node and yarn</id>
<goals>
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/actions/deviceActions.ts b/sdnr/wt/odlux/apps/configurationApp/src/actions/deviceActions.ts
index fc06653..5b4498d 100644
--- a/sdnr/wt/odlux/apps/configurationApp/src/actions/deviceActions.ts
+++ b/sdnr/wt/odlux/apps/configurationApp/src/actions/deviceActions.ts
@@ -202,7 +202,7 @@
if (ind === 0) { defaultNS = namespace };
- viewElement = viewSpecification.elements[property];
+ viewElement = viewSpecification.elements[property] || viewSpecification.elements[`${namespace}:${property}`];
if (!viewElement) throw Error("Property [" + property + "] does not exist.");
if (viewElement.isList && !key) {
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/components/baseProps.ts b/sdnr/wt/odlux/apps/configurationApp/src/components/baseProps.ts
new file mode 100644
index 0000000..ec49191
--- /dev/null
+++ b/sdnr/wt/odlux/apps/configurationApp/src/components/baseProps.ts
@@ -0,0 +1,21 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
+import { ViewElement } from "../models/uiModels";
+
+export type baseProps = { value: ViewElement, inputValue: string, readOnly: boolean, disabled: boolean, onChange(newValue: string): void };
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/components/ifWhenTextInput.tsx b/sdnr/wt/odlux/apps/configurationApp/src/components/ifWhenTextInput.tsx
new file mode 100644
index 0000000..6735888
--- /dev/null
+++ b/sdnr/wt/odlux/apps/configurationApp/src/components/ifWhenTextInput.tsx
@@ -0,0 +1,61 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
+import { ViewElementBase } from "models/uiModels";
+import { TextField, InputAdornment, Input, Tooltip, Divider, IconButton, InputBase, Paper, makeStyles, Theme, createStyles, FormControl, InputLabel, FormHelperText } from "@material-ui/core";
+import * as React from 'react';
+import { faAdjust } from "@fortawesome/free-solid-svg-icons";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { InputProps } from "@material-ui/core/Input";
+
+const useStyles = makeStyles((theme: Theme) =>
+ createStyles({
+ iconDark: {
+ color: '#ff8800'
+ },
+ iconLight: {
+ color: 'orange'
+ },
+ padding: {
+ paddingLeft: 10,
+ paddingRight: 10
+ },
+ }),
+);
+
+type ifwhenProps = { element: ViewElementBase, id: any, label: any, style: any, helperText: string, error: boolean, toogleTooltip(value: boolean): void, [x: string]: any };
+
+export const IfWhenTextInput = (props: ifwhenProps) => {
+
+ const { element, toogleTooltip, id, label, helperText: errorText, error, style, ...otherProps } = props;
+ const classes = useStyles();
+
+
+ const ifFeature = element.ifFeature ? <Tooltip onMouseMove={e => props.toogleTooltip(false)} onMouseOut={e => props.toogleTooltip(true)} title={element.ifFeature}><InputAdornment position="start"><FontAwesomeIcon icon={faAdjust} className={classes.iconDark}></FontAwesomeIcon></InputAdornment></Tooltip> : null;
+ const whenFeature = element.when ? (<Tooltip className={classes.padding} onMouseMove={e => props.toogleTooltip(false)} onMouseOut={e => props.toogleTooltip(true)} title={element.when}>
+ <InputAdornment className={classes.padding} position="end"><FontAwesomeIcon icon={faAdjust} className={classes.iconLight}></FontAwesomeIcon></InputAdornment></Tooltip>) : null;
+
+ return (
+ <FormControl error={error} style={style}>
+ <InputLabel htmlFor={id} >{label}</InputLabel>
+ <Input {...otherProps} id={id} endAdornment={<div>{ifFeature}{whenFeature}</div>} />
+ <FormHelperText>{errorText}</FormHelperText>
+ </FormControl>
+
+ );
+}
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementBoolean.tsx b/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementBoolean.tsx
new file mode 100644
index 0000000..cc141ee
--- /dev/null
+++ b/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementBoolean.tsx
@@ -0,0 +1,58 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
+import { ViewElementBoolean } from "../models/uiModels";
+import * as React from "react"
+import { MenuItem, FormHelperText, Select, FormControl, InputLabel } from "@material-ui/core";
+import { baseProps } from "./baseProps";
+
+type booleanInputProps = baseProps;
+
+export const UiElementBoolean = (props: booleanInputProps) => {
+
+ const element = props.value as ViewElementBoolean;
+
+ let error = "";
+ const value = String(props.inputValue).toLowerCase();
+ if (element.mandatory && value !== "true" && value !== "false") {
+ error = "Error";
+ }
+ return (!props.readOnly || element.id != null
+ ? (<FormControl style={{ width: 485, marginLeft: 20, marginRight: 20 }}>
+ <InputLabel htmlFor={`select-${element.id}`} >{element.label}</InputLabel>
+ <Select
+ required={!!element.mandatory}
+ error={!!error}
+ onChange={(e) => { props.onChange(e.target.value as any) }}
+ readOnly={props.readOnly}
+ disabled={props.disabled}
+ value={value}
+ inputProps={{
+ name: element.id,
+ id: `select-${element.id}`,
+ }}
+ >
+ <MenuItem value={'true'}>{element.trueValue || 'True'}</MenuItem>
+ <MenuItem value={'false'}>{element.falseValue || 'False'}</MenuItem>
+
+ </Select>
+ <FormHelperText>{error}</FormHelperText>
+ </FormControl>)
+ : null
+ );
+}
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementNumber.tsx b/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementNumber.tsx
new file mode 100644
index 0000000..cf46205
--- /dev/null
+++ b/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementNumber.tsx
@@ -0,0 +1,77 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
+import { ViewElementNumber } from "models/uiModels";
+import { Tooltip, InputAdornment } from "@material-ui/core";
+import * as React from 'react';
+import { baseProps } from "./baseProps";
+import { IfWhenTextInput } from "./ifWhenTextInput";
+import { checkRange } from "./verifyer";
+
+type numberInputProps = baseProps;
+
+export const UiElementNumber = (props: numberInputProps) => {
+
+
+ const [error, setError] = React.useState(false);
+ const [helperText, setHelperText] = React.useState("");
+ const [isTooltipVisible, setTooltipVisibility] = React.useState(true);
+
+ const element = props.value as ViewElementNumber;
+
+ const verifyValue = (data: string) => {
+
+ if (data.trim().length > 0) {
+ const num = Number(data);
+ if (!isNaN(num)) {
+ const result = checkRange(element, num);
+ if (result.length > 0) {
+ setError(true);
+ setHelperText(result);
+ } else {
+ setError(false);
+ setHelperText("");
+ }
+ } else {
+ setError(true);
+ setHelperText("Input is not a number.");
+ }
+ } else {
+ setError(false);
+ setHelperText("");
+ }
+
+ props.onChange(data);
+ }
+
+ return (
+ <Tooltip title={isTooltipVisible ? element.description || '' : ''}>
+ <IfWhenTextInput element={element} toogleTooltip={(val: boolean) => setTooltipVisibility(val)}
+ spellCheck={false} autoFocus margin="dense"
+ id={element.id} label={element.label} type="text" value={props.inputValue}
+ style={{ width: 485, marginLeft: 20, marginRight: 20 }}
+ onChange={(e: any) => { verifyValue(e.target.value) }}
+ error={error}
+ readOnly={props.readOnly}
+ disabled={props.disabled}
+ helperText={helperText}
+ startAdornment={element.units != null ? <InputAdornment position="start">{element.units}</InputAdornment> : undefined}
+ />
+ </Tooltip>
+ );
+}
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementReference.tsx b/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementReference.tsx
new file mode 100644
index 0000000..2760eee
--- /dev/null
+++ b/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementReference.tsx
@@ -0,0 +1,48 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
+import React from 'react';
+import { Tooltip, Button, FormControl, Theme, createStyles, makeStyles } from '@material-ui/core';
+
+import { ViewElement } from '../models/uiModels';
+
+const useStyles = makeStyles((theme: Theme) => createStyles({
+ button: {
+ "justifyContent": "left"
+ },
+}));
+
+type UIElementReferenceProps = {
+ element: ViewElement;
+ disabled: boolean;
+ onOpenReference(element: ViewElement): void;
+};
+
+export const UIElementReference: React.FC<UIElementReferenceProps> = (props) => {
+ const classes = useStyles();
+ const { element } = props;
+ return (
+ <FormControl key={element.id} style={{ width: 485, marginLeft: 20, marginRight: 20 }}>
+ <Tooltip title={element.description || ''}>
+ <Button className={classes.button} color="secondary" disabled={props.disabled} onClick={() => {
+ props.onOpenReference(element);
+ }}>{element.label}</Button>
+ </Tooltip>
+ </FormControl>
+ );
+}
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementSelection.tsx b/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementSelection.tsx
new file mode 100644
index 0000000..d460763
--- /dev/null
+++ b/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementSelection.tsx
@@ -0,0 +1,59 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
+import * as React from 'react';
+import { baseProps } from './baseProps';
+import { ViewElementSelection } from '../models/uiModels'
+import { FormControl, InputLabel, Select, FormHelperText, MenuItem } from '@material-ui/core';
+
+
+
+type selectionProps = baseProps;
+
+export const UiElementSelection = (props: selectionProps) => {
+
+ const element = props.value as ViewElementSelection;
+
+ let error = "";
+ const value = String(props.inputValue).toLowerCase();
+ if (element.mandatory && !!value) {
+ error = "Error";
+ }
+
+ return (props.readOnly || props.inputValue != null
+ ? (<FormControl style={{ width: 485, marginLeft: 20, marginRight: 20 }}>
+ <InputLabel htmlFor={`select-${element.id}`} >{element.label}</InputLabel>
+ <Select
+ required={!!element.mandatory}
+ error={!!error}
+ onChange={(e) => { props.onChange(e.target.value as string) }}
+ readOnly={props.readOnly}
+ disabled={props.disabled}
+ value={value.toString().toLowerCase()}
+ inputProps={{
+ name: element.id,
+ id: `select-${element.id}`,
+ }}
+ >
+ {element.options.map(option => (<MenuItem key={option.key} title={option.description} value={option.key}>{option.key}</MenuItem>))}
+ </Select>
+ <FormHelperText>{error}</FormHelperText>
+ </FormControl>)
+ : null
+ );
+}
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementString.tsx b/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementString.tsx
new file mode 100644
index 0000000..43c60b5
--- /dev/null
+++ b/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementString.tsx
@@ -0,0 +1,84 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
+import { Tooltip, TextField } from "@material-ui/core";
+import { ViewElementString } from "../models/uiModels";
+import * as React from "react"
+import { baseProps } from "./baseProps";
+import { IfWhenTextInput } from "./ifWhenTextInput";
+import { checkRange, checkPattern } from "./verifyer";
+
+type stringEntryProps = baseProps & { isKey: boolean };
+
+export const UiElementString = (props: stringEntryProps) => {
+
+ const [isError, setError] = React.useState(false);
+ const [helperText, setHelperText] = React.useState("");
+ const [isTooltipVisible, setTooltipVisibility] = React.useState(true);
+
+ const element = props.value as ViewElementString;
+
+ const verifyValues = (data: string) => {
+
+ if (data.trim().length > 0) {
+
+ let errorMessage = "";
+ const result = checkRange(element, data.length);
+
+ if (result.length > 0)
+ errorMessage += result;
+
+
+ const patternResult = checkPattern(element.pattern, data)
+
+ if (patternResult.error) {
+ errorMessage += patternResult.error;
+ }
+
+ if (errorMessage.length > 0) {
+ setError(true);
+ setHelperText(errorMessage);
+ } else {
+ setError(false);
+ setHelperText("");
+ }
+ } else {
+ setError(false);
+ setHelperText("");
+ }
+
+
+ props.onChange(data);
+
+ }
+
+ return (
+ <Tooltip title={isTooltipVisible ? element.description || '' : ''}>
+ <IfWhenTextInput element={element} toogleTooltip={(val: boolean) => setTooltipVisibility(val)}
+ spellCheck={false} autoFocus margin="dense"
+ id={element.id} label={props.isKey ? "🔑 " + element.label : element.label} type="text" value={props.inputValue}
+ style={{ width: 485, marginLeft: 20, marginRight: 20 }}
+ onChange={(e: any) => { verifyValues(e.target.value) }}
+ error={isError}
+ readOnly={props.readOnly}
+ disabled={props.disabled}
+ helperText={helperText}
+ />
+ </Tooltip>
+ );
+}
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementUnion.tsx b/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementUnion.tsx
new file mode 100644
index 0000000..dc158c0
--- /dev/null
+++ b/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementUnion.tsx
@@ -0,0 +1,94 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
+import * as React from 'react'
+import { baseProps } from './baseProps';
+import { Tooltip } from '@material-ui/core';
+import { IfWhenTextInput } from './ifWhenTextInput';
+import { ViewElementUnion, isViewElementString, isViewElementNumber, isViewElementObject, ViewElementNumber } from '../models/uiModels';
+import { checkRange, checkPattern } from './verifyer';
+
+type UiElementUnionProps = { isKey: boolean } & baseProps;
+
+export const UIElementUnion = (props: UiElementUnionProps) => {
+
+ const [isError, setError] = React.useState(false);
+ const [helperText, setHelperText] = React.useState("");
+ const [isTooltipVisible, setTooltipVisibility] = React.useState(true);
+
+ const element = props.value as ViewElementUnion;
+
+ const verifyValues = (data: string) => {
+
+ debugger;
+ let foundObjectElements = 0;
+ let errorMessage = "";
+ let isPatternCorrect = null;
+
+ for (let i = 0; i < element.elements.length; i++) {
+ const unionElement = element.elements[i];
+
+ if (isViewElementNumber(unionElement)) {
+
+ errorMessage = checkRange(unionElement, Number(data));
+
+ } else if (isViewElementString(unionElement)) {
+ errorMessage += checkRange(unionElement, data.length);
+ isPatternCorrect = checkPattern(unionElement.pattern, data).isValid;
+
+
+ } else if (isViewElementObject(unionElement)) {
+ foundObjectElements++;
+ }
+
+ if (isPatternCorrect || errorMessage.length === 0) {
+ break;
+ }
+ }
+
+ if (errorMessage.length > 0 || isPatternCorrect !== null && !isPatternCorrect) {
+ setError(true);
+ setHelperText("Input is wrong.");
+ } else {
+ setError(false);
+ setHelperText("");
+ }
+
+ if (foundObjectElements > 0 && foundObjectElements != element.elements.length) {
+ throw new Error(`The union element ${element.id} can't be changed.`);
+
+ } else {
+ props.onChange(data);
+ }
+ };
+
+
+
+ return <Tooltip title={isTooltipVisible ? element.description || '' : ''}>
+ <IfWhenTextInput element={element} toogleTooltip={(val: boolean) => setTooltipVisibility(val)}
+ spellCheck={false} autoFocus margin="dense"
+ id={element.id} label={props.isKey ? "🔑 " + element.label : element.label} type="text" value={props.inputValue}
+ onChange={(e: any) => { verifyValues(e.target.value) }}
+ error={isError}
+ style={{ width: 485, marginLeft: 20, marginRight: 20 }}
+ readOnly={props.readOnly}
+ disabled={props.disabled}
+ helperText={helperText}
+ />
+ </Tooltip>;
+}
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/components/verifyer.ts b/sdnr/wt/odlux/apps/configurationApp/src/components/verifyer.ts
new file mode 100644
index 0000000..0a95cd8
--- /dev/null
+++ b/sdnr/wt/odlux/apps/configurationApp/src/components/verifyer.ts
@@ -0,0 +1,280 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
+import { Expression, YangRange, Operator, ViewElementNumber, ViewElementString, isViewElementNumber, isViewElementString } from '../models/uiModels';
+
+export type validated = { isValid: boolean, error?: string }
+
+export type validatedRange = { isValid: boolean, error?: string };
+
+
+const rangeErrorStartNumber = "The entered number must be";
+const rangeErrorinnerMinTextNumber = "greater or equals than";
+const rangeErrorinnerMaxTextNumber = "less or equals than";
+const rangeErrorEndTextNumber = ".";
+
+const rangeErrorStartString = "The entered text must have";
+const rangeErrorinnerMinTextString = "no more than";
+const rangeErrorinnerMaxTextString = "less than";
+const rangeErrorEndTextString = " characters.";
+
+let errorMessageStart = "";
+let errorMessageMiddleMinPart = "";
+let errorMessageMiddleMaxPart = "";
+let errorMessageEnd = "";
+
+
+export function checkRange(element: ViewElementNumber | ViewElementString, data: number): string {
+
+ //let test1: Operator<YangRange> = { operation: "AND", arguments: [{ operation: "OR", arguments: [{ operation: "AND", arguments: [new RegExp("^z", "g"), new RegExp("z$", "g")] }, new RegExp("^abc", "g"), new RegExp("^123", "g")] }, new RegExp("^def", "g"), new RegExp("^ppp", "g"), new RegExp("^aaa", "g")] };
+ //let test1: Operator<YangRange> = { operation: "AND", arguments: [{ operation: "OR", arguments: [{ operation: "AND", arguments: [{ min: -5, max: 10 }, { min: -30, max: -20 }] }, { min: 8, max: 15 }] }] };
+ //let test1: Operator<YangRange> = { operation: "OR", arguments: [{ operation: "OR", arguments: [{ min: -50, max: -40 }] }, { min: -30, max: -20 }, { min: 8, max: 15 }] };
+ //let test1: Operator<YangRange> = { operation: "AND", arguments: [{ operation: "OR", arguments: [{ min: -5, max: 10 }, { min: 17, max: 23 }] }] };
+
+ const number = data;
+
+ var expression = undefined;
+
+ if (isViewElementString(element)) {
+ expression = element.length;
+
+ errorMessageStart = rangeErrorStartString;
+ errorMessageMiddleMaxPart = rangeErrorinnerMaxTextString;
+ errorMessageMiddleMinPart = rangeErrorinnerMinTextString;
+ errorMessageEnd = rangeErrorEndTextString;
+
+ } else if (isViewElementNumber(element)) {
+ expression = element.range;
+
+ errorMessageStart = rangeErrorStartNumber;
+ errorMessageMiddleMaxPart = rangeErrorinnerMaxTextNumber;
+ errorMessageMiddleMinPart = rangeErrorinnerMinTextNumber;
+ errorMessageEnd = rangeErrorEndTextNumber;
+ }
+
+ if (expression) {
+ if (isYangOperator(expression)) {
+
+ const errorMessage = getRangeErrorMessages(expression, data);
+ return errorMessage;
+
+ } else
+ if (isYangRange(expression)) {
+
+ if (!isNaN(expression.min)) {
+ if (number < expression.min) {
+ return `${errorMessageStart} ${errorMessageMiddleMinPart} ${expression.min}${errorMessageEnd}`;
+ }
+ }
+
+ if (!isNaN(expression.max)) {
+ if (number > expression.max) {
+ return `${errorMessageStart} ${errorMessageMiddleMaxPart} ${expression.max}${errorMessageEnd}`;
+ }
+ }
+ }
+ }
+
+
+ return "";
+}
+
+function isYangRange(val: YangRange | Operator<YangRange>): val is YangRange {
+ return (val as YangRange).min !== undefined;
+}
+
+function isYangOperator(val: YangRange | Operator<YangRange>): val is Operator<YangRange> {
+ return (val as Operator<YangRange>).operation !== undefined;
+}
+
+function getRangeErrorMessagesRecursively(value: Operator<YangRange>, data: number): string[] {
+ let currentItteration: string[] = [];
+ console.log(value);
+
+ // itterate over all elements
+ for (let i = 0; i < value.arguments.length; i++) {
+ const element = value.arguments[i];
+
+ let min = undefined;
+ let max = undefined;
+
+ let isNumberCorrect = false;
+
+ if (isYangRange(element)) {
+
+ //check found min values
+ if (!isNaN(element.min)) {
+ if (data < element.min) {
+ min = element.min;
+ } else {
+ isNumberCorrect = true;
+ }
+ }
+
+ // check found max values
+ if (!isNaN(element.max)) {
+ if (data > element.max) {
+ max = element.max;
+ } else {
+ isNumberCorrect = true;
+ }
+ }
+
+ // construct error messages
+ if (min != undefined) {
+ currentItteration.push(`${value.operation.toLocaleLowerCase()} ${errorMessageMiddleMinPart} ${min}`);
+ } else if (max != undefined) {
+ currentItteration.push(`${value.operation.toLocaleLowerCase()} ${errorMessageMiddleMaxPart} ${max}`);
+
+ }
+
+ } else if (isYangOperator(element)) {
+
+ //get errormessages from expression
+ const result = getRangeErrorMessagesRecursively(element, data);
+ if (result.length === 0) {
+ isNumberCorrect = true;
+ }
+ currentItteration = currentItteration.concat(result);
+ }
+
+ // if its an OR operation, the number has been checked and min/max are empty (thus not violated)
+ // delete everything found (because at least one found is correct, therefore all are correct) and break from loop
+ if (min === undefined && max === undefined && isNumberCorrect && value.operation === "OR") {
+
+ currentItteration.splice(0, currentItteration.length);
+ break;
+ }
+ }
+
+ return currentItteration;
+}
+
+function getRangeErrorMessages(value: Operator<YangRange>, data: number): string {
+
+ const currentItteration = getRangeErrorMessagesRecursively(value, data);
+
+ // build complete error message from found parts
+ let errormessage = "";
+ if (currentItteration.length > 1) {
+
+ currentItteration.forEach((element, index) => {
+ if (index === 0) {
+ errormessage = createStartMessage(element);
+ } else if (index === currentItteration.length - 1) {
+ errormessage += ` ${element}${errorMessageEnd}`;
+ } else {
+ errormessage += `, ${element}`
+ }
+ });
+ } else if (currentItteration.length == 1) {
+ errormessage = `${createStartMessage(currentItteration[0])}${errorMessageEnd}`;
+ }
+
+ return errormessage;
+}
+
+function createStartMessage(element: string) {
+
+ //remove leading or or and from text
+ if (element.startsWith("and"))
+ element = element.replace("and", "");
+ else if (element.startsWith("or"))
+ element = element.replace("or", "");
+
+ return `${errorMessageStart} ${element}`;
+}
+
+export const checkPattern = (expression: RegExp | Operator<RegExp> | undefined, data: string): validated => {
+
+ if (expression) {
+ if (isRegExp(expression)) {
+ const isValid = expression.test(data);
+ if (!isValid)
+ return { isValid: isValid, error: "The input is in a wrong format." };
+
+ } else if (isRegExpOperator(expression)) {
+ const result = isPatternValid(expression, data);
+
+ if (!result) {
+ return { isValid: false, error: "The input is in a wrong format." };
+ }
+ }
+ }
+
+ return { isValid: true }
+}
+
+function getRegexRecursively(value: Operator<RegExp>, data: string): boolean[] {
+ let currentItteration: boolean[] = [];
+ for (let i = 0; i < value.arguments.length; i++) {
+ const element = value.arguments[i];
+ if (isRegExp(element)) {
+ // if regex is found, add it to list
+ currentItteration.push(element.test(data))
+ } else if (isRegExpOperator(element)) {
+ //if RegexExpression is found, try to get regex from it
+ currentItteration = currentItteration.concat(getRegexRecursively(element, data));
+ }
+ }
+
+ if (value.operation === "OR") {
+ // if one is true, all are true, all found items can be discarded
+ let result = currentItteration.find(element => element);
+ if (result) {
+ return [];
+ }
+ }
+ return currentItteration;
+}
+
+function isPatternValid(value: Operator<RegExp>, data: string): boolean {
+
+
+ // get all regex
+ const result = getRegexRecursively(value, data);
+ console.log(value);
+
+
+ if (value.operation === "AND") {
+ // if AND operation is executed...
+ // no element can be false
+ const check = result.find(element => element !== true);
+ if (check)
+ return false;
+ else
+ return true;
+ } else {
+ // if OR operation is executed...
+ // ... just one element must be true
+ const check = result.find(element => element === true);
+ if (check)
+ return true;
+ else
+ return false;
+
+ }
+}
+
+function isRegExp(val: RegExp | Operator<RegExp>): val is RegExp {
+ return (val as RegExp).source !== undefined;
+}
+
+function isRegExpOperator(val: RegExp | Operator<RegExp>): val is Operator<RegExp> {
+ return (val as Operator<RegExp>).operation !== undefined;
+}
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/handlers/configurationAppRootHandler.ts b/sdnr/wt/odlux/apps/configurationApp/src/handlers/configurationAppRootHandler.ts
index 04b63d3..1af699a 100644
--- a/sdnr/wt/odlux/apps/configurationApp/src/handlers/configurationAppRootHandler.ts
+++ b/sdnr/wt/odlux/apps/configurationApp/src/handlers/configurationAppRootHandler.ts
@@ -1,3 +1,21 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
import { combineActionHandler } from '../../../../framework/src/flux/middleware';
import { IConnectedNetworkElementsState, connectedNetworkElementsActionHandler } from './connectedNetworkElementsHandler';
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/handlers/connectedNetworkElementsHandler.ts b/sdnr/wt/odlux/apps/configurationApp/src/handlers/connectedNetworkElementsHandler.ts
index 6a68242..e6b808b 100644
--- a/sdnr/wt/odlux/apps/configurationApp/src/handlers/connectedNetworkElementsHandler.ts
+++ b/sdnr/wt/odlux/apps/configurationApp/src/handlers/connectedNetworkElementsHandler.ts
@@ -1,3 +1,21 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
import { createExternal, IExternalTableState } from '../../../../framework/src/components/material-table/utilities';
import { createSearchDataHandler } from '../../../../framework/src/utilities/elasticSearch';
@@ -16,4 +34,3 @@
// set value action, to change a value
} = createExternal<NetworkElementConnection>(connectedNetworkElementsSearchHandler, appState => appState.configuration.connectedNetworkElements);
-
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/handlers/deviceDescriptionHandler.ts b/sdnr/wt/odlux/apps/configurationApp/src/handlers/deviceDescriptionHandler.ts
index 3cc27aa..408399d 100644
--- a/sdnr/wt/odlux/apps/configurationApp/src/handlers/deviceDescriptionHandler.ts
+++ b/sdnr/wt/odlux/apps/configurationApp/src/handlers/deviceDescriptionHandler.ts
@@ -1,3 +1,21 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
import { Module } from "../models/yang";
import { ViewSpecification } from "../models/uiModels";
import { IActionHandler } from "../../../../framework/src/flux/action";
@@ -25,6 +43,6 @@
modules: action.modules,
views: action.views
};
- }
+ }
return state;
};
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/handlers/valueSelectorHandler.ts b/sdnr/wt/odlux/apps/configurationApp/src/handlers/valueSelectorHandler.ts
index c9e7dd2..9af640f 100644
--- a/sdnr/wt/odlux/apps/configurationApp/src/handlers/valueSelectorHandler.ts
+++ b/sdnr/wt/odlux/apps/configurationApp/src/handlers/valueSelectorHandler.ts
@@ -1,3 +1,21 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
import { IActionHandler } from "../../../../framework/src/flux/action";
import { ViewSpecification } from "../models/uiModels";
import { EnableValueSelector, SetSelectedValue, UpdateDeviceDescription, SetCollectingSelectionData, UpdatViewDescription } from "../actions/deviceActions";
@@ -23,7 +41,7 @@
if (action instanceof SetCollectingSelectionData) {
state = {
...state,
- collectingData: action.busy,
+ collectingData: action.busy,
};
} else if (action instanceof EnableValueSelector) {
state = {
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/handlers/viewDescriptionHandler.ts b/sdnr/wt/odlux/apps/configurationApp/src/handlers/viewDescriptionHandler.ts
index 48155ee..c1b3350 100644
--- a/sdnr/wt/odlux/apps/configurationApp/src/handlers/viewDescriptionHandler.ts
+++ b/sdnr/wt/odlux/apps/configurationApp/src/handlers/viewDescriptionHandler.ts
@@ -1,3 +1,21 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
import { IActionHandler } from "../../../../framework/src/flux/action";
import { UpdatViewDescription } from "../actions/deviceActions";
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/models/networkElementConnection.ts b/sdnr/wt/odlux/apps/configurationApp/src/models/networkElementConnection.ts
index 2575500..88f7018 100644
--- a/sdnr/wt/odlux/apps/configurationApp/src/models/networkElementConnection.ts
+++ b/sdnr/wt/odlux/apps/configurationApp/src/models/networkElementConnection.ts
@@ -1,3 +1,21 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
export type NetworkElementConnection = {
id?: string;
nodeId: string;
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/models/uiModels.ts b/sdnr/wt/odlux/apps/configurationApp/src/models/uiModels.ts
index 441d128..7b41c38 100644
--- a/sdnr/wt/odlux/apps/configurationApp/src/models/uiModels.ts
+++ b/sdnr/wt/odlux/apps/configurationApp/src/models/uiModels.ts
@@ -1,3 +1,21 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
export type ViewElementBase = {
"id": string;
"label": string;
@@ -15,7 +33,7 @@
// https://tools.ietf.org/html/rfc7950#section-9.8
export type ViewElementBinary = ViewElementBase & {
"uiType": "binary";
- "length"?: number; // number of octets
+ "length"?: Expression<YangRange>; // number of octets
}
// https://tools.ietf.org/html/rfc7950#section-9.7.4
@@ -29,16 +47,17 @@
// https://tools.ietf.org/html/rfc7950#section-9
export type ViewElementString = ViewElementBase & {
"uiType": "string";
- "pattern"?: string[];
- "length"?: string;
+ "pattern"?: Expression<RegExp>;
+ "length"?: Expression<YangRange>;
"invertMatch"?: true;
}
// https://tools.ietf.org/html/rfc7950#section-9.3
export type ViewElementNumber = ViewElementBase & {
"uiType": "number";
- "min"?: number;
- "max"?: number;
+ "min": number;
+ "max": number;
+ "range"?: Expression<YangRange>;
"units"?: string;
"format"?: string;
"fDigits"?: number;
@@ -85,6 +104,16 @@
"ref": (currentPath: string) => ViewElement | null;
}
+export type ViewElementUnion = ViewElementBase & {
+ "uiType": "union";
+ "elements": ViewElement[];
+}
+
+export type ViewElementChoise = ViewElementBase & {
+ "uiType": "choise";
+ "cases": { [name: string]: { id: string, label: string, description?: string, elements: { [name: string]: ViewElement } } };
+}
+
export type ViewElement =
| ViewElementBits
| ViewElementBinary
@@ -94,14 +123,16 @@
| ViewElementObject
| ViewElementList
| ViewElementSelection
- | ViewElementReference;
+ | ViewElementReference
+ | ViewElementUnion
+ | ViewElementChoise;
export const isViewElementString = (viewElement: ViewElement): viewElement is ViewElementString => {
return viewElement && viewElement.uiType === "string";
}
export const isViewElementNumber = (viewElement: ViewElement): viewElement is ViewElementNumber => {
- return viewElement && viewElement.uiType === "number" ;
+ return viewElement && viewElement.uiType === "number";
}
export const isViewElementBoolean = (viewElement: ViewElement): viewElement is ViewElementBoolean => {
@@ -128,6 +159,15 @@
return viewElement && viewElement.uiType === "reference";
}
+export const isViewElementUnion = (viewElement: ViewElement): viewElement is ViewElementUnion => {
+ return viewElement && viewElement.uiType === "union";
+}
+
+export const isViewElementChoise = (viewElement: ViewElement): viewElement is ViewElementChoise => {
+ return viewElement && viewElement.uiType === "choise";
+}
+
+
export type ViewSpecification = {
"id": string;
"name": string;
@@ -140,3 +180,17 @@
"elements": { [name: string]: ViewElement };
readonly "canEdit": boolean;
}
+
+export type YangRange = {
+ min: number,
+ max: number,
+}
+
+export type Expression<T> =
+ | T
+ | Operator<T>;
+
+export type Operator<T> = {
+ operation: "AND" | "OR";
+ arguments: Expression<T>[];
+}
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/models/yang.ts b/sdnr/wt/odlux/apps/configurationApp/src/models/yang.ts
index 57edf80..11eb44d 100644
--- a/sdnr/wt/odlux/apps/configurationApp/src/models/yang.ts
+++ b/sdnr/wt/odlux/apps/configurationApp/src/models/yang.ts
@@ -1,3 +1,21 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
import { ViewElement, ViewSpecification } from "./uiModels";
export type Token = {
@@ -33,7 +51,7 @@
namespace?: string;
prefix?: string;
identities: { [name: string]: Identity };
- revisions: { [version: string]: Revision } ;
+ revisions: { [version: string]: Revision };
imports: { [prefix: string]: string };
features: { [feature: string]: { description?: string } };
typedefs: { [type: string]: ViewElement };
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/pluginConfiguration.tsx b/sdnr/wt/odlux/apps/configurationApp/src/pluginConfiguration.tsx
index 7fd3a97..0cab7b7 100644
--- a/sdnr/wt/odlux/apps/configurationApp/src/pluginConfiguration.tsx
+++ b/sdnr/wt/odlux/apps/configurationApp/src/pluginConfiguration.tsx
@@ -1,3 +1,21 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
import * as React from "react";
import { withRouter, RouteComponentProps, Route, Switch, Redirect } from 'react-router-dom';
@@ -32,7 +50,7 @@
currentNodeId = undefined;
currentVirtualPath = undefined;
}
- },[]);
+ }, []);
if (props.location.pathname !== lastUrl) {
// ensure the asynchronus update will only be called once per path
lastUrl = props.location.pathname;
@@ -59,9 +77,9 @@
const App = withRouter((props: RouteComponentProps) => (
<Switch>
- <Route path={`${props.match.url}/:nodeId/*`} component={ ConfigurationApplicationRouteAdapter } />
- <Route path={`${props.match.url}/:nodeId`} component={ ConfigurationApplicationRouteAdapter } />
- <Route path={`${props.match.url}`} component={ NetworkElementSelector } />
+ <Route path={`${props.match.url}/:nodeId/*`} component={ConfigurationApplicationRouteAdapter} />
+ <Route path={`${props.match.url}/:nodeId`} component={ConfigurationApplicationRouteAdapter} />
+ <Route path={`${props.match.url}`} component={NetworkElementSelector} />
<Redirect to={`${props.match.url}`} />
</Switch>
));
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/services/restServices.ts b/sdnr/wt/odlux/apps/configurationApp/src/services/restServices.ts
index 061be05..d0ed03a 100644
--- a/sdnr/wt/odlux/apps/configurationApp/src/services/restServices.ts
+++ b/sdnr/wt/odlux/apps/configurationApp/src/services/restServices.ts
@@ -1,3 +1,21 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
import { requestRest, requestRestExt } from "../../../../framework/src/services/restService";
import { convertPropertyNames, replaceHyphen } from "../../../../framework/src/utilities/yangHelper";
@@ -32,7 +50,7 @@
public setConfigData(path: string, data: any) {
return requestRestExt<{ [key: string]: any }>(path, { method: "PUT", body: JSON.stringify(data) });
}
- }
+}
export const restService = new RestService();
export default restService;
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/services/yangService.ts b/sdnr/wt/odlux/apps/configurationApp/src/services/yangService.ts
index 17a4e43..3dc3a86 100644
--- a/sdnr/wt/odlux/apps/configurationApp/src/services/yangService.ts
+++ b/sdnr/wt/odlux/apps/configurationApp/src/services/yangService.ts
@@ -1,3 +1,21 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
type YangInfo = [string, (string | null | undefined)];
const cache: { [path: string]: string } = {
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/views/configurationApplication.tsx b/sdnr/wt/odlux/apps/configurationApp/src/views/configurationApplication.tsx
index 24a4af8..9c92ceb 100644
--- a/sdnr/wt/odlux/apps/configurationApp/src/views/configurationApplication.tsx
+++ b/sdnr/wt/odlux/apps/configurationApp/src/views/configurationApplication.tsx
@@ -16,7 +16,7 @@
* ============LICENSE_END==========================================================================
*/
-import * as React from 'react';
+import React from 'react';
import { RouteComponentProps, withRouter } from 'react-router-dom';
import { WithStyles, withStyles, createStyles, Theme } from '@material-ui/core/styles';
@@ -26,11 +26,12 @@
import MaterialTable, { ColumnModel, ColumnType, MaterialTableCtorType } from "../../../../framework/src/components/material-table";
import { Loader } from "../../../../framework/src/components/material-ui/loader";
-import { SetSelectedValue, splitVPath, updateDataActionAsyncCreator } from "../actions/deviceActions";
-import { ViewSpecification, isViewElementString, isViewElementNumber, isViewElementBoolean, isViewElementObjectOrList, isViewElementSelection } from "../models/uiModels";
+import { SetSelectedValue, splitVPath, updateDataActionAsyncCreator, updateViewActionAsyncCreator } from "../actions/deviceActions";
+import { ViewSpecification, isViewElementString, isViewElementNumber, isViewElementBoolean, isViewElementObjectOrList, isViewElementSelection, isViewElementChoise, ViewElement, ViewElementChoise, isViewElementUnion } from "../models/uiModels";
import Fab from '@material-ui/core/Fab';
import AddIcon from '@material-ui/icons/Add';
+import ArrowBack from '@material-ui/icons/ArrowBack';
import RemoveIcon from '@material-ui/icons/RemoveCircleOutline';
import SaveIcon from '@material-ui/icons/Save';
import EditIcon from '@material-ui/icons/Edit';
@@ -38,7 +39,7 @@
import TextField from "@material-ui/core/TextField";
import FormControl from "@material-ui/core/FormControl";
import IconButton from "@material-ui/core/IconButton";
-import Button from "@material-ui/core/Button";
+
import InputAdornment from "@material-ui/core/InputAdornment";
import InputLabel from "@material-ui/core/InputLabel";
import Select from "@material-ui/core/Select";
@@ -47,6 +48,13 @@
import Link from "@material-ui/core/Link";
import FormHelperText from '@material-ui/core/FormHelperText';
+import { UIElementReference } from '../components/uiElementReference';
+import { UiElementNumber } from '../components/uiElementNumber';
+import { UiElementString } from '../components/uiElementString';
+import { UiElementBoolean } from '../components/uiElementBoolean';
+import { UiElementSelection } from '../components/uiElementSelection';
+import { UIElementUnion } from '../components/uiElementUnion';
+
const styles = (theme: Theme) => createStyles({
header: {
"display": "flex",
@@ -97,6 +105,16 @@
},
},
},
+ section: {
+ padding: "15px",
+ borderBottom: `2px solid ${theme.palette.divider}`,
+ },
+ viewElements: {
+ width: 485, marginLeft: 20, marginRight: 20
+ },
+ verificationElements: {
+ width: 485, marginLeft: 20, marginRight: 20
+ }
});
const mapProps = (state: IApplicationStoreState) => ({
@@ -115,6 +133,7 @@
const mapDispatch = (dispatcher: IDispatcher) => ({
onValueSelected: (value: any) => dispatcher.dispatch(new SetSelectedValue(value)),
onUpdateData: (vPath: string, data: any) => dispatcher.dispatch(updateDataActionAsyncCreator(vPath, data)),
+ reloadView: (vPath: string) => dispatcher.dispatch(updateViewActionAsyncCreator(vPath)),
});
const SelectElementTable = MaterialTable as MaterialTableCtorType<{ [key: string]: any }>;
@@ -126,6 +145,7 @@
editMode: boolean;
canEdit: boolean;
viewData: { [key: string]: any } | null;
+ choises: { [path: string]: { selectedCase: string, data: { [property: string]: any } } };
}
const OldProps = Symbol("OldProps");
@@ -134,27 +154,61 @@
/**
*
*/
- constructor (props: ConfigurationApplicationComponentProps) {
+ constructor(props: ConfigurationApplicationComponentProps) {
super(props);
this.state = {
isNew: false,
canEdit: false,
editMode: false,
- viewData: null
+ viewData: null,
+ choises: {},
}
}
- static getDerivedStateFromProps(nextProps: ConfigurationApplicationComponentProps, prevState: ConfigurationApplicationComponentState & { [OldProps]: ConfigurationApplicationComponentProps }) {
+ static getDerivedStateFromProps(nextProps: ConfigurationApplicationComponentProps, prevState: ConfigurationApplicationComponentState & { [OldProps]: ConfigurationApplicationComponentProps }) {
if (!prevState || !prevState[OldProps] || (prevState[OldProps].viewData !== nextProps.viewData)) {
- const isNew: boolean = nextProps.vPath?.endsWith("[]") || false;
+ const isNew: boolean = nextProps.vPath ?.endsWith("[]") || false;
const state = {
...prevState,
isNew: isNew,
editMode: isNew,
viewData: nextProps.viewData || null,
[OldProps]: nextProps,
+ choises: nextProps.viewSpecification && Object.keys(nextProps.viewSpecification.elements).reduce((acc, cur) => {
+ const elm = nextProps.viewSpecification.elements[cur];
+ if (isViewElementChoise(elm)) {
+ const caseKeys = Object.keys(elm.cases);
+
+ // find the right case for this choise, use the first one with data, at least use index 0
+ const selectedCase = caseKeys.find(key => {
+ const caseElm = elm.cases[key];
+ return Object.keys(caseElm.elements).some(caseElmKey => {
+ const caseElmElm = caseElm.elements[caseElmKey];
+ return nextProps.viewData[caseElmElm.label] != null || nextProps.viewData[caseElmElm.id] != null;
+ });
+ }) || caseKeys[0];
+
+ // extract all data of the active case
+ const caseElements = elm.cases[selectedCase].elements;
+ const data = Object.keys(caseElements).reduce((dataAcc, dataCur) => {
+ const dataElm = caseElements[dataCur];
+ if (nextProps.viewData[dataElm.label] !== undefined) {
+ dataAcc[dataElm.label] = nextProps.viewData[dataElm.label];
+ } else if (nextProps.viewData[dataElm.id] !== undefined) {
+ dataAcc[dataElm.id] = nextProps.viewData[dataElm.id];
+ }
+ return dataAcc;
+ }, {} as { [name: string]: any });
+
+ acc[elm.id] = {
+ selectedCase,
+ data,
+ };
+ }
+ return acc;
+ }, {} as { [path: string]: { selectedCase: string, data: { [property: string]: any } } }) || {}
}
return state;
}
@@ -174,123 +228,203 @@
});
}
- private renderUIElement = (viewSpecification: ViewSpecification, viewData: { [key: string]: any }, keyProperty: string | undefined, editMode: boolean, isNew: boolean) => {
- const elements = viewSpecification.elements;
+ private renderUIElement = (uiElement: ViewElement, viewData: { [key: string]: any }, keyProperty: string | undefined, editMode: boolean, isNew: boolean) => {
+ const isKey = (uiElement.label === keyProperty);
+ const canEdit = editMode && (isNew || (uiElement.config && !isKey));
+ if (isViewElementSelection(uiElement)) {
+
+ return <UiElementSelection
+ key={uiElement.id}
+ inputValue={viewData[uiElement.id] || ''}
+ value={uiElement}
+ readOnly={!canEdit}
+ disabled={editMode && !canEdit}
+ onChange={(e) => { this.changeValueFor(uiElement.id, e) }}
+ />
+
+ } else if (isViewElementBoolean(uiElement)) {
+ return <UiElementBoolean
+ key={uiElement.id}
+ inputValue={viewData[uiElement.id] || ''}
+ value={uiElement}
+ readOnly={!canEdit}
+ disabled={editMode && !canEdit}
+ onChange={(e) => { this.changeValueFor(uiElement.id, e) }} />
+
+ } else if (isViewElementString(uiElement)) {
+ return <UiElementString
+ key={uiElement.id}
+ inputValue={viewData[uiElement.id] || ''}
+ value={uiElement}
+ isKey={isKey}
+ readOnly={!canEdit}
+ disabled={editMode && !canEdit}
+ onChange={(e) => { this.changeValueFor(uiElement.id, e) }} />
+
+ } else if (isViewElementNumber(uiElement)) {
+ return <UiElementNumber
+ key={uiElement.id}
+ value={uiElement}
+ inputValue={viewData[uiElement.id] == null ? '' : viewData[uiElement.id]}
+ readOnly={!canEdit}
+ disabled={editMode && !canEdit}
+ onChange={(e) => { this.changeValueFor(uiElement.id, e) }} />
+ } else if (isViewElementUnion(uiElement)) {
+ return <UIElementUnion
+ key={uiElement.id}
+ isKey={false}
+ value={uiElement}
+ inputValue={viewData[uiElement.id] == null ? '' : viewData[uiElement.id]}
+ readOnly={!canEdit}
+ disabled={editMode && !canEdit}
+ onChange={(e) => { this.changeValueFor(uiElement.id, e) }} />
+ }
+ else {
+ if (process.env.NODE_ENV !== "production") {
+ console.error(`Unknown element type - ${(uiElement as any).uiType} in ${(uiElement as any).id}.`)
+ }
+ return null;
+ }
+ };
+
+ // private renderUIReference = (uiElement: ViewElement, viewData: { [key: string]: any }, keyProperty: string | undefined, editMode: boolean, isNew: boolean) => {
+ // const isKey = (uiElement.label === keyProperty);
+ // const canEdit = editMode && (isNew || (uiElement.config && !isKey));
+ // if (isViewElementObjectOrList(uiElement)) {
+ // return (
+ // <FormControl key={uiElement.id} style={{ width: 485, marginLeft: 20, marginRight: 20 }}>
+ // <Tooltip title={uiElement.description || ''}>
+ // <Button className={this.props.classes.leftButton} color="secondary" disabled={this.state.editMode} onClick={() => {
+ // this.navigate(`/${uiElement.id}`);
+ // }}>{uiElement.label}</Button>
+ // </Tooltip>
+ // </FormControl>
+ // );
+ // } else {
+ // if (process.env.NODE_ENV !== "production") {
+ // console.error(`Unknown reference type - ${(uiElement as any).uiType} in ${(uiElement as any).id}.`)
+ // }
+ // return null;
+ // }
+ // };
+
+ private renderUIChoise = (uiElement: ViewElementChoise, viewData: { [key: string]: any }, keyProperty: string | undefined, editMode: boolean, isNew: boolean) => {
+ const isKey = (uiElement.label === keyProperty);
+
+ const currentChoise = this.state.choises[uiElement.id];
+ const currentCase = currentChoise && uiElement.cases[currentChoise.selectedCase];
+
+ const canEdit = editMode && (isNew || (uiElement.config && !isKey));
+ if (isViewElementChoise(uiElement)) {
+ const subElements = currentCase ?.elements;
+ return (
+ <>
+ <FormControl key={uiElement.id} style={{ width: 485, marginLeft: 20, marginRight: 20 }}>
+ <InputLabel htmlFor={`select-${uiElement.id}`} >{uiElement.label}</InputLabel>
+ <Select
+ required={!!uiElement.mandatory}
+ onChange={(e) => {
+ if (currentChoise.selectedCase === e.target.value) {
+ return; // nothing changed
+ }
+ this.setState({ choises: { ...this.state.choises, [uiElement.id]: { ...this.state.choises[uiElement.id], selectedCase: e.target.value as string } } });
+ }}
+ readOnly={!canEdit}
+ disabled={editMode && !canEdit}
+ value={this.state.choises[uiElement.id].selectedCase}
+ inputProps={{
+ name: uiElement.id,
+ id: `select-${uiElement.id}`,
+ }}
+ >
+ {
+ Object.keys(uiElement.cases).map(caseKey => {
+ const caseElm = uiElement.cases[caseKey];
+ return (
+ <MenuItem key={caseElm.id} title={caseElm.description} value={caseKey}>{caseElm.label}</MenuItem>
+ );
+ })
+ }
+ </Select>
+ </FormControl>
+ {subElements
+ ? Object.keys(subElements).map(elmKey => {
+ const elm = subElements[elmKey];
+ return this.renderUIElement(elm, viewData, keyProperty, editMode, isNew);
+ })
+ : <h3>Invalid Choise</h3>
+ }
+ </>
+ );
+ } else {
+ if (process.env.NODE_ENV !== "production") {
+ console.error(`Unknown type - ${(uiElement as any).uiType} in ${(uiElement as any).id}.`)
+ }
+ return null;
+ }
+ };
+
+ private renderUIView = (viewSpecification: ViewSpecification, viewData: { [key: string]: any }, keyProperty: string | undefined, editMode: boolean, isNew: boolean) => {
+ const { classes } = this.props;
+
+ const orderFunc = (vsA: ViewElement, vsB: ViewElement) => {
+ if (keyProperty) {
+ // if (vsA.label === vsB.label) return 0;
+ if (vsA.label === keyProperty) return -1;
+ if (vsB.label === keyProperty) return +1;
+ }
+
+ // if (vsA.uiType === vsB.uiType) return 0;
+ // if (vsA.uiType !== "object" && vsB.uiType !== "object") return 0;
+ // if (vsA.uiType === "object") return +1;
+ return -1;
+ };
+
+ const sections = Object.keys(viewSpecification.elements).reduce((acc, cur) => {
+ const elm = viewSpecification.elements[cur];
+ if (isViewElementObjectOrList(elm)) {
+ acc.references.push(elm);
+ } else if (isViewElementChoise(elm)) {
+ acc.choises.push(elm);
+ } else {
+ acc.elements.push(elm);
+ }
+ return acc;
+ }, { elements: [] as ViewElement[], references: [] as ViewElement[], choises: [] as ViewElementChoise[] });
+
+ sections.elements = sections.elements.sort(orderFunc);
+
return (
- Object.keys(elements).sort((a, b) => {
- const vsA = elements[a];
- const vsB = elements[b];
- if (keyProperty) {
- // if (vsA.label === vsB.label) return 0;
- if (vsA.label === keyProperty) return -1;
- if (vsB.label === keyProperty) return +1;
+ <>
+ <div className={classes.section} />
+ {sections.elements.length > 0
+ ? (
+ <div className={classes.section}>
+ {sections.elements.map(element => this.renderUIElement(element, viewData, keyProperty, editMode, isNew))}
+ </div>
+ ) : null
}
-
- if (vsA.uiType === vsB.uiType) return 0;
- if (vsA.uiType !== "object" && vsB.uiType !== "object") return 0;
- if (vsA.uiType === "object") return +1;
- return -1;
- }).map(key => {
- const uiElement = elements[key];
- const isKey = (uiElement.label === keyProperty);
- const canEdit = editMode && (isNew || (uiElement.config && !isKey));
- if (isViewElementSelection(uiElement)) {
- let error = ""
- const value = String(viewData[uiElement.id]).toLowerCase();
- if (uiElement.mandatory && !!value) {
- error = "Error";
- }
- return (canEdit || viewData[uiElement.id] != null
- ? (<FormControl key={uiElement.id} style={{ width: 485, marginLeft: 20, marginRight: 20 }}>
- <InputLabel htmlFor={`select-${uiElement.id}`} >{uiElement.label}</InputLabel>
- <Select
- required={!!uiElement.mandatory}
- error={!!error}
- onChange={(e) => { this.changeValueFor(uiElement.id, e.target.value) }}
- readOnly={!canEdit}
- disabled={editMode && !canEdit}
- value={(viewData[uiElement.id] || '').toString().toLowerCase()}
- inputProps={{
- name: uiElement.id,
- id: `select-${uiElement.id}`,
- }}
- >
- {uiElement.options.map(option => (<MenuItem key={option.key} title={option.description} value={option.value}>{option.key}</MenuItem>))}
- </Select>
- <FormHelperText>{error}</FormHelperText>
- </FormControl>)
- : null
- );
- } else if (isViewElementBoolean(uiElement)) {
- let error = ""
- const value = String(viewData[uiElement.id]).toLowerCase();
- if (uiElement.mandatory && value !== "true" && value !== "false") {
- error = "Error";
- }
- return (canEdit || viewData[uiElement.id] != null
- ? (<FormControl key={uiElement.id} style={{ width: 485, marginLeft: 20, marginRight: 20 }}>
- <InputLabel htmlFor={`select-${uiElement.id}`} >{uiElement.label}</InputLabel>
- <Select
- required={!!uiElement.mandatory}
- error={!!error}
- onChange={(e) => { this.changeValueFor(uiElement.id, e.target.value) }}
- readOnly={!canEdit}
- disabled={editMode && !canEdit}
- value={value}
- inputProps={{
- name: uiElement.id,
- id: `select-${uiElement.id}`,
- }}
- >
- <MenuItem value={'true'}>{uiElement.trueValue || 'True'}</MenuItem>
- <MenuItem value={'false'}>{uiElement.falseValue || 'False'}</MenuItem>
-
- </Select>
- <FormHelperText>{error}</FormHelperText>
- </FormControl>)
- : null
- );
- } else if (isViewElementString(uiElement)) {
- return (
- <Tooltip key={uiElement.id} title={uiElement.description || ''}>
- <TextField InputProps={{ readOnly: !canEdit, disabled: editMode && !canEdit }} spellCheck={false} autoFocus margin="dense"
- id={uiElement.id} label={isKey ? "🔑 " + uiElement.label : uiElement.label} type="text" value={viewData[uiElement.id] || ''}
- style={{ width: 485, marginLeft: 20, marginRight: 20 }}
- onChange={(e) => { this.changeValueFor(uiElement.id, e.target.value) }}
- />
- </Tooltip>
- );
- } else if (isViewElementNumber(uiElement)) {
- return (
- <Tooltip key={uiElement.id} title={uiElement.description || ''}>
- <TextField InputProps={{ readOnly: !canEdit, disabled: editMode && !canEdit, startAdornment: uiElement.units != null ? <InputAdornment position="start">{uiElement.units}</InputAdornment> : undefined }} spellCheck={false} autoFocus margin="dense"
- id={uiElement.id} label={uiElement.label} type="text" value={viewData[uiElement.id] == null ? '' : viewData[uiElement.id]}
- style={{ width: 485, marginLeft: 20, marginRight: 20 }}
- onChange={(e) => { this.changeValueFor(uiElement.id, e.target.value) }}
- />
- </Tooltip>
- );
- } else if (isViewElementObjectOrList(uiElement)) {
- return (
- <FormControl key={uiElement.id} style={{ width: 485, marginLeft: 20, marginRight: 20 }}>
- <Tooltip title={uiElement.description || ''}>
- <Button className={this.props.classes.leftButton} color="secondary" disabled={this.state.editMode} onClick={() => {
- this.navigate(`/${uiElement.id}`);
- }}>{uiElement.label}</Button>
- </Tooltip>
- </FormControl>
- );
- } else {
- if (process.env.NODE_ENV !== "production") {
- console.error(`Unknown type - ${(uiElement as any).uiType} in ${(uiElement as any).id}.`)
- }
- return null;
+ {sections.references.length > 0
+ ? (
+ <div className={classes.section}>
+ {sections.references.map(element => (
+ <UIElementReference key={element.id} element={element} disabled={editMode} onOpenReference={(elm) => { this.navigate(`/${elm.id}`) }} />
+ ))}
+ </div>
+ ) : null
}
- })
+ {sections.choises.length > 0
+ ? (
+ <div className={classes.section}>
+ {sections.choises.map(element => this.renderUIChoise(element, viewData, keyProperty, editMode, isNew))}
+ </div>
+ ) : null
+ }
+ </>
);
};
- private renderUIElementList(listSpecification: ViewSpecification, listKeyProperty: string, listData: { [key: string]: any }[]) {
+ private renderUIViewList(listSpecification: ViewSpecification, listKeyProperty: string, listData: { [key: string]: any }[]) {
const listElements = listSpecification.elements;
const navigate = (path: string) => {
@@ -381,11 +515,41 @@
}
</Breadcrumbs>
</div>
+ {this.state.editMode && (
+ <Fab color="secondary" aria-label="edit" className={this.props.classes.fab} onClick={async () => {
+ this.props.vPath && await this.props.reloadView(this.props.vPath);
+ this.setState({ editMode: false });
+ }} ><ArrowBack /></Fab>
+ ) || null}
{ /* do not show edit if this is a list or it can't be edited */
!displayAsList && viewSpecification.canEdit && (<div>
<Fab color="secondary" aria-label="edit" className={this.props.classes.fab} onClick={() => {
if (this.state.editMode) {
- this.props.onUpdateData(this.props.vPath!, this.state.viewData);
+
+ // ensure only active choises will be contained
+ const choiseKeys = Object.keys(viewSpecification.elements).filter(elmKey => isViewElementChoise(viewSpecification.elements[elmKey]));
+ const elementsToRemove = choiseKeys.reduce((acc, cur) => {
+ const choise = viewSpecification.elements[cur] as ViewElementChoise;
+ const selectedCase = this.state.choises[cur].selectedCase;
+ Object.keys(choise.cases).forEach(caseKey => {
+ if (caseKey === selectedCase) return;
+ const caseElements = choise.cases[caseKey].elements;
+ Object.keys(caseElements).forEach(caseElementKey => {
+ acc.push(caseElements[caseElementKey]);
+ });
+ });
+ return acc;
+ }, [] as ViewElement[]);
+
+ const viewData = this.state.viewData;
+ const resultingViewData = viewData && Object.keys(viewData).reduce((acc, cur) => {
+ if (!elementsToRemove.some(elm => elm.label === cur || elm.id === cur)) {
+ acc[cur] = viewData[cur];
+ }
+ return acc;
+ }, {} as { [key: string]: any });
+
+ this.props.onUpdateData(this.props.vPath!, resultingViewData);
}
this.setState({ editMode: !editMode });
}}>
@@ -431,10 +595,10 @@
return (
<div>
- { this.renderBreadCrumps() }
- { displayAsList && viewData instanceof Array
- ? this.renderUIElementList(viewSpecification, keyProperty!, viewData)
- : this.renderUIElement(viewSpecification, viewData!, keyProperty, editMode, isNew)
+ {this.renderBreadCrumps()}
+ {displayAsList && viewData instanceof Array
+ ? this.renderUIViewList(viewSpecification, keyProperty!, viewData)
+ : this.renderUIView(viewSpecification, viewData!, keyProperty, editMode, isNew)
}
</div >
);
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/views/networkElementSelector.tsx b/sdnr/wt/odlux/apps/configurationApp/src/views/networkElementSelector.tsx
index 6fd5c8c..8155bec 100644
--- a/sdnr/wt/odlux/apps/configurationApp/src/views/networkElementSelector.tsx
+++ b/sdnr/wt/odlux/apps/configurationApp/src/views/networkElementSelector.tsx
@@ -1,3 +1,21 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
import * as React from 'react';
import { RouteComponentProps, withRouter } from 'react-router-dom';
@@ -29,7 +47,7 @@
render() {
return (
- <ConnectedElementTable onHandleClick={(e, row) => { this.props.history.push(`${ this.props.match.path }/${row.nodeId}`) }} columns={[
+ <ConnectedElementTable onHandleClick={(e, row) => { this.props.history.push(`${this.props.match.path}/${row.nodeId}`) }} columns={[
{ property: "nodeId", title: "Name", type: ColumnType.text },
{ property: "isRequired", title: "Required ?", type: ColumnType.boolean },
{ property: "host", title: "Host", type: ColumnType.text },
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/yang/yangParser.ts b/sdnr/wt/odlux/apps/configurationApp/src/yang/yangParser.ts
index c7ab5e4..49c2b9b 100644
--- a/sdnr/wt/odlux/apps/configurationApp/src/yang/yangParser.ts
+++ b/sdnr/wt/odlux/apps/configurationApp/src/yang/yangParser.ts
@@ -1,6 +1,24 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
import { Token, Statement, Module, Identity } from "../models/yang";
-import { ViewSpecification, ViewElement, isViewElementObjectOrList, ViewElementBase, isViewElementReference } from "../models/uiModels";
+import { ViewSpecification, ViewElement, isViewElementObjectOrList, ViewElementBase, isViewElementReference, ViewElementChoise, ViewElementBinary, ViewElementString, isViewElementString, isViewElementNumber, ViewElementNumber, Expression, YangRange, ViewElementUnion } from "../models/uiModels";
import { yangService } from "../services/yangService";
export const splitVPath = (vPath: string, vPathParser: RegExp): RegExpMatchArray[] => {
@@ -238,6 +256,8 @@
export class YangParser {
private _groupingsToResolve: (() => void)[] = [];
private _identityToResolve: (() => void)[] = [];
+ private _unionsToResolve: (() => void)[] = [];
+
private _modules: { [name: string]: Module } = {};
private _views: ViewSpecification[] = [{
@@ -248,7 +268,9 @@
parentView: "0",
title: "root",
elements: {},
- }];
+ }];
+
+ public static ResolveStack = Symbol("ResolveStack");
constructor() {
@@ -311,12 +333,12 @@
const revisions = this.extractNodes(rootStatement, "revision");
module.revisions = {
...module.revisions,
- ...revisions.reduce<{ [version: string]: { }}>((acc, version) => {
+ ...revisions.reduce<{ [version: string]: {} }>((acc, version) => {
if (!version.arg) {
throw new Error(`Module [${module.name}] has a version w/o version number.`);
}
const description = this.extractValue(version, "description");
- const reference = this.extractValue(version,"reference");
+ const reference = this.extractValue(version, "reference");
acc[version.arg] = {
description,
reference,
@@ -345,10 +367,10 @@
const imports = this.extractNodes(rootStatement, "import");
module.imports = {
...module.imports,
- ...imports.reduce < { [key: string]: string }>((acc, imp) => {
+ ...imports.reduce<{ [key: string]: string }>((acc, imp) => {
const prefix = imp.sub && imp.sub.filter(s => s.key === "prefix");
if (!imp.arg) {
- throw new Error(`Module [${module.name}] has an import with neither name nor prefix.`);
+ throw new Error(`Module [${module.name}] has an import with neither name nor prefix.`);
}
acc[prefix && prefix.length === 1 && prefix[0].arg || imp.arg] = imp.arg;
return acc;
@@ -389,8 +411,15 @@
}
public postProcess() {
- // process all groupings
+
// execute all post processes like resolving in propper order
+ this._unionsToResolve.forEach(cb => {
+ try { cb(); } catch (error) {
+ console.warn(error.message);
+ }
+ });
+
+ // process all groupings
this._groupingsToResolve.forEach(cb => {
try { cb(); } catch (error) {
console.warn(`Error resolving: [${error.message}]`);
@@ -418,7 +447,7 @@
});
// process Identities
- const traverseIdentity = (identities : Identity[]) => {
+ const traverseIdentity = (identities: Identity[]) => {
const result: Identity[] = [];
for (let identity of identities) {
if (identity.children && identity.children.length > 0) {
@@ -438,7 +467,7 @@
const identity = module.identities[idKey];
if (identity.base != null) {
const base = this.resolveIdentity(identity.base, module);
- base.children?.push(identity);
+ base.children ?.push(identity);
} else {
baseIdentites.push(identity);
}
@@ -455,7 +484,6 @@
});
};
-
private _nextId = 1;
private get nextId() {
return this._nextId++;
@@ -478,7 +506,7 @@
private extractTypeDefinitions(statement: Statement, module: Module, currentPath: string): void {
const typedefs = this.extractNodes(statement, "typedef");
typedefs && typedefs.forEach(def => {
- if (! def.arg) {
+ if (!def.arg) {
throw new Error(`Module: [${module.name}]. Found typefed without name.`);
}
module.typedefs[def.arg] = this.getViewElement(def, module, 0, currentPath, false);
@@ -562,13 +590,14 @@
// extract conditions
const ifFeature = this.extractValue(statement, "if-feature");
const whenCondition = this.extractValue(statement, "when");
+ if (whenCondition) console.warn("Found in [" + module.name + "]" + currentPath + " when: " + whenCondition);
// extract all container
const container = this.extractNodes(statement, "container");
if (container && container.length > 0) {
subViews.push(...container.reduce<ViewSpecification[]>((acc, cur) => {
if (!cur.arg) {
- throw new Error(`Module: [${module.name}]. Found container without name.`);
+ throw new Error(`Module: [${module.name}]${currentPath}. Found container without name.`);
}
const [currentView, subViews] = this.extractSubViews(cur, currentId, module, `${currentPath}/${module.name}:${cur.arg}`);
elements.push({
@@ -589,11 +618,11 @@
if (lists && lists.length > 0) {
subViews.push(...lists.reduce<ViewSpecification[]>((acc, cur) => {
if (!cur.arg) {
- throw new Error(`Module: [${module.name}]. Found list without name.`);
+ throw new Error(`Module: [${module.name}]${currentPath}. Found list without name.`);
}
const key = this.extractValue(cur, "key") || undefined;
if (config && !key) {
- throw new Error(`Module: [${module.name}]. Found configurable list without key.`);
+ throw new Error(`Module: [${module.name}]${currentPath}. Found configurable list without key.`);
}
const [currentView, subViews] = this.extractSubViews(cur, currentId, module, `${currentPath}/${module.name}:${cur.arg}`);
elements.push({
@@ -635,10 +664,70 @@
const choiceStms = this.extractNodes(statement, "choice");
if (choiceStms && choiceStms.length > 0) {
- for (let i = 0; i < choiceStms.length; ++i) {
- const cases = this.extractNodes(choiceStms[i], "case");
- console.warn(`Choice found ${choiceStms[i].arg}::${cases.map(c => c.arg).join(";")}`, choiceStms[i]);
- }
+ elements.push(...choiceStms.reduce<ViewElementChoise[]>((accChoise, curChoise) => {
+ if (!curChoise.arg) {
+ throw new Error(`Module: [${module.name}]${currentPath}. Found choise without name.`);
+ }
+ // extract all cases like containers
+ const cases: { id: string, label: string, description?: string, elements: { [name: string]: ViewElement } }[] = [];
+ const caseStms = this.extractNodes(curChoise, "case");
+ if (caseStms && caseStms.length > 0) {
+ cases.push(...caseStms.reduce((accCase, curCase) => {
+ if (!curCase.arg) {
+ throw new Error(`Module: [${module.name}]${currentPath}/${curChoise.arg}. Found case without name.`);
+ }
+ const description = this.extractValue(curCase, "description") || undefined;
+ const [caseView, caseSubViews] = this.extractSubViews(curCase, parentId, module, `${currentPath}/${module.name}:${curChoise.arg}`);
+ subViews.push(caseView, ...caseSubViews);
+
+ const caseDef: { id: string, label: string, description?: string, elements: { [name: string]: ViewElement } } = {
+ id: parentId === 0 ? `${module.name}:${curCase.arg}` : curCase.arg,
+ label: curCase.arg,
+ description: description,
+ elements: caseView.elements
+ };
+ accCase.push(caseDef);
+ return accCase;
+ }, [] as { id: string, label: string, description?: string, elements: { [name: string]: ViewElement } }[]));
+ }
+
+ // extract all simple cases (one case per leaf, container, etc.)
+ const [choiseView, choiseSubViews] = this.extractSubViews(curChoise, parentId, module, `${currentPath}/${module.name}:${curChoise.arg}`);
+ subViews.push(choiseView, ...choiseSubViews);
+ cases.push(...Object.keys(choiseView.elements).reduce((accElm, curElm) => {
+ const elm = choiseView.elements[curElm];
+ const caseDef: { id: string, label: string, description?: string, elements: { [name: string]: ViewElement } } = {
+ id: elm.id,
+ label: elm.label,
+ description: elm.description,
+ elements: { [elm.id]: elm }
+ };
+ accElm.push(caseDef);
+ return accElm;
+ }, [] as { id: string, label: string, description?: string, elements: { [name: string]: ViewElement } }[]));
+
+ const description = this.extractValue(curChoise, "description") || undefined;
+ const configValue = this.extractValue(curChoise, "config");
+ const config = configValue == null ? true : configValue.toLocaleLowerCase() !== "false";
+
+ const mandatory = this.extractValue(curChoise, "mandatory") === "true" || false;
+
+ const element: ViewElementChoise = {
+ uiType: "choise",
+ id: parentId === 0 ? `${module.name}:${curChoise.arg}` : curChoise.arg,
+ label: curChoise.arg,
+ config: config,
+ mandatory: mandatory,
+ description: description,
+ cases: cases.reduce((acc, cur) => {
+ acc[cur.id] = cur;
+ return acc;
+ }, {} as { [name: string]: { id: string, label: string, description?: string, elements: { [name: string]: ViewElement } } })
+ };
+
+ accChoise.push(element);
+ return accChoise;
+ }, []));
}
const rpcs = this.extractNodes(statement, "rpc");
@@ -707,17 +796,74 @@
return [viewSpec, subViews];
}
+ // https://tools.ietf.org/html/rfc7950#section-9.3.4
+ private static decimalRange = [
+ { min: -9223372036854775808, max: 9223372036854775807 },
+ { min: -922337203685477580.8, max: 922337203685477580.7 },
+ { min: -92233720368547758.08, max: 92233720368547758.07 },
+ { min: -9223372036854775.808, max: 9223372036854775.807 },
+ { min: -922337203685477.5808, max: 922337203685477.5807 },
+ { min: -92233720368547.75808, max: 92233720368547.75807 },
+ { min: -9223372036854.775808, max: 9223372036854.775807 },
+ { min: -922337203685.4775808, max: 922337203685.4775807 },
+ { min: -92233720368.54775808, max: 92233720368.54775807 },
+ { min: -9223372036.854775808, max: 9223372036.854775807 },
+ { min: -922337203.6854775808, max: 922337203.6854775807 },
+ { min: -92233720.36854775808, max: 92233720.36854775807 },
+ { min: -9223372.036854775808, max: 9223372.036854775807 },
+ { min: -922337.2036854775808, max: 922337.2036854775807 },
+ { min: -92233.72036854775808, max: 92233.72036854775807 },
+ { min: -9223.372036854775808, max: 9223.372036854775807 },
+ { min: -922.3372036854775808, max: 922.3372036854775807 },
+ { min: -92.23372036854775808, max: 92.23372036854775807 },
+ { min: -9.223372036854775808, max: 9.223372036854775807 },
+ ];
+
/** Extracts the UI View from the type in the cur statement. */
private getViewElement(cur: Statement, module: Module, parentId: number, currentPath: string, isList: boolean): ViewElement {
const type = this.extractValue(cur, "type");
const defaultVal = this.extractValue(cur, "default") || undefined;
const description = this.extractValue(cur, "description") || undefined;
- const rangeMatch = this.extractValue(cur, "range", /^(\d+)\.\.(\d+)/) || undefined;
const configValue = this.extractValue(cur, "config");
const config = configValue == null ? true : configValue.toLocaleLowerCase() !== "false";
+ const extractRange = (min: number, max: number, property: string = "range"): { expression: Expression<YangRange> | undefined, min: number, max: number } => {
+ const ranges = this.extractValue(this.extractNodes(cur, "type")[0]!, property) || undefined;
+ const range = ranges ?.replace(/min/i, String(min)).replace(/max/i, String(max)).split("|").map(r => {
+ const [minStr, maxStr] = r.split('..');
+ const minValue = Number(minStr);
+ const maxValue = Number(maxStr);
+
+ if (minValue > min) min = minValue;
+ if (maxValue < max) max = maxValue;
+
+ return {
+ min: minValue,
+ max: maxValue
+ };
+ });
+ return {
+ min: min,
+ max: max,
+ expression: range && range.length === 1
+ ? range[0]
+ : range && range.length > 1
+ ? { operation: "OR", arguments: range }
+ : undefined
+ }
+ };
+
+ const extractPattern = (): Expression<RegExp> | undefined => {
+ const pattern = this.extractNodes(this.extractNodes(cur, "type")[0]!, "pattern").map(p => p.arg!).filter(p => !!p).map(p => `^${p}$`);
+ return pattern && pattern.length == 1
+ ? new RegExp(pattern[0])
+ : pattern && pattern.length > 1
+ ? { operation: "AND", arguments: pattern.map(p => new RegExp(p)) }
+ : undefined;
+ }
+
const mandatory = this.extractValue(cur, "mandatory") === "true" || false;
if (!cur.arg) {
@@ -729,7 +875,7 @@
}
const element: ViewElementBase = {
- id: parentId === 0 ? `${module.name}:${cur.arg}`: cur.arg,
+ id: parentId === 0 ? `${module.name}:${cur.arg}` : cur.arg,
label: cur.arg,
config: config,
mandatory: mandatory,
@@ -739,10 +885,12 @@
};
if (type === "string") {
+ const length = extractRange(0, +18446744073709551615, "length");
return ({
...element,
uiType: "string",
- pattern: this.extractNodes(this.extractNodes(cur, "type")[0]!, "pattern").map(p => p.arg!).filter(p => !!p),
+ length: length.expression,
+ pattern: extractPattern(),
});
} else if (type === "boolean") {
return ({
@@ -750,106 +898,109 @@
uiType: "boolean"
});
} else if (type === "uint8") {
+ const range = extractRange(0, +255);
return ({
...element,
uiType: "number",
- min: rangeMatch ? Number(rangeMatch[0]) : 0,
- max: rangeMatch ? Number(rangeMatch[1]) : +255,
+ range: range.expression,
+ min: range.min,
+ max: range.max,
units: this.extractValue(cur, "units") || undefined,
format: this.extractValue(cur, "format") || undefined,
});
} else if (type === "uint16") {
+ const range = extractRange(0, +65535);
return ({
...element,
uiType: "number",
- min: rangeMatch ? Number(rangeMatch[0]) : 0,
- max: rangeMatch ? Number(rangeMatch[1]) : +65535,
+ range: range.expression,
+ min: range.min,
+ max: range.max,
units: this.extractValue(cur, "units") || undefined,
format: this.extractValue(cur, "format") || undefined,
});
} else if (type === "uint32") {
+ const range = extractRange(0, +4294967295);
return ({
...element,
uiType: "number",
- min: rangeMatch ? Number(rangeMatch[0]) : 0,
- max: rangeMatch ? Number(rangeMatch[1]) : +4294967295,
+ range: range.expression,
+ min: range.min,
+ max: range.max,
units: this.extractValue(cur, "units") || undefined,
format: this.extractValue(cur, "format") || undefined,
});
} else if (type === "uint64") {
+ const range = extractRange(0, +18446744073709551615);
return ({
...element,
uiType: "number",
- min: rangeMatch ? Number(rangeMatch[0]) : 0,
- max: rangeMatch ? Number(rangeMatch[1]) : +18446744073709551615,
+ range: range.expression,
+ min: range.min,
+ max: range.max,
units: this.extractValue(cur, "units") || undefined,
format: this.extractValue(cur, "format") || undefined,
});
} else if (type === "int8") {
+ const range = extractRange(-128, +127);
return ({
...element,
uiType: "number",
- min: rangeMatch ? Number(rangeMatch[0]) : -128,
- max: rangeMatch ? Number(rangeMatch[1]) : +127,
+ range: range.expression,
+ min: range.min,
+ max: range.max,
units: this.extractValue(cur, "units") || undefined,
format: this.extractValue(cur, "format") || undefined,
});
} else if (type === "int16") {
+ const range = extractRange(-32768, +32767);
return ({
...element,
uiType: "number",
- min: rangeMatch ? Number(rangeMatch[0]) : -32768,
- max: rangeMatch ? Number(rangeMatch[1]) : +32767,
+ range: range.expression,
+ min: range.min,
+ max: range.max,
units: this.extractValue(cur, "units") || undefined,
format: this.extractValue(cur, "format") || undefined,
});
} else if (type === "int32") {
+ const range = extractRange(-2147483648, +2147483647);
return ({
...element,
uiType: "number",
- min: rangeMatch ? Number(rangeMatch[0]) : -2147483648,
- max: rangeMatch ? Number(rangeMatch[1]) : +2147483647,
+ range: range.expression,
+ min: range.min,
+ max: range.max,
units: this.extractValue(cur, "units") || undefined,
format: this.extractValue(cur, "format") || undefined,
});
} else if (type === "int64") {
+ const range = extractRange(-9223372036854775808, +9223372036854775807);
return ({
...element,
uiType: "number",
- min: rangeMatch ? Number(rangeMatch[0]) : 0,
- max: rangeMatch ? Number(rangeMatch[1]) : +18446744073709551615,
+ range: range.expression,
+ min: range.min,
+ max: range.max,
units: this.extractValue(cur, "units") || undefined,
format: this.extractValue(cur, "format") || undefined,
});
- } else if (type === "decimal16") {
- return ({
- ...element,
- uiType: "number",
- min: rangeMatch ? Number(rangeMatch[0]) : 0,
- max: rangeMatch ? Number(rangeMatch[1]) : +18446744073709551615,
- units: this.extractValue(cur, "units") || undefined,
- format: this.extractValue(cur, "format") || undefined,
- fDigits: Number(this.extractValue(this.extractNodes(cur, "type")[0]!, "fraction-digits")) || -1
- });
- } else if (type === "decimal32") {
- return ({
- ...element,
- uiType: "number",
- min: rangeMatch ? Number(rangeMatch[0]) : 0,
- max: rangeMatch ? Number(rangeMatch[1]) : +18446744073709551615,
- units: this.extractValue(cur, "units") || undefined,
- format: this.extractValue(cur, "format") || undefined,
- fDigits: Number(this.extractValue(this.extractNodes(cur, "type")[0]!, "fraction-digits")) || -1
- });
} else if (type === "decimal64") {
+ // decimalRange
+ const fDigits = Number(this.extractValue(this.extractNodes(cur, "type")[0]!, "fraction-digits")) || -1;
+ if (fDigits === -1) {
+ throw new Error(`Module: [${module.name}][${currentPath}][${cur.arg}]. Found decimal64 with invalid fraction-digits.`);
+ }
+ const range = extractRange(YangParser.decimalRange[fDigits].min, YangParser.decimalRange[fDigits].max);
return ({
...element,
uiType: "number",
- min: rangeMatch ? Number(rangeMatch[0]) : 0,
- max: rangeMatch ? Number(rangeMatch[1]) : +18446744073709551615,
+ fDigits: fDigits,
+ range: range.expression,
+ min: range.min,
+ max: range.max,
units: this.extractValue(cur, "units") || undefined,
format: this.extractValue(cur, "format") || undefined,
- fDigits: Number(this.extractValue(this.extractNodes(cur, "type")[0]!, "fraction-digits")) || -1
});
} else if (type === "enumeration") {
const typeNode = this.extractNodes(cur, "type")[0]!;
@@ -881,7 +1032,7 @@
}
const refPath = this.resolveReferencePath(vPath, module);
const resolve = this.resolveReference.bind(this);
- const res : ViewElement = {
+ const res: ViewElement = {
...element,
uiType: "reference",
referencePath: refPath,
@@ -912,7 +1063,7 @@
options: []
};
this._identityToResolve.push(() => {
- const identity : Identity = this.resolveIdentity(base, module);
+ const identity: Identity = this.resolveIdentity(base, module);
if (!identity) {
throw new Error(`Module: [${module.name}][${currentPath}][${cur.arg}]. Could not resolve identity [${base}].`);
}
@@ -925,7 +1076,7 @@
description: val.description
}));
});
- return res ;
+ return res;
} else if (type === "empty") {
// todo: ❗ handle empty ⚡
/* 9.11. The empty Built-In Type
@@ -939,18 +1090,41 @@
} else if (type === "union") {
// todo: ❗ handle union ⚡
/* 9.12. The union Built-In Type */
- console.warn(`found type: union in [${module.name}][${currentPath}][${element.label}]`);
- return {
+ const typeNode = this.extractNodes(cur, "type")[0]!;
+ const typeNodes = this.extractNodes(typeNode, "type");
+
+ const resultingElement = {
...element,
- uiType: "string",
+ uiType: "union",
+ elements: []
+ } as ViewElementUnion;
+
+ const resolveUnion = () => {
+ resultingElement.elements.push(...typeNodes.map(node => {
+ const stm: Statement = {
+ ...cur,
+ sub: [
+ ...(cur.sub ?.filter(s => s.key !== "type") || []),
+ node
+ ]
+ };
+ return {
+ ...this.getViewElement(stm, module, parentId, currentPath, isList),
+ id: node.arg!
+ };
+ }));
};
+
+ this._unionsToResolve.push(resolveUnion);
+
+ return resultingElement;
} else if (type === "bits") {
const typeNode = this.extractNodes(cur, "type")[0]!;
const bitNodes = this.extractNodes(typeNode, "bit");
return {
...element,
uiType: "bits",
- flags: bitNodes.reduce<{[name: string]: number | undefined; }>((acc, bitNode) => {
+ flags: bitNodes.reduce<{ [name: string]: number | undefined; }>((acc, bitNode) => {
if (!bitNode.arg) {
throw new Error(`Module: [${module.name}][${currentPath}][${cur.arg}]. Found bit without name.`);
}
@@ -961,25 +1135,60 @@
}, {})
};
} else if (type === "binary") {
- const typeNode = this.extractNodes(cur, "type")[0]!;
- const length = Number(this.extractValue(typeNode, "length"));
return {
...element,
uiType: "binary",
- length: length === length ? length : undefined
+ length: extractRange(0, +18446744073709551615, "length"),
};
} else {
// not a build in type, have to resolve type
- const typeRef = this.resolveType(type, module);
+ let typeRef = this.resolveType(type, module);
if (typeRef == null) console.error(new Error(`Could not resolve type ${type} in [${module.name}][${currentPath}].`));
+
+ if (isViewElementString(typeRef)) {
+ typeRef = this.resolveStringType(typeRef, extractPattern(), extractRange(0, +18446744073709551615));
+
+ } else if (isViewElementNumber(typeRef)) {
+ typeRef = this.resolveNumberType(typeRef, extractRange(typeRef.min, typeRef.max));
+ }
+
return ({
...typeRef,
...element,
- description: description
+ description: description,
}) as ViewElement;
}
}
+ private resolveStringType(parentElement: ViewElementString, pattern: Expression<RegExp> | undefined, length: { expression: Expression<YangRange> | undefined, min: number, max: number }) {
+ return {
+ ...parentElement,
+ pattern: pattern != null && parentElement.pattern
+ ? { operation: "AND", arguments: [pattern, parentElement.pattern] }
+ : parentElement.pattern
+ ? parentElement.pattern
+ : pattern,
+ length: length.expression != null && parentElement.length
+ ? { operation: "AND", arguments: [length.expression, parentElement.length] }
+ : parentElement.length
+ ? parentElement.length
+ : length ?.expression,
+ } as ViewElementString;
+ }
+
+ private resolveNumberType(parentElement: ViewElementNumber, range: { expression: Expression<YangRange> | undefined, min: number, max: number }) {
+ return {
+ ...parentElement,
+ range: range.expression != null && parentElement.range
+ ? { operation: "AND", arguments: [range.expression, parentElement.range] }
+ : parentElement.range
+ ? parentElement.range
+ : range,
+ min: range.min,
+ max: range.max,
+ } as ViewElementNumber;
+ }
+
private resolveReferencePath(vPath: string, module: Module) {
const vPathParser = /(?:(?:([^\/\:]+):)?([^\/]+))/g // 1 = opt: namespace / 2 = property
return vPath.replace(vPathParser, (_, ns, property) => {
@@ -988,10 +1197,9 @@
});
}
-
private resolveReference(vPath: string, currentPath: string) {
const vPathParser = /(?:(?:([^\/\[\]\:]+):)?([^\/\[\]]+)(\[[^\]]+\])?)/g // 1 = opt: namespace / 2 = property / 3 = opt: indexPath
- let element : ViewElement | null = null;
+ let element: ViewElement | null = null;
let moduleName = "";
const vPathParts = splitVPath(vPath, vPathParser).map(p => ({ ns: p[1], property: p[2], ind: p[3] }));
@@ -999,7 +1207,7 @@
? splitVPath(currentPath, vPathParser).map(p => ({ ns: p[1], property: p[2], ind: p[3] }))
: [];
- for (let i = 0; i < vPathParts.length; ++i){
+ for (let i = 0; i < vPathParts.length; ++i) {
const vPathPart = vPathParts[i];
if (vPathPart.property === "..") {
resultPathParts.pop();
@@ -1009,26 +1217,26 @@
}
// resolve element by path
- for (let j = 0; j < resultPathParts.length;++j){
+ for (let j = 0; j < resultPathParts.length; ++j) {
const pathPart = resultPathParts[j];
- if (j===0) {
+ if (j === 0) {
+ moduleName = pathPart.ns;
+ const rootModule = this._modules[moduleName];
+ if (!rootModule) throw new Error("Could not resolve module [" + moduleName + "].\r\n" + vPath);
+ element = rootModule.elements[`${pathPart.ns}:${pathPart.property}`];
+ } else if (element && isViewElementObjectOrList(element)) {
+ const view: ViewSpecification = this._views[+element.viewId];
+ if (moduleName !== pathPart.ns) {
moduleName = pathPart.ns;
- const rootModule = this._modules[moduleName];
- if (!rootModule) throw new Error("Could not resolve module [" + moduleName +"].\r\n" + vPath);
- element = rootModule.elements[`${pathPart.ns}:${pathPart.property}`];
- } else if (element && isViewElementObjectOrList(element)) {
- const view: ViewSpecification = this._views[+element.viewId];
- if (moduleName !== pathPart.ns) {
- moduleName = pathPart.ns;
- element = view.elements[`${moduleName}:${pathPart.property}`];
- } else {
- element = view.elements[pathPart.property] || view.elements[`${moduleName}:${pathPart.property}`];
- }
+ element = view.elements[`${moduleName}:${pathPart.property}`];
} else {
- throw new Error("Could not resolve reference.\r\n" + vPath);
+ element = view.elements[pathPart.property] || view.elements[`${moduleName}:${pathPart.property}`];
}
- if (!element) throw new Error("Could not resolve path [" + pathPart.property + "] in ["+ currentPath +"] \r\n" + vPath);
+ } else {
+ throw new Error("Could not resolve reference.\r\n" + vPath);
}
+ if (!element) throw new Error("Could not resolve path [" + pathPart.property + "] in [" + currentPath + "] \r\n" + vPath);
+ }
return element;
}
diff --git a/sdnr/wt/odlux/apps/configurationApp/tsconfig.json b/sdnr/wt/odlux/apps/configurationApp/tsconfig.json
index b0c9b42..c950056 100644
--- a/sdnr/wt/odlux/apps/configurationApp/tsconfig.json
+++ b/sdnr/wt/odlux/apps/configurationApp/tsconfig.json
@@ -4,7 +4,7 @@
"outDir": "./dist",
"sourceMap": true,
"forceConsistentCasingInFileNames": true,
- "allowSyntheticDefaultImports": false,
+ "allowSyntheticDefaultImports": true,
"allowUnreachableCode": false,
"allowUnusedLabels": false,
"noFallthroughCasesInSwitch": true,
diff --git a/sdnr/wt/odlux/apps/connectApp/pom.xml b/sdnr/wt/odlux/apps/connectApp/pom.xml
index cfc7720..619c02a 100644
--- a/sdnr/wt/odlux/apps/connectApp/pom.xml
+++ b/sdnr/wt/odlux/apps/connectApp/pom.xml
@@ -14,7 +14,7 @@
<version>0.7.1-SNAPSHOT</version>
<packaging>bundle</packaging>
- <name>ccsdk-features :: ${project.artifactId}</name>
+ <name>sdnr-wt-odlux-app-connectApp</name>
<licenses>
<license>
<name>Apache License, Version 2.0</name>
@@ -103,10 +103,10 @@
</executions>
</plugin>
<plugin>
- <groupId>de.jacks-it-lab</groupId>
- <artifactId>frontend-maven-plugin</artifactId>
- <version>1.7.2</version>
- <executions>
+ <groupId>de.jacks-it-lab</groupId>
+ <artifactId>frontend-maven-plugin</artifactId>
+ <version>1.7.2</version>
+ <executions>
<execution>
<id>install node and yarn</id>
<goals>
diff --git a/sdnr/wt/odlux/apps/connectApp/src/actions/commonNetworkElementsActions.ts b/sdnr/wt/odlux/apps/connectApp/src/actions/commonNetworkElementsActions.ts
index bf4778b..a6d81c1 100644
--- a/sdnr/wt/odlux/apps/connectApp/src/actions/commonNetworkElementsActions.ts
+++ b/sdnr/wt/odlux/apps/connectApp/src/actions/commonNetworkElementsActions.ts
@@ -23,7 +23,7 @@
import { Dispatch } from '../../../../framework/src/flux/store';
import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
-import { networkElementsReloadAction } from '../handlers/networkElementsHandler';
+import { networkElementsReloadAction, networkElementsReloadActionAsync } from '../handlers/networkElementsHandler';
import { connectionStatusLogReloadAction } from '../handlers/connectionStatusLogHandler';
import { PanelId } from '../models/panelId';
@@ -38,7 +38,7 @@
}
export class AddWebUriList extends Action {
- constructor(public element: guiCutThrough[], public knownElements: string[]) {
+ constructor(public searchedElements: guiCutThrough[], public notSearchedElements: string[], public newlySearchedElements?: string[]) {
super();
}
}
@@ -53,58 +53,65 @@
return new RemoveWebUri(nodeId);
}
+export class SetWeburiSearchBusy extends Action {
+ constructor(public isbusy: boolean) {
+ super();
+ }
+}
+
let isBusy = false;
-export const findWebUrisForGuiCutThroughAsyncAction = (dispatcher: Dispatch) => (networkElements: NetworkElementConnection[], knownElements: string[]) => {
+export const findWebUrisForGuiCutThroughAsyncAction = (networkElements: NetworkElementConnection[]) => async (dispatcher: Dispatch, getState: () => IApplicationStoreState) => {
// keep method from executing simultanously; state not used because change of iu isn't needed
if (isBusy)
return;
isBusy = true;
- const nodeIds = networkElements.map(element => { return element.id as string });
+ const { connect: { guiCutThrough } } = getState();
- if (knownElements.length > 0) {
+ let notConnectedElements: string[] = [];
+ let elementsToSearch: string[] = [];
+ let prevFoundElements: string[] = [];
- let elementsToSearch: string[] = [];
- nodeIds.forEach(element => {
- // find index of nodeId
- const index = knownElements.indexOf(element);
+ networkElements.forEach(item => {
+ const id = item.id as string;
+ if (item.status === "Connected") {
- // if element dosen't exist, add it to list
- if (index === -1) {
- elementsToSearch.push(element)
+ // element is connected and is added to search list, if it doesn't exist already
+ const exists = guiCutThrough.searchedElements.filter(element => element.nodeId === id).length > 0;
+ if (!exists) {
+ elementsToSearch.push(id);
+
+ //element was found previously, but not searched for a weburi
+ if (guiCutThrough.notSearchedElements.length > 0 && guiCutThrough.notSearchedElements.includes(id)) {
+ prevFoundElements.push(id);
+ }
}
- });
-
- // if new elements were found, search for weburi
- if (elementsToSearch.length > 0) {
- const foundWebUris = connectService.getAllWebUriExtensionsForNetworkElementListAsync(elementsToSearch);
- foundWebUris.then(result => {
- dispatcher(new AddWebUriList(result, elementsToSearch));
- isBusy = false;
- })
-
- } else {
- isBusy = false;
}
+ else {
+ // element isn't connected and cannot be searched for a weburi
+ if (!guiCutThrough.notSearchedElements.includes(id)) {
+ notConnectedElements.push(item.id as string);
+ }
+ }
+ });
- } else {
- connectService.getAllWebUriExtensionsForNetworkElementListAsync(nodeIds).then(result => {
- dispatcher(new AddWebUriList(result, nodeIds));
- isBusy = false;
- })
+ if (elementsToSearch.length > 0 || notConnectedElements.length > 0) {
+ const result = await connectService.getAllWebUriExtensionsForNetworkElementListAsync(elementsToSearch);
+ dispatcher(new AddWebUriList(result, notConnectedElements, prevFoundElements));
}
+ isBusy = false;
}
export const setPanelAction = (panelId: PanelId) => {
return new SetPanelAction(panelId);
}
-export const updateCurrentViewAsyncAction = () => (dispatch: Dispatch, getState: () => IApplicationStoreState) => {
+export const updateCurrentViewAsyncAction = () => async (dispatch: Dispatch, getState: () => IApplicationStoreState) => {
const { connect: { currentOpenPanel } } = getState();
if (currentOpenPanel === "NetworkElements") {
- return dispatch(networkElementsReloadAction);
+ return await dispatch(networkElementsReloadActionAsync);
}
else {
return dispatch(connectionStatusLogReloadAction);
diff --git a/sdnr/wt/odlux/apps/connectApp/src/actions/networkElementsActions.ts b/sdnr/wt/odlux/apps/connectApp/src/actions/networkElementsActions.ts
index 1a86f94..1e569a1 100644
--- a/sdnr/wt/odlux/apps/connectApp/src/actions/networkElementsActions.ts
+++ b/sdnr/wt/odlux/apps/connectApp/src/actions/networkElementsActions.ts
@@ -43,7 +43,7 @@
const res = await connectService.deleteNetworkElement(element);
}
else {
- const res = await connectService.updateNetworkElement(element);
+ const res = await connectService.updateNetworkElement(element);
}
dispatch(updateCurrentViewAsyncAction());
dispatch(new AddSnackbarNotification({ message: `Successfully modified [${element.id}]`, options: { variant: 'success' } }));
@@ -54,7 +54,7 @@
export const removeNetworkElementAsyncActionCreator = (element: UpdateNetworkElement) => async (dispatch: Dispatch) => {
const res = await connectService.deleteNetworkElement(element);
await dispatch(unmountNetworkElementAsyncActionCreator(element && element.id));
- dispatch(updateCurrentViewAsyncAction());
+ await dispatch(updateCurrentViewAsyncAction());
};
diff --git a/sdnr/wt/odlux/apps/connectApp/src/components/editNetworkElementDialog.tsx b/sdnr/wt/odlux/apps/connectApp/src/components/editNetworkElementDialog.tsx
index 1e1f115..ce7f48c 100644
--- a/sdnr/wt/odlux/apps/connectApp/src/components/editNetworkElementDialog.tsx
+++ b/sdnr/wt/odlux/apps/connectApp/src/components/editNetworkElementDialog.tsx
@@ -60,8 +60,8 @@
await dispatcher.dispatch(editNetworkElementAsyncActionCreator(element));
await dispatcher.dispatch(mountNetworkElementAsyncActionCreator(mountElement));
},
- removeNetworkElement: (element: UpdateNetworkElement) => {
- dispatcher.dispatch(removeNetworkElementAsyncActionCreator(element));
+ removeNetworkElement: async (element: UpdateNetworkElement) => {
+ await dispatcher.dispatch(removeNetworkElementAsyncActionCreator(element));
dispatcher.dispatch(removeWebUriAction(element.id));
}
});
@@ -158,7 +158,7 @@
const setting = settings[this.props.mode];
return (
<Dialog open={this.props.mode !== EditNetworkElementDialogMode.None}>
- <DialogTitle id="form-dialog-title">{setting.dialogTitle}</DialogTitle>
+ <DialogTitle id="form-dialog-title" aria-label={`${setting.dialogTitle.replace(/ /g, "-").toLowerCase()}-dialog`}>{setting.dialogTitle}</DialogTitle>
<DialogContent>
<DialogContentText>
{setting.dialogDescription}
@@ -179,7 +179,7 @@
</FormControl>
</DialogContent>
<DialogActions>
- <Button onClick={(event) => {
+ <Button aria-label="dialog-confirm-button" onClick={(event) => {
this.onApply({
isRequired: this.state.isRequired,
id: this.state.nodeId,
@@ -192,7 +192,7 @@
event.preventDefault();
event.stopPropagation();
}} > {setting.applyButtonText} </Button>
- <Button onClick={(event) => {
+ <Button aria-label="dialog-cancel-button" onClick={(event) => {
this.onCancel();
event.preventDefault();
event.stopPropagation();
diff --git a/sdnr/wt/odlux/apps/connectApp/src/handlers/connectAppRootHandler.ts b/sdnr/wt/odlux/apps/connectApp/src/handlers/connectAppRootHandler.ts
index 1440599..23a8014 100644
--- a/sdnr/wt/odlux/apps/connectApp/src/handlers/connectAppRootHandler.ts
+++ b/sdnr/wt/odlux/apps/connectApp/src/handlers/connectAppRootHandler.ts
@@ -21,7 +21,7 @@
import { INetworkElementsState, networkElementsActionHandler } from './networkElementsHandler';
import { IConnectionStatusLogState, connectionStatusLogActionHandler } from './connectionStatusLogHandler';
import { IInfoNetworkElementsState, infoNetworkElementsActionHandler } from './infoNetworkElementHandler';
-import { SetPanelAction, AddWebUriList, RemoveWebUri } from '../actions/commonNetworkElementsActions';
+import { SetPanelAction, AddWebUriList, RemoveWebUri, SetWeburiSearchBusy } from '../actions/commonNetworkElementsActions';
import { PanelId } from '../models/panelId';
import { guiCutThrough } from '../models/guiCutTrough';
@@ -41,26 +41,33 @@
}
interface guiCutThroughState {
- availableWebUris: guiCutThrough[];
- knownElements: string[];
+ searchedElements: guiCutThrough[];
+ notSearchedElements: string[];
}
-const guiCutThroughHandler: IActionHandler<guiCutThroughState> = (state = { availableWebUris: [], knownElements: [] }, action) => {
+const guiCutThroughHandler: IActionHandler<guiCutThroughState> = (state = { searchedElements: [], notSearchedElements: [] }, action) => {
if (action instanceof AddWebUriList) {
- let knownElements: string[];
- let availableWebUris: guiCutThrough[];
+ let notSearchedElements: string[];
+ let searchedElements: guiCutThrough[];
- knownElements = state.knownElements.concat(action.knownElements);
+ notSearchedElements = state.notSearchedElements.concat(action.notSearchedElements);
- availableWebUris = state.availableWebUris.concat(action.element);
+ //remove elements, which were just searched
+ if (action.newlySearchedElements) {
+ action.newlySearchedElements.forEach(item => {
+ notSearchedElements = notSearchedElements.filter(id => id !== item);
+ })
+ }
- state = { availableWebUris: availableWebUris, knownElements: knownElements }
+ searchedElements = state.searchedElements.concat(action.searchedElements);
+
+ state = { searchedElements: searchedElements, notSearchedElements: notSearchedElements }
} else if (action instanceof RemoveWebUri) {
const nodeId = action.element;
- const webUris = state.availableWebUris.filter(item => item.nodeId !== nodeId);
- const knownElements = state.knownElements.filter(item => item !== nodeId);
- state = { knownElements: knownElements, availableWebUris: webUris };
+ const webUris = state.searchedElements.filter(item => item.nodeId !== nodeId);
+ const knownElements = state.notSearchedElements.filter(item => item !== nodeId);
+ state = { notSearchedElements: knownElements, searchedElements: webUris };
}
return state;
}
diff --git a/sdnr/wt/odlux/apps/connectApp/src/handlers/networkElementsHandler.ts b/sdnr/wt/odlux/apps/connectApp/src/handlers/networkElementsHandler.ts
index 78c7000..4fe858c 100644
--- a/sdnr/wt/odlux/apps/connectApp/src/handlers/networkElementsHandler.ts
+++ b/sdnr/wt/odlux/apps/connectApp/src/handlers/networkElementsHandler.ts
@@ -31,11 +31,13 @@
createActions: createNetworkElementsActions,
createProperties: createNetworkElementsProperties,
reloadAction: networkElementsReloadAction,
+ reloadActionAsync: networkElementsReloadActionAsync
// set value action, to change a value
} = createExternal<NetworkElementConnection>(networkElementsSearchHandler, appState => {
- const webUris = appState.connect.guiCutThrough.availableWebUris;
+ const webUris = appState.connect.guiCutThrough.searchedElements;
+ // add weburi links, if element is connected & weburi available
if (appState.connect.networkElements.rows && webUris.length > 0) {
appState.connect.networkElements.rows.forEach(element => {
diff --git a/sdnr/wt/odlux/apps/connectApp/src/models/guiCutTrough.ts b/sdnr/wt/odlux/apps/connectApp/src/models/guiCutTrough.ts
index 4b443ba..d44eea6 100644
--- a/sdnr/wt/odlux/apps/connectApp/src/models/guiCutTrough.ts
+++ b/sdnr/wt/odlux/apps/connectApp/src/models/guiCutTrough.ts
@@ -1 +1,19 @@
-export type guiCutThrough = { webUri: string, nodeId: string }
\ No newline at end of file
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
+export type guiCutThrough = { webUri?: string, nodeId: string }
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/connectApp/src/models/networkElementConnection.ts b/sdnr/wt/odlux/apps/connectApp/src/models/networkElementConnection.ts
index 4c2dc9b..f58dc58 100644
--- a/sdnr/wt/odlux/apps/connectApp/src/models/networkElementConnection.ts
+++ b/sdnr/wt/odlux/apps/connectApp/src/models/networkElementConnection.ts
@@ -1,3 +1,21 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
export type NetworkElementConnection = {
id?: string;
nodeId: string;
diff --git a/sdnr/wt/odlux/apps/connectApp/src/models/panelId.ts b/sdnr/wt/odlux/apps/connectApp/src/models/panelId.ts
index b514120..2000d94 100644
--- a/sdnr/wt/odlux/apps/connectApp/src/models/panelId.ts
+++ b/sdnr/wt/odlux/apps/connectApp/src/models/panelId.ts
@@ -1 +1,19 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
export type PanelId = null | "NetworkElements" | "ConnectionStatusLog";
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/connectApp/src/services/connectService.ts b/sdnr/wt/odlux/apps/connectApp/src/services/connectService.ts
index 7a410f4..41449e8 100644
--- a/sdnr/wt/odlux/apps/connectApp/src/services/connectService.ts
+++ b/sdnr/wt/odlux/apps/connectApp/src/services/connectService.ts
@@ -188,14 +188,20 @@
promises.push(requestRest<any>(path, { method: "GET" })
.then(result => {
- if (result['network-element'] && result['network-element'].extension) {
+ if (result != null && result['network-element'] && result['network-element'].extension) {
const webUri = result['network-element'].extension.find((item: any) => item['value-name'] === "webUri")
if (webUri) {
webUris.push({ webUri: webUri.value, nodeId: nodeId });
+ } else {
+ webUris.push({ webUri: undefined, nodeId: nodeId });
}
+ } else {
+ webUris.push({ webUri: undefined, nodeId: nodeId });
}
})
- .catch(error => console.log("network element is unreachable: " + error)))
+ .catch(error => {
+ webUris.push({ webUri: undefined, nodeId: nodeId });
+ }))
})
diff --git a/sdnr/wt/odlux/apps/connectApp/src/views/connectView.tsx b/sdnr/wt/odlux/apps/connectApp/src/views/connectView.tsx
index aa3391c..f8c0f3a 100644
--- a/sdnr/wt/odlux/apps/connectApp/src/views/connectView.tsx
+++ b/sdnr/wt/odlux/apps/connectApp/src/views/connectView.tsx
@@ -25,7 +25,7 @@
import { NetworkElementsList } from '../components/networkElements';
import { ConnectionStatusLog } from '../components/connectionStatusLog';
-import { setPanelAction, findWebUrisForGuiCutThroughAsyncAction } from '../actions/commonNetworkElementsActions';
+import { setPanelAction, findWebUrisForGuiCutThroughAsyncAction, SetWeburiSearchBusy } from '../actions/commonNetworkElementsActions';
import { PanelId } from '../models/panelId';
import { NetworkElementConnection } from 'models/networkElementConnection';
@@ -42,7 +42,8 @@
onLoadNetworkElements: () => {
dispatcher.dispatch(networkElementsReloadAction);
},
- loadWebUris: findWebUrisForGuiCutThroughAsyncAction(dispatcher.dispatch),
+ loadWebUris: async (networkElements: NetworkElementConnection[]) => { await dispatcher.dispatch(findWebUrisForGuiCutThroughAsyncAction(networkElements)) },
+ isBusy: (busy: boolean) => dispatcher.dispatch(new SetWeburiSearchBusy(busy)),
onLoadConnectionStatusLog: () => {
dispatcher.dispatch(connectionStatusLogReloadAction);
},
@@ -55,13 +56,12 @@
class ConnectApplicationComponent extends React.Component<ConnectApplicationComponentProps>{
- componentDidUpdate = () => {
+ componentDidUpdate = async () => {
// search for guicutthroughs after networkelements were found
const networkElements = this.props.netWorkElements;
- const guiCuttrough = this.props.availableGuiCutroughs;
- if (networkElements.rows.length > 0 && networkElements.total !== guiCuttrough.knownElements.length) {
- this.props.loadWebUris(networkElements.rows, guiCuttrough.knownElements);
+ if (networkElements.rows.length > 0) {
+ await this.props.loadWebUris(networkElements.rows);
}
}
diff --git a/sdnr/wt/odlux/apps/connectApp/webpack.config.js b/sdnr/wt/odlux/apps/connectApp/webpack.config.js
index 6d70b04..aa3acf0 100644
--- a/sdnr/wt/odlux/apps/connectApp/webpack.config.js
+++ b/sdnr/wt/odlux/apps/connectApp/webpack.config.js
@@ -126,23 +126,23 @@
},
proxy: {
"/oauth2/": {
- target: "http://10.20.6.29:28181",
+ target: "http://10.20.6.29:48181",
secure: false
},
"/database/": {
- target: "http://10.20.6.29:28181",
+ target: "http://10.20.6.29:48181",
secure: false
},
"/restconf/": {
- target: "http://10.20.6.29:28181",
+ target: "http://10.20.6.29:48181",
secure: false
},
"/help/": {
- target: "http://10.20.6.29:28181",
+ target: "http://10.20.6.29:48181",
secure: false
},
"/websocket": {
- target: "http://10.20.6.29:28181",
+ target: "http://10.20.6.29:48181",
ws: true,
changeOrigin: true,
secure: false
diff --git a/sdnr/wt/odlux/apps/demoApp/pom.xml b/sdnr/wt/odlux/apps/demoApp/pom.xml
index 92ef685..9e96cf4 100644
--- a/sdnr/wt/odlux/apps/demoApp/pom.xml
+++ b/sdnr/wt/odlux/apps/demoApp/pom.xml
@@ -14,7 +14,7 @@
<version>0.7.1-SNAPSHOT</version>
<packaging>bundle</packaging>
- <name>ccsdk-features :: ${project.artifactId}</name>
+ <name>sdnr-wt-odlux-app-demoApp</name>
<licenses>
<license>
<name>Apache License, Version 2.0</name>
@@ -103,10 +103,10 @@
</executions>
</plugin>
<plugin>
- <groupId>de.jacks-it-lab</groupId>
- <artifactId>frontend-maven-plugin</artifactId>
- <version>1.7.2</version>
- <executions>
+ <groupId>de.jacks-it-lab</groupId>
+ <artifactId>frontend-maven-plugin</artifactId>
+ <version>1.7.2</version>
+ <executions>
<execution>
<id>install node and yarn</id>
<goals>
diff --git a/sdnr/wt/odlux/apps/eventLogApp/pom.xml b/sdnr/wt/odlux/apps/eventLogApp/pom.xml
index d84a106..e5ac653 100644
--- a/sdnr/wt/odlux/apps/eventLogApp/pom.xml
+++ b/sdnr/wt/odlux/apps/eventLogApp/pom.xml
@@ -14,7 +14,7 @@
<version>0.7.1-SNAPSHOT</version>
<packaging>bundle</packaging>
- <name>ccsdk-features :: ${project.artifactId}</name>
+ <name>sdnr-wt-odlux-app-eventLogApp</name>
<licenses>
<license>
<name>Apache License, Version 2.0</name>
@@ -103,10 +103,10 @@
</executions>
</plugin>
<plugin>
- <groupId>de.jacks-it-lab</groupId>
- <artifactId>frontend-maven-plugin</artifactId>
- <version>1.7.2</version>
- <executions>
+ <groupId>de.jacks-it-lab</groupId>
+ <artifactId>frontend-maven-plugin</artifactId>
+ <version>1.7.2</version>
+ <executions>
<execution>
<id>install node and yarn</id>
<goals>
diff --git a/sdnr/wt/odlux/apps/faultApp/pom.xml b/sdnr/wt/odlux/apps/faultApp/pom.xml
index 119d636..63825dd 100644
--- a/sdnr/wt/odlux/apps/faultApp/pom.xml
+++ b/sdnr/wt/odlux/apps/faultApp/pom.xml
@@ -14,7 +14,7 @@
<version>0.7.1-SNAPSHOT</version>
<packaging>bundle</packaging>
- <name>ccsdk-features :: ${project.artifactId}</name>
+ <name>sdnr-wt-odlux-app-faultApp</name>
<licenses>
<license>
<name>Apache License, Version 2.0</name>
@@ -103,10 +103,10 @@
</executions>
</plugin>
<plugin>
- <groupId>de.jacks-it-lab</groupId>
- <artifactId>frontend-maven-plugin</artifactId>
- <version>1.7.2</version>
- <executions>
+ <groupId>de.jacks-it-lab</groupId>
+ <artifactId>frontend-maven-plugin</artifactId>
+ <version>1.7.2</version>
+ <executions>
<execution>
<id>install node and yarn</id>
<goals>
diff --git a/sdnr/wt/odlux/apps/helpApp/pom.xml b/sdnr/wt/odlux/apps/helpApp/pom.xml
index b40de2f..760049c 100644
--- a/sdnr/wt/odlux/apps/helpApp/pom.xml
+++ b/sdnr/wt/odlux/apps/helpApp/pom.xml
@@ -14,7 +14,7 @@
<version>0.7.1-SNAPSHOT</version>
<packaging>bundle</packaging>
- <name>ccsdk-features :: ${project.artifactId}</name>
+ <name>sdnr-wt-odlux-app-helpApp</name>
<licenses>
<license>
<name>Apache License, Version 2.0</name>
@@ -103,10 +103,10 @@
</executions>
</plugin>
<plugin>
- <groupId>de.jacks-it-lab</groupId>
- <artifactId>frontend-maven-plugin</artifactId>
- <version>1.7.2</version>
- <executions>
+ <groupId>de.jacks-it-lab</groupId>
+ <artifactId>frontend-maven-plugin</artifactId>
+ <version>1.7.2</version>
+ <executions>
<execution>
<id>install node and yarn</id>
<goals>
diff --git a/sdnr/wt/odlux/apps/inventoryApp/pom.xml b/sdnr/wt/odlux/apps/inventoryApp/pom.xml
index aad75ca..9420b6c 100644
--- a/sdnr/wt/odlux/apps/inventoryApp/pom.xml
+++ b/sdnr/wt/odlux/apps/inventoryApp/pom.xml
@@ -14,7 +14,7 @@
<version>0.7.1-SNAPSHOT</version>
<packaging>bundle</packaging>
- <name>ccsdk-features :: ${project.artifactId}</name>
+ <name>sdnr-wt-odlux-app-inventoryApp</name>
<licenses>
<license>
<name>Apache License, Version 2.0</name>
@@ -103,10 +103,10 @@
</executions>
</plugin>
<plugin>
- <groupId>de.jacks-it-lab</groupId>
- <artifactId>frontend-maven-plugin</artifactId>
- <version>1.7.2</version>
- <executions>
+ <groupId>de.jacks-it-lab</groupId>
+ <artifactId>frontend-maven-plugin</artifactId>
+ <version>1.7.2</version>
+ <executions>
<execution>
<id>install node and yarn</id>
<goals>
diff --git a/sdnr/wt/odlux/apps/maintenanceApp/pom.xml b/sdnr/wt/odlux/apps/maintenanceApp/pom.xml
index 0d51219..0196e39 100644
--- a/sdnr/wt/odlux/apps/maintenanceApp/pom.xml
+++ b/sdnr/wt/odlux/apps/maintenanceApp/pom.xml
@@ -14,7 +14,7 @@
<version>0.7.1-SNAPSHOT</version>
<packaging>bundle</packaging>
- <name>ccsdk-features :: ${project.artifactId}</name>
+ <name>sdnr-wt-odlux-app-maintenanceApp</name>
<licenses>
<license>
<name>Apache License, Version 2.0</name>
@@ -103,10 +103,10 @@
</executions>
</plugin>
<plugin>
- <groupId>de.jacks-it-lab</groupId>
- <artifactId>frontend-maven-plugin</artifactId>
- <version>1.7.2</version>
- <executions>
+ <groupId>de.jacks-it-lab</groupId>
+ <artifactId>frontend-maven-plugin</artifactId>
+ <version>1.7.2</version>
+ <executions>
<execution>
<id>install node and yarn</id>
<goals>
diff --git a/sdnr/wt/odlux/apps/mediatorApp/pom.xml b/sdnr/wt/odlux/apps/mediatorApp/pom.xml
index 038761a..5a3b802 100644
--- a/sdnr/wt/odlux/apps/mediatorApp/pom.xml
+++ b/sdnr/wt/odlux/apps/mediatorApp/pom.xml
@@ -14,7 +14,7 @@
<version>0.7.1-SNAPSHOT</version>
<packaging>bundle</packaging>
- <name>ccsdk-features :: ${project.artifactId}</name>
+ <name>sdnr-wt-odlux-app-mediatorApp</name>
<licenses>
<license>
<name>Apache License, Version 2.0</name>
@@ -103,10 +103,10 @@
</executions>
</plugin>
<plugin>
- <groupId>de.jacks-it-lab</groupId>
- <artifactId>frontend-maven-plugin</artifactId>
- <version>1.7.2</version>
- <executions>
+ <groupId>de.jacks-it-lab</groupId>
+ <artifactId>frontend-maven-plugin</artifactId>
+ <version>1.7.2</version>
+ <executions>
<execution>
<id>install node and yarn</id>
<goals>
diff --git a/sdnr/wt/odlux/apps/minimumApp/pom.xml b/sdnr/wt/odlux/apps/minimumApp/pom.xml
index f1eb06a..81af1fb 100644
--- a/sdnr/wt/odlux/apps/minimumApp/pom.xml
+++ b/sdnr/wt/odlux/apps/minimumApp/pom.xml
@@ -14,7 +14,7 @@
<version>0.7.1-SNAPSHOT</version>
<packaging>bundle</packaging>
- <name>ccsdk-features :: ${project.artifactId}</name>
+ <name>sdnr-wt-odlux-app-minimumApp</name>
<licenses>
<license>
<name>Apache License, Version 2.0</name>
@@ -103,10 +103,10 @@
</executions>
</plugin>
<plugin>
- <groupId>de.jacks-it-lab</groupId>
- <artifactId>frontend-maven-plugin</artifactId>
- <version>1.7.2</version>
- <executions>
+ <groupId>de.jacks-it-lab</groupId>
+ <artifactId>frontend-maven-plugin</artifactId>
+ <version>1.7.2</version>
+ <executions>
<execution>
<id>install node and yarn</id>
<goals>
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/pom.xml b/sdnr/wt/odlux/apps/performanceHistoryApp/pom.xml
index 5968721..e60a6c1 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/pom.xml
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/pom.xml
@@ -14,7 +14,7 @@
<version>0.7.1-SNAPSHOT</version>
<packaging>bundle</packaging>
- <name>ccsdk-features :: ${project.artifactId}</name>
+ <name>sdnr-wt-odlux-app-performanceHistoryApp</name>
<licenses>
<license>
<name>Apache License, Version 2.0</name>
@@ -103,10 +103,10 @@
</executions>
</plugin>
<plugin>
- <groupId>de.jacks-it-lab</groupId>
- <artifactId>frontend-maven-plugin</artifactId>
- <version>1.7.2</version>
- <executions>
+ <groupId>de.jacks-it-lab</groupId>
+ <artifactId>frontend-maven-plugin</artifactId>
+ <version>1.7.2</version>
+ <executions>
<execution>
<id>install node and yarn</id>
<goals>
diff --git a/sdnr/wt/odlux/core/features/pom.xml b/sdnr/wt/odlux/core/features/pom.xml
index b4ded60..c29104e 100644
--- a/sdnr/wt/odlux/core/features/pom.xml
+++ b/sdnr/wt/odlux/core/features/pom.xml
@@ -26,7 +26,7 @@
<version>0.7.1-SNAPSHOT</version>
<packaging>feature</packaging>
- <name>ccsdk-features :: ${project.artifactId}</name>
+ <name>ccsdk-features :: ${project.artifactId} :: feature</name>
<licenses>
<license>
<name>Apache License, Version 2.0</name>
diff --git a/sdnr/wt/odlux/core/installer/pom.xml b/sdnr/wt/odlux/core/installer/pom.xml
index 3f99719..cf00a49 100755
--- a/sdnr/wt/odlux/core/installer/pom.xml
+++ b/sdnr/wt/odlux/core/installer/pom.xml
@@ -1,100 +1,100 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
+ <modelVersion>4.0.0</modelVersion>
- <parent>
- <groupId>org.onap.ccsdk.parent</groupId>
- <artifactId>odlparent-lite</artifactId>
- <version>1.5.2-SNAPSHOT</version>
- <relativePath/>
- </parent>
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>odlparent-lite</artifactId>
+ <version>1.5.2-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
- <groupId>org.onap.ccsdk.features.sdnr.wt</groupId>
- <artifactId>sdnr-wt-odlux-core-installer</artifactId>
- <version>0.7.1-SNAPSHOT</version>
- <packaging>pom</packaging>
+ <groupId>org.onap.ccsdk.features.sdnr.wt</groupId>
+ <artifactId>sdnr-wt-odlux-core-installer</artifactId>
+ <version>0.7.1-SNAPSHOT</version>
+ <packaging>pom</packaging>
- <name>ccsdk-features :: ${project.artifactId}</name>
- <licenses>
- <license>
- <name>Apache License, Version 2.0</name>
- <url>http://www.apache.org/licenses/LICENSE-2.0</url>
- </license>
- </licenses>
+ <name>ccsdk-features :: ${project.artifactId}</name>
+ <licenses>
+ <license>
+ <name>Apache License, Version 2.0</name>
+ <url>http://www.apache.org/licenses/LICENSE-2.0</url>
+ </license>
+ </licenses>
- <properties>
- <application.name>sdnr-wt-odlux-core</application.name>
- <include.transitive.dependencies>false</include.transitive.dependencies>
- </properties>
+ <properties>
+ <application.name>sdnr-wt-odlux-core</application.name>
+ <include.transitive.dependencies>false</include.transitive.dependencies>
+ </properties>
- <dependencies>
- <dependency>
- <groupId>org.onap.ccsdk.features.sdnr.wt</groupId>
- <artifactId>${application.name}-feature</artifactId>
- <version>${project.version}</version>
- <type>xml</type>
- <classifier>features</classifier>
- <exclusions>
- <exclusion>
- <groupId>*</groupId>
- <artifactId>*</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
- <dependency>
- <groupId>org.onap.ccsdk.features.sdnr.wt</groupId>
- <artifactId>${application.name}-provider</artifactId>
- <version>${project.version}</version>
- </dependency>
- </dependencies>
+ <dependencies>
+ <dependency>
+ <groupId>org.onap.ccsdk.features.sdnr.wt</groupId>
+ <artifactId>${application.name}-feature</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ <exclusions>
+ <exclusion>
+ <groupId>*</groupId>
+ <artifactId>*</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.features.sdnr.wt</groupId>
+ <artifactId>${application.name}-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
- <build>
- <plugins>
- <plugin>
- <artifactId>maven-assembly-plugin</artifactId>
- <executions>
- <execution>
- <id>maven-repo-zip</id>
- <goals>
- <goal>single</goal>
- </goals>
- <phase>package</phase>
- <configuration>
- <attach>true</attach>
- <finalName>stage/${application.name}-${project.version}</finalName>
- <descriptors>
- <descriptor>src/assembly/assemble_mvnrepo_zip.xml</descriptor>
- </descriptors>
- <appendAssemblyId>true</appendAssemblyId>
- </configuration>
- </execution>
- </executions>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-dependency-plugin</artifactId>
- <executions>
- <execution>
- <id>copy-nested-dependencies</id>
- <goals>
- <goal>copy-dependencies</goal>
- </goals>
- <phase>prepare-package</phase>
- <configuration>
- <transitive>true</transitive>
- <outputDirectory>${project.build.directory}/assembly/system</outputDirectory>
- <overWriteReleases>false</overWriteReleases>
- <overWriteSnapshots>true</overWriteSnapshots>
- <overWriteIfNewer>true</overWriteIfNewer>
- <useRepositoryLayout>true</useRepositoryLayout>
- <addParentPoms>false</addParentPoms>
- <copyPom>false</copyPom>
- <!--<includeArtifactIds>sdnr-wt-apigateway-provider,${application.name}</includeArtifactIds> -->
- <!--<scope>provided</scope> -->
- </configuration>
- </execution>
- </executions>
- </plugin>
- </plugins>
- </build>
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>maven-repo-zip</id>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <attach>true</attach>
+ <finalName>stage/${application.name}-${project.version}</finalName>
+ <descriptors>
+ <descriptor>src/assembly/assemble_mvnrepo_zip.xml</descriptor>
+ </descriptors>
+ <appendAssemblyId>true</appendAssemblyId>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>copy-nested-dependencies</id>
+ <goals>
+ <goal>copy-dependencies</goal>
+ </goals>
+ <phase>prepare-package</phase>
+ <configuration>
+ <transitive>true</transitive>
+ <outputDirectory>${project.build.directory}/assembly/system</outputDirectory>
+ <overWriteReleases>false</overWriteReleases>
+ <overWriteSnapshots>true</overWriteSnapshots>
+ <overWriteIfNewer>true</overWriteIfNewer>
+ <useRepositoryLayout>true</useRepositoryLayout>
+ <addParentPoms>false</addParentPoms>
+ <copyPom>false</copyPom>
+ <!--<includeArtifactIds>sdnr-wt-apigateway-provider,${application.name}</includeArtifactIds> -->
+ <!--<scope>provided</scope> -->
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
</project>
diff --git a/sdnr/wt/odlux/core/pom.xml b/sdnr/wt/odlux/core/pom.xml
index dafa88b..9840177 100644
--- a/sdnr/wt/odlux/core/pom.xml
+++ b/sdnr/wt/odlux/core/pom.xml
@@ -1,35 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
+ <modelVersion>4.0.0</modelVersion>
- <parent>
- <groupId>org.onap.ccsdk.parent</groupId>
- <artifactId>odlparent-lite</artifactId>
- <version>1.5.2-SNAPSHOT</version>
- <relativePath/>
- </parent>
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>odlparent-lite</artifactId>
+ <version>1.5.2-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
- <groupId>org.onap.ccsdk.features.sdnr.wt</groupId>
- <artifactId>sdnr-wt-odlux-core-top</artifactId>
- <version>0.7.1-SNAPSHOT</version>
- <packaging>pom</packaging>
+ <groupId>org.onap.ccsdk.features.sdnr.wt</groupId>
+ <artifactId>sdnr-wt-odlux-core-top</artifactId>
+ <version>0.7.1-SNAPSHOT</version>
+ <packaging>pom</packaging>
- <name>ccsdk-features :: ${project.artifactId}</name>
- <licenses>
- <license>
- <name>Apache License, Version 2.0</name>
- <url>http://www.apache.org/licenses/LICENSE-2.0</url>
- </license>
- </licenses>
+ <name>odlux-core</name>
+ <licenses>
+ <license>
+ <name>Apache License, Version 2.0</name>
+ <url>http://www.apache.org/licenses/LICENSE-2.0</url>
+ </license>
+ </licenses>
- <modules>
- <module>model</module>
- <module>provider</module>
- <module>features</module>
- <module>installer</module>
- </modules>
+ <modules>
+ <module>model</module>
+ <module>provider</module>
+ <module>features</module>
+ <module>installer</module>
+ </modules>
- <properties>
- <feature-name>sdnr-wt-odlux-core</feature-name>
- </properties>
+ <properties>
+ <feature-name>sdnr-wt-odlux-core</feature-name>
+ </properties>
</project>
diff --git a/sdnr/wt/odlux/core/provider/pom.xml b/sdnr/wt/odlux/core/provider/pom.xml
index 2b36c31..09b26f0 100644
--- a/sdnr/wt/odlux/core/provider/pom.xml
+++ b/sdnr/wt/odlux/core/provider/pom.xml
@@ -1,111 +1,111 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
+ <modelVersion>4.0.0</modelVersion>
- <parent>
- <groupId>org.onap.ccsdk.parent</groupId>
- <artifactId>binding-parent</artifactId>
- <version>1.5.2-SNAPSHOT</version>
- <relativePath/>
- </parent>
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>binding-parent</artifactId>
+ <version>1.5.2-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
- <groupId>org.onap.ccsdk.features.sdnr.wt</groupId>
- <artifactId>sdnr-wt-odlux-core-provider</artifactId>
- <version>0.7.1-SNAPSHOT</version>
- <packaging>bundle</packaging>
+ <groupId>org.onap.ccsdk.features.sdnr.wt</groupId>
+ <artifactId>sdnr-wt-odlux-core-provider</artifactId>
+ <version>0.7.1-SNAPSHOT</version>
+ <packaging>bundle</packaging>
- <name>ccsdk-features :: ${project.artifactId}</name>
- <licenses>
- <license>
- <name>Apache License, Version 2.0</name>
- <url>http://www.apache.org/licenses/LICENSE-2.0</url>
- </license>
- </licenses>
+ <name>ccsdk-features :: ${project.artifactId}</name>
+ <licenses>
+ <license>
+ <name>Apache License, Version 2.0</name>
+ <url>http://www.apache.org/licenses/LICENSE-2.0</url>
+ </license>
+ </licenses>
- <dependencies>
- <dependency>
- <groupId>org.onap.ccsdk.features.sdnr.wt</groupId>
- <artifactId>sdnr-wt-odlux-core-model</artifactId>
- <version>${project.version}</version>
- </dependency>
- <dependency>
- <groupId>${project.groupId}</groupId>
- <artifactId>sdnr-wt-odlux-framework</artifactId>
- <version>${project.version}</version>
- </dependency>
- <dependency>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-server</artifactId>
- <scope>test</scope>
- </dependency>
+ <dependencies>
+ <dependency>
+ <groupId>org.onap.ccsdk.features.sdnr.wt</groupId>
+ <artifactId>sdnr-wt-odlux-core-model</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>sdnr-wt-odlux-framework</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-server</artifactId>
+ <scope>test</scope>
+ </dependency>
- <dependency>
- <groupId>org.osgi</groupId>
- <artifactId>org.osgi.core</artifactId>
- </dependency>
- <dependency>
- <groupId>org.osgi</groupId>
- <artifactId>org.osgi.compendium</artifactId>
- </dependency>
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-api</artifactId>
- </dependency>
- <dependency>
- <groupId>com.google.guava</groupId>
- <artifactId>guava</artifactId>
- </dependency>
- <dependency>
- <groupId>javax.servlet</groupId>
- <artifactId>javax.servlet-api</artifactId>
- </dependency>
- <dependency>
- <groupId>org.mockito</groupId>
- <artifactId>mockito-core</artifactId>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-simple</artifactId>
- <scope>test</scope>
- </dependency>
- </dependencies>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.compendium</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>javax.servlet-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-simple</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
- <build>
- <plugins>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-compiler-plugin</artifactId>
- <configuration>
- <source>1.8</source>
- <target>1.8</target>
- </configuration>
- </plugin>
- <plugin>
- <artifactId>maven-checkstyle-plugin</artifactId>
- <configuration>
- <skip>true</skip>
- </configuration>
- </plugin>
- <plugin>
- <groupId>org.apache.felix</groupId>
- <artifactId>maven-bundle-plugin</artifactId>
- <extensions>true</extensions>
- <configuration>
- <instructions>
- <Import-Package>org.onap.ccsdk.features.sdnr.wt.odlux.*;resolution:=optional,*;
- </Import-Package>
- <Embed-Dependency>sdnr-wt-odlux-framework;inline=true</Embed-Dependency>
- <Embed-Transitive>true</Embed-Transitive>
- <Export-Package>${project.groupId}.*</Export-Package>
- </instructions>
- </configuration>
- </plugin>
- </plugins>
- </build>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>1.8</source>
+ <target>1.8</target>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-checkstyle-plugin</artifactId>
+ <configuration>
+ <skip>true</skip>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Import-Package>org.onap.ccsdk.features.sdnr.wt.odlux.*;resolution:=optional,*;
+ </Import-Package>
+ <Embed-Dependency>sdnr-wt-odlux-framework;inline=true</Embed-Dependency>
+ <Embed-Transitive>true</Embed-Transitive>
+ <Export-Package>${project.groupId}.*</Export-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
</project>
diff --git a/sdnr/wt/odlux/framework/pom.xml b/sdnr/wt/odlux/framework/pom.xml
index fc7a532..78349e4 100644
--- a/sdnr/wt/odlux/framework/pom.xml
+++ b/sdnr/wt/odlux/framework/pom.xml
@@ -1,165 +1,165 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
+ <modelVersion>4.0.0</modelVersion>
- <parent>
- <groupId>org.onap.ccsdk.parent</groupId>
- <artifactId>odlparent</artifactId>
- <version>1.5.2-SNAPSHOT</version>
- <relativePath/>
- </parent>
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>odlparent</artifactId>
+ <version>1.5.2-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
- <groupId>org.onap.ccsdk.features.sdnr.wt</groupId>
- <artifactId>sdnr-wt-odlux-framework</artifactId>
- <version>0.7.1-SNAPSHOT</version>
- <packaging>jar</packaging>
+ <groupId>org.onap.ccsdk.features.sdnr.wt</groupId>
+ <artifactId>sdnr-wt-odlux-framework</artifactId>
+ <version>0.7.1-SNAPSHOT</version>
+ <packaging>jar</packaging>
- <name>ccsdk-features :: ${project.artifactId}</name>
- <licenses>
- <license>
- <name>Apache License, Version 2.0</name>
- <url>http://www.apache.org/licenses/LICENSE-2.0</url>
- </license>
- </licenses>
+ <name>sdnr-wt-odlux-framework</name>
+ <licenses>
+ <license>
+ <name>Apache License, Version 2.0</name>
+ <url>http://www.apache.org/licenses/LICENSE-2.0</url>
+ </license>
+ </licenses>
- <properties>
- <buildtime>${maven.build.timestamp}</buildtime>
- <distversion>ONAP Frankfurt (Neon, mdsal ${odl.mdsal.version})</distversion>
- <buildno>36.1a30021(19/12/12)</buildno>
- <odlux.version>ONAP SDN-R | ONF Wireless for ${distversion} - Build: ${buildtime} ${buildno} ${project.version}</odlux.version>
- </properties>
+ <properties>
+ <buildtime>${maven.build.timestamp}</buildtime>
+ <distversion>ONAP Frankfurt (Neon, mdsal ${odl.mdsal.version})</distversion>
+ <buildno>39.0e1988b(20/01/12)</buildno>
+ <odlux.version>ONAP SDN-R | ONF Wireless for ${distversion} - Build: ${buildtime} ${buildno} ${project.version}</odlux.version>
+ </properties>
- <build>
- <resources>
- <resource>
- <directory>dist</directory>
- <targetPath>odlux</targetPath>
- </resource>
- </resources>
- <plugins>
- <plugin>
- <artifactId>maven-clean-plugin</artifactId>
- <configuration>
- <filesets>
- <fileset>
- <directory>dist</directory>
- <followSymlinks>false</followSymlinks>
- </fileset>
- <fileset>
- <directory>node</directory>
- <followSymlinks>false</followSymlinks>
- </fileset>
- <fileset>
- <directory>node_modules</directory>
- <followSymlinks>false</followSymlinks>
- </fileset>
- <fileset>
- <directory>../node_modules</directory>
- <followSymlinks>false</followSymlinks>
- </fileset>
- <!-- eclipse bug build bin folder in basedir -->
- <fileset>
- <directory>bin</directory>
- <followSymlinks>false</followSymlinks>
- </fileset>
- </filesets>
- </configuration>
- </plugin>
- <plugin>
- <groupId>de.jacks-it-lab</groupId>
- <artifactId>frontend-maven-plugin</artifactId>
- <version>1.7.2</version>
- <executions>
- <execution>
- <id>install node and yarn</id>
- <goals>
- <goal>install-node-and-yarn</goal>
- </goals>
- <!-- optional: default phase is "generate-resources" -->
- <phase>initialize</phase>
- <configuration>
- <nodeVersion>v10.16.3</nodeVersion>
- <yarnVersion>v1.19.0</yarnVersion>
- </configuration>
- </execution>
- <execution>
- <id>clear cache</id>
- <goals>
- <goal>yarn</goal>
- </goals>
- <phase>initialize</phase>
- <configuration>
- <arguments>cache clean</arguments>
- <installDirectory>${project.basedir}</installDirectory>
- <workingDirectory>${project.basedir}/../</workingDirectory>
- </configuration>
- </execution>
- <execution>
- <id>install lerna</id>
- <goals>
- <goal>yarn</goal>
- </goals>
- <phase>initialize</phase>
- <configuration>
- <arguments>add lerna@3.13.1 -W --exact</arguments>
- <installDirectory>${project.basedir}</installDirectory>
- <workingDirectory>${project.basedir}/../</workingDirectory>
- </configuration>
- </execution>
- <execution>
- <id>exec lerna bootstrap</id>
- <goals>
- <goal>lerna</goal>
- </goals>
- <phase>initialize</phase>
- <configuration>
- <lernaInheritsProxyConfigFromMaven>false</lernaInheritsProxyConfigFromMaven>
- <arguments>bootstrap</arguments>
- <installDirectory>${project.basedir}</installDirectory>
- <workingDirectory>${project.basedir}/../</workingDirectory>
- </configuration>
- </execution>
- <execution>
- <id>yarn build</id>
- <goals>
- <goal>yarn</goal>
- </goals>
- <configuration>
- <arguments>run build</arguments>
- </configuration>
- </execution>
- </executions>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-jar-plugin</artifactId>
- </plugin>
- <plugin>
- <groupId>com.google.code.maven-replacer-plugin</groupId>
- <artifactId>replacer</artifactId>
- <version>1.5.2</version>
- <executions>
- <execution>
- <id>replace version</id>
- <phase>prepare-package</phase>
- <goals>
- <goal>replace</goal>
- </goals>
- </execution>
- </executions>
- <configuration>
- <basedir>${project.build.directory}/classes/odlux</basedir>
- <includes>
- <include>app.js</include>
- </includes>
- <replacements>
- <replacement>
- <token>##odlux.version##</token>
- <value>${odlux.version}</value>
- </replacement>
- </replacements>
- </configuration>
- </plugin>
- </plugins>
- </build>
+ <build>
+ <resources>
+ <resource>
+ <directory>dist</directory>
+ <targetPath>odlux</targetPath>
+ </resource>
+ </resources>
+ <plugins>
+ <plugin>
+ <artifactId>maven-clean-plugin</artifactId>
+ <configuration>
+ <filesets>
+ <fileset>
+ <directory>dist</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ <fileset>
+ <directory>node</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ <fileset>
+ <directory>node_modules</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ <fileset>
+ <directory>../node_modules</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ <!-- eclipse bug build bin folder in basedir -->
+ <fileset>
+ <directory>bin</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ </filesets>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>de.jacks-it-lab</groupId>
+ <artifactId>frontend-maven-plugin</artifactId>
+ <version>1.7.2</version>
+ <executions>
+ <execution>
+ <id>install node and yarn</id>
+ <goals>
+ <goal>install-node-and-yarn</goal>
+ </goals>
+ <!-- optional: default phase is "generate-resources" -->
+ <phase>initialize</phase>
+ <configuration>
+ <nodeVersion>v10.16.3</nodeVersion>
+ <yarnVersion>v1.19.0</yarnVersion>
+ </configuration>
+ </execution>
+ <execution>
+ <id>clear cache</id>
+ <goals>
+ <goal>yarn</goal>
+ </goals>
+ <phase>initialize</phase>
+ <configuration>
+ <arguments>cache clean</arguments>
+ <installDirectory>${project.basedir}</installDirectory>
+ <workingDirectory>${project.basedir}/../</workingDirectory>
+ </configuration>
+ </execution>
+ <execution>
+ <id>install lerna</id>
+ <goals>
+ <goal>yarn</goal>
+ </goals>
+ <phase>initialize</phase>
+ <configuration>
+ <arguments>add lerna@3.13.1 -W --exact</arguments>
+ <installDirectory>${project.basedir}</installDirectory>
+ <workingDirectory>${project.basedir}/../</workingDirectory>
+ </configuration>
+ </execution>
+ <execution>
+ <id>exec lerna bootstrap</id>
+ <goals>
+ <goal>lerna</goal>
+ </goals>
+ <phase>initialize</phase>
+ <configuration>
+ <lernaInheritsProxyConfigFromMaven>false</lernaInheritsProxyConfigFromMaven>
+ <arguments>bootstrap</arguments>
+ <installDirectory>${project.basedir}</installDirectory>
+ <workingDirectory>${project.basedir}/../</workingDirectory>
+ </configuration>
+ </execution>
+ <execution>
+ <id>yarn build</id>
+ <goals>
+ <goal>yarn</goal>
+ </goals>
+ <configuration>
+ <arguments>run build</arguments>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>com.google.code.maven-replacer-plugin</groupId>
+ <artifactId>replacer</artifactId>
+ <version>1.5.2</version>
+ <executions>
+ <execution>
+ <id>replace version</id>
+ <phase>prepare-package</phase>
+ <goals>
+ <goal>replace</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <basedir>${project.build.directory}/classes/odlux</basedir>
+ <includes>
+ <include>app.js</include>
+ </includes>
+ <replacements>
+ <replacement>
+ <token>##odlux.version##</token>
+ <value>${odlux.version}</value>
+ </replacement>
+ </replacements>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
</project>
diff --git a/sdnr/wt/odlux/framework/src/app.css b/sdnr/wt/odlux/framework/src/app.css
index 356f36d..f70fbc0 100644
--- a/sdnr/wt/odlux/framework/src/app.css
+++ b/sdnr/wt/odlux/framework/src/app.css
@@ -3,4 +3,14 @@
padding: 0px;
margin: 0px;
font-family: 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif;
+}
+.about-table td{
+ padding:0.5rem 1rem;
+ border-bottom: 1px solid #DDD;
+}
+.about-table pre {
+ background:#FFF;
+ border:1px solid #CCC;
+ padding:1rem;
+ margin: 1rem 0;
}
\ No newline at end of file
diff --git a/sdnr/wt/odlux/framework/src/components/material-table/index.tsx b/sdnr/wt/odlux/framework/src/components/material-table/index.tsx
index 3e31c5e..5206744 100644
--- a/sdnr/wt/odlux/framework/src/components/material-table/index.tsx
+++ b/sdnr/wt/odlux/framework/src/components/material-table/index.tsx
@@ -179,7 +179,7 @@
<TableToolbar tableId={this.props.tableId} numSelected={selected && selected.length} title={this.props.title} customActionButtons={this.props.customActionButtons} onExportToCsv={this.exportToCsv}
onToggleFilter={toggleFilter} />
<div className={classes.tableWrapper}>
- <Table className={classes.table} aria-labelledby="tableTitle">
+ <Table className={classes.table} aria-label={this.props.tableId ? this.props.tableId : 'tableTitle'}>
<EnhancedTableHead
columns={columns}
numSelected={selected && selected.length}
@@ -193,7 +193,7 @@
<TableBody>
{showFilter && <EnhancedTableFilter columns={columns} filter={filter} onFilterChanged={this.onFilterChanged} enableSelection={this.props.enableSelection} /> || null}
{rows // may need ordering here
- .map((entry: TData & { [key: string]: any }) => {
+ .map((entry: TData & { [key: string]: any }, index) => {
const entryId = getId(entry);
const isSelected = this.isSelected(entryId);
return (
@@ -202,6 +202,7 @@
onClick={event => this.handleClick(event, entry, entryId)}
role="checkbox"
aria-checked={isSelected}
+ aria-label={`${(this.props.tableId ? this.props.tableId : 'table')}-row-${(index + 1)}`}
tabIndex={-1}
key={entryId}
selected={isSelected}
diff --git a/sdnr/wt/odlux/framework/src/components/material-table/tableFilter.tsx b/sdnr/wt/odlux/framework/src/components/material-table/tableFilter.tsx
index 737ea85..2075e05 100644
--- a/sdnr/wt/odlux/framework/src/components/material-table/tableFilter.tsx
+++ b/sdnr/wt/odlux/framework/src/components/material-table/tableFilter.tsx
@@ -69,14 +69,14 @@
{col.disableFilter || (col.type === ColumnType.custom)
? null
: (col.type === ColumnType.boolean)
- ? <Select className={classes.input} value={filter[col.property] !== undefined ? filter[col.property] : ''} onChange={this.createFilterHandler(col.property)} inputProps={{ name: `${col.property}-bool`, id: `${col.property}-bool` }} >
- <MenuItem value={undefined}>
+ ? <Select className={classes.input} aria-label={(col.title as string).toLowerCase() + ' filter'} value={filter[col.property] !== undefined ? filter[col.property] : ''} onChange={this.createFilterHandler(col.property)} inputProps={{ name: `${col.property}-bool`, id: `${col.property}-bool` }} >
+ <MenuItem value={undefined} >
<em>None</em>
</MenuItem>
<MenuItem value={true as any as string}>{col.labels ? col.labels["true"] : "true"}</MenuItem>
<MenuItem value={false as any as string}>{col.labels ? col.labels["false"] : "false"}</MenuItem>
</Select>
- : <Input className={classes.input} inputProps={{ 'aria-label': 'Filter' }} value={filter[col.property] || ''} onChange={this.createFilterHandler(col.property)} />}
+ : <Input className={classes.input} inputProps={{ 'aria-label': (col.title as string).toLowerCase() + ' filter' }} value={filter[col.property] || ''} onChange={this.createFilterHandler(col.property)} />}
</TableCell>
);
}, this)}
diff --git a/sdnr/wt/odlux/framework/src/components/material-table/utilities.ts b/sdnr/wt/odlux/framework/src/components/material-table/utilities.ts
index 6e8902c..74682cd 100644
--- a/sdnr/wt/odlux/framework/src/components/material-table/utilities.ts
+++ b/sdnr/wt/odlux/framework/src/components/material-table/utilities.ts
@@ -196,6 +196,29 @@
}).catch(error => new AddErrorInfoAction(error));
};
+ const reloadActionAsync = async (dispatch: Dispatch, getAppState: () => IApplicationStoreState) => {
+ dispatch(new RefreshAction());
+ const ownState = selectState(getAppState());
+ const filter = { ...ownState.preFilter, ...(ownState.showFilter && ownState.filter || {}) };
+
+ try {
+ const result = await Promise.resolve(callback(ownState.page, ownState.rowsPerPage, ownState.orderBy, ownState.order, filter));
+
+
+ if (ownState.page > 0 && ownState.rowsPerPage * ownState.page > result.total) { //if result is smaller than the currently shown page, new search and repaginate
+
+ let newPage = Math.floor(result.total / ownState.rowsPerPage);
+
+ const repaginationResult = await Promise.resolve(callback(newPage, ownState.rowsPerPage, ownState.orderBy, ownState.order, filter));
+ dispatch(new SetResultAction(repaginationResult));
+ } else {
+ dispatch(new SetResultAction(result));
+ }
+ } catch (error) {
+ new AddErrorInfoAction(error);
+ }
+ };
+
const createPreActions = (dispatch: Dispatch, skipRefresh: boolean = false) => {
return {
onPreFilterChanged: (preFilter: { [key: string]: string }) => {
@@ -258,6 +281,7 @@
createActions: createActions,
createProperties: createProperties,
createPreActions: createPreActions,
- actionHandler: externalTableStateActionHandler
+ actionHandler: externalTableStateActionHandler,
+ reloadActionAsync: reloadActionAsync,
}
}
\ No newline at end of file
diff --git a/sdnr/wt/odlux/framework/src/views/about.tsx b/sdnr/wt/odlux/framework/src/views/about.tsx
index d47e09c..59a7151 100644
--- a/sdnr/wt/odlux/framework/src/views/about.tsx
+++ b/sdnr/wt/odlux/framework/src/views/about.tsx
@@ -15,17 +15,68 @@
* the License.
* ============LICENSE_END==========================================================================
*/
-import * as React from 'react';
-
-const AboutComponent = () => {
-
- return (
- <div>
- <h2>About</h2>
- <div style={{ margin: "0 auto" }}>##odlux.version##</div>
- </div>
- );
-};
-
-export const About = AboutComponent;
+import * as React from 'react';
+import * as marked from 'marked';
+import * as hljs from 'highlight.js';
+import { requestRestExt } from '../services/restService';
+const defaultRenderer = new marked.Renderer();
+defaultRenderer.link = (href, title, text) => (
+ `<a target="_blank" rel="noopener noreferrer" href="${href}" title="${title}">${text}</a>`
+);
+interface AboutState {
+ content: string | null;
+}
+
+class AboutComponent extends React.Component<any, AboutState> {
+
+
+ constructor(props: any) {
+ super(props);
+ this.state = { content: null }
+ this.loadAboutContent();
+ }
+ private loadAboutContent(): void {
+ requestRestExt<string>('/about').then((response) => {
+ this.setState({ content: response.status == 200 ? response.data : `${response.status} ${response.message}` || "Server error" })
+ }).catch((error) => {
+ this.setState({ content: error })
+ })
+ }
+ render() {
+
+ const markedOptions: marked.MarkedOptions = {
+ gfm: true,
+ breaks: false,
+ pedantic: false,
+ sanitize: true,
+ smartLists: true,
+ smartypants: false,
+ langPrefix: 'hljs ',
+ ...({}),
+ highlight: (code, lang) => {
+ if (!!(lang && hljs.getLanguage(lang))) {
+ return hljs.highlight(lang, code).value;
+ }
+ return code;
+ }
+ };
+
+
+ const className = "about-table"
+ const style: React.CSSProperties = {};
+
+ const html = (marked(this.state.content || 'loading', { renderer: markedOptions && markedOptions.renderer || defaultRenderer }));
+
+ return (
+ <div
+ dangerouslySetInnerHTML={{ __html: html }}
+ className={className}
+ style={style}
+ />
+
+ );
+ }
+};
+
+export const About = AboutComponent;
export default About;
\ No newline at end of file
diff --git a/sdnr/wt/odlux/framework/webpack.config.js b/sdnr/wt/odlux/framework/webpack.config.js
index 578a0ae..93b748d 100644
--- a/sdnr/wt/odlux/framework/webpack.config.js
+++ b/sdnr/wt/odlux/framework/webpack.config.js
@@ -191,7 +191,11 @@
},
proxy: {
"/oauth2/**/*": {
- target: "http://10.20.6.29:48181",
+ target: "http://172.18.0.3:8181",
+ secure: false
+ },
+ "/about": {
+ target: "http://172.18.0.3:8181",
secure: false
}
}
diff --git a/sdnr/wt/odlux/pom.xml b/sdnr/wt/odlux/pom.xml
index cac9817..df71097 100644
--- a/sdnr/wt/odlux/pom.xml
+++ b/sdnr/wt/odlux/pom.xml
@@ -10,11 +10,11 @@
</parent>
<groupId>org.onap.ccsdk.features.sdnr.wt</groupId>
- <artifactId>sdnr-wt-odlux-top</artifactId>
+ <artifactId>odlux-top</artifactId>
<version>0.7.1-SNAPSHOT</version>
<packaging>pom</packaging>
- <name>ccsdk-features :: ${project.artifactId}</name>
+ <name>odlux</name>
<modules>
<module>framework</module>
@@ -29,34 +29,34 @@
<module>apps/maintenanceApp</module>
<module>apps/minimumApp</module>
<module>apps/performanceHistoryApp</module>
- <module>apps/eventLogApp</module>
+ <module>apps/eventLogApp</module>
<module>apps/configurationApp</module>
<module>apps/app-feature</module>
<module>apps/app-installer</module>
</modules>
<build>
- <plugins>
- <plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>exec-maven-plugin</artifactId>
- <executions>
- <execution><!-- Run our version calculation script -->
- <id>Clean node and node_modules</id>
- <phase>package</phase>
- <goals>
- <goal>exec</goal>
- </goals>
- <configuration>
- <executable>rm</executable>
- <arguments>
- <argument>-r</argument>
- <argument>node_modules</argument>
- </arguments>
- </configuration>
- </execution>
- </executions>
- </plugin>
- </plugins>
- </build>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>exec-maven-plugin</artifactId>
+ <executions>
+ <execution><!-- Run our version calculation script -->
+ <id>Clean node and node_modules</id>
+ <phase>package</phase>
+ <goals>
+ <goal>exec</goal>
+ </goals>
+ <configuration>
+ <executable>rm</executable>
+ <arguments>
+ <argument>-r</argument>
+ <argument>node_modules</argument>
+ </arguments>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
</project>
diff --git a/sdnr/wt/odlux/yarn.lock b/sdnr/wt/odlux/yarn.lock
index 9ce3e4b..e828763 100644
--- a/sdnr/wt/odlux/yarn.lock
+++ b/sdnr/wt/odlux/yarn.lock
@@ -1458,9 +1458,9 @@
universal-user-agent "^4.0.0"
"@octokit/rest@^16.16.0":
- version "16.35.0"
- resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-16.35.0.tgz#7ccc1f802f407d5b8eb21768c6deca44e7b4c0d8"
- integrity sha512-9ShFqYWo0CLoGYhA1FdtdykJuMzS/9H6vSbbQWDX4pWr4p9v+15MsH/wpd/3fIU+tSxylaNO48+PIHqOkBRx3w==
+ version "16.36.0"
+ resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-16.36.0.tgz#99892c57ba632c2a7b21845584004387b56c2cb7"
+ integrity sha512-zoZj7Ya4vWBK4fjTwK2Cnmu7XBB1p9ygSvTk2TthN6DVJXM4hQZQoAiknWFLJWSTix4dnA3vuHtjPZbExYoCZA==
dependencies:
"@octokit/request" "^5.2.0"
"@octokit/request-error" "^1.0.2"
@@ -1543,9 +1543,9 @@
integrity sha512-Exw4yUWMBXM3X+8oqzJNRqZSwUAaS4+7NdvHqQuFi/d+synz++xmX3QIf+BFqneW8N31R8Ky+sikfZUXq07ggQ==
"@types/node@>= 8":
- version "12.12.17"
- resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.17.tgz#191b71e7f4c325ee0fb23bc4a996477d92b8c39b"
- integrity sha512-Is+l3mcHvs47sKy+afn2O1rV4ldZFU7W8101cNlOd+MRbjM4Onida8jSZnJdTe/0Pcf25g9BNIUsuugmE6puHA==
+ version "13.1.6"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-13.1.6.tgz#076028d0b0400be8105b89a0a55550c86684ffec"
+ integrity sha512-Jg1F+bmxcpENHP23sVKkNuU3uaxPnsBMW0cLjleiikFKomJQbsn0Cqk2yDvQArqzZN6ABfBkZ0To7pQ8sLdWDg==
"@types/prop-types@*":
version "15.7.3"
@@ -4877,9 +4877,9 @@
uglify-js "^3.1.4"
handlebars@^4.4.0:
- version "4.5.3"
- resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.5.3.tgz#5cf75bd8714f7605713511a56be7c349becb0482"
- integrity sha512-3yPecJoJHK/4c6aZhSvxOyG4vJKDshV36VHp0iVCDVh7o9w2vwi3NSnL2MMPj3YdduqaBcu7cGbggJQM0br9xA==
+ version "4.7.1"
+ resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.1.tgz#052bd2618964dcb8aebad0940bfeb2d8d1cfbfde"
+ integrity sha512-2dd6soo60cwKNJ90VewNLIzdZPR/E2YhszOTgHpN9V0YuwZk7x33/iZoIBnASwDFVHMY7iJ6NPL8d9f/DWYCTA==
dependencies:
neo-async "^2.6.0"
optimist "^0.6.1"
@@ -7974,9 +7974,9 @@
p-reduce "^1.0.0"
pacote@^9.5.0:
- version "9.5.11"
- resolved "https://registry.yarnpkg.com/pacote/-/pacote-9.5.11.tgz#524152077cb392c47b1fbe198aa28f778bef7ee1"
- integrity sha512-DMDPvFKCjCg6zMS4IfzZyvT57O/bX8XGG00eEoy4K/S4Wj+qiN8KbnmKpsTvfS6OL9r5TAicxMKWbj1yV2Yh4g==
+ version "9.5.12"
+ resolved "https://registry.yarnpkg.com/pacote/-/pacote-9.5.12.tgz#1e11dd7a8d736bcc36b375a9804d41bb0377bf66"
+ integrity sha512-BUIj/4kKbwWg4RtnBncXPJd15piFSVNpTzY0rysSr3VnMowTYgkGKcaHrbReepAkjTr8lH2CVWRi58Spg2CicQ==
dependencies:
bluebird "^3.5.3"
cacache "^12.0.2"
@@ -9140,9 +9140,9 @@
aproba "^1.1.1"
rxjs@^6.4.0:
- version "6.5.3"
- resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.3.tgz#510e26317f4db91a7eb1de77d9dd9ba0a4899a3a"
- integrity sha512-wuYsAYYFdWTAnAaPoKGNhfpWwKZbJW+HgAJ+mImp+Epl7BG8oNWBCTyRM8gba9k4lk8BgWdoYm21Mo/RYhhbgA==
+ version "6.5.4"
+ resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.4.tgz#e0777fe0d184cec7872df147f303572d414e211c"
+ integrity sha512-naMQXcgEo3csAEGvw/NydRA0fuS2nDZJiw1YUWFKU7aPPAPGZEsD4Iimit96qwCieH6y614MCLYwdkrWx7z/7Q==
dependencies:
tslib "^1.9.0"