diff options
Diffstat (limited to 'src/tools/emcoui/src/compositeApps/dialogs/CompositeAppForm.jsx')
-rw-r--r-- | src/tools/emcoui/src/compositeApps/dialogs/CompositeAppForm.jsx | 441 |
1 files changed, 277 insertions, 164 deletions
diff --git a/src/tools/emcoui/src/compositeApps/dialogs/CompositeAppForm.jsx b/src/tools/emcoui/src/compositeApps/dialogs/CompositeAppForm.jsx index 29e17cd7..751ea8eb 100644 --- a/src/tools/emcoui/src/compositeApps/dialogs/CompositeAppForm.jsx +++ b/src/tools/emcoui/src/compositeApps/dialogs/CompositeAppForm.jsx @@ -11,185 +11,298 @@ // 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 from "react"; -import { withStyles } from "@material-ui/core/styles"; +// ======================================================================== +import React, { useState } from "react"; import Button from "@material-ui/core/Button"; import Dialog from "@material-ui/core/Dialog"; -import MuiDialogTitle from "@material-ui/core/DialogTitle"; -import MuiDialogContent from "@material-ui/core/DialogContent"; -import MuiDialogActions from "@material-ui/core/DialogActions"; +import AppBar from "@material-ui/core/AppBar"; +import Toolbar from "@material-ui/core/Toolbar"; +import IconButton from "@material-ui/core/IconButton"; import Typography from "@material-ui/core/Typography"; -import { TextField } from '@material-ui/core'; -const styles = (theme) => ({ - root: { - margin: 0, - padding: theme.spacing(2), +import CloseIcon from "@material-ui/icons/Close"; +import Slide from "@material-ui/core/Slide"; +import { Grid } from "@material-ui/core"; +import { TextField } from "@material-ui/core"; +import { makeStyles } from "@material-ui/core/styles"; +import AddIcon from "@material-ui/icons/Add"; +import NewAppForm from "../../common/Form"; +import AppForm from "./AppForm"; +import { Formik, FieldArray } from "formik"; +import * as Yup from "yup"; + +const Transition = React.forwardRef(function Transition(props, ref) { + return <Slide direction="up" ref={ref} {...props} />; +}); + +const useStyles = makeStyles((theme) => ({ + tableRoot: { + width: "100%", }, - closeButton: { + paper: { + width: "100%", + marginBottom: theme.spacing(2), + }, + table: { + minWidth: 550, + }, + visuallyHidden: { + border: 0, + clip: "rect(0 0 0 0)", + height: 1, + margin: -1, + overflow: "hidden", + padding: 0, position: "absolute", - right: theme.spacing(1), - top: theme.spacing(1), - color: theme.palette.grey[500], + top: 20, + width: 1, }, -}); - - -const DialogContent = withStyles((theme) => ({ - root: { - padding: theme.spacing(2), + appBar: { + position: "relative", + }, + title: { + marginLeft: theme.spacing(2), + flex: 1, + }, + demo: { + backgroundColor: theme.palette.background.paper, }, -}))(MuiDialogContent); - -const DialogActions = withStyles((theme) => ({ root: { - margin: 0, - padding: theme.spacing(1), + flexGrow: 1, + backgroundColor: theme.palette.background.paper, + display: "flex", + height: 424, }, -}))(MuiDialogActions); - + tabs: { + borderRight: `1px solid ${theme.palette.divider}`, + }, +})); -class CreateCompositeAppForm extends React.Component { - constructor(props) { - super(props) - this.state = { - fields: { name: "", version: "", description: "" }, - errors: {} - } - this.handleChange = this.handleChange.bind(this); - this.submituserRegistrationForm = this.submituserRegistrationForm.bind(this); - } +const PROFILE_SUPPORTED_FORMATS = [ + ".tgz", + ".tar.gz", + ".tar", + "application/x-tar", + "application/x-tgz", + "application/x-compressed", + "application/x-gzip", + "application/x-compressed-tar", + "application/gzip", +]; +const APP_PACKAGE_SUPPORTED_FORMATS = [ + ".tgz", + ".tar.gz", + ".tar", + "application/x-tar", + "application/x-tgz", + "application/x-compressed", + "application/x-gzip", + "application/x-compressed-tar", +]; +const serviceBasicValidationSchema = Yup.object({ + name: Yup.string().required(), + description: Yup.string(), + apps: Yup.array() + .of( + Yup.object({ + appName: Yup.string().required("App name is required"), + file: Yup.mixed() + .required("An app package file is required") + .test( + "fileFormat", + "Unsupported file format", + (value) => + value && APP_PACKAGE_SUPPORTED_FORMATS.includes(value.type) + ), + profilePackageFile: Yup.mixed() + .required("A profile package file is required") + .test( + "fileFormat", + "Unsupported file format", + (value) => value && PROFILE_SUPPORTED_FORMATS.includes(value.type) + ), + }) + ) + .required("At least one app is required"), +}); - componentDidMount = () => { - if (this.props.item) { - this.title = "Edit Composite App"; - this.buttonLabel = "Update"; - this.isEdit = true; - } - else { - this.title = "New Composite App"; - this.buttonLabel = "Create"; - this.isEdit = false; - } +const CreateCompositeAppForm = ({ open, handleClose }) => { + const classes = useStyles(); + const [openForm, setOpenForm] = useState(false); + const handleCloseForm = () => { + setOpenForm(false); }; - - componentDidUpdate = (prevProps, prevState) => { - if (this.props.item && ((prevProps.item !== this.props.item))) { - this.setState({ fields: { ...this.props.item.metadata, version: this.props.item.spec.version } }); - } - } - - resetFields = () => { - if (!this.isEdit) { - this.setState({ - fields: { name: "", version: "", description: "" }, - errors: {} - }); - } - else { - this.setState({ fields: { ...this.props.item.metadata, version: this.props.item.spec.version } }); - } - } - - handleClose = () => { - this.resetFields(); - this.props.handleClose(); + const handleAddApp = () => { + setOpenForm(true); }; - - submituserRegistrationForm(e) { - e.preventDefault(); - if (this.validateForm()) { - this.resetFields(); - this.props.handleClose(this.state.fields); - } - } - - validateForm() { - let fields = this.state.fields; - let errors = {}; - let formIsValid = true; - - if (!fields["name"]) { - formIsValid = false; - errors["name"] = "*Please enter your username."; - } - - if (typeof fields["name"] !== "string") { - if (!fields["name"].match(/^[a-zA-Z ]*$/)) { - formIsValid = false; - errors["name"] = "*Please enter alphabet characters only."; - } - } - this.setState({ - errors: errors - }); - return formIsValid; - } - - handleChange = (e) => { - this.setState({ fields: { ...this.state.fields, [e.target.name]: e.target.value } }); - } - - render = () => { - const { classes } = this.props; - return ( - <> + let initialValues = { name: "", description: "", apps: [] }; + return ( + <> + {open && ( <Dialog - maxWidth={"xs"} - onClose={this.handleClose} - aria-labelledby="customized-dialog-title" - open={this.props.open} - disableBackdropClick + open={open} + onClose={() => { + handleClose(); + }} + fullScreen + TransitionComponent={Transition} > - <MuiDialogTitle disableTypography className={classes.root} > - <Typography variant="h6">{this.title}</Typography> - </MuiDialogTitle> + <Formik + initialValues={initialValues} + onSubmit={(values, { setSubmitting }) => { + setSubmitting(false); + handleClose(values); + }} + validationSchema={serviceBasicValidationSchema} + > + {(props) => { + const { + values, + touched, + errors, + isSubmitting, + handleChange, + handleBlur, + handleSubmit, + } = props; + return ( + <> + <form noValidate onSubmit={handleSubmit}> + <AppBar className={classes.appBar}> + <Toolbar> + <IconButton + edge="start" + color="inherit" + onClick={() => { + handleClose(); + }} + aria-label="close" + > + <CloseIcon /> + </IconButton> + <Typography variant="h6" className={classes.title}> + Add Service + </Typography> + <Button + type="submit" + autoFocus + variant="contained" + disabled={isSubmitting} + > + SUBMIT + </Button> + </Toolbar> + </AppBar> + <div style={{ padding: "12px" }}> + <Grid + container + direction="row" + justify="center" + alignItems="center" + style={{ marginTop: "40px" }} + spacing={3} + > + <Grid item xs={6}> + <Grid container spacing={3}> + {errors.apps && + touched.apps && + typeof errors.apps !== "object" && ( + <Grid item xs={12} sm={12}> + <Typography>{errors.apps}</Typography> + </Grid> + )} + + <Grid item xs={12} sm={6}> + <TextField + fullWidth + name="name" + id="input-name" + label="Name" + variant="outlined" + size="small" + value={values.name} + onChange={handleChange} + onBlur={handleBlur} + required + helperText={ + errors.name && + touched.name && + "Name is required" + } + error={errors.name && touched.name} + /> + </Grid> + <Grid item xs={12} sm={6}> + <TextField + fullWidth + name="description" + id="input-description" + label="Description" + variant="outlined" + size="small" + value={values.description} + onChange={handleChange} + onBlur={handleBlur} + /> + </Grid> - <form onSubmit={this.submituserRegistrationForm}> - <DialogContent dividers> - <TextField - style={{ width: "40%", marginBottom: "10px" }} - name="name" - value={this.state.fields.name} - id="input-name" - label="Name" - helperText="Name should be unique" - onChange={this.handleChange} - required - /> - <TextField - style={{ width: "40%", marginBottom: "20px", float: "right" }} - name="version" - value={this.state.fields.version} - onChange={this.handleChange} - id="input-version" - label="Version" - required - /> - <TextField - style={{ width: "100%", marginBottom: "25px" }} - name="description" - value={this.state.fields.description} - onChange={this.handleChange} - id="input-description" - label="Description" - multiline - rowsMax={4} - /> - </DialogContent> - <DialogActions> - <Button autoFocus onClick={this.handleClose} color="secondary"> - Cancel - </Button> - <Button autoFocus type="submit" color="primary"> - {this.buttonLabel} - </Button> - </DialogActions> - </form> + <FieldArray + name="apps" + render={(arrayHelpers) => ( + <> + <NewAppForm + open={openForm} + onClose={handleCloseForm} + onSubmit={(values) => { + arrayHelpers.push({ + appName: values.name, + description: values.description, + }); + setOpenForm(false); + }} + /> + {values.apps && + values.apps.length > 0 && + values.apps.map((app, index) => ( + <Grid key={index} item sm={12} xs={12}> + <AppForm + formikProps={props} + name={app.appName} + description={app.description} + index={index} + initialValues={values} + /> + </Grid> + ))} + </> + )} + /> + <Grid item xs={12}> + <Button + variant="outlined" + size="small" + fullWidth + color="primary" + onClick={() => { + handleAddApp(); + }} + startIcon={<AddIcon />} + > + Add App + </Button> + </Grid> + </Grid> + </Grid> + </Grid> + </div> + </form> + </> + ); + }} + </Formik> </Dialog> - </> - ); - } -} -export default withStyles(styles)(CreateCompositeAppForm) + )} + </> + ); +}; +export default CreateCompositeAppForm; |