Add typescript paths to top level folders
[arvados-workbench2.git] / src / views-components / dialog-update / dialog-collection-update.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 { ArvadosTheme } from '~/common/custom-theme';
9 import { Dialog, DialogActions, DialogContent, DialogTitle, TextField, StyleRulesCallback, withStyles, WithStyles, Button, CircularProgress } from '@material-ui/core';
10 import { COLLECTION_NAME_VALIDATION, COLLECTION_DESCRIPTION_VALIDATION } from '~/validators/create-collection/create-collection-validator';
11 import { COLLECTION_FORM_NAME } from '~/store/collections/updater/collection-updater-action';
12
13 type CssRules = 'content' | 'actions' | 'textField' | 'buttonWrapper' | 'saveButton' | 'circularProgress';
14
15 const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
16     content: {
17         display: 'flex',
18         flexDirection: 'column'
19     },
20     actions: {
21         margin: 0,
22         padding: `${theme.spacing.unit}px ${theme.spacing.unit * 3 - theme.spacing.unit / 2}px 
23                 ${theme.spacing.unit * 3}px ${theme.spacing.unit * 3}px`
24     },
25     textField: {
26         marginBottom: theme.spacing.unit * 3
27     },
28     buttonWrapper: {
29         position: 'relative'
30     },
31     saveButton: {
32         boxShadow: 'none'
33     },
34     circularProgress: {
35         position: 'absolute',
36         top: 0,
37         bottom: 0,
38         left: 0,
39         right: 0,
40         margin: 'auto'
41     }
42 });
43
44 interface DialogCollectionDataProps {
45     open: boolean;
46     handleSubmit: any;
47     submitting: boolean;
48     invalid: boolean;
49     pristine: boolean;
50 }
51
52 interface DialogCollectionAction {
53     handleClose: () => void;
54     onSubmit: (data: { name: string, description: string }) => void;
55 }
56
57 type DialogCollectionProps = DialogCollectionDataProps & DialogCollectionAction & WithStyles<CssRules>;
58
59 interface TextFieldProps {
60     label: string;
61     floatinglabeltext: string;
62     className?: string;
63     input?: string;
64     meta?: any;
65 }
66
67 export const DialogCollectionUpdate = compose(
68     reduxForm({ form: COLLECTION_FORM_NAME }),
69     withStyles(styles))(
70
71         class DialogCollectionUpdate extends React.Component<DialogCollectionProps> {
72
73             render() {
74                 const { classes, open, handleClose, handleSubmit, onSubmit, submitting, invalid, pristine } = this.props;
75                 return (
76                     <Dialog open={open}
77                         onClose={handleClose}
78                         fullWidth={true}
79                         maxWidth='sm'
80                         disableBackdropClick={true}
81                         disableEscapeKeyDown={true}>
82
83                         <form onSubmit={handleSubmit((data: any) => onSubmit(data))}>
84                             <DialogTitle>Edit Collection</DialogTitle>
85                             <DialogContent className={classes.content}>
86                                 <Field name="name"
87                                     disabled={submitting}
88                                     component={this.renderTextField}
89                                     floatinglabeltext="Collection Name"
90                                     validate={COLLECTION_NAME_VALIDATION}
91                                     className={classes.textField}
92                                     label="Collection Name" />
93                                 <Field name="description"
94                                     disabled={submitting}
95                                     component={this.renderTextField}
96                                     floatinglabeltext="Description - optional"
97                                     validate={COLLECTION_DESCRIPTION_VALIDATION}
98                                     className={classes.textField}
99                                     label="Description - optional" />
100                             </DialogContent>
101                             <DialogActions className={classes.actions}>
102                                 <Button onClick={handleClose} color="primary"
103                                     disabled={submitting}>CANCEL</Button>
104                                 <div className={classes.buttonWrapper}>
105                                     <Button type="submit" className={classes.saveButton}
106                                         color="primary"
107                                         disabled={invalid || submitting || pristine}
108                                         variant="contained">
109                                         SAVE
110                                     </Button>
111                                     {submitting && <CircularProgress size={20} className={classes.circularProgress} />}
112                                 </div>
113                             </DialogActions>
114                         </form>
115                     </Dialog>
116                 );
117             }
118
119             renderTextField = ({ input, label, meta: { touched, error }, ...custom }: TextFieldProps) => (
120                 <TextField
121                     helperText={touched && error}
122                     label={label}
123                     className={this.props.classes.textField}
124                     error={touched && !!error}
125                     autoComplete='off'
126                     {...input}
127                     {...custom}
128                 />
129             )
130         }
131     );