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