diff options
Diffstat (limited to 'sdnr/wt/odlux/apps/connectApp')
31 files changed, 1263 insertions, 1157 deletions
diff --git a/sdnr/wt/odlux/apps/connectApp/package.json b/sdnr/wt/odlux/apps/connectApp/package.json index 269fa2a8c..04653d520 100644 --- a/sdnr/wt/odlux/apps/connectApp/package.json +++ b/sdnr/wt/odlux/apps/connectApp/package.json @@ -21,20 +21,20 @@ "author": "Matthias Fischer", "license": "Apache-2.0", "dependencies": { - "@odlux/framework" : "*" + "@odlux/framework": "*" }, "peerDependencies": { - "@types/react": "16.4.14", - "@types/react-dom": "16.0.8", - "@types/react-router-dom": "4.3.1", - "@material-ui/core": "3.8.3", - "@material-ui/icons": "3.0.2", - "@types/classnames": "2.2.6", - "@types/flux": "3.1.8", - "@types/jquery": "3.3.10", - "jquery": "3.3.1", - "react": "16.5.2", - "react-dom": "16.5.2", - "react-router-dom": "4.3.1" + "@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 index 3da282c39..36a5cf8bf 100644 --- a/sdnr/wt/odlux/apps/connectApp/pom.xml +++ b/sdnr/wt/odlux/apps/connectApp/pom.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.onap.ccsdk.parent</groupId> @@ -7,18 +8,20 @@ <version>1.5.1-SNAPSHOT</version> <relativePath/> </parent> - <modelVersion>4.0.0</modelVersion> + <groupId>org.onap.ccsdk.features.sdnr.wt</groupId> <artifactId>sdnr-wt-odlux-app-connectApp</artifactId> <version>0.7.0-SNAPSHOT</version> <packaging>bundle</packaging> - <name>sdnr-wt-odlux-app-connectApp</name> + + <name>ccsdk-features :: ${project.artifactId}</name> <licenses> <license> <name>Apache License, Version 2.0</name> <url>http://www.apache.org/licenses/LICENSE-2.0</url> </license> </licenses> + <dependencies> <dependency> <groupId>${project.groupId}</groupId> @@ -37,8 +40,21 @@ <scope>test</scope> </dependency> </dependencies> + <build> <sourceDirectory>src2/main/java</sourceDirectory> + <resources> + <resource> + <directory>dist</directory> + <targetPath>odlux</targetPath> + </resource> + <resource> + <directory>src2/main/resources</directory> + </resource> + <resource> + <directory>src2/test/resources</directory> + </resource> + </resources> <plugins> <plugin> <artifactId>maven-clean-plugin</artifactId> @@ -61,10 +77,10 @@ <followSymlinks>false</followSymlinks> </fileset> <!-- eclipse bug build bin folder in basedir --> - <fileset> - <directory>bin</directory> - <followSymlinks>false</followSymlinks> - </fileset> + <fileset> + <directory>bin</directory> + <followSymlinks>false</followSymlinks> + </fileset> </filesets> </configuration> </plugin> @@ -87,7 +103,7 @@ </executions> </plugin> <plugin> - <groupId>de.jacksitlab</groupId> + <groupId>de.jacks-it-lab</groupId> <artifactId>frontend-maven-plugin</artifactId> <version>1.7.1</version> <executions> @@ -99,8 +115,8 @@ <!-- optional: default phase is "generate-resources" --> <phase>initialize</phase> <configuration> - <nodeVersion>v8.10.0</nodeVersion> - <yarnVersion>v1.12.3</yarnVersion> + <nodeVersion>v10.16.3</nodeVersion> + <yarnVersion>v1.19.0</yarnVersion> </configuration> </execution> <execution> @@ -130,27 +146,5 @@ </configuration> </plugin> </plugins> - <resources> - <resource> - <directory>dist</directory> - <targetPath>odlux</targetPath> - </resource> - <resource> - <directory>src2/main/resources</directory> - </resource> - <resource> - <directory>src2/test/resources</directory> - </resource> - </resources> </build> - <pluginRepositories> - <pluginRepository> - <id>highstreet repo</id> - <url>https://cloud-highstreet-technologies.com/mvn/</url> - <snapshots> - <enabled>true</enabled> - <updatePolicy>always</updatePolicy> - </snapshots> - </pluginRepository> - </pluginRepositories> </project> 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 index 12f7c8594..84e73ae5a 100644 --- a/sdnr/wt/odlux/apps/connectApp/src/actions/mountedNetworkElementsActions.ts +++ b/sdnr/wt/odlux/apps/connectApp/src/actions/mountedNetworkElementsActions.ts @@ -15,107 +15,45 @@ * the License. * ============LICENSE_END========================================================================== */ + import { Action } from '../../../../framework/src/flux/action'; import { Dispatch } from '../../../../framework/src/flux/store'; -import { MountedNetworkElementType } from '../models/mountedNetworkElements'; -import { RequiredNetworkElementType } from '../models/requiredNetworkElements'; - 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 causing the store to load all mounted network elements. */ -export class LoadAllMountedNetworkElementsAction extends BaseAction { } - -/** Represents an action causing the store to update all mounted network elements. */ -export class AllMountedNetworkElementsLoadedAction extends BaseAction { - constructor(public mountedNetworkElements: MountedNetworkElementType[] | null, public error?: string) { - super(); - } -} - -/** Represents an action causing the store to update all mounted network elements. */ -export class AddOrUpdateMountedNetworkElement extends BaseAction { - constructor(public mountedNetworkElement: MountedNetworkElementType | null, public error?: string) { - super(); - } -} - -export class RemoveMountedNetworkElement extends BaseAction { - constructor(public mountId: string) { - super(); - } -} - -export class UpdateConnectionStateMountedNetworkElement extends BaseAction { - constructor(public mountId: string, connectionState: string) { - super(); - } -} - - -export class UpdateRequiredMountedNetworkElement extends BaseAction { - constructor(public mountId: string, public required: boolean) { - super(); - } -} - -/** - * Represents an action crator for a async thunk action to add an allready mounted element to the state of this app. - * Note: Use this action to add created object notified by the websocket. -*/ -export const addMountedNetworkElementAsyncActionCreator = (mountId: string) => async (dispatch: Dispatch) => { - return connectService.getMountedNetworkElementByMountId(mountId).then(mountedNetworkElement => { - mountedNetworkElement && dispatch(new AddOrUpdateMountedNetworkElement(mountedNetworkElement)); - }).catch(error => { - dispatch(new AddOrUpdateMountedNetworkElement(null, error)); - }); -}; - -export const updateMountedNetworkElementAsyncActionCreator = (mountId: string) => async (dispatch: Dispatch) => { - return connectService.getMountedNetworkElementByMountId(mountId).then(mountedNetworkElement => { - if (mountedNetworkElement) { - dispatch(new AddOrUpdateMountedNetworkElement(mountedNetworkElement)); - } else { - dispatch(new RemoveMountedNetworkElement(mountId)); - } - }).catch(error => { - dispatch(new AddOrUpdateMountedNetworkElement(null, error)); - }); -}; - -/** Represents an async thunk action to load all mounted network elements. */ -export const loadAllMountedNetworkElementsAsync = (dispatch: Dispatch) => { - dispatch(new LoadAllMountedNetworkElementsAction()); - return connectService.getMountedNetworkElementsList().then(mountedNetworkElements => { - mountedNetworkElements && dispatch(new AllMountedNetworkElementsLoadedAction(mountedNetworkElements)); - }).catch(error => { - dispatch(new AllMountedNetworkElementsLoadedAction(null, error)); - }); -}; - /** Represents an action crator for a async thunk action to mount a network element. */ -export const mountNetworkElementAsyncActionCreator = (networkElement: RequiredNetworkElementType) => (dispatch: Dispatch) => { +export const mountNetworkElementAsyncActionCreator = (networkElement: NetworkElementConnection) => (dispatch: Dispatch) => { return connectService.mountNetworkElement(networkElement).then((success) => { - success && ( - dispatch(addMountedNetworkElementAsyncActionCreator(networkElement.mountId)) && - dispatch(new AddSnackbarNotification({ message: `Requesting mount [${networkElement.mountId}]`, options: { variant: 'info' } })) - ) || dispatch(new AddSnackbarNotification({ message: `Failed to mount [${ networkElement.mountId }]`, options: { variant: 'warning' } })); + 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 AddOrUpdateMountedNetworkElement(null, 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 = (mountId: string) => (dispatch: Dispatch) => { - return connectService.unmountNetworkElement(mountId).then((success) => { - success && dispatch(new AddSnackbarNotification({ message: `Requesting unmount [${ mountId }]`, options: { variant: 'info' } })) - || dispatch(new AddSnackbarNotification({ message: `Failed to unmount [${ mountId }]`, options: { variant: 'warning' } })); +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 AddOrUpdateMountedNetworkElement(null, 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/actions/requiredNetworkElementsActions.ts b/sdnr/wt/odlux/apps/connectApp/src/actions/requiredNetworkElementsActions.ts deleted file mode 100644 index 0e55cadf4..000000000 --- a/sdnr/wt/odlux/apps/connectApp/src/actions/requiredNetworkElementsActions.ts +++ /dev/null @@ -1,55 +0,0 @@ -/** - * ============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 { RequiredNetworkElementType } from '../models/requiredNetworkElements'; -import { requiredNetworkElementsReloadAction } from '../handlers/requiredNetworkElementsHandler'; -import { UpdateRequiredMountedNetworkElement } from '../actions/mountedNetworkElementsActions'; - -import { AddSnackbarNotification } from '../../../../framework/src/actions/snackbarActions'; - -import { connectService } from '../services/connectService'; - -/** Represents the base action. */ -export class BaseAction extends Action { } - - -/** Represents an async thunk action creator to add an element to the required network elements. */ -export const addToRequiredNetworkElementsAsyncActionCreator = (element: RequiredNetworkElementType) => (dispatch: Dispatch) => { - connectService.insertRequiredNetworkElement(element).then(_ => { - window.setTimeout(() => { - dispatch(requiredNetworkElementsReloadAction); - dispatch(new UpdateRequiredMountedNetworkElement(element.mountId, true)); - dispatch(new AddSnackbarNotification({ message: `Successfully added [${ element.mountId }]`, options: { variant: 'success' } })); - }, 900); - }); -}; - -/** Represents an async thunk action creator to delete an element from the required network elements. */ -export const removeFromRequiredNetworkElementsAsyncActionCreator = (element: RequiredNetworkElementType) => (dispatch: Dispatch) => { - connectService.deleteRequiredNetworkElement(element).then(_ => { - window.setTimeout(() => { - dispatch(requiredNetworkElementsReloadAction); - dispatch(new UpdateRequiredMountedNetworkElement(element.mountId, false)); - dispatch(new AddSnackbarNotification({ message: `Successfully removed [${ element.mountId }]`, options: { variant: 'success' } })); - }, 900); - }); -}; - - - diff --git a/sdnr/wt/odlux/apps/connectApp/src/components/connectionStatusLog.tsx b/sdnr/wt/odlux/apps/connectApp/src/components/connectionStatusLog.tsx index 3cc104836..4e5ca65e1 100644 --- a/sdnr/wt/odlux/apps/connectApp/src/components/connectionStatusLog.tsx +++ b/sdnr/wt/odlux/apps/connectApp/src/components/connectionStatusLog.tsx @@ -21,32 +21,31 @@ import { IApplicationStoreState } from '../../../../framework/src/store/applicat import { MaterialTable, ColumnType, MaterialTableCtorType } from '../../../../framework/src/components/material-table'; import { createConnectionStatusLogActions, createConnectionStatusLogProperties } from '../handlers/connectionStatusLogHandler'; -import { ConnectionStatusLogType } from '../models/connectionStatusLog'; +import { NetworkElementConnectionLog } from '../models/networkElementConnectionLog'; const mapProps = (state: IApplicationStoreState) => ({ connectionStatusLogProperties: createConnectionStatusLogProperties(state), }); const mapDispatch = (dispatcher: IDispatcher) => ({ - connectionStatusLogActions: createConnectionStatusLogActions(dispatcher.dispatch), + connectionStatusLogActions: createConnectionStatusLogActions(dispatcher.dispatch), }); - -const ConnectionStatusTable = MaterialTable as MaterialTableCtorType<ConnectionStatusLogType>; + +const ConnectionStatusTable = MaterialTable as MaterialTableCtorType<NetworkElementConnectionLog>; type ConnectionStatusLogComponentProps = Connect<typeof mapProps, typeof mapDispatch>; class ConnectionStatusLogComponent extends React.Component<ConnectionStatusLogComponentProps> { render(): JSX.Element { return ( - <ConnectionStatusTable columns={ [ - { property: "timeStamp", title: "Time", type: ColumnType.text }, - { property: "objectId", title: "Name", type: ColumnType.text }, - { property: "elementStatus", title: "Connection status", type: ColumnType.text, disableFilter: true, disableSorting: true }, - ] } idProperty="_id" { ...this.props.connectionStatusLogActions } {...this.props.connectionStatusLogProperties } > + <ConnectionStatusTable tableId="connection-status-table" columns={[ + { property: "timestamp", title: "Time", type: ColumnType.text }, + { property: "nodeId", title: "Node Name", type: ColumnType.text }, + { property: "status", title: "Connection status", type: ColumnType.text }, + ]} idProperty="id" {...this.props.connectionStatusLogActions} {...this.props.connectionStatusLogProperties} > </ConnectionStatusTable> ); }; - } export const ConnectionStatusLog = connect(mapProps, mapDispatch)(ConnectionStatusLogComponent); diff --git a/sdnr/wt/odlux/apps/connectApp/src/components/editNetworkElementDialog.tsx b/sdnr/wt/odlux/apps/connectApp/src/components/editNetworkElementDialog.tsx index 32b23a41e..1e1f11523 100644 --- a/sdnr/wt/odlux/apps/connectApp/src/components/editNetworkElementDialog.tsx +++ b/sdnr/wt/odlux/apps/connectApp/src/components/editNetworkElementDialog.tsx @@ -24,46 +24,47 @@ 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 { - addToRequiredNetworkElementsAsyncActionCreator, - removeFromRequiredNetworkElementsAsyncActionCreator -} from '../actions/requiredNetworkElementsActions'; + editNetworkElementAsyncActionCreator, + addNewNetworkElementAsyncActionCreator, + removeNetworkElementAsyncActionCreator +} from '../actions/networkElementsActions'; import { unmountNetworkElementAsyncActionCreator, mountNetworkElementAsyncActionCreator } from '../actions/mountedNetworkElementsActions'; -import { RequiredNetworkElementType } from '../models/requiredNetworkElements'; +import { NetworkElementConnection, UpdateNetworkElement } from '../models/networkElementConnection'; +import { removeWebUriAction } from '../actions/commonNetworkElementsActions'; export enum EditNetworkElementDialogMode { None = "none", - UnknownNetworkElementToRequiredNetworkElements = "unknownNetworkElementToRequiredNetworkElements", - RequiredNetworkElementToUnknownNetworkElements = "requiredNetworkElementToUnknownNetworkElements", - MountNetworkElementToRequiredNetworkElements = "mountNetworkElementToRequiredNetworkElements", - MountNetworkElementToUnknonwNetworkElements = "mountNetworkElementToRequiredUnknownElements", + EditNetworkElement = "editNetworkElement", + RemoveNetworkElement = "removeNetworkElement", + AddNewNetworkElement = "addNewNetworkElement", MountNetworkElement = "mountNetworkElement", UnmountNetworkElement = "unmountNetworkElement", } const mapDispatch = (dispatcher: IDispatcher) => ({ - addToRequiredNetworkElements: (element: RequiredNetworkElementType) => { - dispatcher.dispatch(addToRequiredNetworkElementsAsyncActionCreator(element)); + addNewNetworkElement: async (element: NetworkElementConnection) => { + await dispatcher.dispatch(addNewNetworkElementAsyncActionCreator(element)); + await dispatcher.dispatch(mountNetworkElementAsyncActionCreator(element)); }, - removeFromRequiredNetworkElements: (element: RequiredNetworkElementType) => { - dispatcher.dispatch(removeFromRequiredNetworkElementsAsyncActionCreator(element)); + mountNetworkElement: (element: NetworkElementConnection) => dispatcher.dispatch(mountNetworkElementAsyncActionCreator(element)), + unmountNetworkElement: (element: NetworkElementConnection) => { + dispatcher.dispatch(unmountNetworkElementAsyncActionCreator(element && element.nodeId)); }, - mountNetworkElement: (element: RequiredNetworkElementType) => { - dispatcher.dispatch(mountNetworkElementAsyncActionCreator(element)); + editNetworkElement: async (element: UpdateNetworkElement, mountElement: NetworkElementConnection) => { + await dispatcher.dispatch(editNetworkElementAsyncActionCreator(element)); + await dispatcher.dispatch(mountNetworkElementAsyncActionCreator(mountElement)); }, - mountAndRquireNetworkElement: (element: RequiredNetworkElementType) => { - dispatcher.dispatch(addToRequiredNetworkElementsAsyncActionCreator(element)); - dispatcher.dispatch(mountNetworkElementAsyncActionCreator(element)); - }, - unmountNetworkElement: (element: RequiredNetworkElementType) => { - dispatcher.dispatch(unmountNetworkElementAsyncActionCreator(element && element.mountId)); + removeNetworkElement: (element: UpdateNetworkElement) => { + dispatcher.dispatch(removeNetworkElementAsyncActionCreator(element)); + dispatcher.dispatch(removeWebUriAction(element.id)); } -} -); +}); type DialogSettings = { dialogTitle: string, @@ -85,37 +86,11 @@ const settings: { [key: string]: DialogSettings } = { enableUsernameEditor: false, enableExtendedEditor: false, }, - [EditNetworkElementDialogMode.UnknownNetworkElementToRequiredNetworkElements] : { - dialogTitle: "Add to required network elements" , - dialogDescription: "Create a new NetworkElement in planning database as clone of existing real NetworkElement." , - applyButtonText: "Add to required network elements" , - cancelButtonText: "Cancel", - enableMountIdEditor: false, - enableUsernameEditor: true, - enableExtendedEditor: false, - }, - [EditNetworkElementDialogMode.RequiredNetworkElementToUnknownNetworkElements]: { - dialogTitle: "Remove from required network elements", - dialogDescription: "Do you really want to remove the required element:", - applyButtonText: "Remove network element", - cancelButtonText: "Cancel", - enableMountIdEditor: false, - enableUsernameEditor: false, - enableExtendedEditor: false, - }, - [EditNetworkElementDialogMode.MountNetworkElementToUnknonwNetworkElements]: { - dialogTitle: "Mount to unknown network elements", - dialogDescription: "Mount this network element:", - applyButtonText: "Mount network element", - cancelButtonText: "Cancel", - enableMountIdEditor: true, - enableUsernameEditor: true, - enableExtendedEditor: true, - }, - [EditNetworkElementDialogMode.MountNetworkElementToRequiredNetworkElements]: { - dialogTitle: "Mount to required network elements", - dialogDescription: "Mount this network element:", - applyButtonText: "Mount network element", + + [EditNetworkElementDialogMode.AddNewNetworkElement]: { + dialogTitle: "Add new network element", + dialogDescription: "Add this new network element:", + applyButtonText: "Add network element", cancelButtonText: "Cancel", enableMountIdEditor: true, enableUsernameEditor: true, @@ -139,83 +114,102 @@ const settings: { [key: string]: DialogSettings } = { 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<undefined,typeof mapDispatch> & { +type EditNetworkElementDialogComponentProps = Connect<undefined, typeof mapDispatch> & { mode: EditNetworkElementDialogMode; - initialNetworkElement: RequiredNetworkElementType; + initialNetworkElement: NetworkElementConnection; onClose: () => void; }; -type EditNetworkElementDialogComponentState = RequiredNetworkElementType & { - required: boolean; -}; +type EditNetworkElementDialogComponentState = NetworkElementConnection; class EditNetworkElementDialogComponent extends React.Component<EditNetworkElementDialogComponentProps, EditNetworkElementDialogComponentState> { constructor(props: EditNetworkElementDialogComponentProps) { super(props); this.state = { - mountId: this.props.initialNetworkElement.mountId, + nodeId: this.props.initialNetworkElement.nodeId, + isRequired: false, host: this.props.initialNetworkElement.host, port: this.props.initialNetworkElement.port, - password: this.props.initialNetworkElement.password, - username: this.props.initialNetworkElement.username, - required: false }; } render(): JSX.Element { const setting = settings[this.props.mode]; return ( - <Dialog open={ this.props.mode !== EditNetworkElementDialogMode.None }> - <DialogTitle id="form-dialog-title">{ setting.dialogTitle }</DialogTitle> + <Dialog open={this.props.mode !== EditNetworkElementDialogMode.None}> + <DialogTitle id="form-dialog-title">{setting.dialogTitle}</DialogTitle> <DialogContent> <DialogContentText> - { setting.dialogDescription } + {setting.dialogDescription} </DialogContentText> - <TextField disabled={ !setting.enableMountIdEditor } spellCheck={false} autoFocus margin="dense" id="name" label="Name" type="text" fullWidth value={ this.state.mountId } onChange={(event)=>{ this.setState({mountId: event.target.value}); } } /> - <TextField disabled={ !setting.enableMountIdEditor } spellCheck={false} margin="dense" id="ipaddress" label="IP address" type="text" fullWidth value={ this.state.host } onChange={(event)=>{ this.setState({host: event.target.value}); } }/> - <TextField disabled={ !setting.enableMountIdEditor } spellCheck={false} margin="dense" id="netconfport" label="NetConf port" type="number" fullWidth value={ this.state.port.toString() } onChange={(event)=>{ this.setState({port: +event.target.value}); } }/> - { setting.enableUsernameEditor && <TextField disabled={ !setting.enableUsernameEditor } spellCheck={ false } margin="dense" id="username" label="Username" type="text" fullWidth value={ this.state.username } onChange={ (event) => { this.setState({ username: event.target.value }); } } /> || null } - { setting.enableUsernameEditor && <TextField disabled={ !setting.enableUsernameEditor } spellCheck={ false } margin="dense" id="password" label="Password" type="password" fullWidth value={ this.state.password } onChange={ (event) => { this.setState({ password: event.target.value }); } } /> || null } + <TextField disabled={!setting.enableMountIdEditor} spellCheck={false} autoFocus margin="dense" id="name" label="Name" aria-label="name" type="text" fullWidth value={this.state.nodeId} onChange={(event) => { this.setState({ nodeId: event.target.value }); }} /> + <TextField disabled={!setting.enableMountIdEditor} spellCheck={false} margin="dense" id="ipaddress" label="IP address" aria-label="ip adress" type="text" fullWidth value={this.state.host} onChange={(event) => { this.setState({ host: event.target.value }); }} /> + <TextField disabled={!setting.enableMountIdEditor} spellCheck={false} margin="dense" id="netconfport" label="NetConf port" aria-label="netconf port" type="number" fullWidth value={this.state.port.toString()} onChange={(event) => { this.setState({ port: +event.target.value }); }} /> + {setting.enableUsernameEditor && <TextField disabled={!setting.enableUsernameEditor} spellCheck={false} margin="dense" id="username" label="Username" aria-label="username" type="text" fullWidth value={this.state.username} onChange={(event) => { this.setState({ username: event.target.value }); }} /> || null} + {setting.enableUsernameEditor && <TextField disabled={!setting.enableUsernameEditor} spellCheck={false} margin="dense" id="password" label="Password" aria-label="password" type="password" fullWidth value={this.state.password} onChange={(event) => { this.setState({ password: event.target.value }); }} /> || null} + <FormControl fullWidth disabled={!setting.enableUsernameEditor}> + <InputLabel htmlFor="active">Required</InputLabel> + <Select value={this.state.isRequired || false} onChange={(event) => { + this.setState({ isRequired: event.target.value as any as boolean }); + }} inputProps={{ name: 'required', id: 'required' }} fullWidth > + <MenuItem value={true as any as string} >True</MenuItem> + <MenuItem value={false as any as string} >False</MenuItem> + </Select> + </FormControl> </DialogContent> <DialogActions> - <Button onClick={ (event) => { + <Button onClick={(event) => { this.onApply({ - mountId: this.state.mountId, + isRequired: this.state.isRequired, + id: this.state.nodeId, + nodeId: this.state.nodeId, host: this.state.host, port: this.state.port, username: this.state.username, - password: this.state.password + password: this.state.password, }); event.preventDefault(); event.stopPropagation(); - } } > { setting.applyButtonText } </Button> - <Button onClick={ (event) => { + }} > {setting.applyButtonText} </Button> + <Button onClick={(event) => { this.onCancel(); event.preventDefault(); event.stopPropagation(); - } } color="secondary"> { setting.cancelButtonText } </Button> + }} color="secondary"> {setting.cancelButtonText} </Button> </DialogActions> </Dialog> ) } - private onApply = (element: RequiredNetworkElementType) => { + private onApply = (element: NetworkElementConnection) => { this.props.onClose && this.props.onClose(); + let updateElement: UpdateNetworkElement = { + id: this.state.nodeId + } switch (this.props.mode) { - case EditNetworkElementDialogMode.UnknownNetworkElementToRequiredNetworkElements: - element && this.props.addToRequiredNetworkElements(element); - break; - case EditNetworkElementDialogMode.RequiredNetworkElementToUnknownNetworkElements: - element && this.props.removeFromRequiredNetworkElements(element); - break; - case EditNetworkElementDialogMode.MountNetworkElementToUnknonwNetworkElements: - element && this.props.mountNetworkElement(element); - break; - case EditNetworkElementDialogMode.MountNetworkElementToRequiredNetworkElements: - element && this.props.mountAndRquireNetworkElement(element); + case EditNetworkElementDialogMode.AddNewNetworkElement: + element && this.props.addNewNetworkElement(element); break; case EditNetworkElementDialogMode.MountNetworkElement: element && this.props.mountNetworkElement(element); @@ -223,6 +217,18 @@ class EditNetworkElementDialogComponent extends React.Component<EditNetworkEleme 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; } }; @@ -230,7 +236,7 @@ class EditNetworkElementDialogComponent extends React.Component<EditNetworkEleme this.props.onClose && this.props.onClose(); } - static getDerivedStateFromProps(props: EditNetworkElementDialogComponentProps, state: EditNetworkElementDialogComponentState & { _initialNetworkElement: RequiredNetworkElementType }): EditNetworkElementDialogComponentState & { _initialNetworkElement: RequiredNetworkElementType } { + static getDerivedStateFromProps(props: EditNetworkElementDialogComponentProps, state: EditNetworkElementDialogComponentState & { _initialNetworkElement: NetworkElementConnection }): EditNetworkElementDialogComponentState & { _initialNetworkElement: NetworkElementConnection } { if (props.initialNetworkElement !== state._initialNetworkElement) { state = { ...state, 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<undefined, typeof mapDispatch> & { + mode: InfoNetworkElementDialogMode; + initialNetworkElement: NetworkElementConnection; + onClose: () => void; +}; + +type InfoNetworkElementDialogComponentState = NetworkElementConnection; + +class InfoNetworkElementDialogComponent extends React.Component<InfoNetworkElementDialogComponentProps, InfoNetworkElementDialogComponentState> { + constructor(props: InfoNetworkElementDialogComponentProps) { + super(props); + + this.state = { + nodeId: this.props.initialNetworkElement.nodeId, + isRequired: false, + host: this.props.initialNetworkElement.host, + port: this.props.initialNetworkElement.port, + }; + } + + render(): JSX.Element { + const setting = settings[this.props.mode]; + const availableCapabilities = this.props.state.connect.elementInfo.elementInfo["netconf-node-topology:available-capabilities"]["available-capability"]; + let 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 ( + <Dialog open={this.props.mode !== InfoNetworkElementDialogMode.None}> + <DialogTitle id="form-dialog-title">{setting.dialogTitle}</DialogTitle> + <DialogContent> + <DialogContentText> + {setting.dialogDescription + " " + this.state.nodeId} + </DialogContentText> + <Table > + <TableHead> + <TableRow> + <TableCell align="right">S.No</TableCell> + <TableCell >Module</TableCell> + <TableCell >Revision</TableCell> + </TableRow> + </TableHead> + <TableBody> + {yangCapabilities.map((yang, index) => ( + <TableRow> + <TableCell>{index + 1}</TableCell> + <TableCell>{yang.module}</TableCell> + <TableCell>{yang.revision}</TableCell> + </TableRow> + ))} + </TableBody> + </Table> + </DialogContent> + <DialogActions> + <Button onClick={(event) => { + this.onCancel(); + event.preventDefault(); + event.stopPropagation(); + }} color="secondary"> {setting.cancelButtonText} </Button> + </DialogActions> + </Dialog> + ) + } + + private onCancel = () => { + this.props.onClose(); + } + + static getDerivedStateFromProps(props: InfoNetworkElementDialogComponentProps, state: InfoNetworkElementDialogComponentState & { _initialNetworkElement: NetworkElementConnection }): InfoNetworkElementDialogComponentState & { _initialNetworkElement: NetworkElementConnection } { + if (props.initialNetworkElement !== state._initialNetworkElement) { + state = { + ...state, + ...props.initialNetworkElement, + _initialNetworkElement: props.initialNetworkElement, + }; + } + return state; + } +} + +export const InfoNetworkElementDialog = connect(undefined, mapDispatch)(InfoNetworkElementDialogComponent); +export default InfoNetworkElementDialog;
\ No newline at end of file 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<typeof styles> & Connect<typeof mapProps, typeof mapDispatch>; +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<NetworkElementConnection>; + +export class NetworkElementsListComponent extends React.Component<NetworkElementsListComponentProps, NetworkElementsListComponentState> { + + 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 ( + <> + <NetworkElementTable tableId="network-element-table" customActionButtons={[addRequireNetworkElementAction]} columns={[ + { property: "nodeId", title: "Node Name", type: ColumnType.text }, + { property: "isRequired", title: "Required", type: ColumnType.boolean }, + { property: "status", title: "Connection Status", type: ColumnType.text }, + { property: "host", title: "Host", type: ColumnType.text }, + { property: "port", title: "Port", type: ColumnType.numeric }, + { property: "coreModelCapability", title: "Core Model", type: ColumnType.text }, + { property: "deviceType", title: "Type", type: ColumnType.text }, + { + property: "actions", title: "Actions", type: ColumnType.custom, customControl: ({ rowData }) => { + counter++; + return ( + <> + <div className={classes.spacer}> + { + rowData.webUri && <Tooltip title={"Web Client"} ><IconButton aria-label={"web-client-button-" + counter} className={classes.button} onClick={event => { console.log(rowData); window.open(rowData.webUri, "_blank") }}><ComputerIcon /></IconButton></Tooltip> + } + <Tooltip title={"Mount"} > + <IconButton aria-label={"mount-button-" + counter} className={classes.button} onClick={event => this.onOpenMountdNetworkElementsDialog(event, rowData)} > + <LinkIcon /></IconButton> + </Tooltip> + <Tooltip title={"Unmount"} > + <IconButton aria-label={"unmount-button-" + counter} className={classes.button} onClick={event => this.onOpenUnmountdNetworkElementsDialog(event, rowData)} > + <LinkOffIcon /></IconButton> + </Tooltip> + <Tooltip title={"Info"} ><IconButton aria-label={"info-button-" + counter} className={classes.button} onClick={event => this.onOpenInfoNetworkElementDialog(event, rowData)} disabled={rowData.status === "Connecting" || rowData.status === "Disconnected"} > + <Info /></IconButton> + </Tooltip> + <Tooltip title={"Edit"} ><IconButton aria-label={"edit-button-" + counter} className={classes.button} onClick={event => this.onOpenEditNetworkElementDialog(event, rowData)} ><EditIcon /></IconButton></Tooltip> + <Tooltip title={"Remove"} ><IconButton aria-label={"remove-button-" + counter} className={classes.button} onClick={event => this.onOpenRemoveNetworkElementDialog(event, rowData)} ><RemoveIcon /></IconButton></Tooltip> + </div> + <div className={classes.spacer}> + <Tooltip title={"Inventory"} ><Button aria-label={"inventory-button-" + counter} className={classes.button} onClick={this.navigateToApplicationHandlerCreator("inventory", rowData)} >I</Button></Tooltip> + </div> + <div className={classes.spacer}> + <Tooltip title={"Fault"} ><Button aria-label={"fault-button-" + counter} className={classes.button} onClick={this.navigateToApplicationHandlerCreator("fault", rowData)} >F</Button></Tooltip> + <Tooltip title={"Configure"} ><Button aria-label={"configure-button-" + counter} className={classes.button} onClick={this.navigateToApplicationHandlerCreator("configuration", rowData)} >C</Button></Tooltip> + <Tooltip title={"Accounting "} ><Button className={classes.button} onClick={this.navigateToApplicationHandlerCreator("accounting", rowData)} disabled={true} >A</Button></Tooltip> + <Tooltip title={"Performance"} ><Button aria-label={"performance-button-" + counter} className={classes.button} onClick={this.navigateToApplicationHandlerCreator("performanceHistory", rowData)}>P</Button></Tooltip> + <Tooltip title={"Security"} ><Button className={classes.button} onClick={this.navigateToApplicationHandlerCreator("security", rowData)} disabled={true} >S</Button></Tooltip> + </div> + </> + ) + } + }, + ]} idProperty="id" {...this.props.networkElementsActions} {...this.props.networkElementsProperties} asynchronus > + </NetworkElementTable> + <EditNetworkElementDialog + initialNetworkElement={networkElementToEdit} + mode={this.state.networkElementEditorMode} + onClose={this.onCloseEditNetworkElementDialog} + /> + <InfoNetworkElementDialog + initialNetworkElement={networkElementToEdit} + mode={this.state.infoNetworkElementEditorMode} + onClose={this.onCloseInfoNetworkElementDialog} + /> + </> + ); + }; + + public componentDidMount() { + this.props.networkElementsActions.onRefresh(); + } + + private onOpenRemoveNetworkElementDialog = (event: React.MouseEvent<HTMLElement>, element: NetworkElementConnection) => { + this.setState({ + networkElementToEdit: element, + networkElementEditorMode: EditNetworkElementDialogMode.RemoveNetworkElement + }); + event.preventDefault(); + event.stopPropagation(); + } + + private onOpenEditNetworkElementDialog = (event: React.MouseEvent<HTMLElement>, 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<HTMLElement>, element: NetworkElementConnection) => { + this.setState({ + networkElementToEdit: element, + networkElementEditorMode: EditNetworkElementDialogMode.UnmountNetworkElement + }); + event.preventDefault(); + event.stopPropagation(); + } + + private onOpenMountdNetworkElementsDialog = (event: React.MouseEvent<HTMLElement>, element: NetworkElementConnection) => { + this.setState({ + networkElementToEdit: element, + networkElementEditorMode: EditNetworkElementDialogMode.MountNetworkElement + }); + event.preventDefault(); + event.stopPropagation(); + } + + private onOpenInfoNetworkElementDialog = (event: React.MouseEvent<HTMLElement>, 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<HTMLElement>) => { + 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/components/requiredNetworkElements.tsx b/sdnr/wt/odlux/apps/connectApp/src/components/requiredNetworkElements.tsx deleted file mode 100644 index 2fb7594aa..000000000 --- a/sdnr/wt/odlux/apps/connectApp/src/components/requiredNetworkElements.tsx +++ /dev/null @@ -1,210 +0,0 @@ -/** - * ============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 Button from '@material-ui/core/Button'; -import IconButton from '@material-ui/core/IconButton'; - -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 { RequiredNetworkElementType } from '../models/requiredNetworkElements'; -import { createRequiredNetworkElementsActions, createRequiredNetworkElementsProperties } from '../handlers/requiredNetworkElementsHandler'; - -import EditNetworkElementDialog, { EditNetworkElementDialogMode } from './editNetworkElementDialog'; -import { Tooltip } from '@material-ui/core'; -import { NetworkElementBaseType } from 'models/networkElementBase'; - -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.unit, - marginRight: theme.spacing.unit, - display: "inline" - } -}); - -const mapProps = (state: IApplicationStoreState) => ({ - requiredNetworkElementsProperties: createRequiredNetworkElementsProperties(state), - mountedNetworkElements: state.connect.mountedNetworkElements -}); - -const mapDispatch = (dispatcher: IDispatcher) => ({ - requiredNetworkElementsActions: createRequiredNetworkElementsActions(dispatcher.dispatch), - navigateToApplication: (applicationName: string, path?: string) => dispatcher.dispatch(new NavigateToApplication(applicationName, path)), -}); - -type RequiredNetworkElementsListComponentProps = WithStyles<typeof styles> & Connect<typeof mapProps, typeof mapDispatch>; -type RequiredNetworkElementsListComponentState = { - networkElementToEdit: RequiredNetworkElementType, - networkElementEditorMode: EditNetworkElementDialogMode -} - -const emptyRequireNetworkElement = { mountId: '', host: '', port: 0 }; - -const RequiredNetworkElementTable = MaterialTable as MaterialTableCtorType<RequiredNetworkElementType>; - -export class RequiredNetworkElementsListComponent extends React.Component<RequiredNetworkElementsListComponentProps, RequiredNetworkElementsListComponentState> { - - constructor(props: RequiredNetworkElementsListComponentProps) { - super(props); - - this.state = { - networkElementToEdit: emptyRequireNetworkElement, - networkElementEditorMode: EditNetworkElementDialogMode.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.MountNetworkElementToRequiredNetworkElements, - networkElementToEdit: emptyRequireNetworkElement, - }); - } - }; - return ( - <> - <RequiredNetworkElementTable customActionButtons={ [addRequireNetworkElementAction] } columns={ [ - { property: "mountId", title: "Name", type: ColumnType.text }, - { - property: "connectionStatus", title: "Connection Status", type: ColumnType.custom, disableFilter: true, disableSorting: true, customControl: ({ rowData }) => { - const unknownNetworkElement = this.props.mountedNetworkElements.elements.find(el => el.mountId === rowData.mountId); - const connectionStatus = unknownNetworkElement && unknownNetworkElement.connectionStatus || 'disconnected'; - const cssClasses = connectionStatus === "connected" - ? classes.connectionStatusConnected - : connectionStatus === "disconnected" - ? classes.connectionStatusDisconnected - : classes.connectionStatusConnecting - return <div className={ cssClasses } >{ connectionStatus } </div> - - } - }, - { property: "host", title: "Host", type: ColumnType.text }, - { property: "port", title: "Port", type: ColumnType.text }, - // { property: "username", title: "Username", type: ColumnType.text }, - // { property: "password", title: "Password", type: ColumnType.text }, - { - property: "actions", title: "Actions", type: ColumnType.custom, customControl: ({ rowData }) => { - const unknownNetworkElement = this.props.mountedNetworkElements.elements.find(el => el.mountId === rowData.mountId); - const connectionStatus = unknownNetworkElement && unknownNetworkElement.connectionStatus || 'disconnected'; - return ( - <> - <div className={ classes.spacer }> - <Tooltip title={ "Mount" } ><IconButton className={ classes.button } onClick={ event => this.onOpenMountdNetworkElementsDialog(event, rowData) }><LinkIcon /></IconButton></Tooltip> - <Tooltip title={ "Unmount" } ><IconButton className={ classes.button } onClick={ event => this.onOpenUnmountdNetworkElementsDialog(event, rowData) }><LinkOffIcon /></IconButton></Tooltip> - <Tooltip title={ "Remove" } ><IconButton className={ classes.button } onClick={ event => this.onOpenRemoveRequiredNetworkElementDialog(event, rowData) } ><RemoveIcon /></IconButton></Tooltip> - </div> - <div className={ classes.spacer }> - <Tooltip title={ "Info" } ><Button className={ classes.button } >I</Button></Tooltip> - </div> - <div className={ classes.spacer }> - <Tooltip title={ "Fault" } ><Button className={ classes.button } onClick={ this.navigateToApplicationHandlerCreator("fault", rowData) } >F</Button></Tooltip> - <Tooltip title={"Configure"} ><Button className={classes.button} onClick={this.navigateToApplicationHandlerCreator("configuration", rowData)} >C</Button></Tooltip> - <Tooltip title={ "Accounting " } ><Button className={ classes.button } onClick={ this.navigateToApplicationHandlerCreator("accounting", rowData) }>A</Button></Tooltip> - <Tooltip title={ "Performance" } ><Button className={ classes.button } onClick={ this.navigateToApplicationHandlerCreator("performance", rowData) }>P</Button></Tooltip> - <Tooltip title={ "Security" } ><Button className={ classes.button } onClick={ this.navigateToApplicationHandlerCreator("security", rowData) }>S</Button></Tooltip> - </div> - </> - ) - } - }, - ] } idProperty="mountId" { ...this.props.requiredNetworkElementsActions } { ...this.props.requiredNetworkElementsProperties } asynchronus > - </RequiredNetworkElementTable> - <EditNetworkElementDialog - initialNetworkElement={ networkElementToEdit } - mode={ this.state.networkElementEditorMode } - onClose={ this.onCloseEditNetworkElementDialog } - /> - </> - ); - }; - - public componentDidMount() { - this.props.requiredNetworkElementsActions.onRefresh(); - } - - private onOpenRemoveRequiredNetworkElementDialog = (event: React.MouseEvent<HTMLElement>, element: RequiredNetworkElementType) => { - this.setState({ - networkElementToEdit: element, - networkElementEditorMode: EditNetworkElementDialogMode.RequiredNetworkElementToUnknownNetworkElements - }); - event.preventDefault(); - event.stopPropagation(); - } - - private onOpenUnmountdNetworkElementsDialog = (event: React.MouseEvent<HTMLElement>, element: RequiredNetworkElementType) => { - this.setState({ - networkElementToEdit: element, - networkElementEditorMode: EditNetworkElementDialogMode.UnmountNetworkElement - }); - event.preventDefault(); - event.stopPropagation(); - } - - private onOpenMountdNetworkElementsDialog = (event: React.MouseEvent<HTMLElement>, element: RequiredNetworkElementType) => { - this.setState({ - networkElementToEdit: element, - networkElementEditorMode: EditNetworkElementDialogMode.MountNetworkElement - }); - event.preventDefault(); - event.stopPropagation(); - } - - private onCloseEditNetworkElementDialog = () => { - this.setState({ - networkElementEditorMode: EditNetworkElementDialogMode.None, - networkElementToEdit: emptyRequireNetworkElement, - }); - } - - private navigateToApplicationHandlerCreator = (applicationName: string, element: NetworkElementBaseType) => (event: React.MouseEvent<HTMLElement>) => { - this.props.navigateToApplication(applicationName, element.mountId); - event.preventDefault(); - event.stopPropagation(); - } -} - -export const RequiredNetworkElementsList = withStyles(styles)(connect(mapProps, mapDispatch)(RequiredNetworkElementsListComponent)); -export default RequiredNetworkElementsList;
\ No newline at end of file diff --git a/sdnr/wt/odlux/apps/connectApp/src/components/unknownNetworkElements.tsx b/sdnr/wt/odlux/apps/connectApp/src/components/unknownNetworkElements.tsx deleted file mode 100644 index 62b969575..000000000 --- a/sdnr/wt/odlux/apps/connectApp/src/components/unknownNetworkElements.tsx +++ /dev/null @@ -1,211 +0,0 @@ -/** - * ============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, Tooltip } from '@material-ui/core'; - -import AddIcon from '@material-ui/icons/Add'; -import LinkOffIcon from '@material-ui/icons/LinkOff'; -import AddCircleIcon from '@material-ui/icons/AddCircleOutline'; - -import Button from '@material-ui/core/Button'; -import IconButton from '@material-ui/core/IconButton'; - -import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore'; -import { MaterialTable, ColumnType, MaterialTableCtorType } from '../../../../framework/src/components/material-table'; -import { Connect, connect, IDispatcher } from '../../../../framework/src/flux/connect'; -import { NavigateToApplication } from '../../../../framework/src/actions/navigationActions'; - -import { RequiredNetworkElementType } from '../models/requiredNetworkElements'; -import { IMountedNetworkElementsState } from '../handlers/mountedNetworkElementsHandler'; -import EditNetworkElementDialog, { EditNetworkElementDialogMode } from './editNetworkElementDialog'; -import { NetworkElementBaseType } from 'models/networkElementBase'; - - -const styles = (theme: Theme) => createStyles({ - button: { - margin: 0, - padding: "6px 6px", - minWidth: 'unset' - }, - spacer: { - marginLeft: theme.spacing.unit, - marginRight: theme.spacing.unit, - display: "inline" - } -}); - -const mapProps = ({ connect: state }: IApplicationStoreState) => ({ - mountedNetworkElements: state.mountedNetworkElements -}); - -const mapDispatch = (dispatcher: IDispatcher) => ({ - navigateToApplication: (applicationName: string, path?: string) => dispatcher.dispatch(new NavigateToApplication(applicationName, path)), -}); -type UnknownNetworkElementDisplayType = NetworkElementBaseType & { - connectionStatus: string, - coreModelRev: string, - airInterfaceRev: string -} - -type UnknownNetworkElementsListProps = WithStyles<typeof styles> & Connect<typeof mapProps, typeof mapDispatch> & {} - -type UnknownNetworkElementsListState = { - - unknownNetworkElements: UnknownNetworkElementDisplayType[]; - - networkElementToEdit: RequiredNetworkElementType; - networkElementEditorMode: EditNetworkElementDialogMode; -} - - -const emptyRequireNetworkElement = { mountId: '', host: '', port: 0 }; -const UnknownNetworkElementTable = MaterialTable as MaterialTableCtorType<UnknownNetworkElementDisplayType>; -export class UnknownNetworkElementsListComponent extends React.Component<UnknownNetworkElementsListProps, UnknownNetworkElementsListState> { - - constructor(props: UnknownNetworkElementsListProps) { - super(props); - - this.state = { - unknownNetworkElements: [], - networkElementToEdit: emptyRequireNetworkElement, - networkElementEditorMode: EditNetworkElementDialogMode.None, - }; - } - - static getDerivedStateFromProps(props: UnknownNetworkElementsListProps, state: UnknownNetworkElementsListState & { _mountedNetworkElements: IMountedNetworkElementsState }) { - if (props.mountedNetworkElements != state._mountedNetworkElements) { - state.unknownNetworkElements = props.mountedNetworkElements.elements.filter(element => !element.required).map(element => { - - // handle onfCoreModelRevision - const onfCoreModelRevision = element.capabilities.find((cap) => { - return cap.module === 'core-model' || cap.module === 'CoreModel-CoreNetworkModule-ObjectClasses' ; - }); - const onfAirInterfaceRevision = element.capabilities.find((cap) => { - return cap.module === 'microwave-model' || cap.module === 'MicrowaveModel-ObjectClasses-AirInterface' ; - }); - return { - mountId: element.mountId, - host: element.host, - port: element.port, - connectionStatus: element.connectionStatus, - coreModelRev: onfCoreModelRevision && onfCoreModelRevision.revision || 'unknown', - airInterfaceRev: onfAirInterfaceRevision && onfAirInterfaceRevision.revision || 'unknown' - } - } - ); - } - return state; - } - - render(): JSX.Element { - const { classes } = this.props; - const { networkElementToEdit, networkElementEditorMode, unknownNetworkElements } = this.state; - const addRequireNetworkElementAction = { - icon: AddIcon, tooltip: 'Add', onClick: () => { - this.setState({ - networkElementEditorMode: EditNetworkElementDialogMode.MountNetworkElementToUnknonwNetworkElements, - networkElementToEdit: emptyRequireNetworkElement, - }); - } - }; - return ( - <> - <UnknownNetworkElementTable customActionButtons={ [addRequireNetworkElementAction] } asynchronus rows={ unknownNetworkElements } columns={ [ - { property: "mountId", title: "Name", type: ColumnType.text }, - { property: "connectionStatus", title: "Connection Status", type: ColumnType.text }, - { property: "host", title: "Host", type: ColumnType.text }, - { property: "port", title: "Port", type: ColumnType.text }, - { property: "coreModelRev", title: "Core Model", type: ColumnType.text }, - { property: "airInterfaceRev", title: "Air interface", type: ColumnType.text }, - { - property: "actions", title: "Actions", type: ColumnType.custom, customControl: ({ rowData }) => ( - <> - <div className={ classes.spacer }> - <Tooltip title={ "Unmount" } ><IconButton className={ classes.button } onClick={ event => this.onOpenUnmountdNetworkElementsDialog(event, rowData) } ><LinkOffIcon /></IconButton></Tooltip> - <Tooltip title={ "Add to required" } ><IconButton className={ classes.button } onClick={ event => this.onOpenAddToRequiredNetworkElementsDialog(event, rowData) } ><AddCircleIcon /></IconButton></Tooltip> - </div> - <div className={ classes.spacer }> - <Tooltip title={ "Info" } ><Button className={ classes.button } >I</Button></Tooltip> - </div> - <div className={ classes.spacer }> - <Tooltip title={ "Fault" } ><Button className={ classes.button } onClick={ this.navigateToApplicationHandlerCreator("fault", rowData) } >F</Button></Tooltip> - <Tooltip title={ "Configure" } ><Button className={ classes.button } onClick={ this.navigateToApplicationHandlerCreator("configuration", rowData) } >C</Button></Tooltip> - <Tooltip title={ "Accounting " } ><Button className={ classes.button } onClick={ this.navigateToApplicationHandlerCreator("accounting", rowData) }>A</Button></Tooltip> - <Tooltip title={ "Performance" } ><Button className={ classes.button } onClick={ this.navigateToApplicationHandlerCreator("performance", rowData) }>P</Button></Tooltip> - <Tooltip title={ "Security" } ><Button className={ classes.button } onClick={ this.navigateToApplicationHandlerCreator("security", rowData) }>S</Button></Tooltip> - </div> - </> - ) - }, - ] } idProperty="mountId" > - </UnknownNetworkElementTable> - - <EditNetworkElementDialog - mode={ networkElementEditorMode } - initialNetworkElement={ networkElementToEdit } - onClose={ this.onCloseEditNetworkElementDialog } - /> - </> - ); - }; - - private onOpenAddToRequiredNetworkElementsDialog = (event: React.MouseEvent<HTMLElement>, element: UnknownNetworkElementDisplayType) => { - this.setState({ - networkElementToEdit: { - mountId: element.mountId, - host: element.host, - port: element.port, - username: 'admin', - password: 'admin', - }, - networkElementEditorMode: EditNetworkElementDialogMode.UnknownNetworkElementToRequiredNetworkElements - }); - event.preventDefault(); - event.stopPropagation(); - } - - private onOpenUnmountdNetworkElementsDialog = (event: React.MouseEvent<HTMLElement>, element: UnknownNetworkElementDisplayType) => { - this.setState({ - networkElementToEdit: { - mountId: element.mountId, - host: element.host, - port: element.port - }, - networkElementEditorMode: EditNetworkElementDialogMode.UnmountNetworkElement - }); - event.preventDefault(); - event.stopPropagation(); - } - - private onCloseEditNetworkElementDialog = () => { - this.setState({ - networkElementEditorMode: EditNetworkElementDialogMode.None, - networkElementToEdit: emptyRequireNetworkElement, - }); - } - - private navigateToApplicationHandlerCreator = (applicationName: string, element: NetworkElementBaseType) => (event: React.MouseEvent<HTMLElement>) => { - this.props.navigateToApplication(applicationName, element.mountId); - event.preventDefault(); - event.stopPropagation(); - } - -} - -export const UnknownNetworkElementsList = withStyles(styles)(connect(mapProps, mapDispatch)(UnknownNetworkElementsListComponent)); -export default UnknownNetworkElementsList; 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<PanelId> = (state = null, action) => { + if (action instanceof SetPanelAction) { + state = action.panelId; + } + return state; +} + +interface guiCutThroughState { + availableWebUris: guiCutThrough[]; + knownElements: string[]; +} + +const guiCutThroughHandler: IActionHandler<guiCutThroughState> = (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<IConnectAppStoreState>(actionHandlers); +export default connectAppRootHandler; diff --git a/sdnr/wt/odlux/apps/connectApp/src/handlers/connectAppRootHandler.tsx b/sdnr/wt/odlux/apps/connectApp/src/handlers/connectAppRootHandler.tsx deleted file mode 100644 index 1c27f4b32..000000000 --- a/sdnr/wt/odlux/apps/connectApp/src/handlers/connectAppRootHandler.tsx +++ /dev/null @@ -1,42 +0,0 @@ -/** - * ============LICENSE_START======================================================================== - * ONAP : ccsdk feature sdnr wt odlux - * ================================================================================================= - * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved. - * ================================================================================================= - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - * ============LICENSE_END========================================================================== - */ -import { combineActionHandler } from '../../../../framework/src/flux/middleware'; -import { IRequiredNetworkElementsState, requiredNetworkElementsActionHandler } from './requiredNetworkElementsHandler'; -import { IMountedNetworkElementsState, mountedNetworkElementsActionHandler } from './mountedNetworkElementsHandler'; -import { IConnectionStatusLogState, connectionStatusLogActionHandler } from './connectionStatusLogHandler'; - -export interface IConnectAppStoreState { - requiredNetworkElements: IRequiredNetworkElementsState; - mountedNetworkElements: IMountedNetworkElementsState; - connectionStatusLog: IConnectionStatusLogState; -} - -declare module '../../../../framework/src/store/applicationStore' { - interface IApplicationStoreState { - connect: IConnectAppStoreState - } -} - -const actionHandlers = { - requiredNetworkElements: requiredNetworkElementsActionHandler, - mountedNetworkElements: mountedNetworkElementsActionHandler, - connectionStatusLog: connectionStatusLogActionHandler -}; - -export const connectAppRootHandler = combineActionHandler <IConnectAppStoreState>(actionHandlers); -export default connectAppRootHandler; diff --git a/sdnr/wt/odlux/apps/connectApp/src/handlers/requiredNetworkElementsHandler.tsx b/sdnr/wt/odlux/apps/connectApp/src/handlers/connectionStatusLogHandler.ts index 10b3b1b07..6863ec33b 100644 --- a/sdnr/wt/odlux/apps/connectApp/src/handlers/requiredNetworkElementsHandler.tsx +++ b/sdnr/wt/odlux/apps/connectApp/src/handlers/connectionStatusLogHandler.ts @@ -18,18 +18,18 @@ import { createExternal,IExternalTableState } from '../../../../framework/src/components/material-table/utilities'; import { createSearchDataHandler } from '../../../../framework/src/utilities/elasticSearch'; -import { RequiredNetworkElementType } from '../models/requiredNetworkElements'; -export interface IRequiredNetworkElementsState extends IExternalTableState<RequiredNetworkElementType> { } +import { NetworkElementConnectionLog } from '../models/networkElementConnectionLog'; +export interface IConnectionStatusLogState extends IExternalTableState<NetworkElementConnectionLog> { } // create eleactic search material data fetch handler -const requiredNetworkElementsSearchHandler = createSearchDataHandler<RequiredNetworkElementType>('mwtn/required-networkelement'); +const connectionStatusLogSearchHandler = createSearchDataHandler<NetworkElementConnectionLog>('connectionlog'); export const { - actionHandler: requiredNetworkElementsActionHandler, - createActions: createRequiredNetworkElementsActions, - createProperties: createRequiredNetworkElementsProperties, - reloadAction: requiredNetworkElementsReloadAction, + actionHandler: connectionStatusLogActionHandler, + createActions: createConnectionStatusLogActions, + createProperties: createConnectionStatusLogProperties, + reloadAction: connectionStatusLogReloadAction, // set value action, to change a value -} = createExternal<RequiredNetworkElementType>(requiredNetworkElementsSearchHandler, appState => appState.connect.requiredNetworkElements); +} = createExternal<NetworkElementConnectionLog>(connectionStatusLogSearchHandler, appState => appState.connect.connectionStatusLog); diff --git a/sdnr/wt/odlux/apps/connectApp/src/handlers/connectionStatusLogHandler.tsx b/sdnr/wt/odlux/apps/connectApp/src/handlers/connectionStatusLogHandler.tsx deleted file mode 100644 index 57e1930ed..000000000 --- a/sdnr/wt/odlux/apps/connectApp/src/handlers/connectionStatusLogHandler.tsx +++ /dev/null @@ -1,51 +0,0 @@ -/** - * ============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 { ConnectionStatusLogType } from '../models/connectionStatusLog'; -export interface IConnectionStatusLogState extends IExternalTableState<ConnectionStatusLogType> { } - -// create eleactic search material data fetch handler -const connectionStatusLogSearchHandler = createSearchDataHandler<{ event: ConnectionStatusLogType }, ConnectionStatusLogType>('sdnevents_v1/eventlog', null, - (event) => ({ - _id: event._id, - timeStamp: event._source.event.timeStamp, - objectId: event._source.event.objectId, - type: event._source.event.type, - elementStatus: event._source.event.type === 'ObjectCreationNotificationXml' - ? 'mounted' - : event._source.event.type === 'ObjectDeletionNotificationXml' - ? 'unmounted' - : event._source.event.type === 'AttributeValueChangedNotificationXml' - ? event._source.event.newValue - : 'unknown', - newValue: '' - - }), - (name) => `event.${ name }`); - -export const { - actionHandler: connectionStatusLogActionHandler, - createActions: createConnectionStatusLogActions, - createProperties: createConnectionStatusLogProperties, - reloadAction: connectionStatusLogReloadAction, - - // set value action, to change a value -} = createExternal<ConnectionStatusLogType>(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<IInfoNetworkElementsState> = (state = infoNetworkElementsStateInit, action) => { + if (action instanceof LoadAllElementInfoAction) { + state = { + ...state, + busy: true + }; + } else if (action instanceof AllElementInfoLoadedAction) { + if (!action.error && action.elementInfo) { + state = { + ...state, + elementInfo: action.elementInfo, + busy: false + }; + } else { + state = { + ...state, + busy: false + }; + } + } + return state; +};
\ No newline at end of file diff --git a/sdnr/wt/odlux/apps/connectApp/src/handlers/mountedNetworkElementsHandler.tsx b/sdnr/wt/odlux/apps/connectApp/src/handlers/mountedNetworkElementsHandler.tsx deleted file mode 100644 index 089268946..000000000 --- a/sdnr/wt/odlux/apps/connectApp/src/handlers/mountedNetworkElementsHandler.tsx +++ /dev/null @@ -1,111 +0,0 @@ -/** - * ============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 { - AddOrUpdateMountedNetworkElement, - AllMountedNetworkElementsLoadedAction, - LoadAllMountedNetworkElementsAction, - RemoveMountedNetworkElement, - UpdateConnectionStateMountedNetworkElement, - UpdateRequiredMountedNetworkElement -} from '../actions/mountedNetworkElementsActions'; - -import { MountedNetworkElementType } from '../models/mountedNetworkElements'; - -export interface IMountedNetworkElementsState { - elements: MountedNetworkElementType[]; - busy: boolean; -} - -const mountedNetworkElementsStateInit: IMountedNetworkElementsState = { - elements: [], - busy: false -}; - -export const mountedNetworkElementsActionHandler: IActionHandler<IMountedNetworkElementsState> = (state = mountedNetworkElementsStateInit, action) => { - if (action instanceof LoadAllMountedNetworkElementsAction) { - - state = { - ...state, - busy: true - }; - - } else if (action instanceof AllMountedNetworkElementsLoadedAction) { - if (!action.error && action.mountedNetworkElements) { - state = { - ...state, - elements: action.mountedNetworkElements, - busy: false - }; - } else { - state = { - ...state, - busy: false - }; - } - } else if (action instanceof AddOrUpdateMountedNetworkElement) { - if (!action.mountedNetworkElement) return state; // should handle error here - const index = state.elements.findIndex(el => el.mountId === (action.mountedNetworkElement && action.mountedNetworkElement.mountId)); - if (index > -1) { - state = { - ...state, - elements: [ - ...state.elements.slice(0, index), - action.mountedNetworkElement, - ...state.elements.slice(index + 1) - ] - } - } else { - state = { - ...state, - elements: [...state.elements, action.mountedNetworkElement], - } - }; - } else if (action instanceof RemoveMountedNetworkElement) { - state = { - ...state, - elements: state.elements.filter(e => e.mountId !== action.mountId), - }; - } else if (action instanceof UpdateConnectionStateMountedNetworkElement) { - const index = state.elements.findIndex(el => el.mountId === action.mountId); - if (index > -1) { - state = { - ...state, - elements: [ - ...state.elements.slice(0, index), - { ...state.elements[index], connectionStatus: action.mountId }, - ...state.elements.slice(index + 1) - ] - } - } - } else if (action instanceof UpdateRequiredMountedNetworkElement) { - const index = state.elements.findIndex(el => el.mountId === action.mountId); - if (index > -1 && (state.elements[index].required !== action.required)) { - state = { - ...state, - elements: [ - ...state.elements.slice(0, index), - { ...state.elements[index], required: action.required }, - ...state.elements.slice(index + 1) - ] - } - } - }; - 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<NetworkElementConnection> { } + +// create eleactic search material data fetch handler +const networkElementsSearchHandler = createSearchDataHandler<NetworkElementConnection>('network-element-connection'); + +export const { + actionHandler: networkElementsActionHandler, + createActions: createNetworkElementsActions, + createProperties: createNetworkElementsProperties, + reloadAction: networkElementsReloadAction, + + // set value action, to change a value +} = createExternal<NetworkElementConnection>(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 index 0f95005de..9c8a2063e 100644 --- a/sdnr/wt/odlux/apps/connectApp/src/index.html +++ b/sdnr/wt/odlux/apps/connectApp/src/index.html @@ -5,7 +5,7 @@ <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> - <link rel="stylesheet" href="./vendor.css" > + <link rel="stylesheet" href="./vendor.css"> <title>connectApp</title> </head> @@ -15,9 +15,10 @@ <script type="text/javascript" src="./config.js"></script> <script> // run the application - require(["app","connectApp", "faultApp"], function (app, connectApp, faultApp) { + require(["app", "connectApp", "faultApp", "inventoryApp", "configurationApp"], function (app, connectApp, faultApp, inventoryApp, configurationApp) { connectApp.register(); faultApp.register(); + inventoryApp.register(); app("./app.tsx").runApplication(); }); </script> 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/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/requiredNetworkElements.ts b/sdnr/wt/odlux/apps/connectApp/src/models/networkElementConnectionLog.ts index 42d22afc0..a1535cbe5 100644 --- a/sdnr/wt/odlux/apps/connectApp/src/models/requiredNetworkElements.ts +++ b/sdnr/wt/odlux/apps/connectApp/src/models/networkElementConnectionLog.ts @@ -15,13 +15,11 @@ * the License. * ============LICENSE_END========================================================================== */ -import { NetworkElementBaseType } from "./networkElementBase"; -/** -* Represents data of Required Network Elements. -*/ -export type RequiredNetworkElementType = NetworkElementBaseType & { - username?: string; - password?: string; +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 index 357245d46..694009d1b 100644 --- a/sdnr/wt/odlux/apps/connectApp/src/models/topologyNetconf.ts +++ b/sdnr/wt/odlux/apps/connectApp/src/models/topologyNetconf.ts @@ -15,14 +15,6 @@ * the License. * ============LICENSE_END========================================================================== */ -export interface UnavailableCapability { - capability: string; - "failure-reason": string; -} - -export interface NetconfNodeTopologyUnavailableCapabilities { - "unavailable-capability": UnavailableCapability[]; -} export interface AvailableCapability { "capability-origin": string; @@ -33,18 +25,9 @@ export interface NetconfNodeTopologyAvailableCapabilities { "available-capability": AvailableCapability[]; } -export interface NetconfNodeTopologyClusteredConnectionStatus { - "netconf-master-node": string -} - export interface TopologyNode { "node-id": string; - "netconf-node-topology:clustered-connection-status": NetconfNodeTopologyClusteredConnectionStatus; - "netconf-node-topology:unavailable-capabilities": NetconfNodeTopologyUnavailableCapabilities; "netconf-node-topology:available-capabilities": NetconfNodeTopologyAvailableCapabilities; - "netconf-node-topology:host": string; - "netconf-node-topology:connection-status": string; - "netconf-node-topology:port": number; } export interface Topology { diff --git a/sdnr/wt/odlux/apps/connectApp/src/models/mountedNetworkElements.ts b/sdnr/wt/odlux/apps/connectApp/src/models/yangCapabilitiesType.ts index 0be38a615..230468287 100644 --- a/sdnr/wt/odlux/apps/connectApp/src/models/mountedNetworkElements.ts +++ b/sdnr/wt/odlux/apps/connectApp/src/models/yangCapabilitiesType.ts @@ -15,14 +15,8 @@ * the License. * ============LICENSE_END========================================================================== */ -import { NetworkElementBaseType } from "./networkElementBase"; - -/** -* Represents data of an mounted network elements. -*/ -export type MountedNetworkElementType = NetworkElementBaseType & { - connectionStatus: string; - required: boolean; - capabilities: { module: string, revision: string }[]; -}; +export type AvailableCapabilities = { + module: string, + revision: string +}
\ No newline at end of file diff --git a/sdnr/wt/odlux/apps/connectApp/src/plugin.tsx b/sdnr/wt/odlux/apps/connectApp/src/pluginConnect.tsx index aa08e7b15..f711c440c 100644 --- a/sdnr/wt/odlux/apps/connectApp/src/plugin.tsx +++ b/sdnr/wt/odlux/apps/connectApp/src/pluginConnect.tsx @@ -22,15 +22,10 @@ import applicationManager from '../../../framework/src/services/applicationManag import { subscribe, IFormatedMessage } from '../../../framework/src/services/notificationService'; import connectAppRootHandler from './handlers/connectAppRootHandler'; -import ConnectApplication from './views/connectView'; - -import { - addMountedNetworkElementAsyncActionCreator, - updateMountedNetworkElementAsyncActionCreator, - loadAllMountedNetworkElementsAsync -} from './actions/mountedNetworkElementsActions'; +import ConnectApplication from './views/connectView'; import { AddSnackbarNotification } from '../../../framework/src/actions/snackbarActions'; +import { updateCurrentViewAsyncAction } from './actions/commonNetworkElementsActions'; type ObjectNotification = { counter: string; @@ -48,22 +43,14 @@ export function register() { menuEntry: "Connect" }); - const updateAllMountedNetworkElements = () => { - applicationApi.applicationStoreInitialized.then(applicationStore => { applicationStore.dispatch(loadAllMountedNetworkElementsAsync); }) - }; - - applicationApi.loginEvent.addHandler(updateAllMountedNetworkElements); - updateAllMountedNetworkElements(); - // subscribe to the websocket notifications subscribe<ObjectNotification & IFormatedMessage>(["ObjectCreationNotification", "ObjectDeletionNotification", "AttributeValueChangedNotification"], (msg => { const store = applicationApi.applicationStore; if (msg && msg.notifType === "ObjectCreationNotification" && store) { - store.dispatch(addMountedNetworkElementAsyncActionCreator(msg.objectId)); 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.dispatch(updateMountedNetworkElementAsyncActionCreator(msg.objectId)); } + 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 index b50a06ee1..7a410f4ae 100644 --- a/sdnr/wt/odlux/apps/connectApp/src/services/connectService.ts +++ b/sdnr/wt/odlux/apps/connectApp/src/services/connectService.ts @@ -15,150 +15,66 @@ * the License. * ============LICENSE_END========================================================================== */ -import { RequiredNetworkElementType } from '../models/requiredNetworkElements'; -import { MountedNetworkElementType } from '../models/mountedNetworkElements'; -import { Topology, TopologyNode } from '../models/topologyNetconf'; import { requestRest } from '../../../../framework/src/services/restService'; -import { Result, HitEntry } from '../../../../framework/src/models/elasticSearch'; +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. - */ +* Represents a web api accessor service for all Network Elements actions. +*/ class ConnectService { - /** - * Gets all known required network elements from the backend. - */ - public async getAllRequiredNetworkElements(): Promise<(RequiredNetworkElementType & { _id: string })[] | null> { - const path = 'database/mwtn/required-networkelement/_search'; - const query = { "query": { "match_all": {} } }; - - const result = await requestRest<Result<RequiredNetworkElementType>>(path, { method: "POST", body: JSON.stringify(query) }); - return result && result.hits && result.hits.hits && result.hits.hits.map(ne => ({ - _id: ne._id, - mountId: ne._source && ne._source.mountId, - host: ne._source && ne._source.host, - port: ne._source && ne._source.port, - username: ne._source && ne._source.username, - password: ne._source && ne._source.password, - })) || null; - } - public async getRequiredNetworkElementByMountId(mountId:string): Promise<(RequiredNetworkElementType & { _id: string }) | null> { - const path = `database/mwtn/required-networkelement/${mountId}`; - - const result = await requestRest<HitEntry<RequiredNetworkElementType> & { found: boolean }>(path, { method: "GET" }); - return result && result.found && result._source && { - _id: result._id, - mountId: result._source.mountId, - host: result._source.host, - port: result._source.port, - username: result._source.username, - password: result._source.password, - } || null; + /** + * Inserts a network elements. + */ + public async createNetworkElement(element: NetworkElementConnection): Promise<NetworkElementConnection | null> { + const path = `/restconf/operations/data-provider:create-network-element-connection`; + const result = await requestRest<NetworkElementConnection>(path, { + method: "POST", body: JSON.stringify(convertPropertyNames({ input: element }, replaceUpperCase)) + }); + return result || null; } /** - * Inserts data into the required network elements table. - */ - public async insertRequiredNetworkElement(element: RequiredNetworkElementType): Promise<RequiredNetworkElementType | null> { - const path = `database/mwtn/required-networkelement/${ element.mountId }`; - const result = await requestRest<RequiredNetworkElementType>(path, { method: "POST", body: JSON.stringify(element) }); + * Updates a network element. + */ + public async updateNetworkElement(element: UpdateNetworkElement): Promise<NetworkElementConnection | null> { + const path = `/restconf/operations/data-provider:update-network-element-connection`; + const result = await requestRest<NetworkElementConnection>(path, { + method: "POST", body: JSON.stringify(convertPropertyNames({ input: element }, replaceUpperCase)) + }); return result || null; } /** - * Deletes data from the Required Network Elements backend. + * Deletes a network element. */ - public async deleteRequiredNetworkElement(element: RequiredNetworkElementType): Promise<RequiredNetworkElementType | null> { - const path = `database/mwtn/required-networkelement/${ element.mountId }`; - const result = await requestRest<RequiredNetworkElementType>(path, { method: "DELETE", body: JSON.stringify(element) }); + public async deleteNetworkElement(element: UpdateNetworkElement): Promise<NetworkElementConnection | null> { + const query = { + "id": element.id + }; + const path = `/restconf/operations/data-provider:delete-network-element-connection`; + const result = await requestRest<NetworkElementConnection>(path, { + method: "POST", body: JSON.stringify(convertPropertyNames({ input: query }, replaceUpperCase)) + }); return result || null; } - private static mapTopologyNode = (mountPoint: TopologyNode, required: boolean ) => { - // handle onfCapabilities - let onfCapabilities: { module: string, revision: string }[] | undefined = undefined; - - const capId = 'netconf-node-topology:available-capabilities'; - if (mountPoint[capId] && mountPoint[capId]['available-capability']) { - onfCapabilities = mountPoint[capId]['available-capability'].filter((cap) => { - return cap.capability.includes('?revision='); - }).map((cap) => { - return { - module: cap.capability.split(')')[1], - revision: cap.capability.split('?revision=')[1].substring(0, 10) - }; - }).sort((a, b) => { - if (a.module < b.module) return -1; - if (a.module > b.module) return 1; - return 0; - }); - } - - // handle clustered-connection-status - const statusId = 'netconf-node-topology:clustered-connection-status'; - let client = 'localhost'; - - if (mountPoint[statusId] && mountPoint[statusId]['netconf-master-node']) { - let node = mountPoint[statusId]['netconf-master-node']; - node = node.substring(node.indexOf('@')); - client = node.substring(1, node.indexOf(':')); - } - const mountId = mountPoint["node-id"]; - return { - mountId: mountId, - host: mountPoint["netconf-node-topology:host"], - port: mountPoint["netconf-node-topology:port"], - connectionStatus: mountPoint['netconf-node-topology:connection-status'], - capabilities: onfCapabilities || [], - required: required, - client - } - } - - /** Get all mounted network elements and fills the property required according to the database contents. */ - public async getMountedNetworkElementsList(): Promise<MountedNetworkElementType[] | null> { - const path = 'restconf/operational/network-topology:network-topology/topology/topology-netconf'; - - const topologyRequestPomise = requestRest<{ topology: Topology[] | null }>(path, { method: "GET" }); - const requiredNetworkElementsPromise = this.getAllRequiredNetworkElements(); - - const [netconfResponse, requiredNetworkElements] = await Promise.all([topologyRequestPomise, requiredNetworkElementsPromise]); - - // process topologyNetconf (get all known network elements) - const topologyNetconf = netconfResponse && netconfResponse.topology && netconfResponse.topology.find(topology => topology["topology-id"] === 'topology-netconf'); - let mountPoints = topologyNetconf && topologyNetconf.node && topologyNetconf.node.filter( - mountPoint => mountPoint['node-id'] !== 'controller-config').map(mountedElement => { - const required = requiredNetworkElements && requiredNetworkElements.some( - requiredElement => requiredElement.mountId === mountedElement["node-id"]); - return ConnectService.mapTopologyNode(mountedElement, !!required); - }); - - return mountPoints || []; - } - - /** Get one mounted network element. */ - public async getMountedNetworkElementByMountId(mountId: string): Promise<MountedNetworkElementType | null> { - const path = 'restconf/operational/network-topology:network-topology/topology/topology-netconf/node/' + mountId; - const getMountedNetworkElementByMountIdPromise = requestRest<{ node: TopologyNode[] | null }>(path, { method: "GET" }); - const getRequiredNetworkElementByMountIdPromise = this.getRequiredNetworkElementByMountId(mountId); - - const [mountedNetworkElement, requiredNetworkElement] = await Promise.all([getMountedNetworkElementByMountIdPromise, getRequiredNetworkElementByMountIdPromise]); - return mountedNetworkElement && mountedNetworkElement.node && ConnectService.mapTopologyNode(mountedNetworkElement.node[0], requiredNetworkElement && requiredNetworkElement.mountId === mountedNetworkElement.node[0]["node-id"] || false) || null; - } - - /** Mounts an required network element. */ - public async mountNetworkElement(networkElement: RequiredNetworkElementType): Promise<boolean> { - const path = 'restconf/config/network-topology:network-topology/topology/topology-netconf/node/' + networkElement.mountId; + /** Mounts network element. */ + public async mountNetworkElement(networkElement: NetworkElementConnection): Promise<boolean> { + const path = 'restconf/config/network-topology:network-topology/topology/topology-netconf/node/' + networkElement.nodeId; const mountXml = [ '<node xmlns="urn:TBD:params:xml:ns:yang:network-topology">', - `<node-id>${ networkElement.mountId }</node-id>`, - `<host xmlns="urn:opendaylight:netconf-node-topology">${ networkElement.host }</host>`, - `<port xmlns="urn:opendaylight:netconf-node-topology">${ networkElement.port }</port>`, - `<username xmlns="urn:opendaylight:netconf-node-topology">${ networkElement.username }</username>`, - `<password xmlns="urn:opendaylight:netconf-node-topology">${ networkElement.password }</password>`, + `<node-id>${networkElement.nodeId}</node-id>`, + `<host xmlns="urn:opendaylight:netconf-node-topology">${networkElement.host}</host>`, + `<port xmlns="urn:opendaylight:netconf-node-topology">${networkElement.port}</port>`, + `<username xmlns="urn:opendaylight:netconf-node-topology">${networkElement.username}</username>`, + `<password xmlns="urn:opendaylight:netconf-node-topology">${networkElement.password}</password>`, ' <tcp-only xmlns="urn:opendaylight:netconf-node-topology">false</tcp-only>', ' <!-- non-mandatory fields with default values, you can safely remove these if you do not wish to override any of these values-->', @@ -189,8 +105,8 @@ class ConnectService { }; /** Unmounts a network element by its id. */ - public async unmountNetworkElement(mountId: string): Promise<boolean> { - const path = 'restconf/config/network-topology:network-topology/topology/topology-netconf/node/' + mountId; + public async unmountNetworkElement(nodeId: string): Promise<boolean> { + const path = 'restconf/config/network-topology:network-topology/topology/topology-netconf/node/' + nodeId; try { const result = await requestRest<string>(path, { @@ -208,6 +124,84 @@ class ConnectService { } }; + /** Yang capabilities of the selected network elements. */ + public async infoNetworkElement(nodeId: string): Promise<TopologyNode | null> { + const path = 'restconf/operational/network-topology:network-topology/topology/topology-netconf/node/' + nodeId; + const topologyRequestPomise = requestRest<Topology>(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<Result<ConnectionStatus>>(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<any>(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<any>(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(); diff --git a/sdnr/wt/odlux/apps/connectApp/src/views/connectView.tsx b/sdnr/wt/odlux/apps/connectApp/src/views/connectView.tsx index c86b384e1..aa3391c47 100644 --- a/sdnr/wt/odlux/apps/connectApp/src/views/connectView.tsx +++ b/sdnr/wt/odlux/apps/connectApp/src/views/connectView.tsx @@ -18,99 +18,94 @@ 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 { requiredNetworkElementsReloadAction, createRequiredNetworkElementsActions } from '../handlers/requiredNetworkElementsHandler'; -import { loadAllMountedNetworkElementsAsync } from '../actions/mountedNetworkElementsActions'; +import { networkElementsReloadAction, createNetworkElementsActions } from '../handlers/networkElementsHandler'; import { connectionStatusLogReloadAction, createConnectionStatusLogActions } from '../handlers/connectionStatusLogHandler'; -import { RequiredNetworkElementsList } from '../components/requiredNetworkElements'; +import { NetworkElementsList } from '../components/networkElements'; import { ConnectionStatusLog } from '../components/connectionStatusLog'; -import { UnknownNetworkElementsList } from '../components/unknownNetworkElements'; +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) => ({ - requiredNetworkElementsActions: createRequiredNetworkElementsActions(dispatcher.dispatch), + networkElementsActions: createNetworkElementsActions(dispatcher.dispatch), connectionStatusLogActions: createConnectionStatusLogActions(dispatcher.dispatch), - onLoadUnknownNetworkElements: () => { - dispatcher.dispatch(loadAllMountedNetworkElementsAsync); - }, - onLoadRequiredNetworkElements: () => { - dispatcher.dispatch(requiredNetworkElementsReloadAction); + onLoadNetworkElements: () => { + dispatcher.dispatch(networkElementsReloadAction); }, + loadWebUris: findWebUrisForGuiCutThroughAsyncAction(dispatcher.dispatch), onLoadConnectionStatusLog: () => { dispatcher.dispatch(connectionStatusLogReloadAction); + }, + switchActivePanel: (panelId: PanelId) => { + dispatcher.dispatch(setPanelAction(panelId)); } }); -type PanelId = null | "RequiredNetworkElements" | "UnknownNetworkElements" | "ConnectionStatusLog"; +type ConnectApplicationComponentProps = Connect<typeof mapProps, typeof mapDispatcher>; -type ConnectApplicationComponentProps = Connect<undefined, typeof mapDispatcher> ; +class ConnectApplicationComponent extends React.Component<ConnectApplicationComponentProps>{ -type ConnectApplicationComponentState = { - activePanel: PanelId; -}; + componentDidUpdate = () => { + // search for guicutthroughs after networkelements were found + const networkElements = this.props.netWorkElements; + const guiCuttrough = this.props.availableGuiCutroughs; -class ConnectApplicationComponent extends React.Component<ConnectApplicationComponentProps, ConnectApplicationComponentState>{ - /** - * Initialises this instance - */ - constructor(props: ConnectApplicationComponentProps) { - super(props); - - this.state = { - activePanel: null - }; + 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.state.activePanel ? null : panelId; - this.setState({ - activePanel: nextActivePanel - }, () => { - switch (nextActivePanel) { - case 'RequiredNetworkElements': - this.props.onLoadRequiredNetworkElements(); - break; - case 'UnknownNetworkElements': - // todo: should we update the application state ? - 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; - } - }); + 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 { activePanel } = this.state; + const { panelId } = this.props; return ( <> - <Panel activePanel={ activePanel } panelId={ 'RequiredNetworkElements' } onToggle={ this.onTogglePanel } title={ "Required Network Elements" }> - <RequiredNetworkElementsList /> - </Panel> - <Panel activePanel={ activePanel } panelId={ 'UnknownNetworkElements' } onToggle={ this.onTogglePanel } title={ "Unknown Network Elements" }> - <UnknownNetworkElementsList /> + <Panel activePanel={panelId} panelId={'NetworkElements'} onToggle={this.onTogglePanel} title={"Network Elements"}> + <NetworkElementsList /> </Panel> - <Panel activePanel={ activePanel } panelId={ 'ConnectionStatusLog' } onToggle={ this.onTogglePanel } title={ "Connection Status Log" }> + <Panel activePanel={panelId} panelId={'ConnectionStatusLog'} onToggle={this.onTogglePanel} title={"Connection Status Log"}> <ConnectionStatusLog /> </Panel> </> ); }; public componentDidMount() { - this.onTogglePanel("RequiredNetworkElements"); - this.props.onLoadUnknownNetworkElements(); - this.props.requiredNetworkElementsActions.onToggleFilter(); + this.onTogglePanel("NetworkElements"); + this.props.networkElementsActions.onToggleFilter(); this.props.connectionStatusLogActions.onToggleFilter(); } } -export const ConnectApplication = (connect(undefined, mapDispatcher)(ConnectApplicationComponent)); +export const ConnectApplication = (connect(mapProps, mapDispatcher)(ConnectApplicationComponent)); export default ConnectApplication;
\ No newline at end of file diff --git a/sdnr/wt/odlux/apps/connectApp/webpack.config.js b/sdnr/wt/odlux/apps/connectApp/webpack.config.js index a70e62976..6d70b04b0 100644 --- a/sdnr/wt/odlux/apps/connectApp/webpack.config.js +++ b/sdnr/wt/odlux/apps/connectApp/webpack.config.js @@ -26,7 +26,7 @@ module.exports = (env) => { context: path.resolve(__dirname, "src"), entry: { - connectApp: ["./plugin.tsx"] + connectApp: ["./pluginConnect.tsx"] }, devtool: env === "release" ? false : "source-map", @@ -125,12 +125,26 @@ module.exports = (env) => { colors: true }, proxy: { - "/restconf": { - target: "http://localhost:8181", + "/oauth2/": { + target: "http://10.20.6.29:28181", secure: false }, - "/database": { - target: "http://localhost:8181", + "/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 } } |