refs #14280 Merge branch 'origin/14280-query-language'
[arvados-workbench2.git] / src / views-components / search-bar / search-bar-advanced-properties-view.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 { Dispatch } from 'redux';
7 import { connect } from 'react-redux';
8 import { InjectedFormProps, formValueSelector } from 'redux-form';
9 import { Grid, withStyles, StyleRulesCallback, WithStyles, Button } from '@material-ui/core';
10 import { RootState } from '~/store/store';
11 import {
12     SEARCH_BAR_ADVANCE_FORM_NAME,
13     changeAdvanceFormProperty,
14     updateAdvanceFormProperties
15 } from '~/store/search-bar/search-bar-actions';
16 import { PropertyValue } from '~/models/search-bar';
17 import { ArvadosTheme } from '~/common/custom-theme';
18 import { SearchBarKeyField, SearchBarValueField } from '~/views-components/form-fields/search-bar-form-fields';
19 import { Chips } from '~/components/chips/chips';
20 import { formatPropertyValue } from "~/common/formatters";
21
22 type CssRules = 'label' | 'button';
23
24 const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
25     label: {
26         color: theme.palette.grey["500"],
27         fontSize: '0.8125rem',
28         alignSelf: 'center'
29     },
30     button: {
31         boxShadow: 'none'
32     }
33 });
34
35 interface SearchBarAdvancedPropertiesViewDataProps {
36     submitting: boolean;
37     invalid: boolean;
38     pristine: boolean;
39     propertyValues: PropertyValue;
40     fields: PropertyValue[];
41 }
42
43 interface SearchBarAdvancedPropertiesViewActionProps {
44     setProps: () => void;
45     addProp: (propertyValues: PropertyValue) => void;
46     getAllFields: (propertyValues: PropertyValue[]) => PropertyValue[] | [];
47 }
48
49 type SearchBarAdvancedPropertiesViewProps = SearchBarAdvancedPropertiesViewDataProps
50     & SearchBarAdvancedPropertiesViewActionProps
51     & InjectedFormProps & WithStyles<CssRules>;
52
53 const selector = formValueSelector(SEARCH_BAR_ADVANCE_FORM_NAME);
54 const mapStateToProps = (state: RootState) => {
55     return {
56         propertyValues: selector(state, 'key', 'value')
57     };
58 };
59
60 const mapDispatchToProps = (dispatch: Dispatch) => ({
61     setProps: (propertyValues: PropertyValue[]) => {
62         dispatch<any>(changeAdvanceFormProperty('properties', propertyValues));
63     },
64     addProp: (propertyValues: PropertyValue) => {
65         dispatch<any>(updateAdvanceFormProperties(propertyValues));
66         dispatch<any>(changeAdvanceFormProperty('key'));
67         dispatch<any>(changeAdvanceFormProperty('value'));
68     },
69     getAllFields: (fields: any) => {
70         return fields.getAll() || [];
71     }
72 });
73
74 export const SearchBarAdvancedPropertiesView = connect(mapStateToProps, mapDispatchToProps)(
75     withStyles(styles)(
76         ({ classes, fields, propertyValues, setProps, addProp, getAllFields }: SearchBarAdvancedPropertiesViewProps) =>
77             <Grid container item xs={12} spacing={16}>
78                 <Grid item xs={2} className={classes.label}>Properties</Grid>
79                 <Grid item xs={4}>
80                     <SearchBarKeyField />
81                 </Grid>
82                 <Grid item xs={4}>
83                     <SearchBarValueField />
84                 </Grid>
85                 <Grid container item xs={2} justify='flex-end' alignItems="center">
86                     <Button className={classes.button} onClick={() => addProp(propertyValues)}
87                         color="primary"
88                         size='small'
89                         variant="contained"
90                         disabled={!Boolean(propertyValues.key && propertyValues.value)}>
91                         Add
92                     </Button>
93                 </Grid>
94                 <Grid item xs={2} />
95                 <Grid container item xs={10} spacing={8}>
96                     <Chips values={getAllFields(fields)}
97                         deletable
98                         onChange={setProps}
99                         getLabel={(field: PropertyValue) => formatPropertyValue(field)} />
100                 </Grid>
101             </Grid>
102     )
103 );