feat: radio and select fields are filterable by options (#3136)

This commit is contained in:
Jarrod Flesch
2023-08-07 16:58:42 -04:00
committed by GitHub
parent fd0f078586
commit b117e73464
4 changed files with 107 additions and 2 deletions

View File

@@ -0,0 +1,81 @@
import React from 'react';
import { useTranslation } from 'react-i18next';
import ReactSelect from '../../../ReactSelect';
import { getTranslation } from '../../../../../../utilities/getTranslation';
import { Props } from './types';
import { Option, OptionObject } from '../../../../../../fields/config/types';
const formatOptions = (options: Option[]): OptionObject[] => options.map((option) => {
if (typeof option === 'object' && (option.value || option.value === '')) {
return option;
}
return {
label: option,
value: option,
} as OptionObject;
});
export const Select: React.FC<Props> = ({ onChange, value, options: optionsFromProps, operator }) => {
const { i18n } = useTranslation();
const [options, setOptions] = React.useState(formatOptions(optionsFromProps));
const isMulti = ['in', 'not_in'].includes(operator);
let valueToRender;
if (isMulti && Array.isArray(value)) {
valueToRender = value.map((val) => {
const matchingOption = options.find((option) => option.value === val);
return {
label: matchingOption ? getTranslation(matchingOption.label, i18n) : val,
value: matchingOption?.value ?? val,
};
});
} else if (value) {
const matchingOption = options.find((option) => option.value === value);
valueToRender = {
label: matchingOption ? getTranslation(matchingOption.label, i18n) : value,
value: matchingOption?.value ?? value,
};
}
const onSelect = React.useCallback((selectedOption) => {
let newValue;
if (!selectedOption) {
newValue = null;
} else if (isMulti) {
if (Array.isArray(selectedOption)) {
newValue = selectedOption.map((option) => option.value);
} else {
newValue = [];
}
} else {
newValue = selectedOption.value;
}
onChange(newValue);
}, [
isMulti,
onChange,
]);
React.useEffect(() => {
setOptions(formatOptions(optionsFromProps));
}, [optionsFromProps]);
React.useEffect(() => {
if (!isMulti && Array.isArray(value)) {
onChange(value[0]);
}
}, [isMulti, onChange, value]);
return (
<ReactSelect
onChange={onSelect}
value={valueToRender}
options={options.map((option) => ({ ...option, label: getTranslation(option.label, i18n) }))}
isMulti={isMulti}
/>
);
};

View File

@@ -0,0 +1,9 @@
import { Operator } from '../../../../../../types';
import { Option } from '../../../../../../fields/config/types';
export type Props = {
onChange: (val: string) => void,
value: string,
options: Option[]
operator: Operator
}

View File

@@ -7,6 +7,7 @@ import Date from './Date';
import Number from './Number';
import Text from './Text';
import Relationship from './Relationship';
import { Select } from './Select';
import useDebounce from '../../../../hooks/useDebounce';
import { FieldCondition } from '../types';
@@ -17,6 +18,7 @@ const valueFields = {
Number,
Text,
Relationship,
Select,
};
const baseClass = 'condition';
@@ -56,7 +58,15 @@ const Condition: React.FC<Props> = (props) => {
});
}, [debouncedValue, dispatch, orIndex, andIndex]);
const ValueComponent = valueFields[activeField?.component] || valueFields.Text;
const booleanSelect = ['exists'].includes(operatorValue) || activeField.props.type === 'checkbox';
const ValueComponent = booleanSelect ? Select : (valueFields[activeField?.component] || valueFields.Text);
let selectOptions;
if (booleanSelect) {
selectOptions = ['true', 'false'];
} else if ('options' in activeField?.props) {
selectOptions = activeField.props.options;
}
return (
<div className={baseClass}>
@@ -95,6 +105,7 @@ const Condition: React.FC<Props> = (props) => {
DefaultComponent={ValueComponent}
componentProps={{
...activeField?.props,
options: selectOptions,
operator: operatorValue,
value: internalValue,
onChange: setInternalValue,

View File

@@ -112,8 +112,12 @@ const fieldTypeConditions = {
component: 'Relationship',
operators: [...base],
},
radio: {
component: 'Select',
operators: [...base],
},
select: {
component: 'Text',
component: 'Select',
operators: [...base],
},
checkbox: {