summaryrefslogtreecommitdiffstats
path: root/sdnr/wt/odlux/apps/connectApp/src/components
diff options
context:
space:
mode:
authorHerbert Eiselt <herbert.eiselt@highstreet-technologies.com>2019-02-11 14:54:12 +0100
committerHerbert Eiselt <herbert.eiselt@highstreet-technologies.com>2019-02-11 14:54:53 +0100
commit3d202a04b99f0e61b6ccf8b7a5610e1a15ca58e7 (patch)
treeab756cfa8de5eced886d3947423d198be8c0ce62 /sdnr/wt/odlux/apps/connectApp/src/components
parent12a8c669f52c0e84d580c078cee849b25133b585 (diff)
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 <herbert.eiselt@highstreet-technologies.com>
Diffstat (limited to 'sdnr/wt/odlux/apps/connectApp/src/components')
-rw-r--r--sdnr/wt/odlux/apps/connectApp/src/components/connectionStatusLog.tsx36
-rw-r--r--sdnr/wt/odlux/apps/connectApp/src/components/editNetworkElementDialog.tsx228
-rw-r--r--sdnr/wt/odlux/apps/connectApp/src/components/requiredNetworkElements.tsx194
-rw-r--r--sdnr/wt/odlux/apps/connectApp/src/components/unknownNetworkElements.tsx196
4 files changed, 654 insertions, 0 deletions
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<ConnectionStatusLogType>;
+
+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>
+ );
+ };
+
+}
+
+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<undefined,typeof mapDispatch> & {
+ mode: EditNetworkElementDialogMode;
+ initialNetworkElement: RequiredNetworkElementType;
+ onClose: () => void;
+};
+
+type EditNetworkElementDialogComponentState = RequiredNetworkElementType & {
+ required: boolean;
+};
+
+class EditNetworkElementDialogComponent extends React.Component<EditNetworkElementDialogComponentProps, EditNetworkElementDialogComponentState> {
+ 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 (
+ <Dialog open={ this.props.mode !== EditNetworkElementDialogMode.None }>
+ <DialogTitle id="form-dialog-title">{ setting.dialogTitle }</DialogTitle>
+ <DialogContent>
+ <DialogContentText>
+ { 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 }
+ </DialogContent>
+ <DialogActions>
+ <Button onClick={ (event) => {
+ this.onApply({
+ mountId: this.state.mountId,
+ host: this.state.host,
+ port: this.state.port,
+ username: this.state.username,
+ password: this.state.password
+ });
+ event.preventDefault();
+ event.stopPropagation();
+ } } > { setting.applyButtonText } </Button>
+ <Button onClick={ (event) => {
+ this.onCancel();
+ event.preventDefault();
+ event.stopPropagation();
+ } } color="secondary"> { setting.cancelButtonText } </Button>
+ </DialogActions>
+ </Dialog>
+ )
+ }
+
+ 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<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("faultApp", rowData) } >F</Button></Tooltip>
+ <Tooltip title={ "Configure" } ><Button className={ classes.button } onClick={ this.navigateToApplicationHandlerCreator("configureApp", rowData)} >C</Button></Tooltip>
+ <Tooltip title={ "Accounting " } ><Button className={ classes.button } onClick={ this.navigateToApplicationHandlerCreator("accountingApp", rowData) }>A</Button></Tooltip>
+ <Tooltip title={ "Performance" } ><Button className={ classes.button } onClick={ this.navigateToApplicationHandlerCreator("performanceApp", rowData) }>P</Button></Tooltip>
+ <Tooltip title={ "Security" } ><Button className={ classes.button } onClick={ this.navigateToApplicationHandlerCreator("securityApp", 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
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<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 }>
+ <div className={ classes.spacer }>
+ <Tooltip title={ "Fault" } ><Button className={ classes.button } onClick={ this.navigateToApplicationHandlerCreator("faultApp", rowData) } >F</Button></Tooltip>
+ <Tooltip title={ "Configure" } ><Button className={ classes.button } onClick={ this.navigateToApplicationHandlerCreator("configureApp", rowData) } >C</Button></Tooltip>
+ <Tooltip title={ "Accounting " } ><Button className={ classes.button } onClick={ this.navigateToApplicationHandlerCreator("accountingApp", rowData) }>A</Button></Tooltip>
+ <Tooltip title={ "Performance" } ><Button className={ classes.button } onClick={ this.navigateToApplicationHandlerCreator("performanceApp", rowData) }>P</Button></Tooltip>
+ <Tooltip title={ "Security" } ><Button className={ classes.button } onClick={ this.navigateToApplicationHandlerCreator("securityApp", rowData) }>S</Button></Tooltip>
+ </div>
+ </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;