From e6d0d67fdbe3fc70c996c8df33bd65d3b151dfad Mon Sep 17 00:00:00 2001 From: herbert Date: Sat, 14 Dec 2019 01:05:47 +0100 Subject: update odlux and featureaggregator v2 update odlux and featureaggregator bundles Issue-ID: SDNC-1008 Signed-off-by: herbert Change-Id: I0018d7bfa3a0e6896c1b210b539a574af9808e22 Signed-off-by: herbert --- sdnr/wt/odlux/apps/connectApp/.babelrc | 17 ++ sdnr/wt/odlux/apps/connectApp/package.json | 40 ++++ sdnr/wt/odlux/apps/connectApp/pom.xml | 147 ++++++++++++ .../src/actions/commonNetworkElementsActions.ts | 113 +++++++++ .../src/actions/infoNetworkElementActions.ts | 57 +++++ .../src/actions/mountedNetworkElementsActions.ts | 60 +++++ .../src/actions/networkElementsActions.ts | 61 +++++ .../src/components/connectionStatusLog.tsx | 52 +++++ .../src/components/editNetworkElementDialog.tsx | 252 ++++++++++++++++++++ .../src/components/infoNetworkElementDialog.tsx | 154 ++++++++++++ .../connectApp/src/components/networkElements.tsx | 259 +++++++++++++++++++++ .../src/handlers/connectAppRootHandler.ts | 83 +++++++ .../src/handlers/connectionStatusLogHandler.ts | 35 +++ .../src/handlers/infoNetworkElementHandler.ts | 60 +++++ .../src/handlers/networkElementsHandler.ts | 58 +++++ sdnr/wt/odlux/apps/connectApp/src/index.html | 27 +++ .../connectApp/src/models/connectionStatusLog.ts | 27 +++ .../apps/connectApp/src/models/guiCutTrough.ts | 1 + .../connectApp/src/models/networkElementBase.ts | 22 ++ .../src/models/networkElementConnection.ts | 36 +++ .../src/models/networkElementConnectionLog.ts | 25 ++ .../wt/odlux/apps/connectApp/src/models/panelId.ts | 1 + .../apps/connectApp/src/models/topologyNetconf.ts | 36 +++ .../connectApp/src/models/yangCapabilitiesType.ts | 22 ++ .../wt/odlux/apps/connectApp/src/pluginConnect.tsx | 56 +++++ .../apps/connectApp/src/services/connectService.ts | 208 +++++++++++++++++ .../apps/connectApp/src/views/connectView.tsx | 111 +++++++++ .../sdnr/wt/odlux/bundles/MyOdluxBundle.java | 68 ++++++ .../resources/OSGI-INF/blueprint/blueprint.xml | 9 + .../sdnr/wt/odlux/bundles/test/TestBundleRes.java | 45 ++++ .../apps/connectApp/src2/test/resources/test.js | 5 + sdnr/wt/odlux/apps/connectApp/tsconfig.json | 37 +++ sdnr/wt/odlux/apps/connectApp/webpack.config.js | 153 ++++++++++++ 33 files changed, 2337 insertions(+) create mode 100644 sdnr/wt/odlux/apps/connectApp/.babelrc create mode 100644 sdnr/wt/odlux/apps/connectApp/package.json create mode 100644 sdnr/wt/odlux/apps/connectApp/pom.xml create mode 100644 sdnr/wt/odlux/apps/connectApp/src/actions/commonNetworkElementsActions.ts create mode 100644 sdnr/wt/odlux/apps/connectApp/src/actions/infoNetworkElementActions.ts create mode 100644 sdnr/wt/odlux/apps/connectApp/src/actions/mountedNetworkElementsActions.ts create mode 100644 sdnr/wt/odlux/apps/connectApp/src/actions/networkElementsActions.ts create mode 100644 sdnr/wt/odlux/apps/connectApp/src/components/connectionStatusLog.tsx create mode 100644 sdnr/wt/odlux/apps/connectApp/src/components/editNetworkElementDialog.tsx create mode 100644 sdnr/wt/odlux/apps/connectApp/src/components/infoNetworkElementDialog.tsx create mode 100644 sdnr/wt/odlux/apps/connectApp/src/components/networkElements.tsx create mode 100644 sdnr/wt/odlux/apps/connectApp/src/handlers/connectAppRootHandler.ts create mode 100644 sdnr/wt/odlux/apps/connectApp/src/handlers/connectionStatusLogHandler.ts create mode 100644 sdnr/wt/odlux/apps/connectApp/src/handlers/infoNetworkElementHandler.ts create mode 100644 sdnr/wt/odlux/apps/connectApp/src/handlers/networkElementsHandler.ts create mode 100644 sdnr/wt/odlux/apps/connectApp/src/index.html create mode 100644 sdnr/wt/odlux/apps/connectApp/src/models/connectionStatusLog.ts create mode 100644 sdnr/wt/odlux/apps/connectApp/src/models/guiCutTrough.ts create mode 100644 sdnr/wt/odlux/apps/connectApp/src/models/networkElementBase.ts create mode 100644 sdnr/wt/odlux/apps/connectApp/src/models/networkElementConnection.ts create mode 100644 sdnr/wt/odlux/apps/connectApp/src/models/networkElementConnectionLog.ts create mode 100644 sdnr/wt/odlux/apps/connectApp/src/models/panelId.ts create mode 100644 sdnr/wt/odlux/apps/connectApp/src/models/topologyNetconf.ts create mode 100644 sdnr/wt/odlux/apps/connectApp/src/models/yangCapabilitiesType.ts create mode 100644 sdnr/wt/odlux/apps/connectApp/src/pluginConnect.tsx create mode 100644 sdnr/wt/odlux/apps/connectApp/src/services/connectService.ts create mode 100644 sdnr/wt/odlux/apps/connectApp/src/views/connectView.tsx create mode 100644 sdnr/wt/odlux/apps/connectApp/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java create mode 100644 sdnr/wt/odlux/apps/connectApp/src2/main/resources/OSGI-INF/blueprint/blueprint.xml create mode 100644 sdnr/wt/odlux/apps/connectApp/src2/test/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/test/TestBundleRes.java create mode 100644 sdnr/wt/odlux/apps/connectApp/src2/test/resources/test.js create mode 100644 sdnr/wt/odlux/apps/connectApp/tsconfig.json create mode 100644 sdnr/wt/odlux/apps/connectApp/webpack.config.js (limited to 'sdnr/wt/odlux/apps/connectApp') diff --git a/sdnr/wt/odlux/apps/connectApp/.babelrc b/sdnr/wt/odlux/apps/connectApp/.babelrc new file mode 100644 index 000000000..3d8cd1260 --- /dev/null +++ b/sdnr/wt/odlux/apps/connectApp/.babelrc @@ -0,0 +1,17 @@ +{ + "presets": [ + ["@babel/preset-react"], + ["@babel/preset-env", { + "targets": { + "chrome": "66" + }, + "spec": true, + "loose": false, + "modules": false, + "debug": false, + "useBuiltIns": "usage", + "forceAllTransforms": true + }] + ], + "plugins": [] +} diff --git a/sdnr/wt/odlux/apps/connectApp/package.json b/sdnr/wt/odlux/apps/connectApp/package.json new file mode 100644 index 000000000..04653d520 --- /dev/null +++ b/sdnr/wt/odlux/apps/connectApp/package.json @@ -0,0 +1,40 @@ +{ + "name": "@odlux/connect-app", + "version": "0.1.1", + "description": "A react based modular UI to display network connect data from a database.", + "main": "index.js", + "scripts": { + "start": "webpack-dev-server --env debug", + "build": "webpack --env release --config webpack.config.js", + "build:dev": "webpack --env debug --config webpack.config.js" + }, + "repository": { + "type": "git", + "url": "https://git.mfico.de/highstreet-technologies/odlux.git" + }, + "keywords": [ + "reactjs", + "redux", + "ui", + "framework" + ], + "author": "Matthias Fischer", + "license": "Apache-2.0", + "dependencies": { + "@odlux/framework": "*" + }, + "peerDependencies": { + "@types/react": "16.9.11", + "@types/react-dom": "16.9.4", + "@types/react-router-dom": "4.3.1", + "@material-ui/core": "4.6.1", + "@material-ui/icons": "4.5.1", + "@types/classnames": "2.2.6", + "@types/flux": "3.1.8", + "@types/jquery": "3.3.10", + "jquery": "3.3.1", + "react": "16.11.0", + "react-dom": "16.11.0", + "react-router-dom": "4.3.1" + } +} \ No newline at end of file diff --git a/sdnr/wt/odlux/apps/connectApp/pom.xml b/sdnr/wt/odlux/apps/connectApp/pom.xml new file mode 100644 index 000000000..f52fa1111 --- /dev/null +++ b/sdnr/wt/odlux/apps/connectApp/pom.xml @@ -0,0 +1,147 @@ + + + + + org.onap.ccsdk.parent + odlparent + 1.5.1-SNAPSHOT + + + 4.0.0 + org.onap.ccsdk.features.sdnr.wt + sdnr-wt-odlux-app-connectApp + 0.7.0-SNAPSHOT + bundle + sdnr-wt-odlux-app-connectApp + + + Apache License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0 + + + + + ${project.groupId} + sdnr-wt-odlux-core-model + ${project.version} + + + ${project.groupId} + sdnr-wt-odlux-core-provider + ${project.version} + test + + + junit + junit + test + + + + src2/main/java + + + maven-clean-plugin + + + + dist + false + + + node + false + + + node_modules + false + + + ../node_modules + false + + + + bin + false + + + + + + org.codehaus.mojo + build-helper-maven-plugin + + + add-test-source + generate-test-sources + + add-test-source + + + + src2/test/java + + + + + + + de.jacks-it-lab + frontend-maven-plugin + 1.7.1 + + + install node and yarn + + install-node-and-yarn + + + initialize + + v10.16.3 + v1.19.0 + + + + yarn build + + yarn + + + run build + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + org.apache.felix + maven-bundle-plugin + true + + + org.onap.ccsdk.features.sdnr.wt.odlux.model.*,com.opensymphony.* + + + + + + + + dist + odlux + + + src2/main/resources + + + src2/test/resources + + + + diff --git a/sdnr/wt/odlux/apps/connectApp/src/actions/commonNetworkElementsActions.ts b/sdnr/wt/odlux/apps/connectApp/src/actions/commonNetworkElementsActions.ts new file mode 100644 index 000000000..bf4778b5b --- /dev/null +++ b/sdnr/wt/odlux/apps/connectApp/src/actions/commonNetworkElementsActions.ts @@ -0,0 +1,113 @@ +// update action erstellen, die unterscheiden kann, ob die eine oder die andere Ansicht gerade aktive ist und diese katualisiert. +// Diese action wird dann bei jeder aktualisierung in den anderen Actions und bei eintreffen von notifikationen verwendet. + +/** + * ============LICENSE_START======================================================================== + * ONAP : ccsdk feature sdnr wt odlux + * ================================================================================================= + * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved. + * ================================================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + * ============LICENSE_END========================================================================== + */ + +import { Action } from '../../../../framework/src/flux/action'; +import { Dispatch } from '../../../../framework/src/flux/store'; +import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore'; + +import { networkElementsReloadAction } from '../handlers/networkElementsHandler'; +import { connectionStatusLogReloadAction } from '../handlers/connectionStatusLogHandler'; + +import { PanelId } from '../models/panelId'; +import { guiCutThrough } from '../models/guiCutTrough'; +import connectService from '../services/connectService'; +import { NetworkElementConnection } from '../models/networkElementConnection'; + +export class SetPanelAction extends Action { + constructor(public panelId: PanelId) { + super(); + } +} + +export class AddWebUriList extends Action { + constructor(public element: guiCutThrough[], public knownElements: string[]) { + super(); + } +} + +export class RemoveWebUri extends Action { + constructor(public element: string) { + super(); + } +} + +export const removeWebUriAction = (nodeId: string) => { + return new RemoveWebUri(nodeId); +} + +let isBusy = false; +export const findWebUrisForGuiCutThroughAsyncAction = (dispatcher: Dispatch) => (networkElements: NetworkElementConnection[], knownElements: string[]) => { + + // 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 }); + + if (knownElements.length > 0) { + + let elementsToSearch: string[] = []; + + nodeIds.forEach(element => { + // find index of nodeId + const index = knownElements.indexOf(element); + + // if element dosen't exist, add it to list + if (index === -1) { + elementsToSearch.push(element) + } + }); + + // 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 { + connectService.getAllWebUriExtensionsForNetworkElementListAsync(nodeIds).then(result => { + dispatcher(new AddWebUriList(result, nodeIds)); + isBusy = false; + }) + } +} + +export const setPanelAction = (panelId: PanelId) => { + return new SetPanelAction(panelId); +} + +export const updateCurrentViewAsyncAction = () => (dispatch: Dispatch, getState: () => IApplicationStoreState) => { + const { connect: { currentOpenPanel } } = getState(); + if (currentOpenPanel === "NetworkElements") { + return dispatch(networkElementsReloadAction); + } + else { + return dispatch(connectionStatusLogReloadAction); + } +}; + diff --git a/sdnr/wt/odlux/apps/connectApp/src/actions/infoNetworkElementActions.ts b/sdnr/wt/odlux/apps/connectApp/src/actions/infoNetworkElementActions.ts new file mode 100644 index 000000000..4ae28aab2 --- /dev/null +++ b/sdnr/wt/odlux/apps/connectApp/src/actions/infoNetworkElementActions.ts @@ -0,0 +1,57 @@ +/** + * ============LICENSE_START======================================================================== + * ONAP : ccsdk feature sdnr wt odlux + * ================================================================================================= + * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved. + * ================================================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + * ============LICENSE_END========================================================================== + */ +import { Action } from '../../../../framework/src/flux/action'; +import { Dispatch } from '../../../../framework/src/flux/store'; + +import { TopologyNode } from '../models/topologyNetconf'; +import { connectService } from '../services/connectService'; + +/** + * Represents the base action. + */ +export class BaseAction extends Action { } + +/** + * Represents an action causing the store to load all element Yang capabilities. + */ +export class LoadAllElementInfoAction extends BaseAction { } + +/** + * Represents an action causing the store to update element Yang capabilities. + */ +export class AllElementInfoLoadedAction extends BaseAction { + /** + * Initialize this instance. + * @param elementInfo The information of the element which is returned. + */ + constructor(public elementInfo: TopologyNode | null, public error?: string) { + super(); + } +} + +/** + * Represents an asynchronous thunk action to load all yang capabilities. + */ +export const loadAllInfoElementAsync = (nodeId: string) => (dispatch: Dispatch) => { + dispatch(new LoadAllElementInfoAction()); + connectService.infoNetworkElement(nodeId).then(info => { + dispatch(new AllElementInfoLoadedAction(info)); + }, error => { + dispatch(new AllElementInfoLoadedAction(null, error)); + }); +} \ No newline at end of file diff --git a/sdnr/wt/odlux/apps/connectApp/src/actions/mountedNetworkElementsActions.ts b/sdnr/wt/odlux/apps/connectApp/src/actions/mountedNetworkElementsActions.ts new file mode 100644 index 000000000..84e73ae5a --- /dev/null +++ b/sdnr/wt/odlux/apps/connectApp/src/actions/mountedNetworkElementsActions.ts @@ -0,0 +1,60 @@ +/** + * ============LICENSE_START======================================================================== + * ONAP : ccsdk feature sdnr wt odlux + * ================================================================================================= + * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved. + * ================================================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + * ============LICENSE_END========================================================================== + */ + +import { Action } from '../../../../framework/src/flux/action'; +import { Dispatch } from '../../../../framework/src/flux/store'; + +import { connectService } from '../services/connectService'; +import { NetworkElementConnection } from '../models/networkElementConnection'; +import { AddSnackbarNotification } from '../../../../framework/src/actions/snackbarActions'; +import { updateCurrentViewAsyncAction } from './commonNetworkElementsActions'; + +/** Represents the base action. */ +export class BaseAction extends Action { } + +/** Represents an action crator for a async thunk action to mount a network element. */ +export const mountNetworkElementAsyncActionCreator = (networkElement: NetworkElementConnection) => (dispatch: Dispatch) => { + return connectService.mountNetworkElement(networkElement).then((success) => { + if (success) { + dispatch(updateCurrentViewAsyncAction()); + dispatch(new AddSnackbarNotification({ message: `Requesting mount [${networkElement.nodeId}]`, options: { variant: 'info' } })) + } else { + dispatch(new AddSnackbarNotification({ message: `Failed to mount [${networkElement.nodeId}]`, options: { variant: 'warning' } })); + } + }).catch(error => { + dispatch(new AddSnackbarNotification({ message: `Failed to mount [${networkElement.nodeId}]`, options: { variant: 'error' } })); + console.error(error); + }); +}; + +/** Represents an action crator for a async thunk action to unmount a network element. */ +export const unmountNetworkElementAsyncActionCreator = (nodeId: string) => (dispatch: Dispatch) => { + return connectService.unmountNetworkElement(nodeId).then((success) => { + if (success) { + dispatch(updateCurrentViewAsyncAction()); + dispatch(new AddSnackbarNotification({ message: `Requesting unmount [${nodeId}]`, options: { variant: 'info' } })); + } else { + dispatch(new AddSnackbarNotification({ message: `Failed to unmount [${nodeId}]`, options: { variant: 'warning' } })); + } + }).catch(error => { + dispatch(new AddSnackbarNotification({ message: `Failed to unmount [${nodeId}]`, options: { variant: 'error' } })); + console.error(error); + }); +}; + + diff --git a/sdnr/wt/odlux/apps/connectApp/src/actions/networkElementsActions.ts b/sdnr/wt/odlux/apps/connectApp/src/actions/networkElementsActions.ts new file mode 100644 index 000000000..1a86f94b1 --- /dev/null +++ b/sdnr/wt/odlux/apps/connectApp/src/actions/networkElementsActions.ts @@ -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 { Action } from '../../../../framework/src/flux/action'; +import { Dispatch } from '../../../../framework/src/flux/store'; + +import { AddSnackbarNotification } from '../../../../framework/src/actions/snackbarActions'; + +import { NetworkElementConnection, ConnectionStatus, UpdateNetworkElement } from '../models/networkElementConnection'; +import { connectService } from '../services/connectService'; +import { updateCurrentViewAsyncAction } from './commonNetworkElementsActions'; +import { unmountNetworkElementAsyncActionCreator } from './mountedNetworkElementsActions'; + +/** Represents the base action. */ +export class BaseAction extends Action { } + +/** Represents an async thunk action creator to add an element to the network elements. */ +export const addNewNetworkElementAsyncActionCreator = (element: NetworkElementConnection) => async (dispatch: Dispatch) => { + const res = await connectService.createNetworkElement({ ...element }); + dispatch(updateCurrentViewAsyncAction()); + dispatch(new AddSnackbarNotification({ message: `Successfully added [${element.nodeId}]`, options: { variant: 'success' } })); +}; + +/** Represents an async thunk action creator to edit network element. */ +export const editNetworkElementAsyncActionCreator = (element: UpdateNetworkElement) => async (dispatch: Dispatch) => { + const connectionStatus: ConnectionStatus[] = await connectService.getNetworkElementConnectionStatus(element.id).then(ne => (ne)) || []; + const currentConnectionStatus = connectionStatus[0].status; + if (currentConnectionStatus === "Disconnected") { + const res = await connectService.deleteNetworkElement(element); + } + else { + const res = await connectService.updateNetworkElement(element); + } + dispatch(updateCurrentViewAsyncAction()); + dispatch(new AddSnackbarNotification({ message: `Successfully modified [${element.id}]`, options: { variant: 'success' } })); +}; + + +/** Represents an async thunk action creator to delete an element from network elements. */ +export const removeNetworkElementAsyncActionCreator = (element: UpdateNetworkElement) => async (dispatch: Dispatch) => { + const res = await connectService.deleteNetworkElement(element); + await dispatch(unmountNetworkElementAsyncActionCreator(element && element.id)); + dispatch(updateCurrentViewAsyncAction()); +}; + + + diff --git a/sdnr/wt/odlux/apps/connectApp/src/components/connectionStatusLog.tsx b/sdnr/wt/odlux/apps/connectApp/src/components/connectionStatusLog.tsx new file mode 100644 index 000000000..4e5ca65e1 --- /dev/null +++ b/sdnr/wt/odlux/apps/connectApp/src/components/connectionStatusLog.tsx @@ -0,0 +1,52 @@ +/** + * ============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 connect, { IDispatcher, Connect } from '../../../../framework/src/flux/connect'; +import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore'; +import { MaterialTable, ColumnType, MaterialTableCtorType } from '../../../../framework/src/components/material-table'; + +import { createConnectionStatusLogActions, createConnectionStatusLogProperties } from '../handlers/connectionStatusLogHandler'; +import { NetworkElementConnectionLog } from '../models/networkElementConnectionLog'; + +const mapProps = (state: IApplicationStoreState) => ({ + connectionStatusLogProperties: createConnectionStatusLogProperties(state), +}); + +const mapDispatch = (dispatcher: IDispatcher) => ({ + connectionStatusLogActions: createConnectionStatusLogActions(dispatcher.dispatch), +}); + +const ConnectionStatusTable = MaterialTable as MaterialTableCtorType; + +type ConnectionStatusLogComponentProps = Connect; + +class ConnectionStatusLogComponent extends React.Component { + render(): JSX.Element { + return ( + + + ); + }; +} + +export const ConnectionStatusLog = connect(mapProps, mapDispatch)(ConnectionStatusLogComponent); +export default ConnectionStatusLog; \ No newline at end of file diff --git a/sdnr/wt/odlux/apps/connectApp/src/components/editNetworkElementDialog.tsx b/sdnr/wt/odlux/apps/connectApp/src/components/editNetworkElementDialog.tsx new file mode 100644 index 000000000..1e1f11523 --- /dev/null +++ b/sdnr/wt/odlux/apps/connectApp/src/components/editNetworkElementDialog.tsx @@ -0,0 +1,252 @@ +/** + * ============LICENSE_START======================================================================== + * ONAP : ccsdk feature sdnr wt odlux + * ================================================================================================= + * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved. + * ================================================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + * ============LICENSE_END========================================================================== + */ +import * as React from 'react'; + +import Button from '@material-ui/core/Button'; +import TextField from '@material-ui/core/TextField'; +import Dialog from '@material-ui/core/Dialog'; +import DialogActions from '@material-ui/core/DialogActions'; +import DialogContent from '@material-ui/core/DialogContent'; +import DialogContentText from '@material-ui/core/DialogContentText'; +import DialogTitle from '@material-ui/core/DialogTitle'; +import { FormControl, InputLabel, Select, MenuItem } from '@material-ui/core'; + +import { IDispatcher, connect, Connect } from '../../../../framework/src/flux/connect'; + +import { + editNetworkElementAsyncActionCreator, + addNewNetworkElementAsyncActionCreator, + removeNetworkElementAsyncActionCreator +} from '../actions/networkElementsActions'; + +import { unmountNetworkElementAsyncActionCreator, mountNetworkElementAsyncActionCreator } from '../actions/mountedNetworkElementsActions'; +import { NetworkElementConnection, UpdateNetworkElement } from '../models/networkElementConnection'; +import { removeWebUriAction } from '../actions/commonNetworkElementsActions'; + +export enum EditNetworkElementDialogMode { + None = "none", + EditNetworkElement = "editNetworkElement", + RemoveNetworkElement = "removeNetworkElement", + AddNewNetworkElement = "addNewNetworkElement", + MountNetworkElement = "mountNetworkElement", + UnmountNetworkElement = "unmountNetworkElement", +} + +const mapDispatch = (dispatcher: IDispatcher) => ({ + addNewNetworkElement: async (element: NetworkElementConnection) => { + await dispatcher.dispatch(addNewNetworkElementAsyncActionCreator(element)); + await dispatcher.dispatch(mountNetworkElementAsyncActionCreator(element)); + }, + mountNetworkElement: (element: NetworkElementConnection) => dispatcher.dispatch(mountNetworkElementAsyncActionCreator(element)), + unmountNetworkElement: (element: NetworkElementConnection) => { + dispatcher.dispatch(unmountNetworkElementAsyncActionCreator(element && element.nodeId)); + }, + editNetworkElement: async (element: UpdateNetworkElement, mountElement: NetworkElementConnection) => { + await dispatcher.dispatch(editNetworkElementAsyncActionCreator(element)); + await dispatcher.dispatch(mountNetworkElementAsyncActionCreator(mountElement)); + }, + removeNetworkElement: (element: UpdateNetworkElement) => { + dispatcher.dispatch(removeNetworkElementAsyncActionCreator(element)); + dispatcher.dispatch(removeWebUriAction(element.id)); + } +}); + +type DialogSettings = { + dialogTitle: string, + dialogDescription: string, + applyButtonText: string, + cancelButtonText: string, + enableMountIdEditor: boolean, + enableUsernameEditor: boolean, + enableExtendedEditor: boolean, +} + +const settings: { [key: string]: DialogSettings } = { + [EditNetworkElementDialogMode.None]: { + dialogTitle: "", + dialogDescription: "", + applyButtonText: "", + cancelButtonText: "", + enableMountIdEditor: false, + enableUsernameEditor: false, + enableExtendedEditor: false, + }, + + [EditNetworkElementDialogMode.AddNewNetworkElement]: { + dialogTitle: "Add new network element", + dialogDescription: "Add this new network element:", + applyButtonText: "Add network element", + cancelButtonText: "Cancel", + enableMountIdEditor: true, + enableUsernameEditor: true, + enableExtendedEditor: true, + }, + [EditNetworkElementDialogMode.MountNetworkElement]: { + dialogTitle: "Mount network element", + dialogDescription: "mount this network element:", + applyButtonText: "mount network element", + cancelButtonText: "Cancel", + enableMountIdEditor: false, + enableUsernameEditor: false, + enableExtendedEditor: false, + }, + [EditNetworkElementDialogMode.UnmountNetworkElement]: { + dialogTitle: "Unmount network element", + dialogDescription: "unmount this network element:", + applyButtonText: "Unmount network element", + cancelButtonText: "Cancel", + enableMountIdEditor: false, + enableUsernameEditor: false, + enableExtendedEditor: false, + }, + [EditNetworkElementDialogMode.EditNetworkElement]: { + dialogTitle: "Modify the network elements", + dialogDescription: "Modify this network element", + applyButtonText: "Modify", + cancelButtonText: "Cancel", + enableMountIdEditor: false, + enableUsernameEditor: true, + enableExtendedEditor: false, + }, + [EditNetworkElementDialogMode.RemoveNetworkElement]: { + dialogTitle: "Remove network element", + dialogDescription: "Do you really want to remove this network element:", + applyButtonText: "Remove network element", + cancelButtonText: "Cancel", + enableMountIdEditor: false, + enableUsernameEditor: false, + enableExtendedEditor: false, + } +} + +type EditNetworkElementDialogComponentProps = Connect & { + mode: EditNetworkElementDialogMode; + initialNetworkElement: NetworkElementConnection; + onClose: () => void; +}; + +type EditNetworkElementDialogComponentState = NetworkElementConnection; + +class EditNetworkElementDialogComponent extends React.Component { + constructor(props: EditNetworkElementDialogComponentProps) { + super(props); + + this.state = { + nodeId: this.props.initialNetworkElement.nodeId, + isRequired: false, + host: this.props.initialNetworkElement.host, + port: this.props.initialNetworkElement.port, + }; + } + + render(): JSX.Element { + const setting = settings[this.props.mode]; + return ( + + {setting.dialogTitle} + + + {setting.dialogDescription} + + { this.setState({ nodeId: event.target.value }); }} /> + { this.setState({ host: event.target.value }); }} /> + { this.setState({ port: +event.target.value }); }} /> + {setting.enableUsernameEditor && { this.setState({ username: event.target.value }); }} /> || null} + {setting.enableUsernameEditor && { this.setState({ password: event.target.value }); }} /> || null} + + Required + + + + + + + + + ) + } + + private onApply = (element: NetworkElementConnection) => { + this.props.onClose && this.props.onClose(); + let updateElement: UpdateNetworkElement = { + id: this.state.nodeId + } + switch (this.props.mode) { + case EditNetworkElementDialogMode.AddNewNetworkElement: + element && this.props.addNewNetworkElement(element); + break; + case EditNetworkElementDialogMode.MountNetworkElement: + element && this.props.mountNetworkElement(element); + break; + case EditNetworkElementDialogMode.UnmountNetworkElement: + element && this.props.unmountNetworkElement(element); + break; + case EditNetworkElementDialogMode.EditNetworkElement: + if (this.props.initialNetworkElement.isRequired !== this.state.isRequired) + updateElement.isRequired = this.state.isRequired; + if (this.props.initialNetworkElement.username !== this.state.username) + updateElement.username = this.state.username; + if (this.props.initialNetworkElement.password !== this.state.password) + updateElement.password = this.state.password; + element && this.props.editNetworkElement(updateElement, element); + break; + case EditNetworkElementDialogMode.RemoveNetworkElement: + element && this.props.removeNetworkElement(updateElement); + break; + } + }; + + private onCancel = () => { + this.props.onClose && this.props.onClose(); + } + + static getDerivedStateFromProps(props: EditNetworkElementDialogComponentProps, state: EditNetworkElementDialogComponentState & { _initialNetworkElement: NetworkElementConnection }): EditNetworkElementDialogComponentState & { _initialNetworkElement: NetworkElementConnection } { + if (props.initialNetworkElement !== state._initialNetworkElement) { + state = { + ...state, + ...props.initialNetworkElement, + _initialNetworkElement: props.initialNetworkElement, + }; + } + return state; + } +} + +export const EditNetworkElementDialog = connect(undefined, mapDispatch)(EditNetworkElementDialogComponent); +export default EditNetworkElementDialog; \ No newline at end of file diff --git a/sdnr/wt/odlux/apps/connectApp/src/components/infoNetworkElementDialog.tsx b/sdnr/wt/odlux/apps/connectApp/src/components/infoNetworkElementDialog.tsx new file mode 100644 index 000000000..ea9d419ec --- /dev/null +++ b/sdnr/wt/odlux/apps/connectApp/src/components/infoNetworkElementDialog.tsx @@ -0,0 +1,154 @@ +/** + * ============LICENSE_START======================================================================== + * ONAP : ccsdk feature sdnr wt odlux + * ================================================================================================= + * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved. + * ================================================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + * ============LICENSE_END========================================================================== + */ +import * as React from 'react'; + +import Button from '@material-ui/core/Button'; +import Dialog from '@material-ui/core/Dialog'; +import DialogActions from '@material-ui/core/DialogActions'; +import DialogContent from '@material-ui/core/DialogContent'; +import DialogContentText from '@material-ui/core/DialogContentText'; +import DialogTitle from '@material-ui/core/DialogTitle'; +import Table from '@material-ui/core/Table'; +import TableBody from '@material-ui/core/TableBody'; +import TableCell from '@material-ui/core/TableCell'; +import TableHead from '@material-ui/core/TableHead'; +import TableRow from '@material-ui/core/TableRow'; +import { IDispatcher, connect, Connect } from '../../../../framework/src/flux/connect'; + +import { NetworkElementConnection } from '../models/networkElementConnection'; +import { AvailableCapabilities } from '../models/yangCapabilitiesType' + +export enum InfoNetworkElementDialogMode { + None = "none", + InfoNetworkElement = "infoNetworkElement" +} + +const mapDispatch = (dispatcher: IDispatcher) => ({ +}); + +type DialogSettings = { + dialogTitle: string, + dialogDescription: string, + cancelButtonText: string, +} + +const settings: { [key: string]: DialogSettings } = { + [InfoNetworkElementDialogMode.None]: { + dialogTitle: "", + dialogDescription: "", + cancelButtonText: "", + }, + [InfoNetworkElementDialogMode.InfoNetworkElement]: { + dialogTitle: "Yang capabilities of the network element", + dialogDescription: "Available capabilities of the network element", + cancelButtonText: "Cancel", + } +} + +type InfoNetworkElementDialogComponentProps = Connect & { + mode: InfoNetworkElementDialogMode; + initialNetworkElement: NetworkElementConnection; + onClose: () => void; +}; + +type InfoNetworkElementDialogComponentState = NetworkElementConnection; + +class InfoNetworkElementDialogComponent extends React.Component { + constructor(props: InfoNetworkElementDialogComponentProps) { + super(props); + + this.state = { + nodeId: this.props.initialNetworkElement.nodeId, + isRequired: false, + host: this.props.initialNetworkElement.host, + port: this.props.initialNetworkElement.port, + }; + } + + render(): JSX.Element { + const setting = settings[this.props.mode]; + const availableCapabilities = this.props.state.connect.elementInfo.elementInfo["netconf-node-topology:available-capabilities"]["available-capability"]; + let yangCapabilities: AvailableCapabilities[] = []; + + availableCapabilities.forEach(value => { + const capabilty = value.capability; + const indexRevision = capabilty.indexOf("revision="); + const indexModule = capabilty.indexOf(")", indexRevision); + if (indexRevision > 0 && indexModule > 0) { + yangCapabilities.push({ + module: capabilty.substr(indexModule + 1), + revision: capabilty.substr(indexRevision + 9, 10) + }); + } + }); + + return ( + + {setting.dialogTitle} + + + {setting.dialogDescription + " " + this.state.nodeId} + + + + + S.No + Module + Revision + + + + {yangCapabilities.map((yang, index) => ( + + {index + 1} + {yang.module} + {yang.revision} + + ))} + +
+
+ + + +
+ ) + } + + private onCancel = () => { + this.props.onClose(); + } + + static getDerivedStateFromProps(props: InfoNetworkElementDialogComponentProps, state: InfoNetworkElementDialogComponentState & { _initialNetworkElement: NetworkElementConnection }): InfoNetworkElementDialogComponentState & { _initialNetworkElement: NetworkElementConnection } { + if (props.initialNetworkElement !== state._initialNetworkElement) { + state = { + ...state, + ...props.initialNetworkElement, + _initialNetworkElement: props.initialNetworkElement, + }; + } + return state; + } +} + +export const InfoNetworkElementDialog = connect(undefined, mapDispatch)(InfoNetworkElementDialogComponent); +export default InfoNetworkElementDialog; \ No newline at end of file diff --git a/sdnr/wt/odlux/apps/connectApp/src/components/networkElements.tsx b/sdnr/wt/odlux/apps/connectApp/src/components/networkElements.tsx new file mode 100644 index 000000000..0f4b0e8ff --- /dev/null +++ b/sdnr/wt/odlux/apps/connectApp/src/components/networkElements.tsx @@ -0,0 +1,259 @@ +/** +* ============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 { Theme, createStyles, withStyles, WithStyles } from '@material-ui/core/styles'; + +import AddIcon from '@material-ui/icons/Add'; +import LinkIcon from '@material-ui/icons/Link'; +import LinkOffIcon from '@material-ui/icons/LinkOff'; +import RemoveIcon from '@material-ui/icons/RemoveCircleOutline'; +import EditIcon from '@material-ui/icons/Edit'; +import Info from '@material-ui/icons/Info'; +import ComputerIcon from '@material-ui/icons/Computer'; + +import Button from '@material-ui/core/Button'; +import IconButton from '@material-ui/core/IconButton'; +import Tooltip from '@material-ui/core/Tooltip'; + +import { MaterialTable, ColumnType, MaterialTableCtorType } from '../../../../framework/src/components/material-table'; +import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore'; +import { connect, Connect, IDispatcher } from '../../../../framework/src/flux/connect'; +import { NavigateToApplication } from '../../../../framework/src/actions/navigationActions'; + +import { createNetworkElementsActions, createNetworkElementsProperties } from '../handlers/networkElementsHandler'; + +import { NetworkElementConnection } from '../models/networkElementConnection'; +import EditNetworkElementDialog, { EditNetworkElementDialogMode } from './editNetworkElementDialog'; + +import InfoNetworkElementDialog, { InfoNetworkElementDialogMode } from './infoNetworkElementDialog'; +import { loadAllInfoElementAsync } from '../actions/infoNetworkElementActions'; +import { TopologyNode } from '../models/topologyNetconf'; + +const styles = (theme: Theme) => createStyles({ + connectionStatusConnected: { + color: 'darkgreen', + }, + connectionStatusConnecting: { + color: 'blue', + }, + connectionStatusDisconnected: { + color: 'red', + }, + button: { + margin: 0, + padding: "6px 6px", + minWidth: 'unset' + }, + spacer: { + marginLeft: theme.spacing(1), + marginRight: theme.spacing(1), + display: "inline" + } +}); + +const mapProps = (state: IApplicationStoreState) => ({ + networkElementsProperties: createNetworkElementsProperties(state), +}); + +const mapDispatch = (dispatcher: IDispatcher) => ({ + networkElementsActions: createNetworkElementsActions(dispatcher.dispatch), + navigateToApplication: (applicationName: string, path?: string) => dispatcher.dispatch(new NavigateToApplication(applicationName, path)), + networkElementInfo: async (nodeId: string) => await dispatcher.dispatch(loadAllInfoElementAsync(nodeId)), +}); + +type NetworkElementsListComponentProps = WithStyles & Connect; +type NetworkElementsListComponentState = { + networkElementToEdit: NetworkElementConnection, + networkElementEditorMode: EditNetworkElementDialogMode, + infoNetworkElementEditorMode: InfoNetworkElementDialogMode, + elementInfo: TopologyNode | null +} + +const emptyRequireNetworkElement: NetworkElementConnection = { id: "", nodeId: "", host: "", port: 0, status: "Disconnected", isRequired: false }; + +const NetworkElementTable = MaterialTable as MaterialTableCtorType; + +export class NetworkElementsListComponent extends React.Component { + + constructor(props: NetworkElementsListComponentProps) { + super(props); + + this.state = { + networkElementToEdit: emptyRequireNetworkElement, + networkElementEditorMode: EditNetworkElementDialogMode.None, + elementInfo: null, + infoNetworkElementEditorMode: InfoNetworkElementDialogMode.None + }; + } + + // private navigationCreator + + render(): JSX.Element { + const { classes } = this.props; + const { networkElementToEdit } = this.state; + const addRequireNetworkElementAction = { + icon: AddIcon, tooltip: 'Add', onClick: () => { + this.setState({ + networkElementEditorMode: EditNetworkElementDialogMode.AddNewNetworkElement, + networkElementToEdit: emptyRequireNetworkElement, + }); + } + }; + let counter = 0; + return ( + <> + { + counter++; + return ( + <> +
+ { + rowData.webUri && { console.log(rowData); window.open(rowData.webUri, "_blank") }}> + } + + this.onOpenMountdNetworkElementsDialog(event, rowData)} > + + + + this.onOpenUnmountdNetworkElementsDialog(event, rowData)} > + + + this.onOpenInfoNetworkElementDialog(event, rowData)} disabled={rowData.status === "Connecting" || rowData.status === "Disconnected"} > + + + this.onOpenEditNetworkElementDialog(event, rowData)} > + this.onOpenRemoveNetworkElementDialog(event, rowData)} > +
+
+ +
+
+ + + + + +
+ + ) + } + }, + ]} idProperty="id" {...this.props.networkElementsActions} {...this.props.networkElementsProperties} asynchronus > +
+ + + + ); + }; + + public componentDidMount() { + this.props.networkElementsActions.onRefresh(); + } + + private onOpenRemoveNetworkElementDialog = (event: React.MouseEvent, element: NetworkElementConnection) => { + this.setState({ + networkElementToEdit: element, + networkElementEditorMode: EditNetworkElementDialogMode.RemoveNetworkElement + }); + event.preventDefault(); + event.stopPropagation(); + } + + private onOpenEditNetworkElementDialog = (event: React.MouseEvent, element: NetworkElementConnection) => { + this.setState({ + networkElementToEdit: { + nodeId: element.nodeId, + isRequired: element.isRequired, + host: element.host, + port: element.port, + username: element.username, + password: element.password, + }, + networkElementEditorMode: EditNetworkElementDialogMode.EditNetworkElement + }); + event.preventDefault(); + event.stopPropagation(); + } + + private onOpenUnmountdNetworkElementsDialog = (event: React.MouseEvent, element: NetworkElementConnection) => { + this.setState({ + networkElementToEdit: element, + networkElementEditorMode: EditNetworkElementDialogMode.UnmountNetworkElement + }); + event.preventDefault(); + event.stopPropagation(); + } + + private onOpenMountdNetworkElementsDialog = (event: React.MouseEvent, element: NetworkElementConnection) => { + this.setState({ + networkElementToEdit: element, + networkElementEditorMode: EditNetworkElementDialogMode.MountNetworkElement + }); + event.preventDefault(); + event.stopPropagation(); + } + + private onOpenInfoNetworkElementDialog = (event: React.MouseEvent, element: NetworkElementConnection) => { + this.props.networkElementInfo(element.nodeId); + this.setState({ + networkElementToEdit: element, + infoNetworkElementEditorMode: InfoNetworkElementDialogMode.InfoNetworkElement, + }); + event.preventDefault(); + event.stopPropagation(); + } + + private onCloseEditNetworkElementDialog = () => { + this.setState({ + networkElementEditorMode: EditNetworkElementDialogMode.None, + networkElementToEdit: emptyRequireNetworkElement, + }); + } + private onCloseInfoNetworkElementDialog = () => { + this.setState({ + infoNetworkElementEditorMode: InfoNetworkElementDialogMode.None, + networkElementToEdit: emptyRequireNetworkElement, + }); + } + + private navigateToApplicationHandlerCreator = (applicationName: string, element: NetworkElementConnection) => (event: React.MouseEvent) => { + this.props.navigateToApplication(applicationName, element.nodeId); + event.preventDefault(); + event.stopPropagation(); + } +} + +export const NetworkElementsList = withStyles(styles)(connect(mapProps, mapDispatch)(NetworkElementsListComponent)); +export default NetworkElementsList; \ No newline at end of file diff --git a/sdnr/wt/odlux/apps/connectApp/src/handlers/connectAppRootHandler.ts b/sdnr/wt/odlux/apps/connectApp/src/handlers/connectAppRootHandler.ts new file mode 100644 index 000000000..1440599fd --- /dev/null +++ b/sdnr/wt/odlux/apps/connectApp/src/handlers/connectAppRootHandler.ts @@ -0,0 +1,83 @@ +/** + * ============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 { combineActionHandler } from '../../../../framework/src/flux/middleware'; +import { INetworkElementsState, networkElementsActionHandler } from './networkElementsHandler'; +import { IConnectionStatusLogState, connectionStatusLogActionHandler } from './connectionStatusLogHandler'; +import { IInfoNetworkElementsState, infoNetworkElementsActionHandler } from './infoNetworkElementHandler'; +import { SetPanelAction, AddWebUriList, RemoveWebUri } from '../actions/commonNetworkElementsActions'; +import { PanelId } from '../models/panelId'; +import { guiCutThrough } from '../models/guiCutTrough'; + +export interface IConnectAppStoreState { + networkElements: INetworkElementsState; + connectionStatusLog: IConnectionStatusLogState; + currentOpenPanel: PanelId; + elementInfo: IInfoNetworkElementsState; + guiCutThrough: guiCutThroughState; +} + +const currentOpenPanelHandler: IActionHandler = (state = null, action) => { + if (action instanceof SetPanelAction) { + state = action.panelId; + } + return state; +} + +interface guiCutThroughState { + availableWebUris: guiCutThrough[]; + knownElements: string[]; +} + +const guiCutThroughHandler: IActionHandler = (state = { availableWebUris: [], knownElements: [] }, action) => { + if (action instanceof AddWebUriList) { + let knownElements: string[]; + let availableWebUris: guiCutThrough[]; + + knownElements = state.knownElements.concat(action.knownElements); + + availableWebUris = state.availableWebUris.concat(action.element); + + state = { availableWebUris: availableWebUris, knownElements: knownElements } + + } 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 }; + } + return state; +} + +declare module '../../../../framework/src/store/applicationStore' { + interface IApplicationStoreState { + connect: IConnectAppStoreState + } +} + +const actionHandlers = { + networkElements: networkElementsActionHandler, + connectionStatusLog: connectionStatusLogActionHandler, + currentOpenPanel: currentOpenPanelHandler, + elementInfo: infoNetworkElementsActionHandler, + guiCutThrough: guiCutThroughHandler +}; + +export const connectAppRootHandler = combineActionHandler(actionHandlers); +export default connectAppRootHandler; diff --git a/sdnr/wt/odlux/apps/connectApp/src/handlers/connectionStatusLogHandler.ts b/sdnr/wt/odlux/apps/connectApp/src/handlers/connectionStatusLogHandler.ts new file mode 100644 index 000000000..6863ec33b --- /dev/null +++ b/sdnr/wt/odlux/apps/connectApp/src/handlers/connectionStatusLogHandler.ts @@ -0,0 +1,35 @@ +/** + * ============LICENSE_START======================================================================== + * ONAP : ccsdk feature sdnr wt odlux + * ================================================================================================= + * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved. + * ================================================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + * ============LICENSE_END========================================================================== + */ +import { createExternal,IExternalTableState } from '../../../../framework/src/components/material-table/utilities'; +import { createSearchDataHandler } from '../../../../framework/src/utilities/elasticSearch'; + +import { NetworkElementConnectionLog } from '../models/networkElementConnectionLog'; +export interface IConnectionStatusLogState extends IExternalTableState { } + +// create eleactic search material data fetch handler +const connectionStatusLogSearchHandler = createSearchDataHandler('connectionlog'); + +export const { + actionHandler: connectionStatusLogActionHandler, + createActions: createConnectionStatusLogActions, + createProperties: createConnectionStatusLogProperties, + reloadAction: connectionStatusLogReloadAction, + + // set value action, to change a value +} = createExternal(connectionStatusLogSearchHandler, appState => appState.connect.connectionStatusLog); + diff --git a/sdnr/wt/odlux/apps/connectApp/src/handlers/infoNetworkElementHandler.ts b/sdnr/wt/odlux/apps/connectApp/src/handlers/infoNetworkElementHandler.ts new file mode 100644 index 000000000..d67a81ec4 --- /dev/null +++ b/sdnr/wt/odlux/apps/connectApp/src/handlers/infoNetworkElementHandler.ts @@ -0,0 +1,60 @@ +/** + * ============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 { AllElementInfoLoadedAction, LoadAllElementInfoAction } from '../actions/infoNetworkElementActions'; + +import { TopologyNode } from '../models/topologyNetconf'; + +export interface IInfoNetworkElementsState { + elementInfo: TopologyNode; + busy: boolean; +} + +const infoNetworkElementsStateInit: IInfoNetworkElementsState = { + elementInfo: { + "node-id": "", + "netconf-node-topology:available-capabilities": { + "available-capability": [] + } + }, + busy: false +}; + +export const infoNetworkElementsActionHandler: IActionHandler = (state = infoNetworkElementsStateInit, action) => { + if (action instanceof LoadAllElementInfoAction) { + state = { + ...state, + busy: true + }; + } else if (action instanceof AllElementInfoLoadedAction) { + if (!action.error && action.elementInfo) { + state = { + ...state, + elementInfo: action.elementInfo, + busy: false + }; + } else { + state = { + ...state, + busy: false + }; + } + } + return state; +}; \ No newline at end of file diff --git a/sdnr/wt/odlux/apps/connectApp/src/handlers/networkElementsHandler.ts b/sdnr/wt/odlux/apps/connectApp/src/handlers/networkElementsHandler.ts new file mode 100644 index 000000000..78c7000d2 --- /dev/null +++ b/sdnr/wt/odlux/apps/connectApp/src/handlers/networkElementsHandler.ts @@ -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 { createExternal, IExternalTableState } from '../../../../framework/src/components/material-table/utilities'; +import { createSearchDataHandler } from '../../../../framework/src/utilities/elasticSearch'; + +import { NetworkElementConnection } from '../models/networkElementConnection'; +import connectService from '../services/connectService'; +import { requestRest } from '../../../../framework/src/services/restService'; +export interface INetworkElementsState extends IExternalTableState { } + +// create eleactic search material data fetch handler +const networkElementsSearchHandler = createSearchDataHandler('network-element-connection'); + +export const { + actionHandler: networkElementsActionHandler, + createActions: createNetworkElementsActions, + createProperties: createNetworkElementsProperties, + reloadAction: networkElementsReloadAction, + + // set value action, to change a value +} = createExternal(networkElementsSearchHandler, appState => { + + const webUris = appState.connect.guiCutThrough.availableWebUris; + if (appState.connect.networkElements.rows && webUris.length > 0) { + + appState.connect.networkElements.rows.forEach(element => { + + if (element.status === "Connected") { + const webUri = webUris.find(item => item.nodeId === element.id as string); + if (webUri) { + element.webUri = webUri.webUri; + element.isWebUriUnreachable = false; + } + else { + element.isWebUriUnreachable = true + } + } + }); + } + + return appState.connect.networkElements +}); + diff --git a/sdnr/wt/odlux/apps/connectApp/src/index.html b/sdnr/wt/odlux/apps/connectApp/src/index.html new file mode 100644 index 000000000..9c8a2063e --- /dev/null +++ b/sdnr/wt/odlux/apps/connectApp/src/index.html @@ -0,0 +1,27 @@ + + + + + + + + + connectApp + + + +
+ + + + + + \ No newline at end of file diff --git a/sdnr/wt/odlux/apps/connectApp/src/models/connectionStatusLog.ts b/sdnr/wt/odlux/apps/connectApp/src/models/connectionStatusLog.ts new file mode 100644 index 000000000..df43c217a --- /dev/null +++ b/sdnr/wt/odlux/apps/connectApp/src/models/connectionStatusLog.ts @@ -0,0 +1,27 @@ +/** + * ============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 ConnectionStatusLogType = { + _id: string; + elementStatus: string; + timeStamp: string; + objectId: string; + type: string; + newValue: string; +} + diff --git a/sdnr/wt/odlux/apps/connectApp/src/models/guiCutTrough.ts b/sdnr/wt/odlux/apps/connectApp/src/models/guiCutTrough.ts new file mode 100644 index 000000000..4b443bac8 --- /dev/null +++ b/sdnr/wt/odlux/apps/connectApp/src/models/guiCutTrough.ts @@ -0,0 +1 @@ +export type guiCutThrough = { webUri: string, nodeId: string } \ No newline at end of file diff --git a/sdnr/wt/odlux/apps/connectApp/src/models/networkElementBase.ts b/sdnr/wt/odlux/apps/connectApp/src/models/networkElementBase.ts new file mode 100644 index 000000000..39278a8e1 --- /dev/null +++ b/sdnr/wt/odlux/apps/connectApp/src/models/networkElementBase.ts @@ -0,0 +1,22 @@ +/** + * ============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 NetworkElementBaseType = { + mountId: string, + host: string, + port: number, +} \ No newline at end of file diff --git a/sdnr/wt/odlux/apps/connectApp/src/models/networkElementConnection.ts b/sdnr/wt/odlux/apps/connectApp/src/models/networkElementConnection.ts new file mode 100644 index 000000000..4c2dc9b09 --- /dev/null +++ b/sdnr/wt/odlux/apps/connectApp/src/models/networkElementConnection.ts @@ -0,0 +1,36 @@ +export type NetworkElementConnection = { + id?: string; + nodeId: string; + isRequired: boolean; + host: string; + port: number; + username?: string; + password?: string; + webUri?: string; + isWebUriUnreachable?: boolean; + status?: "Connected" | "mounted" | "unmounted" | "Connecting" | "Disconnected" | "idle"; + coreModelCapability?: string; + deviceType?: string; + nodeDetails?: { + availableCapabilites: { + capabilityOrigin: string; + capability: string; + }[]; + unavailableCapabilities: { + failureReason: string; + capability: string; + }[]; + } +} + + +export type UpdateNetworkElement = { + id: string; + isRequired?: boolean; + username?: string; + password?: string; +} + +export type ConnectionStatus = { + status: string +} \ No newline at end of file diff --git a/sdnr/wt/odlux/apps/connectApp/src/models/networkElementConnectionLog.ts b/sdnr/wt/odlux/apps/connectApp/src/models/networkElementConnectionLog.ts new file mode 100644 index 000000000..a1535cbe5 --- /dev/null +++ b/sdnr/wt/odlux/apps/connectApp/src/models/networkElementConnectionLog.ts @@ -0,0 +1,25 @@ +/** + * ============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 NetworkElementConnectionLog = { + id: string; + nodeId: string; + status: "connected" | "mounted" | "unmounted" | "connecting" | "disconnected" | "idle"; + timestamp: string; +} + diff --git a/sdnr/wt/odlux/apps/connectApp/src/models/panelId.ts b/sdnr/wt/odlux/apps/connectApp/src/models/panelId.ts new file mode 100644 index 000000000..b51412055 --- /dev/null +++ b/sdnr/wt/odlux/apps/connectApp/src/models/panelId.ts @@ -0,0 +1 @@ +export type PanelId = null | "NetworkElements" | "ConnectionStatusLog"; \ No newline at end of file diff --git a/sdnr/wt/odlux/apps/connectApp/src/models/topologyNetconf.ts b/sdnr/wt/odlux/apps/connectApp/src/models/topologyNetconf.ts new file mode 100644 index 000000000..694009d1b --- /dev/null +++ b/sdnr/wt/odlux/apps/connectApp/src/models/topologyNetconf.ts @@ -0,0 +1,36 @@ +/** + * ============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 interface AvailableCapability { + "capability-origin": string; + capability: string; +} + +export interface NetconfNodeTopologyAvailableCapabilities { + "available-capability": AvailableCapability[]; +} + +export interface TopologyNode { + "node-id": string; + "netconf-node-topology:available-capabilities": NetconfNodeTopologyAvailableCapabilities; +} + +export interface Topology { + "topology-id": string; + node: TopologyNode[]; +} diff --git a/sdnr/wt/odlux/apps/connectApp/src/models/yangCapabilitiesType.ts b/sdnr/wt/odlux/apps/connectApp/src/models/yangCapabilitiesType.ts new file mode 100644 index 000000000..230468287 --- /dev/null +++ b/sdnr/wt/odlux/apps/connectApp/src/models/yangCapabilitiesType.ts @@ -0,0 +1,22 @@ +/** + * ============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 AvailableCapabilities = { + module: string, + revision: string +} \ No newline at end of file diff --git a/sdnr/wt/odlux/apps/connectApp/src/pluginConnect.tsx b/sdnr/wt/odlux/apps/connectApp/src/pluginConnect.tsx new file mode 100644 index 000000000..f711c440c --- /dev/null +++ b/sdnr/wt/odlux/apps/connectApp/src/pluginConnect.tsx @@ -0,0 +1,56 @@ +/** + * ============LICENSE_START======================================================================== + * ONAP : ccsdk feature sdnr wt odlux + * ================================================================================================= + * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved. + * ================================================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + * ============LICENSE_END========================================================================== + */ + +import { faPlug } from '@fortawesome/free-solid-svg-icons'; + +import applicationManager from '../../../framework/src/services/applicationManager'; +import { subscribe, IFormatedMessage } from '../../../framework/src/services/notificationService'; + +import connectAppRootHandler from './handlers/connectAppRootHandler'; +import ConnectApplication from './views/connectView'; + +import { AddSnackbarNotification } from '../../../framework/src/actions/snackbarActions'; +import { updateCurrentViewAsyncAction } from './actions/commonNetworkElementsActions'; + +type ObjectNotification = { + counter: string; + nodeName: string; + objectId: string; + timeStamp: string; +} + +export function register() { + const applicationApi = applicationManager.registerApplication({ + name: "connect", + icon: faPlug, + rootComponent: ConnectApplication, + rootActionHandler: connectAppRootHandler, + menuEntry: "Connect" + }); + + // subscribe to the websocket notifications + subscribe(["ObjectCreationNotification", "ObjectDeletionNotification", "AttributeValueChangedNotification"], (msg => { + const store = applicationApi.applicationStore; + if (msg && msg.notifType === "ObjectCreationNotification" && store) { + store.dispatch(new AddSnackbarNotification({ message: `Adding network element [${msg.objectId}]`, options: { variant: 'info' } })); + } else if (msg && (msg.notifType === "ObjectDeletionNotification" || msg.notifType === "AttributeValueChangedNotification") && store) { + store.dispatch(new AddSnackbarNotification({ message: `Updating network element [${msg.objectId}]`, options: { variant: 'info' } })); + } + store && store.dispatch(updateCurrentViewAsyncAction()); + })); +} \ 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 new file mode 100644 index 000000000..7a410f4ae --- /dev/null +++ b/sdnr/wt/odlux/apps/connectApp/src/services/connectService.ts @@ -0,0 +1,208 @@ +/** + * ============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 } from '../../../../framework/src/services/restService'; +import { NetworkElementConnection, ConnectionStatus, UpdateNetworkElement } from '../models/networkElementConnection'; +import { convertPropertyNames, replaceUpperCase } from '../../../../framework/src/utilities/yangHelper'; +import { Result } from '../../../../framework/src/models/elasticSearch'; + +import { Topology, TopologyNode } from '../models/topologyNetconf'; +import { guiCutThrough } from '../models/guiCutTrough'; + +/** +* Represents a web api accessor service for all Network Elements actions. +*/ +class ConnectService { + + /** + * Inserts a network elements. + */ + public async createNetworkElement(element: NetworkElementConnection): Promise { + const path = `/restconf/operations/data-provider:create-network-element-connection`; + const result = await requestRest(path, { + method: "POST", body: JSON.stringify(convertPropertyNames({ input: element }, replaceUpperCase)) + }); + return result || null; + } + + /** + * Updates a network element. + */ + public async updateNetworkElement(element: UpdateNetworkElement): Promise { + const path = `/restconf/operations/data-provider:update-network-element-connection`; + const result = await requestRest(path, { + method: "POST", body: JSON.stringify(convertPropertyNames({ input: element }, replaceUpperCase)) + }); + return result || null; + } + + /** + * Deletes a network element. + */ + public async deleteNetworkElement(element: UpdateNetworkElement): Promise { + const query = { + "id": element.id + }; + const path = `/restconf/operations/data-provider:delete-network-element-connection`; + const result = await requestRest(path, { + method: "POST", body: JSON.stringify(convertPropertyNames({ input: query }, replaceUpperCase)) + }); + return result || null; + } + + /** Mounts network element. */ + public async mountNetworkElement(networkElement: NetworkElementConnection): Promise { + const path = 'restconf/config/network-topology:network-topology/topology/topology-netconf/node/' + networkElement.nodeId; + const mountXml = [ + '', + `${networkElement.nodeId}`, + `${networkElement.host}`, + `${networkElement.port}`, + `${networkElement.username}`, + `${networkElement.password}`, + ' false', + + ' ', + ' false', + ' 20000', + ' 100', + ' 2000', + ' 1.5', + + ' ', + ' 120', + ''].join(''); + + try { + const result = await requestRest(path, { + method: 'PUT', + headers: { + 'Content-Type': 'application/xml', + 'Accept': 'application/xml' + }, + body: mountXml + }); + // expect an empty answer + return result !== null; + } catch { + return false; + } + }; + + /** Unmounts a network element by its id. */ + public async unmountNetworkElement(nodeId: string): Promise { + const path = 'restconf/config/network-topology:network-topology/topology/topology-netconf/node/' + nodeId; + + try { + const result = await requestRest(path, { + method: 'DELETE', + headers: { + 'Content-Type': 'application/xml', + 'Accept': 'application/xml' + }, + }); + // expect an empty answer + return result !== null; + + } catch { + return false; + } + }; + + /** Yang capabilities of the selected network elements. */ + public async infoNetworkElement(nodeId: string): Promise { + const path = 'restconf/operational/network-topology:network-topology/topology/topology-netconf/node/' + nodeId; + const topologyRequestPomise = requestRest(path, { method: "GET" }); + + return topologyRequestPomise && topologyRequestPomise.then(result => { + return result && result.node && result.node[0] || null; + }); + } + + /** + * Get the connection state of the network element. + */ + public async getNetworkElementConnectionStatus(element: string): Promise<(ConnectionStatus)[] | null> { + const path = `/restconf/operations/data-provider:read-network-element-connection-list`; + const query = { + "input": { + "filter": [{ + "property": "node-id", + "filtervalue": element + }], + "pagination": { + "size": 20, + "page": 1 + } + } + } + const result = await requestRest>(path, { method: "POST", body: JSON.stringify(query) }); + return result && result.output && result.output.data && result.output.data.map(ne => ({ + status: ne.status + })) || null; + } + + public async getWebUriExtensionForNetworkElementAsync(ne: string) { + const path = 'restconf/config/network-topology:network-topology/topology/topology-netconf/node/' + ne + '/yang-ext:mount/core-model:network-element'; + try { + const result = await requestRest(path, { method: "GET" }); + + if (result['network-element'].extension) { + const webUri = result['network-element'].extension.find((item: any) => item['value-name'] === "webUri") + if (webUri) { + return webUri.value as string; + } + } + } catch (error) { + console.log(ne + ' unrechable: ' + error) + } + + return undefined; + + } + + public getAllWebUriExtensionsForNetworkElementListAsync(ne: string[]) { + + let promises: any[] = []; + let webUris: guiCutThrough[] = [] + + ne.forEach(nodeId => { + const path = 'restconf/config/network-topology:network-topology/topology/topology-netconf/node/' + nodeId + '/yang-ext:mount/core-model:network-element'; + + // add search request to array + promises.push(requestRest(path, { method: "GET" }) + .then(result => { + + if (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 }); + } + } + }) + .catch(error => console.log("network element is unreachable: " + error))) + + }) + + // wait until all promises are done and return weburis + return Promise.all(promises).then(result => { return webUris }); + } + +} +export const connectService = new ConnectService(); +export default connectService; diff --git a/sdnr/wt/odlux/apps/connectApp/src/views/connectView.tsx b/sdnr/wt/odlux/apps/connectApp/src/views/connectView.tsx new file mode 100644 index 000000000..aa3391c47 --- /dev/null +++ b/sdnr/wt/odlux/apps/connectApp/src/views/connectView.tsx @@ -0,0 +1,111 @@ +/** + * ============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 connect, { IDispatcher, Connect } from '../../../../framework/src/flux/connect'; +import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore'; +import { Panel } from '../../../../framework/src/components/material-ui'; +import { networkElementsReloadAction, createNetworkElementsActions } from '../handlers/networkElementsHandler'; +import { connectionStatusLogReloadAction, createConnectionStatusLogActions } from '../handlers/connectionStatusLogHandler'; + +import { NetworkElementsList } from '../components/networkElements'; +import { ConnectionStatusLog } from '../components/connectionStatusLog'; +import { setPanelAction, findWebUrisForGuiCutThroughAsyncAction } from '../actions/commonNetworkElementsActions'; +import { PanelId } from '../models/panelId'; +import { NetworkElementConnection } from 'models/networkElementConnection'; + +const mapProps = (state: IApplicationStoreState) => ({ + panelId: state.connect.currentOpenPanel, + user: state.framework.authenticationState.user, + netWorkElements: state.connect.networkElements, + availableGuiCutroughs: state.connect.guiCutThrough +}); + +const mapDispatcher = (dispatcher: IDispatcher) => ({ + networkElementsActions: createNetworkElementsActions(dispatcher.dispatch), + connectionStatusLogActions: createConnectionStatusLogActions(dispatcher.dispatch), + onLoadNetworkElements: () => { + dispatcher.dispatch(networkElementsReloadAction); + }, + loadWebUris: findWebUrisForGuiCutThroughAsyncAction(dispatcher.dispatch), + onLoadConnectionStatusLog: () => { + dispatcher.dispatch(connectionStatusLogReloadAction); + }, + switchActivePanel: (panelId: PanelId) => { + dispatcher.dispatch(setPanelAction(panelId)); + } +}); + +type ConnectApplicationComponentProps = Connect; + +class ConnectApplicationComponent extends React.Component{ + + componentDidUpdate = () => { + // 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); + } + } + + private onTogglePanel = (panelId: PanelId) => { + const nextActivePanel = panelId === this.props.panelId ? null : panelId; + this.props.switchActivePanel(nextActivePanel); + + switch (nextActivePanel) { + case 'NetworkElements': + this.props.onLoadNetworkElements(); + break; + case 'ConnectionStatusLog': + this.props.onLoadConnectionStatusLog(); + break; + case null: + // do nothing if all panels are closed + break; + default: + console.warn("Unknown nextActivePanel [" + nextActivePanel + "] in connectView"); + break; + } + + }; + + render(): JSX.Element { + const { panelId } = this.props; + + return ( + <> + + + + + + + + ); + }; + public componentDidMount() { + this.onTogglePanel("NetworkElements"); + this.props.networkElementsActions.onToggleFilter(); + this.props.connectionStatusLogActions.onToggleFilter(); + } +} + +export const ConnectApplication = (connect(mapProps, mapDispatcher)(ConnectApplicationComponent)); +export default ConnectApplication; \ No newline at end of file diff --git a/sdnr/wt/odlux/apps/connectApp/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java b/sdnr/wt/odlux/apps/connectApp/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java new file mode 100644 index 000000000..1e882fc69 --- /dev/null +++ b/sdnr/wt/odlux/apps/connectApp/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java @@ -0,0 +1,68 @@ +/******************************************************************************* + * ============LICENSE_START======================================================================== + * ONAP : ccsdk feature sdnr wt + * ================================================================================================= + * 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========================================================================== + ******************************************************************************/ +package org.onap.ccsdk.features.sdnr.wt.odlux.bundles; + +import org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles.OdluxBundle; +import org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles.OdluxBundleLoader; + +public class MyOdluxBundle extends OdluxBundle { + + @Override + public void initialize() { + super.initialize(); + } + + @Override + public void clean() { + super.clean(); + } + + @Override + public String getResourceFileContent(String filename) { + return super.getResourceFileContent(filename); + } + + @Override + public boolean hasResource(String filename) { + return super.hasResource(filename); + } + + @Override + public void setBundleName(String bundleName) { + super.setBundleName(bundleName); + } + + @Override + public void setLoader(OdluxBundleLoader loader) { + super.setLoader(loader); + } + + @Override + public String getBundleName() { + return super.getBundleName(); + } + + @Override + public OdluxBundleLoader getLoader() { + return super.getLoader(); + } + + public MyOdluxBundle() { + super(); + } +} diff --git a/sdnr/wt/odlux/apps/connectApp/src2/main/resources/OSGI-INF/blueprint/blueprint.xml b/sdnr/wt/odlux/apps/connectApp/src2/main/resources/OSGI-INF/blueprint/blueprint.xml new file mode 100644 index 000000000..adc9b777b --- /dev/null +++ b/sdnr/wt/odlux/apps/connectApp/src2/main/resources/OSGI-INF/blueprint/blueprint.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/sdnr/wt/odlux/apps/connectApp/src2/test/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/test/TestBundleRes.java b/sdnr/wt/odlux/apps/connectApp/src2/test/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/test/TestBundleRes.java new file mode 100644 index 000000000..edf68e096 --- /dev/null +++ b/sdnr/wt/odlux/apps/connectApp/src2/test/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/test/TestBundleRes.java @@ -0,0 +1,45 @@ +/******************************************************************************* + * ============LICENSE_START======================================================================== + * ONAP : ccsdk feature sdnr wt + * ================================================================================================= + * 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========================================================================== + ******************************************************************************/ +package org.onap.ccsdk.features.sdnr.wt.odlux.bundles.test; + +import static org.junit.Assert.*; + +import org.junit.Test; +import org.onap.ccsdk.features.sdnr.wt.odlux.OdluxBundleLoaderImpl; +import org.onap.ccsdk.features.sdnr.wt.odlux.bundles.MyOdluxBundle; + +public class TestBundleRes { + + @Test + public void test() { + OdluxBundleLoaderImpl loader = OdluxBundleLoaderImpl.getInstance(); + MyOdluxBundle b = new MyOdluxBundle(); + b.setLoader(loader); + b.setIndex(0); + b.setBundleName("abc"); + b.initialize(); + assertTrue(loader.getNumberOfBundles()==1); + assertNotNull(b.getLoader()); + assertEquals("abc",b.getBundleName()); + assertTrue(b.hasResource("test.js")); + assertNotNull(b.getResourceFileContent("test.js")); + b.clean(); + assertTrue(loader.getNumberOfBundles()==0); + } + +} diff --git a/sdnr/wt/odlux/apps/connectApp/src2/test/resources/test.js b/sdnr/wt/odlux/apps/connectApp/src2/test/resources/test.js new file mode 100644 index 000000000..b47fdc39f --- /dev/null +++ b/sdnr/wt/odlux/apps/connectApp/src2/test/resources/test.js @@ -0,0 +1,5 @@ +asdac sad +as +d +sad + sadfa \ No newline at end of file diff --git a/sdnr/wt/odlux/apps/connectApp/tsconfig.json b/sdnr/wt/odlux/apps/connectApp/tsconfig.json new file mode 100644 index 000000000..a66b5d828 --- /dev/null +++ b/sdnr/wt/odlux/apps/connectApp/tsconfig.json @@ -0,0 +1,37 @@ +{ + "compilerOptions": { + "baseUrl": "./src", + "outDir": "./dist", + "sourceMap": true, + "forceConsistentCasingInFileNames": true, + "allowSyntheticDefaultImports": false, + "allowUnreachableCode": false, + "allowUnusedLabels": false, + "noFallthroughCasesInSwitch": true, + "noImplicitAny": true, + "noImplicitReturns": true, + "noImplicitThis": true, + "strictNullChecks": true, + "pretty": true, + "newLine": "LF", + "module": "es2015", + "target": "es2016", + "moduleResolution": "node", + "experimentalDecorators": true, + "jsx": "preserve", + "lib": [ + "dom", + "es2015", + "es2016" + ], + "types": [ + "prop-types", + "react", + "react-dom" + ] + }, + "exclude": [ + "dist", + "node_modules" + ] +} diff --git a/sdnr/wt/odlux/apps/connectApp/webpack.config.js b/sdnr/wt/odlux/apps/connectApp/webpack.config.js new file mode 100644 index 000000000..6d70b04b0 --- /dev/null +++ b/sdnr/wt/odlux/apps/connectApp/webpack.config.js @@ -0,0 +1,153 @@ +/** + * Webpack 4 configuration file + * see https://webpack.js.org/configuration/ + * see https://webpack.js.org/configuration/dev-server/ + */ + +"use strict"; + +const path = require("path"); +const webpack = require("webpack"); +const CopyWebpackPlugin = require("copy-webpack-plugin"); +const TerserPlugin = require('terser-webpack-plugin'); + +// const __dirname = (path => path.replace(/^([a-z]\:)/, c => c.toUpperCase()))(process.__dirname()); + +module.exports = (env) => { + const distPath = path.resolve(__dirname, env === "release" ? "." : "../..", "dist"); + const frameworkPath = path.resolve(__dirname, env === "release" ? "../../framework" : "../..", "dist"); + return [{ + name: "App", + + mode: "none", //disable default behavior + + target: "web", + + context: path.resolve(__dirname, "src"), + + entry: { + connectApp: ["./pluginConnect.tsx"] + }, + + devtool: env === "release" ? false : "source-map", + + resolve: { + extensions: [".ts", ".tsx", ".js", ".jsx"] + }, + + output: { + path: distPath, + filename: "[name].js", + library: "[name]", + libraryTarget: "umd2", + chunkFilename: "[name].js" + }, + module: { + rules: [{ + test: /\.tsx?$/, + exclude: /node_modules/, + use: [{ + loader: "babel-loader" + }, { + loader: "ts-loader" + }] + }, { + test: /\.jsx?$/, + exclude: /node_modules/, + use: [{ + loader: "babel-loader" + }] + }] + }, + + optimization: { + noEmitOnErrors: true, + namedModules: env !== "release", + minimize: env === "release", + minimizer: env !== "release" ? [] : [new TerserPlugin({ + terserOptions: { + warnings: false, // false, true, "verbose" + compress: { + drop_console: true, + drop_debugger: true, + } + } + })], + }, + plugins: [ + new webpack.DllReferencePlugin({ + context: path.resolve(__dirname, "../../framework/src"), + manifest: require(path.resolve(frameworkPath, "vendor-manifest.json")), + sourceType: "umd2" + }), + new webpack.DllReferencePlugin({ + context: path.resolve(__dirname, "../../framework/src"), + manifest: require(path.resolve(frameworkPath, "app-manifest.json")), + sourceType: "umd2" + }), + ...(env === "release") ? [ + new webpack.DefinePlugin({ + "process.env": { + NODE_ENV: "'production'", + VERSION: JSON.stringify(require("./package.json").version) + } + }), + ] : [ + new webpack.DefinePlugin({ + "process.env": { + NODE_ENV: "'development'", + VERSION: JSON.stringify(require("./package.json").version) + } + }), + new CopyWebpackPlugin([{ + from: 'index.html', + to: distPath + }]), + ] + ], + + devServer: { + public: "http://localhost:3100", + contentBase: frameworkPath, + + compress: true, + headers: { + "Access-Control-Allow-Origin": "*" + }, + host: "0.0.0.0", + port: 3100, + disableHostCheck: true, + historyApiFallback: true, + inline: true, + hot: false, + quiet: false, + stats: { + colors: true + }, + proxy: { + "/oauth2/": { + target: "http://10.20.6.29:28181", + secure: false + }, + "/database/": { + target: "http://10.20.6.29:28181", + secure: false + }, + "/restconf/": { + target: "http://10.20.6.29:28181", + secure: false + }, + "/help/": { + target: "http://10.20.6.29:28181", + secure: false + }, + "/websocket": { + target: "http://10.20.6.29:28181", + ws: true, + changeOrigin: true, + secure: false + } + } + } + }]; +} -- cgit 1.2.3-korg