summaryrefslogtreecommitdiffstats
path: root/sdnr/wt/odlux/apps
diff options
context:
space:
mode:
Diffstat (limited to 'sdnr/wt/odlux/apps')
-rw-r--r--sdnr/wt/odlux/apps/connectApp/src/actions/commonNetworkElementsActions.ts26
-rw-r--r--sdnr/wt/odlux/apps/connectApp/src/actions/infoNetworkElementActions.ts105
-rw-r--r--sdnr/wt/odlux/apps/connectApp/src/components/infoNetworkElementDialog.tsx281
-rw-r--r--sdnr/wt/odlux/apps/connectApp/src/components/networkElements.tsx14
-rw-r--r--sdnr/wt/odlux/apps/connectApp/src/handlers/connectAppRootHandler.ts8
-rw-r--r--sdnr/wt/odlux/apps/connectApp/src/handlers/infoNetworkElementHandler.ts117
-rw-r--r--sdnr/wt/odlux/apps/connectApp/src/models/topologyNetconf.ts25
-rw-r--r--sdnr/wt/odlux/apps/connectApp/src/models/yangCapabilitiesType.ts6
-rw-r--r--sdnr/wt/odlux/apps/connectApp/src/services/connectService.ts457
9 files changed, 577 insertions, 462 deletions
diff --git a/sdnr/wt/odlux/apps/connectApp/src/actions/commonNetworkElementsActions.ts b/sdnr/wt/odlux/apps/connectApp/src/actions/commonNetworkElementsActions.ts
index 0c3266216..26aa8d2d7 100644
--- a/sdnr/wt/odlux/apps/connectApp/src/actions/commonNetworkElementsActions.ts
+++ b/sdnr/wt/odlux/apps/connectApp/src/actions/commonNetworkElementsActions.ts
@@ -64,6 +64,9 @@ export const findWebUrisForGuiCutThroughAsyncAction = (networkElementIds: string
// keep method from executing simultanously; state not used because change of iu isn't needed
+ if (isBusy)
+ return;
+ isBusy = true;
const { connect: { guiCutThrough, networkElements } } = getState();
@@ -78,16 +81,16 @@ export const findWebUrisForGuiCutThroughAsyncAction = (networkElementIds: string
if (item.status === "Connected") {
// if (item.coreModelCapability !== "Unsupported") {
- // element is connected and is added to search list, if it doesn't exist already
- const exists = guiCutThrough.searchedElements.filter(element => element.id === id).length > 0;
- if (!exists) {
- elementsToSearch.push(id);
-
- //element was found previously, but wasn't connected
- if (guiCutThrough.notSearchedElements.length > 0 && guiCutThrough.notSearchedElements.includes(id)) {
- prevFoundElements.push(id);
- }
+ // element is connected and is added to search list, if it doesn't exist already
+ const exists = guiCutThrough.searchedElements.filter(element => element.id === id).length > 0;
+ if (!exists) {
+ elementsToSearch.push(id);
+
+ //element was found previously, but wasn't connected
+ if (guiCutThrough.notSearchedElements.length > 0 && guiCutThrough.notSearchedElements.includes(id)) {
+ prevFoundElements.push(id);
}
+ }
// } else {
// // element does not support core model and must not be searched for a weburi
// const id = item.id as string;
@@ -113,9 +116,10 @@ export const findWebUrisForGuiCutThroughAsyncAction = (networkElementIds: string
if (elementsToSearch.length > 0 || notConnectedElements.length > 0 || unsupportedElements.length > 0) {
- const result = await connectService.getAllWebUriExtensionsForNetworkElementListAsync(elementsToSearch);
- dispatcher(new AddWebUriList(result, notConnectedElements, unsupportedElements, prevFoundElements));
+ const result = await connectService.getAllWebUriExtensionsForNetworkElementListAsync(elementsToSearch);
+ dispatcher(new AddWebUriList(result, notConnectedElements, unsupportedElements, prevFoundElements));
}
+ isBusy = false;
}
diff --git a/sdnr/wt/odlux/apps/connectApp/src/actions/infoNetworkElementActions.ts b/sdnr/wt/odlux/apps/connectApp/src/actions/infoNetworkElementActions.ts
index 4ae28aab2..bb744e236 100644
--- a/sdnr/wt/odlux/apps/connectApp/src/actions/infoNetworkElementActions.ts
+++ b/sdnr/wt/odlux/apps/connectApp/src/actions/infoNetworkElementActions.ts
@@ -15,43 +15,68 @@
* 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
+ import { Action } from '../../../../framework/src/flux/action';
+ import { Dispatch } from '../../../../framework/src/flux/store';
+
+ import { Module, 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 action causing the store to update element Yang capabilities Module Features.
+ */
+ export class AllElementInfoFeatureLoadedAction extends BaseAction {
+ /**
+ * Initialize this instance.
+ * @param elementFeatureInfo The information of the element which is returned.
+ */
+ constructor(public elementFeatureInfo: Module[] | null | undefined, 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));
+ });
+ }
+
+ /**
+ * Represents an asynchronous thunk action to load all yang features.
+ */
+ export const loadAllInfoElementFeaturesAsync = (nodeId: string) => (dispatch: Dispatch) => {
+ dispatch(new LoadAllElementInfoAction());
+ connectService.infoNetworkElementFeatures(nodeId).then(infoFeatures => {
+ dispatch(new AllElementInfoFeatureLoadedAction(infoFeatures));
+ }, error => {
+ dispatch(new AllElementInfoFeatureLoadedAction(null, error));
+ });
+ } \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/connectApp/src/components/infoNetworkElementDialog.tsx b/sdnr/wt/odlux/apps/connectApp/src/components/infoNetworkElementDialog.tsx
index df8515e58..9b71eb354 100644
--- a/sdnr/wt/odlux/apps/connectApp/src/components/infoNetworkElementDialog.tsx
+++ b/sdnr/wt/odlux/apps/connectApp/src/components/infoNetworkElementDialog.tsx
@@ -15,142 +15,145 @@
* 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: "OK",
- }
-}
-
-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)
- });
- }
- });
-
- yangCapabilities = yangCapabilities.sort((a,b) => a.module === b.module ? 0 : a.module > b.module ? 1 : -1);
-
- 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 aria-label="yang-capabilities-table">
- <TableHead>
- <TableRow>
- <TableCell align="right">S.No</TableCell>
- <TableCell >Module</TableCell>
- <TableCell >Revision</TableCell>
- </TableRow>
- </TableHead>
- <TableBody>
- {yangCapabilities.map((yang, index) => (
- <TableRow aria-label="yang-capabilities-row">
- <TableCell>{index + 1}</TableCell>
- <TableCell aria-label="yang-module"><a href={`/yang-schema/${yang.module}`} target={"_blank"}> {yang.module} </a></TableCell>
- <TableCell aria-label="yang-revision">{yang.revision}</TableCell>
- </TableRow>
- ))}
- </TableBody>
- </Table>
- </DialogContent>
- <DialogActions>
- <Button aria-label="ok-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
+ 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 DialogTitle from '@material-ui/core/DialogTitle';
+ import { MaterialTable, ColumnType, MaterialTableCtorType } from '../../../../framework/src/components/material-table';
+ 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) => ({
+ });
+
+
+ const InfoElementTable = MaterialTable as MaterialTableCtorType<AvailableCapabilities>;
+
+ 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: "",
+ cancelButtonText: "OK",
+ }
+ }
+
+ 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 yangFeatures = this.props.state.connect.elementFeatureInfo.elementFeatureInfo;
+ 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) {
+ let moduleName = capabilty.substr(indexModule + 1);
+ let ModuleFeaturesList;
+ for(let index = 0; index < yangFeatures.length; index++) {
+ if(yangFeatures[index].name == moduleName) {
+ ModuleFeaturesList = yangFeatures[index].feature? yangFeatures[index].feature : null;
+ break;
+ }
+ }
+ const featuresListCommaSeparated= ModuleFeaturesList? ModuleFeaturesList.toString() : ""
+ let featuresList = featuresListCommaSeparated.replace(',',', ');
+
+ yangCapabilities.push({
+ module: moduleName,
+ revision: capabilty.substr(indexRevision + 9, 10),
+ features: featuresList
+ });
+ }
+ });
+
+ yangCapabilities = yangCapabilities.sort((a,b) => a.module === b.module ? 0 : a.module > b.module ? 1 : -1);
+
+ return (
+ <>
+ <Dialog open={this.props.mode !== InfoNetworkElementDialogMode.None} >
+ <DialogTitle id="form-dialog-title">{setting.dialogTitle + ' - ' + this.state.nodeId}</DialogTitle>
+ <InfoElementTable stickyHeader tableId="info-element-table" asynchronus columns={[
+ { property: "module", title: "Module", type: ColumnType.text, width:900 },
+ {
+ property: "revision", title: "Revision", type: ColumnType.custom, customControl: ({ rowData }) => {
+ return (
+ <div>
+ <a href={'/yang-schema/' + rowData.module + '/' + rowData.revision} target="_blank" > {rowData.revision} </a>
+ </div>
+ )
+ }
+ },
+ { property: "features", title: "Features", type: ColumnType.text, width:500 },
+ ]} idProperty="id" rows={yangCapabilities} >
+ </InfoElementTable>
+ <DialogActions>
+ <Button aria-label="ok-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
index 84a22a99a..73706f678 100644
--- a/sdnr/wt/odlux/apps/connectApp/src/components/networkElements.tsx
+++ b/sdnr/wt/odlux/apps/connectApp/src/components/networkElements.tsx
@@ -36,12 +36,12 @@ import { NavigateToApplication } from '../../../../framework/src/actions/navigat
import { createNetworkElementsActions, createNetworkElementsProperties } from '../handlers/networkElementsHandler';
import { NetworkElementConnection } from '../models/networkElementConnection';
-import { TopologyNode } from '../models/topologyNetconf';
+import { ModuleSet, TopologyNode } from '../models/topologyNetconf';
import EditNetworkElementDialog, { EditNetworkElementDialogMode } from './editNetworkElementDialog';
import RefreshNetworkElementsDialog, { RefreshNetworkElementsDialogMode } from './refreshNetworkElementsDialog';
import InfoNetworkElementDialog, { InfoNetworkElementDialogMode } from './infoNetworkElementDialog';
-import { loadAllInfoElementAsync } from '../actions/infoNetworkElementActions';
+import { loadAllInfoElementAsync, loadAllInfoElementFeaturesAsync } from '../actions/infoNetworkElementActions';
import { connectService } from '../services/connectService';
import { getAccessPolicyByUrl } from '../../../../framework/src/services/restService';
@@ -92,6 +92,7 @@ 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)),
+ networkElementFeaturesInfo: async (nodeId: string) => await dispatcher.dispatch(loadAllInfoElementFeaturesAsync(nodeId))
});
type NetworkElementsListComponentProps = WithStyles<typeof styles> & Connect<typeof mapProps, typeof mapDispatch>;
@@ -100,7 +101,8 @@ type NetworkElementsListComponentState = {
networkElementEditorMode: EditNetworkElementDialogMode,
refreshNetworkElementsEditorMode: RefreshNetworkElementsDialogMode,
infoNetworkElementEditorMode: InfoNetworkElementDialogMode,
- elementInfo: TopologyNode | null
+ elementInfo: TopologyNode | null,
+ elementInfoFeature: ModuleSet | null
}
const emptyRequireNetworkElement: NetworkElementConnection = { id: "", nodeId: "", host: "", port: 0, status: "Disconnected", isRequired: false };
@@ -117,6 +119,7 @@ export class NetworkElementsListComponent extends React.Component<NetworkElement
networkElementEditorMode: EditNetworkElementDialogMode.None,
refreshNetworkElementsEditorMode: RefreshNetworkElementsDialogMode.None,
elementInfo: null,
+ elementInfoFeature:null,
infoNetworkElementEditorMode: InfoNetworkElementDialogMode.None
};
}
@@ -164,7 +167,7 @@ export class NetworkElementsListComponent extends React.Component<NetworkElement
const canAdd = true;
const addRequireNetworkElementAction = {
- icon: AddIcon, tooltip: 'Add', onClick: () => {
+ icon: AddIcon, tooltip: 'Add', ariaLabel:"add-element", onClick: () => {
this.setState({
networkElementEditorMode: EditNetworkElementDialogMode.AddNewNetworkElement,
networkElementToEdit: emptyRequireNetworkElement,
@@ -173,7 +176,7 @@ export class NetworkElementsListComponent extends React.Component<NetworkElement
};
const refreshNetworkElementsAction = {
- icon: Refresh, tooltip: 'Refresh Network Elements table', onClick: () => {
+ icon: Refresh, tooltip: 'Refresh Network Elements table', ariaLabel:'refresh', onClick: () => {
this.setState({
refreshNetworkElementsEditorMode: RefreshNetworkElementsDialogMode.RefreshNetworkElementsTable
});
@@ -266,6 +269,7 @@ export class NetworkElementsListComponent extends React.Component<NetworkElement
private onOpenInfoNetworkElementDialog = (event: React.MouseEvent<HTMLElement>, element: NetworkElementConnection) => {
this.props.networkElementInfo(element.nodeId);
+ this.props.networkElementFeaturesInfo(element.nodeId);
this.setState({
networkElementToEdit: element,
infoNetworkElementEditorMode: InfoNetworkElementDialogMode.InfoNetworkElement,
diff --git a/sdnr/wt/odlux/apps/connectApp/src/handlers/connectAppRootHandler.ts b/sdnr/wt/odlux/apps/connectApp/src/handlers/connectAppRootHandler.ts
index 70b64c976..81ee97a0a 100644
--- a/sdnr/wt/odlux/apps/connectApp/src/handlers/connectAppRootHandler.ts
+++ b/sdnr/wt/odlux/apps/connectApp/src/handlers/connectAppRootHandler.ts
@@ -20,7 +20,7 @@ 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 { IInfoNetworkElementsState, infoNetworkElementsActionHandler, IInfoNetworkElementFeaturesState, infoNetworkElementFeaturesActionHandler } from './infoNetworkElementHandler';
import { SetPanelAction, AddWebUriList, RemoveWebUri, SetWeburiSearchBusy } from '../actions/commonNetworkElementsActions';
import { PanelId } from '../models/panelId';
import { guiCutThrough } from '../models/guiCutTrough';
@@ -31,6 +31,7 @@ export interface IConnectAppStoreState {
connectionStatusLog: IConnectionStatusLogState;
currentOpenPanel: PanelId;
elementInfo: IInfoNetworkElementsState;
+ elementFeatureInfo: IInfoNetworkElementFeaturesState;
guiCutThrough: guiCutThroughState;
connectionStatusCount: IConnectionStatusCount;
}
@@ -48,7 +49,7 @@ interface guiCutThroughState {
unsupportedElements: string[];
}
-const guiCutThroughHandler: IActionHandler<guiCutThroughState> = (state = { searchedElements: [], notSearchedElements: [], unsupportedElements:[] }, action) => {
+const guiCutThroughHandler: IActionHandler<guiCutThroughState> = (state = { searchedElements: [], notSearchedElements: [], unsupportedElements: [] }, action) => {
if (action instanceof AddWebUriList) {
let notSearchedElements: string[];
let searchedElements: guiCutThrough[];
@@ -73,7 +74,7 @@ const guiCutThroughHandler: IActionHandler<guiCutThroughState> = (state = { sear
const webUris = state.searchedElements.filter(item => item.id !== nodeId);
const knownElements = state.notSearchedElements.filter(item => item !== nodeId);
const unsupportedElement = state.unsupportedElements.filter(item => item != nodeId);
- state = { notSearchedElements: knownElements, searchedElements: webUris, unsupportedElements: unsupportedElement };
+ state = { notSearchedElements: knownElements, searchedElements: webUris, unsupportedElements: unsupportedElement };
}
return state;
}
@@ -89,6 +90,7 @@ const actionHandlers = {
connectionStatusLog: connectionStatusLogActionHandler,
currentOpenPanel: currentOpenPanelHandler,
elementInfo: infoNetworkElementsActionHandler,
+ elementFeatureInfo: infoNetworkElementFeaturesActionHandler,
guiCutThrough: guiCutThroughHandler,
connectionStatusCount: connectionStatusCountHandler
};
diff --git a/sdnr/wt/odlux/apps/connectApp/src/handlers/infoNetworkElementHandler.ts b/sdnr/wt/odlux/apps/connectApp/src/handlers/infoNetworkElementHandler.ts
index d67a81ec4..3e2d1cec1 100644
--- a/sdnr/wt/odlux/apps/connectApp/src/handlers/infoNetworkElementHandler.ts
+++ b/sdnr/wt/odlux/apps/connectApp/src/handlers/infoNetworkElementHandler.ts
@@ -15,46 +15,79 @@
* the License.
* ============LICENSE_END==========================================================================
*/
-import { IActionHandler } from '../../../../framework/src/flux/action';
+ 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
+ import { AllElementInfoLoadedAction, AllElementInfoFeatureLoadedAction, LoadAllElementInfoAction } from '../actions/infoNetworkElementActions';
+
+ import { Module, TopologyNode } from '../models/topologyNetconf';
+
+ export interface IInfoNetworkElementsState {
+ elementInfo: TopologyNode;
+ busy: boolean;
+ }
+
+ export interface IInfoNetworkElementFeaturesState {
+ elementFeatureInfo: Module[];
+ busy: boolean;
+ }
+
+ const infoNetworkElementsStateInit: IInfoNetworkElementsState = {
+ elementInfo: {
+ "node-id": "",
+ "netconf-node-topology:available-capabilities": {
+ "available-capability": []
+ }
+ },
+ busy: false
+ };
+
+ const infoNetworkElementFeaturesStateInit: IInfoNetworkElementFeaturesState = {
+ elementFeatureInfo: [],
+ 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;
+ };
+
+ export const infoNetworkElementFeaturesActionHandler: IActionHandler<IInfoNetworkElementFeaturesState> = (state = infoNetworkElementFeaturesStateInit, action) => {
+ if (action instanceof LoadAllElementInfoAction) {
+ state = {
+ ...state,
+ busy: true
+ };
+ } else if (action instanceof AllElementInfoFeatureLoadedAction) {
+ if (!action.error && action.elementFeatureInfo) {
+ state = {
+ ...state,
+ elementFeatureInfo: action.elementFeatureInfo,
+ busy: false
+ };
+ } else {
+ state = {
+ ...state,
+ busy: false
+ };
+ }
+ }
+ return state;
+ }; \ 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 ef22aab43..936e20bc2 100644
--- a/sdnr/wt/odlux/apps/connectApp/src/models/topologyNetconf.ts
+++ b/sdnr/wt/odlux/apps/connectApp/src/models/topologyNetconf.ts
@@ -16,7 +16,7 @@
* ============LICENSE_END==========================================================================
*/
-export interface AvailableCapability {
+ export interface AvailableCapability {
"capability-origin": string;
capability: string;
}
@@ -34,3 +34,26 @@ export interface Topology {
"topology-id": string;
"network-topology:node": TopologyNode[];
}
+
+/**
+ * Represents the type of the features of the Module.
+ */
+export interface Module {
+ feature?: string[];
+ location?: string[];
+ name: string;
+ namespace?: string;
+ revision?: string;
+}
+
+export interface ModuleFeatures {
+ module: Module[];
+}
+
+export interface ModuleSet {
+ "module-set": ModuleFeatures[];
+}
+
+export interface FeatureTopology {
+ "ietf-yang-library:yang-library" : ModuleSet
+}
diff --git a/sdnr/wt/odlux/apps/connectApp/src/models/yangCapabilitiesType.ts b/sdnr/wt/odlux/apps/connectApp/src/models/yangCapabilitiesType.ts
index 230468287..c8cf7049c 100644
--- a/sdnr/wt/odlux/apps/connectApp/src/models/yangCapabilitiesType.ts
+++ b/sdnr/wt/odlux/apps/connectApp/src/models/yangCapabilitiesType.ts
@@ -16,7 +16,9 @@
* ============LICENSE_END==========================================================================
*/
-export type AvailableCapabilities = {
+ export type AvailableCapabilities = {
+ id?: string,
module: string,
- revision: string
+ revision: string,
+ features: string
} \ 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 5d7667a7f..ed8b0f67d 100644
--- a/sdnr/wt/odlux/apps/connectApp/src/services/connectService.ts
+++ b/sdnr/wt/odlux/apps/connectApp/src/services/connectService.ts
@@ -16,224 +16,243 @@
* ============LICENSE_END==========================================================================
*/
-import { requestRest } from '../../../../framework/src/services/restService';
-import { NetworkElementConnection, ConnectionStatus, UpdateNetworkElement } from '../models/networkElementConnection';
-import { convertPropertyNames, replaceUpperCase } from '../../../../framework/src/utilities/yangHelper';
-import { Result } from '../../../../framework/src/models/elasticSearch';
-
-import { Topology, TopologyNode } from '../models/topologyNetconf';
-import { guiCutThrough } from '../models/guiCutTrough';
-
-/**
-* Represents a web api accessor service for all Network Elements actions.
-*/
-class ConnectService {
- public getNetworkElementUri = (nodeId: string) => '/rests/data/network-topology:network-topology/topology=topology-netconf/node=' + nodeId;
- public getNetworkElementConnectDataProviderUri = (operation: "create" | "update" | "delete" ) => `/rests/operations/data-provider:${operation}-network-element-connection`;
- public getAllWebUriExtensionsForNetworkElementListUri = (nodeId: string) => this.getNetworkElementUri(nodeId) + '/yang-ext:mount/core-model:network-element';
-
- /**
- * Inserts a network elements.
- */
- public async createNetworkElement(element: NetworkElementConnection): Promise<NetworkElementConnection | null> {
- const path = this.getNetworkElementConnectDataProviderUri("create") ;
- const result = await requestRest<NetworkElementConnection>(path, {
- method: "POST", body: JSON.stringify(convertPropertyNames({ "data-provider:input": element }, replaceUpperCase))
- });
- return result || null;
- }
-
- /**
- * Updates a network element.
- */
- public async updateNetworkElement(element: UpdateNetworkElement): Promise<NetworkElementConnection | null> {
- const path = this.getNetworkElementConnectDataProviderUri("update");
- const result = await requestRest<NetworkElementConnection>(path, {
- method: "POST", body: JSON.stringify(convertPropertyNames({ "data-provider:input": element }, replaceUpperCase))
- });
- return result || null;
- }
-
- /**
- * Deletes a network element.
+ import { requestRest } from '../../../../framework/src/services/restService';
+ import { NetworkElementConnection, ConnectionStatus, UpdateNetworkElement } from '../models/networkElementConnection';
+ import { convertPropertyNames, replaceUpperCase } from '../../../../framework/src/utilities/yangHelper';
+ import { Result } from '../../../../framework/src/models/elasticSearch';
+
+ import { FeatureTopology, Topology, TopologyNode, Module } from '../models/topologyNetconf';
+ import { guiCutThrough } from '../models/guiCutTrough';
+
+ /**
+ * Represents a web api accessor service for all Network Elements actions.
+ */
+ class ConnectService {
+ public getNetworkElementUri = (nodeId: string) => '/rests/data/network-topology:network-topology/topology=topology-netconf/node=' + nodeId;
+ public getNetworkElementConnectDataProviderUri = (operation: "create" | "update" | "delete" ) => `/rests/operations/data-provider:${operation}-network-element-connection`;
+ public getAllWebUriExtensionsForNetworkElementListUri = (nodeId: string) => this.getNetworkElementUri(nodeId) + '/yang-ext:mount/core-model:network-element';
+ public getNetworkElementYangLibraryFeature = (nodeId: string) => '/rests/data/network-topology:network-topology/topology=topology-netconf/node=' + nodeId + '/yang-ext:mount/ietf-yang-library:yang-library?content=nonconfig'
+
+ /**
+ * Inserts a network elements.
*/
- public async deleteNetworkElement(element: UpdateNetworkElement): Promise<NetworkElementConnection | null> {
- const query = {
- "id": element.id
- };
- const path = this.getNetworkElementConnectDataProviderUri("delete");
- const result = await requestRest<NetworkElementConnection>(path, {
- method: "POST", body: JSON.stringify(convertPropertyNames({ "data-provider:input": query }, replaceUpperCase))
- });
- return result || null;
- }
-
- /** Mounts network element. */
- public async mountNetworkElement(networkElement: NetworkElementConnection): Promise<boolean> {
- const path = this.getNetworkElementUri(networkElement.nodeId);
- const mountXml = [
- '<node xmlns="urn:TBD:params:xml:ns:yang:network-topology">',
- `<node-id>${networkElement.nodeId}</node-id>`,
- `<host xmlns="urn:opendaylight:netconf-node-topology">${networkElement.host}</host>`,
- `<port xmlns="urn:opendaylight:netconf-node-topology">${networkElement.port}</port>`,
- `<username xmlns="urn:opendaylight:netconf-node-topology">${networkElement.username}</username>`,
- `<password xmlns="urn:opendaylight:netconf-node-topology">${networkElement.password}</password>`,
- ' <tcp-only xmlns="urn:opendaylight:netconf-node-topology">false</tcp-only>',
-
- ' <!-- non-mandatory fields with default values, you can safely remove these if you do not wish to override any of these values-->',
- ' <reconnect-on-changed-schema xmlns="urn:opendaylight:netconf-node-topology">false</reconnect-on-changed-schema>',
- ' <connection-timeout-millis xmlns="urn:opendaylight:netconf-node-topology">20000</connection-timeout-millis>',
- ' <max-connection-attempts xmlns="urn:opendaylight:netconf-node-topology">100</max-connection-attempts>',
- ' <between-attempts-timeout-millis xmlns="urn:opendaylight:netconf-node-topology">2000</between-attempts-timeout-millis>',
- ' <sleep-factor xmlns="urn:opendaylight:netconf-node-topology">1.5</sleep-factor>',
-
- ' <!-- keepalive-delay set to 0 turns off keepalives-->',
- ' <keepalive-delay xmlns="urn:opendaylight:netconf-node-topology">120</keepalive-delay>',
- '</node>'].join('');
-
- try {
- const result = await requestRest<string>(path, {
- method: 'PUT',
- headers: {
- 'Content-Type': 'application/xml',
- 'Accept': 'application/xml'
- },
- body: mountXml
- });
- // expect an empty answer
- return result !== null;
- } catch {
- return false;
- }
- };
-
- /** Unmounts a network element by its id. */
- public async unmountNetworkElement(nodeId: string): Promise<boolean> {
- const path = this.getNetworkElementUri(nodeId);
-
- try {
- const result = await requestRest<string>(path, {
- method: 'DELETE',
- headers: {
- 'Content-Type': 'application/xml',
- 'Accept': 'application/xml'
- },
- });
- // expect an empty answer
- return result !== null;
-
- } catch {
- return false;
- }
- };
-
- /** Yang capabilities of the selected network elements. */
- public async infoNetworkElement(nodeId: string): Promise<TopologyNode | null> {
- const path = this.getNetworkElementUri(nodeId);
- const topologyRequestPomise = requestRest<Topology>(path, { method: "GET" });
-
- return topologyRequestPomise && topologyRequestPomise.then(result => {
- return result && result["network-topology:node"] && result["network-topology:node"][0] || null;
- });
- }
-
- /**
- * Get the connection state of the network element.
+ public async createNetworkElement(element: NetworkElementConnection): Promise<NetworkElementConnection | null> {
+ const path = this.getNetworkElementConnectDataProviderUri("create") ;
+ const result = await requestRest<NetworkElementConnection>(path, {
+ method: "POST", body: JSON.stringify(convertPropertyNames({ "data-provider:input": element }, replaceUpperCase))
+ });
+ return result || null;
+ }
+
+ /**
+ * Updates a network element.
*/
- public async getNetworkElementConnectionStatus(element: string): Promise<(ConnectionStatus)[] | null> {
- const path = `/rests/operations/data-provider:read-network-element-connection-list`;
- const query = {
- "data-provider:input": {
- "filter": [{
- "property": "node-id",
- "filtervalue": element
- }],
- "pagination": {
- "size": 20,
- "page": 1
- }
- }
- }
- const result = await requestRest<Result<ConnectionStatus>>(path, { method: "POST", body: JSON.stringify(query) });
- return result && result["data-provider:output"] && result["data-provider:output"].data && result["data-provider:output"].data.map(ne => ({
- status: ne.status
- })) || null;
- }
-
- public async getAllWebUriExtensionsForNetworkElementListAsync(neList: string[]): Promise<(guiCutThrough)[]> {
- const path = `/rests/operations/data-provider:read-gui-cut-through-entry`;
- let webUriList: guiCutThrough[] = []
- const query = {
- "data-provider:input": {
- "filter": [{
- "property": "id",
- "filtervalues": neList
- }],
- "pagination": {
- "size": 20,
- "page": 1
- }
- }
- }
-
- const result = await requestRest<Result<guiCutThrough>>(path, { method: "POST", body: JSON.stringify(query) });
- const resultData = result && result["data-provider:output"] && result["data-provider:output"].data;
- neList.forEach(nodeId => {
- let entryNotFound = true;
- if (resultData) {
- const BreakException = {};
- try {
- resultData.forEach(entry => {
- if (entry.id == nodeId) {
- entryNotFound = false;
- if (entry.weburi) {
- webUriList.push({ id: nodeId, weburi: entry.weburi });
- } else {
- webUriList.push({ id: nodeId, weburi: undefined });
- }
- throw BreakException;
- }
- });
- } catch (e) {}
- }
- if (entryNotFound)
- webUriList.push({ id: nodeId, weburi: undefined });
- });
- return webUriList;
- }
-
- // public async getAllWebUriExtensionsForNetworkElementListAsync(ne: string[]): Promise<(guiCutThrough)[] | null> {
-
- // let promises: any[] = [];
- // let webUris: guiCutThrough[] = []
-
- // ne.forEach(nodeId => {
- // const path = this.getAllWebUriExtensionsForNetworkElementListUri(nodeId);
-
- // // add search request to array
- // promises.push(requestRest<any>(path, { method: "GET" })
- // .then(result => {
- // if (result != null && result['core-model:network-element'] && result['core-model:network-element'].extension) {
- // const webUri = result['core-model:network-element'].extension.find((item: any) => item['value-name'] === "webUri")
- // if (webUri) {
- // webUris.push({ weburi: webUri.value, id: nodeId });
- // } else {
- // webUris.push({ weburi: undefined, id: nodeId });
- // }
- // } else {
- // webUris.push({ weburi: undefined, id: nodeId });
- // }
- // })
- // .catch(error => {
- // webUris.push({ weburi: undefined, id: nodeId });
- // }))
- // })
- // // wait until all promises are done and return weburis
- // return Promise.all(promises).then(result => { return webUris });
- // }
-
-}
-
-
-
-export const connectService = new ConnectService();
+ public async updateNetworkElement(element: UpdateNetworkElement): Promise<NetworkElementConnection | null> {
+ const path = this.getNetworkElementConnectDataProviderUri("update");
+ const result = await requestRest<NetworkElementConnection>(path, {
+ method: "POST", body: JSON.stringify(convertPropertyNames({ "data-provider:input": element }, replaceUpperCase))
+ });
+ return result || null;
+ }
+
+ /**
+ * Deletes a network element.
+ */
+ public async deleteNetworkElement(element: UpdateNetworkElement): Promise<NetworkElementConnection | null> {
+ const query = {
+ "id": element.id
+ };
+ const path = this.getNetworkElementConnectDataProviderUri("delete");
+ const result = await requestRest<NetworkElementConnection>(path, {
+ method: "POST", body: JSON.stringify(convertPropertyNames({ "data-provider:input": query }, replaceUpperCase))
+ });
+ return result || null;
+ }
+
+ /** Mounts network element. */
+ public async mountNetworkElement(networkElement: NetworkElementConnection): Promise<boolean> {
+ const path = this.getNetworkElementUri(networkElement.nodeId);
+ const mountXml = [
+ '<node xmlns="urn:TBD:params:xml:ns:yang:network-topology">',
+ `<node-id>${networkElement.nodeId}</node-id>`,
+ `<host xmlns="urn:opendaylight:netconf-node-topology">${networkElement.host}</host>`,
+ `<port xmlns="urn:opendaylight:netconf-node-topology">${networkElement.port}</port>`,
+ `<username xmlns="urn:opendaylight:netconf-node-topology">${networkElement.username}</username>`,
+ `<password xmlns="urn:opendaylight:netconf-node-topology">${networkElement.password}</password>`,
+ ' <tcp-only xmlns="urn:opendaylight:netconf-node-topology">false</tcp-only>',
+
+ ' <!-- non-mandatory fields with default values, you can safely remove these if you do not wish to override any of these values-->',
+ ' <reconnect-on-changed-schema xmlns="urn:opendaylight:netconf-node-topology">false</reconnect-on-changed-schema>',
+ ' <connection-timeout-millis xmlns="urn:opendaylight:netconf-node-topology">20000</connection-timeout-millis>',
+ ' <max-connection-attempts xmlns="urn:opendaylight:netconf-node-topology">100</max-connection-attempts>',
+ ' <between-attempts-timeout-millis xmlns="urn:opendaylight:netconf-node-topology">2000</between-attempts-timeout-millis>',
+ ' <sleep-factor xmlns="urn:opendaylight:netconf-node-topology">1.5</sleep-factor>',
+
+ ' <!-- keepalive-delay set to 0 turns off keepalives-->',
+ ' <keepalive-delay xmlns="urn:opendaylight:netconf-node-topology">120</keepalive-delay>',
+ '</node>'].join('');
+
+ try {
+ const result = await requestRest<string>(path, {
+ method: 'PUT',
+ headers: {
+ 'Content-Type': 'application/xml',
+ 'Accept': 'application/xml'
+ },
+ body: mountXml
+ });
+ // expect an empty answer
+ return result !== null;
+ } catch {
+ return false;
+ }
+ };
+
+ /** Unmounts a network element by its id. */
+ public async unmountNetworkElement(nodeId: string): Promise<boolean> {
+ const path = this.getNetworkElementUri(nodeId);
+
+ try {
+ const result = await requestRest<string>(path, {
+ method: 'DELETE',
+ headers: {
+ 'Content-Type': 'application/xml',
+ 'Accept': 'application/xml'
+ },
+ });
+ // expect an empty answer
+ return result !== null;
+
+ } catch {
+ return false;
+ }
+ };
+
+ /** Yang capabilities of the selected network elements. */
+ public async infoNetworkElement(nodeId: string): Promise<TopologyNode | null> {
+ const path = this.getNetworkElementUri(nodeId);
+ const topologyRequestPomise = requestRest<Topology>(path, { method: "GET" });
+
+ return topologyRequestPomise && topologyRequestPomise.then(result => {
+ return result && result["network-topology:node"] && result["network-topology:node"][0] || null;
+ });
+ }
+
+
+ /** Yang features of the selected network element module. */
+ public async infoNetworkElementFeatures(nodeId: string): Promise<Module[] | null | undefined> {
+ const path = this.getNetworkElementYangLibraryFeature(nodeId);
+ const topologyRequestPomise = requestRest<FeatureTopology>(path, { method: "GET" });
+
+ return topologyRequestPomise && topologyRequestPomise.then(result => {
+ const resultFinal = result && result['ietf-yang-library:yang-library']
+ && result["ietf-yang-library:yang-library"]["module-set"] &&
+ result["ietf-yang-library:yang-library"]["module-set"][0] &&
+ result["ietf-yang-library:yang-library"]["module-set"][0]['module'] || null;
+ return resultFinal;
+ });
+ }
+
+
+
+ /**
+ * Get the connection state of the network element.
+ */
+ public async getNetworkElementConnectionStatus(element: string): Promise<(ConnectionStatus)[] | null> {
+ const path = `/rests/operations/data-provider:read-network-element-connection-list`;
+ const query = {
+ "data-provider:input": {
+ "filter": [{
+ "property": "node-id",
+ "filtervalue": element
+ }],
+ "pagination": {
+ "size": 20,
+ "page": 1
+ }
+ }
+ }
+ const result = await requestRest<Result<ConnectionStatus>>(path, { method: "POST", body: JSON.stringify(query) });
+ return result && result["data-provider:output"] && result["data-provider:output"].data && result["data-provider:output"].data.map(ne => ({
+ status: ne.status
+ })) || null;
+ }
+
+ public async getAllWebUriExtensionsForNetworkElementListAsync(neList: string[]): Promise<(guiCutThrough)[]> {
+ const path = `/rests/operations/data-provider:read-gui-cut-through-entry`;
+ let webUriList: guiCutThrough[] = []
+ const query = {
+ "data-provider:input": {
+ "filter": [{
+ "property": "id",
+ "filtervalues": neList
+ }],
+ "pagination": {
+ "size": 20,
+ "page": 1
+ }
+ }
+ }
+
+ const result = await requestRest<Result<guiCutThrough>>(path, { method: "POST", body: JSON.stringify(query) });
+ const resultData = result && result["data-provider:output"] && result["data-provider:output"].data;
+ neList.forEach(nodeId => {
+ let entryNotFound = true;
+ if (resultData) {
+ const BreakException = {};
+ try {
+ resultData.forEach(entry => {
+ if (entry.id == nodeId) {
+ entryNotFound = false;
+ if (entry.weburi) {
+ webUriList.push({ id: nodeId, weburi: entry.weburi });
+ } else {
+ webUriList.push({ id: nodeId, weburi: undefined });
+ }
+ throw BreakException;
+ }
+ });
+ } catch (e) {}
+ }
+ if (entryNotFound)
+ webUriList.push({ id: nodeId, weburi: undefined });
+ });
+ return webUriList;
+ }
+
+ // public async getAllWebUriExtensionsForNetworkElementListAsync(ne: string[]): Promise<(guiCutThrough)[] | null> {
+
+ // let promises: any[] = [];
+ // let webUris: guiCutThrough[] = []
+
+ // ne.forEach(nodeId => {
+ // const path = this.getAllWebUriExtensionsForNetworkElementListUri(nodeId);
+
+ // // add search request to array
+ // promises.push(requestRest<any>(path, { method: "GET" })
+ // .then(result => {
+ // if (result != null && result['core-model:network-element'] && result['core-model:network-element'].extension) {
+ // const webUri = result['core-model:network-element'].extension.find((item: any) => item['value-name'] === "webUri")
+ // if (webUri) {
+ // webUris.push({ weburi: webUri.value, id: nodeId });
+ // } else {
+ // webUris.push({ weburi: undefined, id: nodeId });
+ // }
+ // } else {
+ // webUris.push({ weburi: undefined, id: nodeId });
+ // }
+ // })
+ // .catch(error => {
+ // webUris.push({ weburi: undefined, id: nodeId });
+ // }))
+ // })
+ // // wait until all promises are done and return weburis
+ // return Promise.all(promises).then(result => { return webUris });
+ // }
+
+ }
+
+
+
+ export const connectService = new ConnectService();
+ \ No newline at end of file