From 3d202a04b99f0e61b6ccf8b7a5610e1a15ca58e7 Mon Sep 17 00:00:00 2001 From: Herbert Eiselt Date: Mon, 11 Feb 2019 14:54:12 +0100 Subject: Add sdnr wt odlux Add complete sdnr wireless transport app odlux core and apps Change-Id: I5dcbfb8f3b790e3bda7c8df67bd69d81958f65e5 Issue-ID: SDNC-576 Signed-off-by: Herbert Eiselt --- .../src/components/connectionStatusLog.tsx | 36 ++++ .../src/components/editNetworkElementDialog.tsx | 228 +++++++++++++++++++++ .../src/components/requiredNetworkElements.tsx | 194 ++++++++++++++++++ .../src/components/unknownNetworkElements.tsx | 196 ++++++++++++++++++ 4 files changed, 654 insertions(+) create mode 100644 sdnr/wt/odlux/apps/connectApp/src/components/connectionStatusLog.tsx create mode 100644 sdnr/wt/odlux/apps/connectApp/src/components/editNetworkElementDialog.tsx create mode 100644 sdnr/wt/odlux/apps/connectApp/src/components/requiredNetworkElements.tsx create mode 100644 sdnr/wt/odlux/apps/connectApp/src/components/unknownNetworkElements.tsx (limited to 'sdnr/wt/odlux/apps/connectApp/src/components') diff --git a/sdnr/wt/odlux/apps/connectApp/src/components/connectionStatusLog.tsx b/sdnr/wt/odlux/apps/connectApp/src/components/connectionStatusLog.tsx new file mode 100644 index 000000000..b4b08fcf3 --- /dev/null +++ b/sdnr/wt/odlux/apps/connectApp/src/components/connectionStatusLog.tsx @@ -0,0 +1,36 @@ +import * as React from 'react'; +import connect, { IDispatcher, Connect } from '../../../../framework/src/flux/connect'; +import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore'; +import { MaterialTable, ColumnType, MaterialTableCtorType } from '../../../../framework/src/components/material-table'; + +import { createConnectionStatusLogActions, createConnectionStatusLogProperties } from '../handlers/connectionStatusLogHandler'; +import { ConnectionStatusLogType } from '../models/connectionStatusLog'; + +const mapProps = (state: IApplicationStoreState) => ({ + connectionStatusLogProperties: createConnectionStatusLogProperties(state), +}); + +const mapDispatch = (dispatcher: IDispatcher) => ({ + connectionStatusLogActions: createConnectionStatusLogActions(dispatcher.dispatch), +}); + +const ConnectionStatusTable = MaterialTable as MaterialTableCtorType; + +type ConnectionStatusLogComponentProps = Connect; + +class ConnectionStatusLogComponent extends React.Component { + render(): JSX.Element { + return ( + + + ); + }; + +} + +export const ConnectionStatusLog = connect(mapProps, mapDispatch)(ConnectionStatusLogComponent); +export default ConnectionStatusLog; \ No newline at end of file diff --git a/sdnr/wt/odlux/apps/connectApp/src/components/editNetworkElementDialog.tsx b/sdnr/wt/odlux/apps/connectApp/src/components/editNetworkElementDialog.tsx new file mode 100644 index 000000000..ee876e854 --- /dev/null +++ b/sdnr/wt/odlux/apps/connectApp/src/components/editNetworkElementDialog.tsx @@ -0,0 +1,228 @@ +import * as React from 'react'; + +import Button from '@material-ui/core/Button'; +import TextField from '@material-ui/core/TextField'; +import Dialog from '@material-ui/core/Dialog'; +import DialogActions from '@material-ui/core/DialogActions'; +import DialogContent from '@material-ui/core/DialogContent'; +import DialogContentText from '@material-ui/core/DialogContentText'; +import DialogTitle from '@material-ui/core/DialogTitle'; + +import { IDispatcher, connect, Connect } from '../../../../framework/src/flux/connect'; + +import { + addToRequiredNetworkElementsAsyncActionCreator, + removeFromRequiredNetworkElementsAsyncActionCreator +} from '../actions/requiredNetworkElementsActions'; + +import { RequiredNetworkElementType } from '../models/requiredNetworkElements'; +import { unmountNetworkElementActionCreatorAsync, mountNetworkElementActionCreatorAsync } from '../actions/mountedNetworkElementsActions'; +export enum EditNetworkElementDialogMode { + None = "none", + UnknownNetworkElementToRequiredNetworkElements = "unknownNetworkElementToRequiredNetworkElements", + RequiredNetworkElementToUnknownNetworkElements = "requiredNetworkElementToUnknownNetworkElements", + MountNetworkElementToRequiredNetworkElements = "mountNetworkElementToRequiredNetworkElements", + MountNetworkElementToUnknonwNetworkElements = "mountNetworkElementToRequiredUnknownElements", + MountNetworkElement = "mountNetworkElement", + UnmountNetworkElement = "unmountNetworkElement", +} + +const mapDispatch = (dispatcher: IDispatcher) => ({ + addToRequiredNetworkElements: (element: RequiredNetworkElementType) => { + dispatcher.dispatch(addToRequiredNetworkElementsAsyncActionCreator(element)); + }, + removeFromRequiredNetworkElements: (element: RequiredNetworkElementType) => { + dispatcher.dispatch(removeFromRequiredNetworkElementsAsyncActionCreator(element)); + }, + mountNetworkElement: (element: RequiredNetworkElementType) => { + dispatcher.dispatch(mountNetworkElementActionCreatorAsync(element)); + }, + mountAndRquireNetworkElement: (element: RequiredNetworkElementType) => { + dispatcher.dispatch(addToRequiredNetworkElementsAsyncActionCreator(element)); + dispatcher.dispatch(mountNetworkElementActionCreatorAsync(element)); + }, + unmountNetworkElement: (element: RequiredNetworkElementType) => { + dispatcher.dispatch(unmountNetworkElementActionCreatorAsync(element && element.mountId)); + } +} +); + +type DialogSettings = { + dialogTitle: string, + dialogDescription: string, + applyButtonText: string, + cancelButtonText: string, + enableMountIdEditor: boolean, + enableUsernameEditor: boolean, + enableExtendedEditor: boolean, +} + +const settings: { [key: string]: DialogSettings } = { + [EditNetworkElementDialogMode.None]: { + dialogTitle: "", + dialogDescription: "", + applyButtonText: "", + cancelButtonText: "", + enableMountIdEditor: false, + enableUsernameEditor: false, + enableExtendedEditor: false, + }, + [EditNetworkElementDialogMode.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", + cancelButtonText: "Cancel", + enableMountIdEditor: true, + enableUsernameEditor: true, + enableExtendedEditor: true, + }, + [EditNetworkElementDialogMode.MountNetworkElement]: { + dialogTitle: "Mount network element", + dialogDescription: "mount this network element:", + applyButtonText: "mount network element", + cancelButtonText: "Cancel", + enableMountIdEditor: false, + enableUsernameEditor: false, + enableExtendedEditor: false, + }, + [EditNetworkElementDialogMode.UnmountNetworkElement]: { + dialogTitle: "Unmount network element", + dialogDescription: "unmount this network element:", + applyButtonText: "Unmount network element", + cancelButtonText: "Cancel", + enableMountIdEditor: false, + enableUsernameEditor: false, + enableExtendedEditor: false, + }, +} + +type EditNetworkElementDialogComponentProps = Connect & { + mode: EditNetworkElementDialogMode; + initialNetworkElement: RequiredNetworkElementType; + onClose: () => void; +}; + +type EditNetworkElementDialogComponentState = RequiredNetworkElementType & { + required: boolean; +}; + +class EditNetworkElementDialogComponent extends React.Component { + constructor(props: EditNetworkElementDialogComponentProps) { + super(props); + + this.state = { + mountId: this.props.initialNetworkElement.mountId, + 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 ( + + { setting.dialogTitle } + + + { setting.dialogDescription } + + { this.setState({mountId: event.target.value}); } } /> + { this.setState({host: event.target.value}); } }/> + { this.setState({port: +event.target.value}); } }/> + { setting.enableUsernameEditor && { this.setState({ username: event.target.value }); } } /> || null } + { setting.enableUsernameEditor && { this.setState({ password: event.target.value }); } } /> || null } + + + + + + + ) + } + + private onApply = (element: RequiredNetworkElementType) => { + this.props.onClose && this.props.onClose(); + 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); + break; + case EditNetworkElementDialogMode.MountNetworkElement: + element && this.props.mountNetworkElement(element); + break; + case EditNetworkElementDialogMode.UnmountNetworkElement: + element && this.props.unmountNetworkElement(element); + break; + } + }; + + private onCancel = () => { + this.props.onClose && this.props.onClose(); + } + + static getDerivedStateFromProps(props: EditNetworkElementDialogComponentProps, state: EditNetworkElementDialogComponentState & { _initialNetworkElement: RequiredNetworkElementType }): EditNetworkElementDialogComponentState & { _initialNetworkElement: RequiredNetworkElementType } { + if (props.initialNetworkElement !== state._initialNetworkElement) { + state = { + ...state, + ...props.initialNetworkElement, + _initialNetworkElement: props.initialNetworkElement, + }; + } + return state; + } +} + +export const EditNetworkElementDialog = connect(undefined, mapDispatch)(EditNetworkElementDialogComponent); +export default EditNetworkElementDialog; \ No newline at end of file diff --git a/sdnr/wt/odlux/apps/connectApp/src/components/requiredNetworkElements.tsx b/sdnr/wt/odlux/apps/connectApp/src/components/requiredNetworkElements.tsx new file mode 100644 index 000000000..13f5fec20 --- /dev/null +++ b/sdnr/wt/odlux/apps/connectApp/src/components/requiredNetworkElements.tsx @@ -0,0 +1,194 @@ +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: theme.palette.primary.main, + }, + 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.connectApp.mountedNetworkElements +}); + +const mapDispatch = (dispatcher: IDispatcher) => ({ + requiredNetworkElementsActions: createRequiredNetworkElementsActions(dispatcher.dispatch), + navigateToApplication: (applicationName: string, path?: string) => dispatcher.dispatch(new NavigateToApplication(applicationName, path)), +}); + +type RequiredNetworkElementsListComponentProps = WithStyles & Connect; +type RequiredNetworkElementsListComponentState = { + networkElementToEdit: RequiredNetworkElementType, + networkElementEditorMode: EditNetworkElementDialogMode +} + +const emptyRequireNetworkElement = { mountId: '', host: '', port: 0 }; + +const RequiredNetworkElementTable = MaterialTable as MaterialTableCtorType; + +export class RequiredNetworkElementsListComponent extends React.Component { + + 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 ( + <> + { + 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
{ connectionStatus }
+ + } + }, + { 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 ( + <> +
+ this.onOpenMountdNetworkElementsDialog(event, rowData) }> + this.onOpenUnmountdNetworkElementsDialog(event, rowData) }> + this.onOpenRemoveRequiredNetworkElementDialog(event, rowData) } > +
+
+ +
+
+ + + + + +
+ + ) + } + }, + ] } idProperty="mountId" { ...this.props.requiredNetworkElementsActions } { ...this.props.requiredNetworkElementsProperties } asynchronus > +
+ + + ); + }; + + public componentDidMount() { + this.props.requiredNetworkElementsActions.onRefresh(); + } + + private onOpenRemoveRequiredNetworkElementDialog = (event: React.MouseEvent, element: RequiredNetworkElementType) => { + this.setState({ + networkElementToEdit: element, + networkElementEditorMode: EditNetworkElementDialogMode.RequiredNetworkElementToUnknownNetworkElements + }); + event.preventDefault(); + event.stopPropagation(); + } + + private onOpenUnmountdNetworkElementsDialog = (event: React.MouseEvent, element: RequiredNetworkElementType) => { + this.setState({ + networkElementToEdit: element, + networkElementEditorMode: EditNetworkElementDialogMode.UnmountNetworkElement + }); + event.preventDefault(); + event.stopPropagation(); + } + + private onOpenMountdNetworkElementsDialog = (event: React.MouseEvent, 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) => { + 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 new file mode 100644 index 000000000..432103128 --- /dev/null +++ b/sdnr/wt/odlux/apps/connectApp/src/components/unknownNetworkElements.tsx @@ -0,0 +1,196 @@ +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 = ({ connectApp: 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 & Connect & {} + +type UnknownNetworkElementsListState = { + + unknownNetworkElements: UnknownNetworkElementDisplayType[]; + + networkElementToEdit: RequiredNetworkElementType; + networkElementEditorMode: EditNetworkElementDialogMode; +} + + +const emptyRequireNetworkElement = { mountId: '', host: '', port: 0 }; +const UnknownNetworkElementTable = MaterialTable as MaterialTableCtorType; +export class UnknownNetworkElementsListComponent extends React.Component { + + 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 ( + <> + ( + <> +
+ this.onOpenUnmountdNetworkElementsDialog(event, rowData) } > + this.onOpenAddToRequiredNetworkElementsDialog(event, rowData) } > +
+
+ +
+
+
+ + + + + +
+
+ + ) + }, + ] } idProperty="mountId" > +
+ + + + ); + }; + + private onOpenAddToRequiredNetworkElementsDialog = (event: React.MouseEvent, 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, 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) => { + this.props.navigateToApplication(applicationName, element.mountId); + event.preventDefault(); + event.stopPropagation(); + } + +} + +export const UnknownNetworkElementsList = withStyles(styles)(connect(mapProps, mapDispatch)(UnknownNetworkElementsListComponent)); +export default UnknownNetworkElementsList; -- cgit 1.2.3-korg