merge master
[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     invalid: boolean;
58     pristine: boolean;
59 }
60
61 interface TextFieldProps {
62     label: string;
63     floatinglabeltext: string;
64     className?: string;
65     input?: string;
66     meta?: any;
67 }
68
69 export const DialogProjectCreate = compose(
70     reduxForm({ form: 'projectCreateDialog' }),
71     withStyles(styles))(
72     class DialogProjectCreate extends React.Component<DialogProjectProps & WithStyles<CssRules>> {
73         render() {
74             const { classes, open, handleClose, handleSubmit, onSubmit, submitting, invalid, pristine } = this.props;
75
76             return (
77                 <Dialog
78                     open={open}
79                     onClose={handleClose}
80                     disableBackdropClick={true}
81                     disableEscapeKeyDown={true}>
82                     <div className={classes.dialog}>
83                         <form onSubmit={handleSubmit((data: any) => onSubmit(data))}>
84                             <DialogTitle id="form-dialog-title" className={classes.dialogTitle}>Create a
85                                 project</DialogTitle>
86                             <DialogContent className={classes.formContainer}>
87                                 <Field name="name"
88                                        component={this.renderTextField}
89                                        floatinglabeltext="Project Name"
90                                        validate={PROJECT_NAME_VALIDATION}
91                                        className={classes.textField}
92                                        label="Project Name"/>
93                                 <Field name="description"
94                                        component={this.renderTextField}
95                                        floatinglabeltext="Description - optional"
96                                        validate={PROJECT_DESCRIPTION_VALIDATION}
97                                        className={classes.textField}
98                                        label="Description - optional"/>
99                             </DialogContent>
100                             <DialogActions className={classes.dialogActions}>
101                                 <Button onClick={handleClose} className={classes.button} color="primary"
102                                         disabled={submitting}>CANCEL</Button>
103                                 <Button type="submit"
104                                         className={classes.lastButton}
105                                         color="primary"
106                                         disabled={invalid || submitting || pristine}
107                                         variant="contained">
108                                     CREATE A PROJECT
109                                 </Button>
110                                 {submitting && <CircularProgress size={20} className={classes.createProgress}/>}
111                             </DialogActions>
112                         </form>
113                     </div>
114                 </Dialog>
115             );
116         }
117
118         renderTextField = ({ input, label, meta: { touched, error }, ...custom }: TextFieldProps) => (
119             <TextField
120                 helperText={touched && error}
121                 label={label}
122                 className={this.props.classes.textField}
123                 error={touched && !!error}
124                 autoComplete='off'
125                 {...input}
126                 {...custom}
127             />
128         )
129     }
130 );