Merge branch '13781-Data-operations-Creating-a-project-validation'
[arvados-workbench2.git] / src / views-components / dialog-create / dialog-project-create.tsx
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 import * as React from 'react';
6 import { reduxForm, Field } from 'redux-form';
7 import { compose } from 'redux';
8 import TextField from '@material-ui/core/TextField';
9 import Dialog from '@material-ui/core/Dialog';
10 import DialogActions from '@material-ui/core/DialogActions';
11 import DialogContent from '@material-ui/core/DialogContent';
12 import DialogTitle from '@material-ui/core/DialogTitle';
13 import { Button, StyleRulesCallback, WithStyles, withStyles, CircularProgress } from '@material-ui/core';
14
15 import { PROJECT_NAME_VALIDATION, PROJECT_DESCRIPTION_VALIDATION } from '../../validators/create-project/create-project-validator';
16
17 type CssRules = "button" | "lastButton" | "formContainer" | "textField" | "dialog" | "dialogTitle" | "createProgress" | "dialogActions";
18
19 const styles: StyleRulesCallback<CssRules> = theme => ({
20     button: {
21         marginLeft: theme.spacing.unit
22     },
23     lastButton: {
24         marginLeft: theme.spacing.unit,
25         marginRight: "20px",
26     },
27     formContainer: {
28         display: "flex",
29         flexDirection: "column",
30         marginTop: "20px",
31     },
32     dialogTitle: {
33         paddingBottom: "0"
34     },
35     textField: {
36         marginTop: "32px",
37     },
38     dialog: {
39         minWidth: "600px",
40         minHeight: "320px"
41     },
42     createProgress: {
43         position: "absolute",
44         minWidth: "20px",
45         right: "95px"
46     },
47     dialogActions: {
48         marginBottom: "24px"
49     }
50 });
51 interface DialogProjectProps {
52     open: boolean;
53     handleClose: () => void;
54     onSubmit: (data: { name: string, description: string }) => void;
55     handleSubmit: any;
56     submitting: boolean;
57 }
58
59 interface TextFieldProps {
60     label: string;
61     floatinglabeltext: string;
62     className?: string;
63     input?: string;
64     meta?: any;
65 }
66
67 export const DialogProjectCreate = compose(
68     reduxForm({ form: 'projectCreateDialog' }),
69     withStyles(styles))(
70     class DialogProjectCreate extends React.Component<DialogProjectProps & WithStyles<CssRules>> {
71         render() {
72             const { classes, open, handleClose, handleSubmit, onSubmit, submitting } = this.props;
73
74             return (
75                 <Dialog
76                     open={open}
77                     onClose={handleClose}
78                     disableBackdropClick={true}
79                     disableEscapeKeyDown={true}>
80                     <div className={classes.dialog}>
81                         <form onSubmit={handleSubmit((data: any) => onSubmit(data))}>
82                             <DialogTitle id="form-dialog-title" className={classes.dialogTitle}>Create a
83                                 project</DialogTitle>
84                             <DialogContent className={classes.formContainer}>
85                                 <Field name="name"
86                                        component={this.renderTextField}
87                                        floatinglabeltext="Project Name"
88                                        validate={PROJECT_NAME_VALIDATION}
89                                        className={classes.textField}
90                                        label="Project Name"/>
91                                 <Field name="description"
92                                        component={this.renderTextField}
93                                        floatinglabeltext="Description - optional"
94                                        validate={PROJECT_DESCRIPTION_VALIDATION}
95                                        className={classes.textField}
96                                        label="Description - optional"/>
97                             </DialogContent>
98                             <DialogActions className={classes.dialogActions}>
99                                 <Button onClick={handleClose} className={classes.button} color="primary"
100                                         disabled={submitting}>CANCEL</Button>
101                                 <Button type="submit"
102                                         className={classes.lastButton}
103                                         color="primary"
104                                         disabled={submitting}
105                                         variant="contained">
106                                     CREATE A PROJECT
107                                 </Button>
108                                 {submitting && <CircularProgress size={20} className={classes.createProgress}/>}
109                             </DialogActions>
110                         </form>
111                     </div>
112                 </Dialog>
113             );
114         }
115
116         renderTextField = ({ input, label, meta: { touched, error }, ...custom }: TextFieldProps) => (
117             <TextField
118                 helperText={touched && error}
119                 label={label}
120                 className={this.props.classes.textField}
121                 error={touched && !!error}
122                 autoComplete='off'
123                 {...input}
124                 {...custom}
125             />
126         )
127     }
128 );