/** * ============LICENSE_START======================================================================== * ONAP : ccsdk feature sdnr wt odlux * ================================================================================================= * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved. * ================================================================================================= * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express * or implied. See the License for the specific language governing permissions and limitations under * the License. * ============LICENSE_END========================================================================== */ import * as React from 'react'; import { Theme } from '@mui/material/styles'; import { WithStyles } from '@mui/styles'; import createStyles from '@mui/styles/createStyles'; import withStyles from '@mui/styles/withStyles'; import AddIcon from '@mui/icons-material/Add'; import Refresh from '@mui/icons-material/Refresh'; import LinkIcon from '@mui/icons-material/Link'; import LinkOffIcon from '@mui/icons-material/LinkOff'; import RemoveIcon from '@mui/icons-material/RemoveCircleOutline'; import EditIcon from '@mui/icons-material/Edit'; import Info from '@mui/icons-material/Info'; import ComputerIcon from '@mui/icons-material/Computer'; import { MenuItem, Divider, Typography } from '@mui/material'; import { MaterialTable, ColumnType, MaterialTableCtorType } from '../../../../framework/src/components/material-table'; import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore'; import { connect, Connect, IDispatcher } from '../../../../framework/src/flux/connect'; import { NavigateToApplication } from '../../../../framework/src/actions/navigationActions'; import { createNetworkElementsActions, createNetworkElementsProperties } from '../handlers/networkElementsHandler'; import { NetworkElementConnection } from '../models/networkElementConnection'; import { ModuleSet, TopologyNode } from '../models/topologyNetconf'; import EditNetworkElementDialog, { EditNetworkElementDialogMode } from './editNetworkElementDialog'; import RefreshNetworkElementsDialog, { RefreshNetworkElementsDialogMode } from './refreshNetworkElementsDialog'; import InfoNetworkElementDialog, { InfoNetworkElementDialogMode } from './infoNetworkElementDialog'; import { loadAllInfoElementAsync, loadAllInfoElementFeaturesAsync } from '../actions/infoNetworkElementActions'; import { connectService } from '../services/connectService'; import { getAccessPolicyByUrl } from '../../../../framework/src/services/restService'; const styles = (theme: Theme) => createStyles({ connectionStatusConnected: { color: 'darkgreen', }, connectionStatusConnecting: { color: 'blue', }, connectionStatusDisconnected: { color: 'red', }, button: { margin: 0, padding: "6px 6px", minWidth: 'unset' }, spacer: { marginLeft: theme.spacing(1), marginRight: theme.spacing(1), display: "inline" } }); type GetStatelessComponentProps = T extends (props: infer P & { children?: React.ReactNode }) => any ? P : any const MenuItemExt: React.FC> = (props) => { const [disabled, setDisabled] = React.useState(true); const onMouseDown = (ev: React.MouseEvent) => { if (ev.button === 1) { setDisabled(!disabled); ev.preventDefault(); } }; return (
); }; const mapProps = (state: IApplicationStoreState) => ({ networkElementsProperties: createNetworkElementsProperties(state), applicationState: state, }); const mapDispatch = (dispatcher: IDispatcher) => ({ networkElementsActions: createNetworkElementsActions(dispatcher.dispatch), navigateToApplication: (applicationName: string, path?: string) => dispatcher.dispatch(new NavigateToApplication(applicationName, path)), networkElementInfo: async (nodeId: string) => await dispatcher.dispatch(loadAllInfoElementAsync(nodeId)), networkElementFeaturesInfo: async (nodeId: string) => await dispatcher.dispatch(loadAllInfoElementFeaturesAsync(nodeId)) }); type NetworkElementsListComponentProps = WithStyles & Connect; type NetworkElementsListComponentState = { networkElementToEdit: NetworkElementConnection, networkElementEditorMode: EditNetworkElementDialogMode, refreshNetworkElementsEditorMode: RefreshNetworkElementsDialogMode, infoNetworkElementEditorMode: InfoNetworkElementDialogMode, elementInfo: TopologyNode | null, elementInfoFeature: ModuleSet | null } const emptyRequireNetworkElement: NetworkElementConnection = { id: "", nodeId: "", host: "", port: 0, status: "Disconnected", isRequired: false }; let initialSorted = false; const NetworkElementTable = MaterialTable as MaterialTableCtorType; export class NetworkElementsListComponent extends React.Component { constructor(props: NetworkElementsListComponentProps) { super(props); this.state = { networkElementToEdit: emptyRequireNetworkElement, networkElementEditorMode: EditNetworkElementDialogMode.None, refreshNetworkElementsEditorMode: RefreshNetworkElementsDialogMode.None, elementInfo: null, elementInfoFeature: null, infoNetworkElementEditorMode: InfoNetworkElementDialogMode.None }; } getContextMenu(rowData: NetworkElementConnection): JSX.Element[] { const mountUri = rowData.id && connectService.getNetworkElementUri(rowData.id); const mountPolicy = mountUri && getAccessPolicyByUrl(mountUri); const canMount = mountPolicy && mountPolicy.POST || false; const { configuration } = this.props.applicationState as any; const buttonArray = [ this.onOpenMountdNetworkElementsDialog(event, rowData)} disabled={!canMount} >Mount, this.onOpenUnmountdNetworkElementsDialog(event, rowData)} disabled={!canMount} >Unmount, , this.onOpenInfoNetworkElementDialog(event, rowData)} disabled={rowData.status === "Connecting" || rowData.status === "Disconnected"} >Info, this.onOpenEditNetworkElementDialog(event, rowData)}>Edit, this.onOpenRemoveNetworkElementDialog(event, rowData)} >Remove, , this.props.navigateToApplication("inventory", rowData.nodeId)}>Inventory, , this.props.navigateToApplication("fault", rowData.nodeId)} >Fault, this.props.navigateToApplication("configuration", rowData.nodeId)} disabled={rowData.status === "Connecting" || rowData.status === "Disconnected" || !configuration}>Configure, this.props.navigateToApplication("accounting", rowData.nodeId)} disabled={true}>Accounting, this.props.navigateToApplication("performanceHistory", rowData.nodeId)}>Performance, this.props.navigateToApplication("security", rowData.nodeId)} disabled={true} >Security, ]; if (rowData.weburi) { // add an icon for gui cuttrough, if weburi is available return [ window.open(rowData.weburi, "_blank")} >Web Client].concat(buttonArray) } else { return buttonArray; } } // private navigationCreator render(): JSX.Element { const { classes } = this.props; const { networkElementToEdit } = this.state; let savedRadio = "password"; if (this.state.networkElementToEdit.password && this.state.networkElementToEdit.password.length > 0) { savedRadio = 'password' } else if (this.state.networkElementToEdit.tlsKey && this.state.networkElementToEdit.tlsKey.length > 0) { savedRadio = 'tlsKey' } // const mountUri = rowData.id && connectService.getNetworkElementUri(rowData.id); // const mountPolicy = mountUri && getAccessPolicyByUrl(mountUri); // const canAdd = mountPolicy && mountPolicy.POST || false; const canAdd = true; const addRequireNetworkElementAction = { icon: AddIcon, tooltip: 'Add', ariaLabel: "add-element", onClick: () => { this.setState({ networkElementEditorMode: EditNetworkElementDialogMode.AddNewNetworkElement, networkElementToEdit: emptyRequireNetworkElement, }); } }; const refreshNetworkElementsAction = { icon: Refresh, tooltip: 'Refresh Network Elements table', ariaLabel: 'refresh', onClick: () => { this.setState({ refreshNetworkElementsEditorMode: RefreshNetworkElementsDialogMode.RefreshNetworkElementsTable }); } }; return <> { return this.getContextMenu(rowData); }} > ; }; public componentDidMount() { if (!initialSorted) { initialSorted = true; this.props.networkElementsActions.onHandleRequestSort("node-id"); } else { this.props.networkElementsActions.onRefresh(); } } private onOpenAddNetworkElementDialog = (event: React.MouseEvent, element: NetworkElementConnection) => { this.setState({ networkElementToEdit: element, networkElementEditorMode: EditNetworkElementDialogMode.AddNewNetworkElement }); } private onOpenRemoveNetworkElementDialog = (event: React.MouseEvent, element: NetworkElementConnection) => { this.setState({ networkElementToEdit: element, networkElementEditorMode: EditNetworkElementDialogMode.RemoveNetworkElement }); } private onOpenEditNetworkElementDialog = (event: React.MouseEvent, element: NetworkElementConnection) => { let radioSaved; if (element.password && element.password.length > 0) radioSaved = 'password' else if (element.tlsKey && element.tlsKey.length > 0) radioSaved = 'tlsKey' this.setState({ networkElementToEdit: { nodeId: element.nodeId, isRequired: element.isRequired, host: element.host, port: element.port, username: element.username, password: element.password, tlsKey: element.tlsKey }, networkElementEditorMode: EditNetworkElementDialogMode.EditNetworkElement }); } private onOpenUnmountdNetworkElementsDialog = (event: React.MouseEvent, element: NetworkElementConnection) => { this.setState({ networkElementToEdit: element, networkElementEditorMode: EditNetworkElementDialogMode.UnmountNetworkElement }); } private onOpenMountdNetworkElementsDialog = (event: React.MouseEvent, element: NetworkElementConnection) => { this.setState({ networkElementToEdit: element, networkElementEditorMode: EditNetworkElementDialogMode.MountNetworkElement }); } private onOpenInfoNetworkElementDialog = (event: React.MouseEvent, element: NetworkElementConnection) => { this.props.networkElementInfo(element.nodeId); this.props.networkElementFeaturesInfo(element.nodeId); this.setState({ networkElementToEdit: element, infoNetworkElementEditorMode: InfoNetworkElementDialogMode.InfoNetworkElement, }); } private onCloseEditNetworkElementDialog = () => { this.setState({ networkElementEditorMode: EditNetworkElementDialogMode.None, networkElementToEdit: emptyRequireNetworkElement, }); } private onCloseInfoNetworkElementDialog = () => { this.setState({ infoNetworkElementEditorMode: InfoNetworkElementDialogMode.None, networkElementToEdit: emptyRequireNetworkElement, }); } private onCloseRefreshNetworkElementsDialog = () => { this.setState({ refreshNetworkElementsEditorMode: RefreshNetworkElementsDialogMode.None }); } } export const NetworkElementsList = withStyles(styles)(connect(mapProps, mapDispatch)(NetworkElementsListComponent));