diff options
Diffstat (limited to 'sdnr/wt-odlux/odlux/apps/connectApp/src/components/editNetworkElementDialog.tsx')
-rw-r--r-- | sdnr/wt-odlux/odlux/apps/connectApp/src/components/editNetworkElementDialog.tsx | 425 |
1 files changed, 425 insertions, 0 deletions
diff --git a/sdnr/wt-odlux/odlux/apps/connectApp/src/components/editNetworkElementDialog.tsx b/sdnr/wt-odlux/odlux/apps/connectApp/src/components/editNetworkElementDialog.tsx new file mode 100644 index 000000000..b0db63476 --- /dev/null +++ b/sdnr/wt-odlux/odlux/apps/connectApp/src/components/editNetworkElementDialog.tsx @@ -0,0 +1,425 @@ +/** + * ============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 React from 'react'; + +import Button from '@mui/material/Button'; +import Dialog from '@mui/material/Dialog'; +import DialogActions from '@mui/material/DialogActions'; +import DialogContent from '@mui/material/DialogContent'; +import DialogContentText from '@mui/material/DialogContentText'; +import DialogTitle from '@mui/material/DialogTitle'; +import FormControl from '@mui/material/FormControl'; +import FormControlLabel from '@mui/material/FormControlLabel'; +import InputLabel from '@mui/material/InputLabel'; +import MenuItem from '@mui/material/MenuItem'; +import Radio from '@mui/material/Radio'; +import RadioGroup from '@mui/material/RadioGroup'; +import Select from '@mui/material/Select'; +import TextField from '@mui/material/TextField'; +import Typography from '@mui/material/Typography'; + +import { connect, Connect, IDispatcher } from '../../../../framework/src/flux/connect'; + +import { removeWebUriAction } from '../actions/commonNetworkElementsActions'; +import { mountNetworkElementAsyncActionCreator, unmountNetworkElementAsyncActionCreator } from '../actions/mountedNetworkElementsActions'; +import { + addNewNetworkElementAsyncActionCreator, editNetworkElementAsyncActionCreator, removeNetworkElementAsyncActionCreator, +} from '../actions/networkElementsActions'; +import { loadAllTlsKeyListAsync } from '../actions/tlsKeyActions'; +import { NetworkElementConnection, propertyOf, UpdateNetworkElement } from '../models/networkElementConnection'; + +export enum EditNetworkElementDialogMode { + None = 'none', + EditNetworkElement = 'editNetworkElement', + RemoveNetworkElement = 'removeNetworkElement', + AddNewNetworkElement = 'addNewNetworkElement', + MountNetworkElement = 'mountNetworkElement', + UnmountNetworkElement = 'unmountNetworkElement', +} + +const mapDispatch = (dispatcher: IDispatcher) => ({ + addNewNetworkElement: async (element: NetworkElementConnection) => { + await dispatcher.dispatch(addNewNetworkElementAsyncActionCreator(element)); + await dispatcher.dispatch(mountNetworkElementAsyncActionCreator(element)); + }, + mountNetworkElement: (element: NetworkElementConnection) => dispatcher.dispatch(mountNetworkElementAsyncActionCreator(element)), + unmountNetworkElement: (element: NetworkElementConnection) => { + dispatcher.dispatch(unmountNetworkElementAsyncActionCreator(element && element.nodeId)); + }, + editNetworkElement: async (element: UpdateNetworkElement, mountElement: NetworkElementConnection) => { + + const values = Object.keys(element); + console.log('edit element'); + console.log(values); + + //make sure properties are there in case they get renamed + const idProperty = propertyOf<UpdateNetworkElement>('id'); + const isRequiredProperty = propertyOf<UpdateNetworkElement>('isRequired'); + + + if (values.length === 2 && values.includes(idProperty as string) && values.includes(isRequiredProperty as string)) { + // do not mount network element/node, if only isRequired is changed + await dispatcher.dispatch(editNetworkElementAsyncActionCreator(element)); + + } else if (!(values.length === 1 && values.includes(idProperty as string))) { //do not edit or mount network element/node , if only id was saved into object (no changes made!) + await dispatcher.dispatch(editNetworkElementAsyncActionCreator(element)); + await dispatcher.dispatch(mountNetworkElementAsyncActionCreator(mountElement)); + } + }, + removeNetworkElement: async (element: UpdateNetworkElement) => { + await dispatcher.dispatch(removeNetworkElementAsyncActionCreator(element)); + dispatcher.dispatch(removeWebUriAction(element.id)); + }, + getAvailableTlsKeys: async () => dispatcher.dispatch(loadAllTlsKeyListAsync()), +}); + +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.AddNewNetworkElement]: { + dialogTitle: 'Add New Node', + dialogDescription: 'Add this new node:', + applyButtonText: 'Add node', + cancelButtonText: 'Cancel', + enableMountIdEditor: true, + enableUsernameEditor: true, + enableExtendedEditor: true, + }, + [EditNetworkElementDialogMode.MountNetworkElement]: { + dialogTitle: 'Mount Node', + dialogDescription: 'Mount this node:', + applyButtonText: 'Mount node', + cancelButtonText: 'Cancel', + enableMountIdEditor: false, + enableUsernameEditor: false, + enableExtendedEditor: false, + }, + [EditNetworkElementDialogMode.UnmountNetworkElement]: { + dialogTitle: 'Unmount Node', + dialogDescription: 'Unmount this node:', + applyButtonText: 'Unmount node', + cancelButtonText: 'Cancel', + enableMountIdEditor: false, + enableUsernameEditor: false, + enableExtendedEditor: false, + }, + [EditNetworkElementDialogMode.EditNetworkElement]: { + dialogTitle: 'Modify Node', + dialogDescription: 'Modify this node', + applyButtonText: 'Modify', + cancelButtonText: 'Cancel', + enableMountIdEditor: false, + enableUsernameEditor: true, + enableExtendedEditor: false, + }, + [EditNetworkElementDialogMode.RemoveNetworkElement]: { + dialogTitle: 'Remove Node', + dialogDescription: 'Do you really want to remove this node?', + applyButtonText: 'Remove node', + cancelButtonText: 'Cancel', + enableMountIdEditor: false, + enableUsernameEditor: false, + enableExtendedEditor: false, + }, +}; + +type EditNetworkElementDialogComponentProps = Connect<undefined, typeof mapDispatch> & { + mode: EditNetworkElementDialogMode; + initialNetworkElement: NetworkElementConnection; + onClose: () => void; + radioChecked: string; +}; + +type EditNetworkElementDialogComponentState = NetworkElementConnection & { + isNameValid: boolean; + isHostSet: boolean; + isPasswordSelected: boolean; + isTlsSelected: boolean; + radioSelected: string; + showPasswordTextField: boolean; + showTlsDropdown: boolean; +}; + +class EditNetworkElementDialogComponent extends React.Component<EditNetworkElementDialogComponentProps, EditNetworkElementDialogComponentState> { + constructor(props: EditNetworkElementDialogComponentProps) { + super(props); + this.handleRadioChange = this.handleRadioChange.bind(this); + // Initialization of state is partly overwritten by update via react getDerivedStateFromProps() below. + // Change initialization values in parent "networkElements.tsx" in "const emptyRequireNetworkElement" + this.state = { + nodeId: this.props.initialNetworkElement.nodeId, + isRequired: this.props.initialNetworkElement.isRequired, + host: this.props.initialNetworkElement.host, + port: this.props.initialNetworkElement.port, + isNameValid: true, + isHostSet: true, + isPasswordSelected: true, + isTlsSelected: false, + radioSelected: '', + showPasswordTextField: true, + showTlsDropdown: false, + }; + } + + public handleRadioChange = (event: any) => { + this.setState({ + radioSelected: event.target.value, + showPasswordTextField: event.target.value === 'password', + showTlsDropdown: event.target.value === 'tlsKey', + }); + }; + + render(): JSX.Element { + const setting = settings[this.props.mode]; + let { showPasswordTextField, showTlsDropdown, radioSelected } = this.state; + radioSelected = this.state.radioSelected.length > 0 ? this.state.radioSelected : this.props.radioChecked; + + if (radioSelected === 'password') { + radioSelected = 'password'; + showPasswordTextField = true; + showTlsDropdown = false; + } else if (radioSelected === 'tlsKey') { + radioSelected = 'tlsKey'; + showPasswordTextField = false; + showTlsDropdown = true; + } + + let tlsKeysList = this.props.state.connect.availableTlsKeys ? this.props.state.connect.availableTlsKeys.tlsKeysList ? this.props.state.connect.availableTlsKeys.tlsKeysList : [] : []; + + return ( + <Dialog open={this.props.mode !== EditNetworkElementDialogMode.None}> + <DialogTitle id="form-dialog-title" aria-label={`${setting.dialogTitle.replace(/ /g, '-').toLowerCase()}-dialog`}>{setting.dialogTitle}</DialogTitle> + <DialogContent> + <DialogContentText> + {setting.dialogDescription} + </DialogContentText> + <TextField variant="standard" disabled={!setting.enableMountIdEditor} spellCheck={false} autoFocus margin="dense" + id="name" label="Node ID" aria-label="name" type="text" fullWidth value={this.state.nodeId} onChange={(event) => { this.setState({ nodeId: event.target.value }); }} /> + {!this.state.isNameValid && <Typography variant="body1" color="error">Node ID cannot be empty.</Typography>} + <TextField variant="standard" disabled={!setting.enableMountIdEditor} spellCheck={false} margin="dense" + id="ipaddress" label="Host/IP address" aria-label="ip adress" type="text" fullWidth value={this.state.host} onChange={(event) => { this.setState({ host: event.target.value }); }} /> + {!this.state.isHostSet && <Typography variant="body1" color="error">Host/IP address cannot be empty.</Typography>} + + <TextField variant="standard" disabled={!setting.enableMountIdEditor} spellCheck={false} margin="dense" + id="netconfport" label="NETCONF port" aria-label="netconf port" type="number" fullWidth value={this.state.port.toString()} + onChange={(event) => { this.setState({ port: +event.target.value }); }} /> + {setting.enableUsernameEditor && <TextField variant="standard" disabled={!setting.enableUsernameEditor} spellCheck={false} margin="dense" + id="username" label="Username" aria-label="username" type="text" fullWidth value={this.state.username} onChange={(event) => { this.setState({ username: event.target.value }); }} /> || null} + + {setting.enableUsernameEditor && + <RadioGroup row aria-label="password-tls-key" name="password-tls-key" value={radioSelected} + onChange={this.handleRadioChange} > + <FormControlLabel aria-label="passwordSelection" value='password' control={<Radio color="secondary" />} label="Password" onChange={this.onRadioSelect} /> + <FormControlLabel aria-label="tlsKeySelection" value='tlsKey' control={<Radio color="secondary" />} label="TlsKey" onChange={this.onRadioSelect} /> + </RadioGroup> || null} + + {setting.enableUsernameEditor && showPasswordTextField && + <TextField variant="standard" disabled={!setting.enableUsernameEditor || !showPasswordTextField} spellCheck={false} margin="dense" + id="password" aria-label="password" type="password" fullWidth value={this.state.password} + onChange={(event) => { this.setState({ password: event.target.value }); }} + /> || null} + + <FormControl variant="standard" fullWidth disabled={!setting.enableUsernameEditor}> + {setting.enableUsernameEditor && showTlsDropdown && + <div> + <InputLabel htmlFor="pass">--Select tls-key--</InputLabel> + <Select variant="standard" disabled={!setting.enableUsernameEditor || !showTlsDropdown} + id="tlsKey" aria-label="tlsKey" value={this.state.tlsKey} fullWidth // displayEmpty + onChange={(event) => { this.setState({ tlsKey: event.target.value as any }); }} + inputProps={{ name: 'tlsKey', id: 'tlsKey' }} > + <MenuItem value={''} disabled >--Select tls-key--</MenuItem> + {tlsKeysList.map(tlsKey => + (<MenuItem value={tlsKey.key} key={tlsKey.key} aria-label={tlsKey.key} >{tlsKey.key}</MenuItem>))} + </Select> + </div> + } + </FormControl> + + <FormControl variant="standard" fullWidth disabled={!setting.enableUsernameEditor}> + <InputLabel htmlFor="active">Required</InputLabel> + <Select variant="standard" aria-label="required-selection" value={this.state.isRequired || false} onChange={(event) => { + this.setState({ isRequired: event.target.value as any as boolean }); + }} inputProps={{ name: 'required', id: 'required' }} fullWidth > + <MenuItem value={true as any as string} aria-label="true">True</MenuItem> + <MenuItem value={false as any as string} aria-label="false">False</MenuItem> + </Select> + </FormControl> + </DialogContent> + <DialogActions> + <Button aria-label="dialog-confirm-button" onClick={(event) => { + + if (this.areRequieredFieldsValid()) { + this.onApply({ + isRequired: this.state.isRequired, + id: this.state.nodeId, + nodeId: this.state.nodeId, + host: this.state.host, + port: this.state.port, + username: this.state.username, + password: this.state.password, + tlsKey: this.state.tlsKey, + }); + } + event.preventDefault(); + event.stopPropagation(); + }} color="inherit" > {setting.applyButtonText} </Button> + <Button aria-label="dialog-cancel-button" onClick={(event) => { + this.onCancel(); + event.preventDefault(); + event.stopPropagation(); + }} color="secondary"> {setting.cancelButtonText} </Button> + </DialogActions> + </Dialog> + ); + } + + public renderTlsKeys = () => { + try { + this.props.getAvailableTlsKeys(); + } catch (err) { + console.log(err); + } + }; + + public componentDidMount() { + this.renderTlsKeys(); + } + + public onRadioSelect = (e: any) => { + if (e.target.value == 'password') { + this.setState({ isPasswordSelected: true, isTlsSelected: false }); + } else if (e.target.value == 'tlsKey') { + this.setState({ isPasswordSelected: false, isTlsSelected: true }); + } + }; + + private onApply = (element: NetworkElementConnection) => { + if (this.props.onClose) this.props.onClose(); + let updateElement: UpdateNetworkElement = { + id: this.state.nodeId, + }; + if (this.state.isPasswordSelected) { + element.tlsKey = ''; + } else if (this.state.isTlsSelected) { //check here + element.password = ''; + } + + switch (this.props.mode) { + case EditNetworkElementDialogMode.AddNewNetworkElement: + if (element) this.props.addNewNetworkElement(element); + this.setState({ + radioSelected: '', + isPasswordSelected: true, + }); + break; + case EditNetworkElementDialogMode.MountNetworkElement: + if (element) this.props.mountNetworkElement(element); + break; + case EditNetworkElementDialogMode.UnmountNetworkElement: + if (element) this.props.unmountNetworkElement(element); + break; + case EditNetworkElementDialogMode.EditNetworkElement: + if (this.props.initialNetworkElement.isRequired !== this.state.isRequired) + updateElement.isRequired = this.state.isRequired; + if (this.props.initialNetworkElement.username !== this.state.username) + updateElement.username = this.state.username; + if (this.props.initialNetworkElement.password !== this.state.password && this.state.isPasswordSelected) { + updateElement.password = this.state.password; + updateElement.tlsKey = ''; + } + if (this.props.initialNetworkElement.tlsKey !== this.state.tlsKey && this.state.isTlsSelected) { + updateElement.tlsKey = this.state.tlsKey; + updateElement.password = ''; + } + if (element) this.props.editNetworkElement(updateElement, element); + this.setState({ + radioSelected: '', + }); + break; + case EditNetworkElementDialogMode.RemoveNetworkElement: + if (element) this.props.removeNetworkElement(updateElement); + break; + } + + this.setState({ password: '', username: '', tlsKey: '' }); + this.resetRequieredFields(); + }; + + private onCancel = () => { + if (this.props.onClose) this.props.onClose(); + this.setState({ password: '', username: '', tlsKey: '', radioSelected: '' }); + this.resetRequieredFields(); + }; + + private resetRequieredFields() { + this.setState({ isNameValid: true, isHostSet: true }); + } + + private areRequieredFieldsValid() { + let areFieldsValid = true; + + if (this.state.nodeId == undefined || this.state.nodeId.trim().length === 0) { + this.setState({ isNameValid: false }); + areFieldsValid = false; + } else { + this.setState({ isNameValid: true }); + } + + if (this.state.host == undefined || this.state.host.trim().length === 0) { + this.setState({ isHostSet: false }); + areFieldsValid = false; + } else { + this.setState({ isHostSet: true }); + } + + return areFieldsValid; + } + + static getDerivedStateFromProps(props: EditNetworkElementDialogComponentProps, state: EditNetworkElementDialogComponentState & { initialNetworkElement: NetworkElementConnection }): EditNetworkElementDialogComponentState & { initialNetworkElement: NetworkElementConnection } { + let returnState = state; + if (props.initialNetworkElement !== state.initialNetworkElement) { + returnState = { + ...state, + ...props.initialNetworkElement, + initialNetworkElement: props.initialNetworkElement, + }; + } + return returnState; + } +} + +export const EditNetworkElementDialog = connect(undefined, mapDispatch)(EditNetworkElementDialogComponent); +export default EditNetworkElementDialog;
\ No newline at end of file |