diff options
Diffstat (limited to 'src/tools/emcoui/src/compositeApps/dialogs/AppNetworkForm.jsx')
-rw-r--r-- | src/tools/emcoui/src/compositeApps/dialogs/AppNetworkForm.jsx | 524 |
1 files changed, 524 insertions, 0 deletions
diff --git a/src/tools/emcoui/src/compositeApps/dialogs/AppNetworkForm.jsx b/src/tools/emcoui/src/compositeApps/dialogs/AppNetworkForm.jsx new file mode 100644 index 00000000..055dc3e6 --- /dev/null +++ b/src/tools/emcoui/src/compositeApps/dialogs/AppNetworkForm.jsx @@ -0,0 +1,524 @@ +//======================================================================= +// Copyright (c) 2017-2020 Aarna Networks, Inc. +// 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. +// ======================================================================== +import React, { useState } from "react"; +import { makeStyles } from "@material-ui/core/styles"; +import Button from "@material-ui/core/Button"; +import Typography from "@material-ui/core/Typography"; +import { Grid, IconButton } from "@material-ui/core"; +import { TextField, Select, MenuItem, InputLabel } from "@material-ui/core"; +import AddIcon from "@material-ui/icons/Add"; +import CardContent from "@material-ui/core/CardContent"; +import Card from "@material-ui/core/Card"; +import apiService from "../../services/apiService"; +import DeleteIcon from "@material-ui/icons/Delete"; +import { Formik } from "formik"; +import Notification from "../../common/Notification"; + +function NetworkForm({ formikProps, ...props }) { + const [clusters, setClusters] = useState(props.clusters); + const [notificationDetails, setNotificationDetails] = useState({}); + const useStyles = makeStyles({ + root: { + minWidth: 275, + }, + title: { + fontSize: 14, + }, + pos: { + marginBottom: 12, + }, + }); + + const handleAddNetworkInterface = (providerIndex, clusterIndex, values) => { + let updatedFields = []; + if ( + values.apps[props.index].clusters[providerIndex].selectedClusters[ + clusterIndex + ].interfaces + ) { + updatedFields = [ + ...values.apps[props.index].clusters[providerIndex].selectedClusters[ + clusterIndex + ].interfaces, + { + networkName: "", + ip: "", + subnet: "", + }, + ]; + } else { + updatedFields = [ + { + networkName: "", + ip: "", + subnet: "", + }, + ]; + } + + let request = { + providerName: values.apps[props.index].clusters[providerIndex].provider, + clusterName: + values.apps[props.index].clusters[providerIndex].selectedClusters[ + clusterIndex + ].name, + }; + apiService + .getClusterProviderNetworks(request) + .then((networks) => { + let networkData = []; + if (networks && networks.length > 0) { + networks.forEach((network) => { + networkData.push({ + name: network.metadata.name, + subnets: network.spec.ipv4Subnets, + }); + }); + } + + apiService + .getClusterNetworks(request) + .then((clusterNetworks) => { + if (clusterNetworks && clusterNetworks.length > 0) { + clusterNetworks.forEach((clusterNetwork) => { + networkData.push({ + name: clusterNetwork.metadata.name, + subnets: clusterNetwork.spec.ipv4Subnets, + }); + }); + } + //add interface entry onyl of there is atlease one available network + if (networkData.length > 0) { + setClusters((clusters) => { + clusters[providerIndex].selectedClusters[ + clusterIndex + ].interfaces = updatedFields; + clusters[providerIndex].selectedClusters[ + clusterIndex + ].networks = networkData; + clusters[providerIndex].selectedClusters[ + clusterIndex + ].availableNetworks = getAvailableNetworks( + clusters[providerIndex].selectedClusters[clusterIndex] + ); + return clusters; + }); + formikProps.setFieldValue( + `apps[${props.index}].clusters[${providerIndex}].selectedClusters[${clusterIndex}].interfaces`, + updatedFields + ); + } else { + setNotificationDetails({ + show: true, + message: `No network available for this cluster`, + severity: "warning", + }); + } + }) + .catch((err) => { + console.log("error getting cluster networks : ", err); + }); + }) + .catch((err) => { + console.log("error getting cluster provider networks : ", err); + }) + .finally(() => { + return updatedFields; + }); + }; + + const handleSelectNetowrk = ( + e, + providerIndex, + clusterIndex, + interfaceIndex + ) => { + setClusters((clusters) => { + clusters[providerIndex].selectedClusters[clusterIndex].interfaces[ + interfaceIndex + ] = { + networkName: e.target.value, + ip: "", + subnet: "", + }; + clusters[providerIndex].selectedClusters[ + clusterIndex + ].availableNetworks = getAvailableNetworks( + clusters[providerIndex].selectedClusters[clusterIndex], + "handleAddNetworkInterface" + ); + return clusters; + }); + formikProps.handleChange(e); + }; + const handleRemoveNetwork = (providerIndex, clusterIndex, interfaceIndex) => { + setClusters((clusters) => { + clusters[providerIndex].selectedClusters[clusterIndex].interfaces.splice( + interfaceIndex, + 1 + ); + clusters[providerIndex].selectedClusters[ + clusterIndex + ].availableNetworks = getAvailableNetworks( + clusters[providerIndex].selectedClusters[clusterIndex] + ); + return clusters; + }); + formikProps.setFieldValue( + `apps[${props.index}].clusters[${providerIndex}].selectedClusters[${clusterIndex}].interfaces`, + clusters[providerIndex].selectedClusters[clusterIndex].interfaces + ); + }; + const getAvailableNetworks = (cluster) => { + let availableNetworks = []; + cluster.networks.forEach((network) => { + let match = false; + cluster.interfaces.forEach((networkInterface) => { + if (network.name === networkInterface.networkName) { + match = true; + return; + } + }); + if (!match) availableNetworks.push(network); + }); + return availableNetworks; + }; + + const classes = useStyles(); + return ( + <> + <Notification notificationDetails={notificationDetails} /> + <Grid + key="networkForm" + container + spacing={3} + style={{ + height: "400px", + overflowY: "auto", + width: "100%", + scrollbarWidth: "thin", + }} + > + {(!clusters || clusters.length < 1) && ( + <Grid item xs={12}> + <Typography variant="h6">No clusters selected</Typography> + </Grid> + )} + {clusters && + clusters.map((cluster, providerIndex) => ( + <Grid key={cluster.provider + providerIndex} item xs={12}> + <Card className={classes.root}> + <CardContent> + <Grid container spacing={2}> + <Grid item xs={12}> + <Typography + className={classes.title} + color="textSecondary" + gutterBottom + > + {cluster.provider} + </Typography> + </Grid> + {cluster.selectedClusters.map( + (selectedCluster, clusterIndex) => ( + <React.Fragment key={selectedCluster.name}> + <Grid item xs={12}> + <Typography>{selectedCluster.name}</Typography> + </Grid> + <Formik> + {() => { + const { + values, + errors, + handleChange, + handleBlur, + } = formikProps; + return ( + <> + {selectedCluster.interfaces && + selectedCluster.interfaces.length > 0 + ? selectedCluster.interfaces.map( + (networkInterface, interfaceIndex) => ( + <Grid + spacing={1} + container + item + key={interfaceIndex} + xs={12} + > + <Grid item xs={4}> + <InputLabel id="network-select-label"> + Network + </InputLabel> + <Select + fullWidth + labelId="network-select-label" + id="network-select" + name={`apps[${props.index}].clusters[${providerIndex}].selectedClusters[${clusterIndex}].interfaces[${interfaceIndex}].networkName`} + value={ + values.apps[props.index] + .clusters[providerIndex] + .selectedClusters[ + clusterIndex + ].interfaces[interfaceIndex] + .networkName + } + onChange={(e) => { + handleSelectNetowrk( + e, + providerIndex, + clusterIndex, + interfaceIndex + ); + }} + > + {values.apps[props.index] + .clusters[providerIndex] + .selectedClusters[ + clusterIndex + ].interfaces[interfaceIndex] + .networkName && ( + <MenuItem + key={ + values.apps[props.index] + .clusters[providerIndex] + .selectedClusters[ + clusterIndex + ].interfaces[ + interfaceIndex + ].networkName + } + value={ + values.apps[props.index] + .clusters[providerIndex] + .selectedClusters[ + clusterIndex + ].interfaces[ + interfaceIndex + ].networkName + } + > + { + values.apps[props.index] + .clusters[providerIndex] + .selectedClusters[ + clusterIndex + ].interfaces[ + interfaceIndex + ].networkName + } + </MenuItem> + )} + {selectedCluster.availableNetworks && + selectedCluster.availableNetworks.map( + (network) => ( + <MenuItem + key={network.name} + value={network.name} + > + {network.name} + </MenuItem> + ) + )} + </Select> + </Grid> + + <Grid item xs={4}> + <InputLabel id="subnet-select-label"> + Subnet + </InputLabel> + <Select + fullWidth + labelId="subnet-select-label" + id="subnet-select-label" + name={`apps[${props.index}].clusters[${providerIndex}].selectedClusters[${clusterIndex}].interfaces[${interfaceIndex}].subnet`} + value={ + values.apps[props.index] + .clusters[providerIndex] + .selectedClusters[ + clusterIndex + ].interfaces[interfaceIndex] + .subnet + } + onChange={handleChange} + > + {values.apps[props.index] + .clusters[providerIndex] + .selectedClusters[ + clusterIndex + ].interfaces[interfaceIndex] + .networkName === "" + ? null + : selectedCluster.networks + .filter( + (network) => + network.name === + values.apps[ + props.index + ].clusters[ + providerIndex + ].selectedClusters[ + clusterIndex + ].interfaces[ + interfaceIndex + ].networkName + )[0] + .subnets.map((subnet) => ( + <MenuItem + key={subnet.name} + value={subnet.name} + > + {subnet.name}( + {subnet.subnet}) + </MenuItem> + ))} + </Select> + </Grid> + <Grid item xs={3}> + <TextField + width={"65%"} + name={`apps[${props.index}].clusters[${providerIndex}].selectedClusters[${clusterIndex}].interfaces[${interfaceIndex}].ip`} + onBlur={handleBlur} + id="ip" + label="IP Address" + value={ + values.apps[props.index] + .clusters[providerIndex] + .selectedClusters[ + clusterIndex + ].interfaces[interfaceIndex] + .ip + } + onChange={handleChange} + helperText={ + (errors.apps && + errors.apps[props.index] && + errors.apps[props.index] + .clusters && + errors.apps[props.index] + .clusters[clusterIndex] && + errors.apps[props.index] + .clusters[clusterIndex] + .selectedClusters[ + clusterIndex + ] && + errors.apps[props.index] + .clusters[clusterIndex] + .selectedClusters[ + clusterIndex + ].interfaces[ + interfaceIndex + ] && + errors.apps[props.index] + .clusters[clusterIndex] + .selectedClusters[ + clusterIndex + ].interfaces[interfaceIndex] + .ip) || + "blank for auto assign" + } + error={ + errors.apps && + errors.apps[props.index] && + errors.apps[props.index] + .clusters && + errors.apps[props.index] + .clusters[clusterIndex] && + errors.apps[props.index] + .clusters[clusterIndex] + .selectedClusters[ + clusterIndex + ] && + errors.apps[props.index] + .clusters[clusterIndex] + .selectedClusters[ + clusterIndex + ].interfaces[ + interfaceIndex + ] && + errors.apps[props.index] + .clusters[clusterIndex] + .selectedClusters[ + clusterIndex + ].interfaces[interfaceIndex] + .ip && + true + } + /> + </Grid> + <Grid item xs={1}> + <IconButton + color="secondary" + onClick={() => { + handleRemoveNetwork( + providerIndex, + clusterIndex, + interfaceIndex + ); + }} + > + <DeleteIcon fontSize="small" /> + </IconButton> + </Grid> + </Grid> + ) + ) + : null} + <Grid + key={selectedCluster.name + "addButton"} + item + xs={12} + > + <Button + variant="outlined" + size="small" + fullWidth + color="primary" + disabled={ + selectedCluster.interfaces && + selectedCluster.interfaces.length > 0 && + selectedCluster.networks.length === + selectedCluster.interfaces.length + } + onClick={() => { + handleAddNetworkInterface( + providerIndex, + clusterIndex, + values + ); + }} + startIcon={<AddIcon />} + > + Add Network Interface + </Button> + </Grid> + </> + ); + }} + </Formik> + </React.Fragment> + ) + )} + </Grid> + </CardContent> + </Card> + </Grid> + ))} + </Grid> + </> + ); +} + +export default NetworkForm; |