17782: Fixes absolute import paths from '~/somedir/...' to 'somedir/...'
[arvados-workbench2.git] / src / views-components / search-bar / search-bar-advanced-properties-view.tsx
index 5e2acb7584930726408343daadda68daf0427dd0..11ed14cb8a36f9273e61f3e427bb8b9ff0bb4d0c 100644 (file)
@@ -3,27 +3,28 @@
 // SPDX-License-Identifier: AGPL-3.0
 
 import * as React from 'react';
-import { Dispatch } from 'redux';
+import { Dispatch, compose } from 'redux';
 import { connect } from 'react-redux';
 import { InjectedFormProps, formValueSelector } from 'redux-form';
 import { Grid, withStyles, StyleRulesCallback, WithStyles, Button } from '@material-ui/core';
-import { RootState } from '~/store/store';
-import { 
-    SEARCH_BAR_ADVANCE_FORM_NAME, 
-    changeAdvanceFormProperty, 
-    updateAdvanceFormProperties 
-} from '~/store/search-bar/search-bar-actions';
-import { PropertyValues } from '~/models/search-bar';
-import { ArvadosTheme } from '~/common/custom-theme';
-import { SearchBarKeyField, SearchBarValueField } from '~/views-components/form-fields/search-bar-form-fields';
-import { Chips } from '~/components/chips/chips';
+import { RootState } from 'store/store';
+import {
+    SEARCH_BAR_ADVANCED_FORM_NAME,
+    changeAdvancedFormProperty,
+    resetAdvancedFormProperty
+} from 'store/search-bar/search-bar-actions';
+import { PropertyValue } from 'models/search-bar';
+import { ArvadosTheme } from 'common/custom-theme';
+import { SearchBarKeyField, SearchBarValueField } from 'views-components/form-fields/search-bar-form-fields';
+import { Chips } from 'components/chips/chips';
+import { formatPropertyValue } from "common/formatters";
+import { Vocabulary } from 'models/vocabulary';
+import { connectVocabulary } from '../resource-properties-form/property-field-common';
+import * as _ from 'lodash';
 
-type CssRules = 'root' | 'label' | 'button';
+type CssRules = 'label' | 'button';
 
 const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
-    root: {
-
-    },
     label: {
         color: theme.palette.grey["500"],
         fontSize: '0.8125rem',
@@ -38,46 +39,61 @@ interface SearchBarAdvancedPropertiesViewDataProps {
     submitting: boolean;
     invalid: boolean;
     pristine: boolean;
-    propertyValues: PropertyValues;
-    fields: PropertyValues[];
+    propertyValues: PropertyValue;
+    fields: PropertyValue[];
+    vocabulary: Vocabulary;
 }
 
 interface SearchBarAdvancedPropertiesViewActionProps {
     setProps: () => void;
-    addProp: (propertyValues: PropertyValues) => void;
-    getAllFields: (propertyValues: PropertyValues[]) => PropertyValues[] | [];
+    addProp: (propertyValues: PropertyValue, properties: PropertyValue[]) => void;
+    getAllFields: (propertyValues: PropertyValue[]) => PropertyValue[] | [];
 }
 
-type SearchBarAdvancedPropertiesViewProps = SearchBarAdvancedPropertiesViewDataProps 
-    & SearchBarAdvancedPropertiesViewActionProps 
+type SearchBarAdvancedPropertiesViewProps = SearchBarAdvancedPropertiesViewDataProps
+    & SearchBarAdvancedPropertiesViewActionProps
     & InjectedFormProps & WithStyles<CssRules>;
 
-const selector = formValueSelector(SEARCH_BAR_ADVANCE_FORM_NAME);
+const selector = formValueSelector(SEARCH_BAR_ADVANCED_FORM_NAME);
 const mapStateToProps = (state: RootState) => {
     return {
-        propertyValues: selector(state, 'propertyKey', 'propertyValue')
+        propertyValues: selector(state, 'key', 'value', 'keyID', 'valueID')
     };
 };
 
 const mapDispatchToProps = (dispatch: Dispatch) => ({
-    setProps: (propertyValues: PropertyValues[]) => {
-        dispatch<any>(changeAdvanceFormProperty('properties', propertyValues));
+    setProps: (propertyValues: PropertyValue[]) => {
+        dispatch<any>(changeAdvancedFormProperty('properties', propertyValues));
     },
-    addProp: (propertyValues: PropertyValues) => {
-        dispatch<any>(updateAdvanceFormProperties(propertyValues));
-        dispatch<any>(changeAdvanceFormProperty('propertyKey'));
-        dispatch<any>(changeAdvanceFormProperty('propertyValue'));
+    addProp: (propertyValue: PropertyValue, properties: PropertyValue[]) => {
+        // Remove potential duplicates
+        properties = properties.filter(x => ! _.isEqual(
+            {
+                key: x.keyID || x.key,
+                value: x.valueID || x.value
+            }, {
+                key: propertyValue.keyID || propertyValue.key,
+                value: propertyValue.valueID || propertyValue.value
+            }));
+        dispatch<any>(changeAdvancedFormProperty(
+            'properties',
+            [...properties, propertyValue]
+        ));
+        dispatch<any>(resetAdvancedFormProperty('key'));
+        dispatch<any>(resetAdvancedFormProperty('value'));
+        dispatch<any>(resetAdvancedFormProperty('keyID'));
+        dispatch<any>(resetAdvancedFormProperty('valueID'));
     },
     getAllFields: (fields: any) => {
         return fields.getAll() || [];
     }
 });
 
-export const SearchBarAdvancedPropertiesView = 
-    connect(mapStateToProps, mapDispatchToProps)
-
-    (withStyles(styles)(
-        ({ classes, fields, propertyValues, setProps, addProp, getAllFields }: SearchBarAdvancedPropertiesViewProps) =>
+export const SearchBarAdvancedPropertiesView = compose(
+    connectVocabulary,
+    connect(mapStateToProps, mapDispatchToProps))(
+    withStyles(styles)(
+        ({ classes, fields, propertyValues, setProps, addProp, getAllFields, vocabulary }: SearchBarAdvancedPropertiesViewProps) =>
             <Grid container item xs={12} spacing={16}>
                 <Grid item xs={2} className={classes.label}>Properties</Grid>
                 <Grid item xs={4}>
@@ -87,20 +103,21 @@ export const SearchBarAdvancedPropertiesView =
                     <SearchBarValueField />
                 </Grid>
                 <Grid container item xs={2} justify='flex-end' alignItems="center">
-                    <Button className={classes.button} onClick={() => addProp(propertyValues)}
+                    <Button className={classes.button} onClick={() => addProp(propertyValues, getAllFields(fields))}
                         color="primary"
                         size='small'
-                        variant="contained">
+                        variant="contained"
+                        disabled={!Boolean(propertyValues.key && propertyValues.value)}>
                         Add
                     </Button>
                 </Grid>
                 <Grid item xs={2} />
                 <Grid container item xs={10} spacing={8}>
-                    <Chips values={getAllFields(fields)} 
+                    <Chips values={getAllFields(fields)}
                         deletable
-                        onChange={setProps} 
-                        getLabel={(field: PropertyValues) => `${field.propertyKey}: ${field.propertyValue}`} />
+                        onChange={setProps}
+                        getLabel={(field: PropertyValue) => formatPropertyValue(field, vocabulary)} />
                 </Grid>
             </Grid>
     )
-);
\ No newline at end of file
+);