Add typescript paths to top level folders
[arvados-workbench2.git] / src / views / collection-panel / collection-tag-form.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, reset } from 'redux-form';
7 import { compose, Dispatch } from 'redux';
8 import { ArvadosTheme } from '~/common/custom-theme';
9 import { StyleRulesCallback, withStyles, WithStyles, TextField, Button, CircularProgress } from '@material-ui/core';
10 import { TagProperty } from '~/models/tag';
11 import { createCollectionTag, COLLECTION_TAG_FORM_NAME } from '~/store/collection-panel/collection-panel-action';
12 import { TAG_VALUE_VALIDATION, TAG_KEY_VALIDATION } from '~/validators/validators';
13
14 type CssRules = 'form' | 'textField' | 'buttonWrapper' | 'saveButton' | 'circularProgress';
15
16 const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
17     form: {
18         marginBottom: theme.spacing.unit * 4
19     },
20     textField: {
21         marginRight: theme.spacing.unit
22     },
23     buttonWrapper: {
24         position: 'relative',
25         display: 'inline-block'
26     },
27     saveButton: {
28         boxShadow: 'none'
29     },
30     circularProgress: {
31         position: 'absolute',
32         top: 0,
33         bottom: 0,
34         left: 0,
35         right: 0,
36         margin: 'auto'
37     }
38 });
39
40 interface CollectionTagFormDataProps {
41     submitting: boolean;
42     invalid: boolean;
43     pristine: boolean;
44 }
45
46 interface CollectionTagFormActionProps {
47     handleSubmit: any;
48 }
49
50 interface TextFieldProps {
51     label: string;
52     floatinglabeltext: string;
53     className?: string;
54     input?: string;
55     meta?: any;
56 }
57
58 type CollectionTagFormProps = CollectionTagFormDataProps & CollectionTagFormActionProps & WithStyles<CssRules>;
59
60 export const CollectionTagForm = compose(
61     reduxForm({
62         form: COLLECTION_TAG_FORM_NAME,
63         onSubmit: (data: TagProperty, dispatch: Dispatch) => {
64             dispatch<any>(createCollectionTag(data));
65             dispatch(reset(COLLECTION_TAG_FORM_NAME));
66         }
67     }),
68     withStyles(styles))(
69
70     class CollectionTagForm extends React.Component<CollectionTagFormProps> {
71
72             render() {
73                 const { classes, submitting, pristine, invalid, handleSubmit } = this.props;
74                 return (
75                     <form className={classes.form} onSubmit={handleSubmit}>
76                         <Field name="key"
77                             disabled={submitting}
78                             component={this.renderTextField}
79                             floatinglabeltext="Key"
80                             validate={TAG_KEY_VALIDATION}
81                             className={classes.textField}
82                             label="Key" />
83                         <Field name="value"
84                             disabled={submitting}
85                             component={this.renderTextField}
86                             floatinglabeltext="Value"
87                             validate={TAG_VALUE_VALIDATION}
88                             className={classes.textField}
89                             label="Value" />
90                         <div className={classes.buttonWrapper}>
91                             <Button type="submit" className={classes.saveButton}
92                                 color="primary"
93                                 size='small'
94                                 disabled={invalid || submitting || pristine}
95                                 variant="contained">
96                                 ADD
97                             </Button>
98                             {submitting && <CircularProgress size={20} className={classes.circularProgress} />}
99                         </div>
100                     </form>
101                 );
102             }
103
104             renderTextField = ({ input, label, meta: { touched, error }, ...custom }: TextFieldProps) => (
105                 <TextField
106                     helperText={touched && error}
107                     label={label}
108                     className={this.props.classes.textField}
109                     error={touched && !!error}
110                     autoComplete='off'
111                     {...input}
112                     {...custom}
113                 />
114             )
115
116         }
117
118     );