Merge branch 'master' into 13903-edit-collection-popup
[arvados-workbench2.git] / src / views-components / dialog-create / dialog-collection-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 { COLLECTION_NAME_VALIDATION, COLLECTION_DESCRIPTION_VALIDATION } from '../../validators/create-project/create-project-validator';
16
17 type CssRules = "button" | "lastButton" | "formContainer" | "textField" | "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     },
31     textField: {
32         marginBottom: theme.spacing.unit * 3
33     },
34     createProgress: {
35         position: "absolute",
36         minWidth: "20px",
37         right: "110px"
38     },
39     dialogActions: {
40         marginBottom: theme.spacing.unit * 3
41     }
42 });
43 interface DialogCollectionCreateProps {
44     open: boolean;
45     handleClose: () => void;
46     onSubmit: (data: { name: string, description: string }) => void;
47     handleSubmit: any;
48     submitting: boolean;
49     invalid: boolean;
50     pristine: boolean;
51 }
52
53 interface TextFieldProps {
54     label: string;
55     floatinglabeltext: string;
56     className?: string;
57     input?: string;
58     meta?: any;
59 }
60
61 export const DialogCollectionCreate = compose(
62     reduxForm({ form: 'collectionCreateDialog' }),
63     withStyles(styles))(
64     class DialogCollectionCreate extends React.Component<DialogCollectionCreateProps & WithStyles<CssRules>> {
65         render() {
66             const { classes, open, handleClose, handleSubmit, onSubmit, submitting, invalid, pristine } = this.props;
67
68             return (
69                 <Dialog
70                     open={open}
71                     onClose={handleClose}
72                     fullWidth={true}
73                     maxWidth='sm'
74                     disableBackdropClick={true}
75                     disableEscapeKeyDown={true}>
76                     <form onSubmit={handleSubmit((data: any) => onSubmit(data))}>
77                         <DialogTitle id="form-dialog-title">Create a collection</DialogTitle>
78                         <DialogContent className={classes.formContainer}>
79                             <Field name="name"
80                                     disabled={submitting}
81                                     component={this.renderTextField}
82                                     floatinglabeltext="Collection Name"
83                                     validate={COLLECTION_NAME_VALIDATION}
84                                     className={classes.textField}
85                                     label="Collection Name"/>
86                             <Field name="description"
87                                     disabled={submitting}
88                                     component={this.renderTextField}
89                                     floatinglabeltext="Description - optional"
90                                     validate={COLLECTION_DESCRIPTION_VALIDATION}
91                                     className={classes.textField}
92                                     label="Description - optional"/>
93                         </DialogContent>
94                         <DialogActions className={classes.dialogActions}>
95                             <Button onClick={handleClose} className={classes.button} color="primary"
96                                     disabled={submitting}>CANCEL</Button>
97                             <Button type="submit"
98                                     className={classes.lastButton}
99                                     color="primary"
100                                     disabled={invalid || submitting || pristine}
101                                     variant="contained">
102                                 CREATE A COLLECTION
103                             </Button>
104                             {submitting && <CircularProgress size={20} className={classes.createProgress}/>}
105                         </DialogActions>
106                     </form>
107                 </Dialog>
108             );
109         }
110
111         renderTextField = ({ input, label, meta: { touched, error }, ...custom }: TextFieldProps) => (
112             <TextField
113                 helperText={touched && error}
114                 label={label}
115                 className={this.props.classes.textField}
116                 error={touched && !!error}
117                 autoComplete='off'
118                 {...input}
119                 {...custom}
120             />
121         )
122     }
123 );