Merge branch '14258-collection-filtering'
[arvados.git] / src / views-components / project-properties-dialog / project-properties-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, Button, CircularProgress } from '@material-ui/core';
10 import { TagProperty } from '~/models/tag';
11 import { TextField } from '~/components/text-field/text-field';
12 import { TAG_VALUE_VALIDATION, TAG_KEY_VALIDATION } from '~/validators/validators';
13 import { PROJECT_PROPERTIES_FORM_NAME, createProjectProperty } from '~/store/details-panel/details-panel-action';
14
15 type CssRules = 'root' | 'keyField' | 'valueField' | 'buttonWrapper' | 'saveButton' | 'circularProgress';
16
17 const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
18     root: {
19         width: '100%',
20         display: 'flex'
21     },
22     keyField: {
23         width: '40%',
24         marginRight: theme.spacing.unit * 3
25     },
26     valueField: {
27         width: '40%',
28         marginRight: theme.spacing.unit * 3
29     },
30     buttonWrapper: {
31         paddingTop: '14px',
32         position: 'relative',
33     },
34     saveButton: {
35         boxShadow: 'none'
36     },
37     circularProgress: {
38         position: 'absolute',
39         top: -9,
40         bottom: 0,
41         left: 0,
42         right: 0,
43         margin: 'auto'
44     }
45 });
46
47 interface ProjectPropertiesFormDataProps {
48     submitting: boolean;
49     invalid: boolean;
50     pristine: boolean;
51 }
52
53 interface ProjectPropertiesFormActionProps {
54     handleSubmit: any;
55 }
56
57 type ProjectPropertiesFormProps = ProjectPropertiesFormDataProps & ProjectPropertiesFormActionProps & WithStyles<CssRules>;
58
59 export const ProjectPropertiesForm = compose(
60     reduxForm({
61         form: PROJECT_PROPERTIES_FORM_NAME,
62         onSubmit: (data: TagProperty, dispatch: Dispatch) => {
63             dispatch<any>(createProjectProperty(data));
64             dispatch(reset(PROJECT_PROPERTIES_FORM_NAME));
65         }
66     }),
67     withStyles(styles))(
68         ({ classes, submitting, pristine, invalid, handleSubmit }: ProjectPropertiesFormProps) => 
69             <form onSubmit={handleSubmit} className={classes.root}>
70                 <div className={classes.keyField}>
71                     <Field name="key"
72                         disabled={submitting}
73                         component={TextField}
74                         validate={TAG_KEY_VALIDATION}
75                         label="Key" />
76                 </div>
77                 <div className={classes.valueField}>
78                     <Field name="value"
79                         disabled={submitting}
80                         component={TextField}
81                         validate={TAG_VALUE_VALIDATION}
82                         label="Value" />
83                 </div>
84                 <div className={classes.buttonWrapper}>
85                     <Button type="submit" className={classes.saveButton}
86                         color="primary"
87                         size='small'
88                         disabled={invalid || submitting || pristine}
89                         variant="contained">
90                         ADD
91                     </Button>
92                     {submitting && <CircularProgress size={20} className={classes.circularProgress} />}
93                 </div>
94             </form>
95         );