Fix filtering bugs

Summary: Doc: https://docs.google.com/document/d/1miofxds9DJgWScj0zFyBbdpRH5Rj0T9FqiCapof5-vU/edit#heading=h.pg8svtdjlx7

Reviewed By: antonk52

Differential Revision: D49411941

fbshipit-source-id: 530b0abcbba57e2503da4641d17fd1a507955b45
This commit is contained in:
Andrey Goncharov
2023-09-19 08:19:25 -07:00
committed by Facebook GitHub Bot
parent 6f38ecfd01
commit f6ffbfe3e2
5 changed files with 29 additions and 19 deletions

View File

@@ -14,12 +14,14 @@ type PowerSearchEnumSetTermProps = {
onCancel: () => void; onCancel: () => void;
onChange: (value: string[]) => void; onChange: (value: string[]) => void;
enumLabels: {[key: string]: string}; enumLabels: {[key: string]: string};
defaultValue?: string[];
}; };
export const PowerSearchEnumSetTerm: React.FC<PowerSearchEnumSetTermProps> = ({ export const PowerSearchEnumSetTerm: React.FC<PowerSearchEnumSetTermProps> = ({
onCancel, onCancel,
onChange, onChange,
enumLabels, enumLabels,
defaultValue,
}) => { }) => {
const options = React.useMemo(() => { const options = React.useMemo(() => {
return Object.entries(enumLabels).map(([key, label]) => ({ return Object.entries(enumLabels).map(([key, label]) => ({
@@ -29,15 +31,19 @@ export const PowerSearchEnumSetTerm: React.FC<PowerSearchEnumSetTermProps> = ({
}, [enumLabels]); }, [enumLabels]);
const selectValueRef = React.useRef<string[]>(); const selectValueRef = React.useRef<string[]>();
if (defaultValue && !selectValueRef.current) {
selectValueRef.current = defaultValue;
}
return ( return (
<Select <Select
mode="multiple" mode="multiple"
autoFocus autoFocus={!defaultValue}
style={{minWidth: 100}} style={{minWidth: 100}}
placeholder="..." placeholder="..."
options={options} options={options}
defaultOpen defaultOpen={!defaultValue}
defaultValue={defaultValue}
onBlur={() => { onBlur={() => {
if (!selectValueRef.current?.length) { if (!selectValueRef.current?.length) {
onCancel(); onCancel();

View File

@@ -13,19 +13,24 @@ import React from 'react';
type PowerSearchStringSetTermProps = { type PowerSearchStringSetTermProps = {
onCancel: () => void; onCancel: () => void;
onChange: (value: string[]) => void; onChange: (value: string[]) => void;
defaultValue?: string[];
}; };
export const PowerSearchStringSetTerm: React.FC< export const PowerSearchStringSetTerm: React.FC<
PowerSearchStringSetTermProps PowerSearchStringSetTermProps
> = ({onCancel, onChange}) => { > = ({onCancel, onChange, defaultValue}) => {
const selectValueRef = React.useRef<string[]>(); const selectValueRef = React.useRef<string[]>();
if (defaultValue && !selectValueRef.current) {
selectValueRef.current = defaultValue;
}
return ( return (
<Select <Select
mode="tags" mode="tags"
autoFocus autoFocus={!defaultValue}
style={{minWidth: 100}} style={{minWidth: 100}}
placeholder="..." placeholder="..."
defaultValue={defaultValue}
onBlur={() => { onBlur={() => {
if (!selectValueRef.current?.length) { if (!selectValueRef.current?.length) {
onCancel(); onCancel();

View File

@@ -33,19 +33,19 @@ export type SearchExpressionTerm = Required<IncompleteSearchExpressionTerm>;
type PowerSearchTermProps = { type PowerSearchTermProps = {
searchTerm: IncompleteSearchExpressionTerm; searchTerm: IncompleteSearchExpressionTerm;
searchValueRenderer: 'input' | 'button';
onCancel: () => void; onCancel: () => void;
onFinalize: (completeSearchTerm: SearchExpressionTerm) => void; onFinalize: (completeSearchTerm: SearchExpressionTerm) => void;
}; };
export const PowerSearchTerm: React.FC<PowerSearchTermProps> = ({ export const PowerSearchTerm: React.FC<PowerSearchTermProps> = ({
searchTerm, searchTerm,
searchValueRenderer,
onCancel, onCancel,
onFinalize, onFinalize,
}) => { }) => {
const hasValue = searchTerm.searchValue != null;
let searchValueComponent: React.ReactNode = null; let searchValueComponent: React.ReactNode = null;
if (searchValueRenderer === 'input') { if (!hasValue) {
switch (searchTerm.operator.valueType) { switch (searchTerm.operator.valueType) {
case 'STRING': { case 'STRING': {
searchValueComponent = ( searchValueComponent = (
@@ -183,6 +183,7 @@ export const PowerSearchTerm: React.FC<PowerSearchTermProps> = ({
}); });
}} }}
enumLabels={searchTerm.operator.enumLabels} enumLabels={searchTerm.operator.enumLabels}
defaultValue={searchTerm.searchValue}
/> />
); );
break; break;
@@ -197,6 +198,7 @@ export const PowerSearchTerm: React.FC<PowerSearchTermProps> = ({
searchValue: newValue, searchValue: newValue,
}); });
}} }}
defaultValue={searchTerm.searchValue}
/> />
); );
break; break;

View File

@@ -84,17 +84,14 @@ export const PowerSearch: React.FC<PowerSearchProps> = ({
return groupedOptions; return groupedOptions;
}, [config.fields]); }, [config.fields]);
const lastSearchTermHasSearchValue =
searchExpression.length > 0
? searchExpression[searchExpression.length - 1].searchValue !== undefined
: false;
const searchTermFinderRef = React.useRef<{ const searchTermFinderRef = React.useRef<{
focus: () => void; focus: () => void;
blur: () => void; blur: () => void;
scrollTo: () => void; scrollTo: () => void;
}>(null); }>(null);
console.log('searchExpression', searchExpression);
return ( return (
<PowerSearchContainer> <PowerSearchContainer>
<Space size={[theme.space.tiny, 0]}> <Space size={[theme.space.tiny, 0]}>
@@ -106,15 +103,10 @@ export const PowerSearch: React.FC<PowerSearchProps> = ({
}} }}
/> />
{searchExpression.map((searchTerm, i) => { {searchExpression.map((searchTerm, i) => {
const isLastTerm = i === searchExpression.length - 1;
return ( return (
<PowerSearchTerm <PowerSearchTerm
key={i.toString()} key={i.toString()}
searchTerm={searchTerm} searchTerm={searchTerm}
searchValueRenderer={
lastSearchTermHasSearchValue || !isLastTerm ? 'button' : 'input'
}
onCancel={() => { onCancel={() => {
setSearchExpression((prevSearchExpression) => { setSearchExpression((prevSearchExpression) => {
if (prevSearchExpression[i]) { if (prevSearchExpression[i]) {

View File

@@ -339,6 +339,11 @@ export function createInitialState<T>(
}); });
} }
let searchExpression = config.initialSearchExpression;
if (prefs?.searchExpression?.length) {
searchExpression = prefs.searchExpression;
}
const res: DataManagerState<T> = { const res: DataManagerState<T> = {
config, config,
storageKey, storageKey,
@@ -352,7 +357,7 @@ export function createInitialState<T>(
items: new Set(prefs!.selection.items), items: new Set(prefs!.selection.items),
} }
: emptySelection, : emptySelection,
searchExpression: prefs?.searchExpression ?? config.initialSearchExpression, searchExpression,
filterExceptions: undefined, filterExceptions: undefined,
autoScroll: prefs?.autoScroll ?? config.autoScroll ?? false, autoScroll: prefs?.autoScroll ?? config.autoScroll ?? false,
sideBySide: false, sideBySide: false,
@@ -473,7 +478,7 @@ export function computeDataTableFilter(
if (!searchExpression || !searchExpression.length) { if (!searchExpression || !searchExpression.length) {
return true; return true;
} }
return searchExpression.some((searchTerm) => { return searchExpression.every((searchTerm) => {
const value = getValueAtPath(item, searchTerm.field.key); const value = getValueAtPath(item, searchTerm.field.key);
if (!value) { if (!value) {
console.warn( console.warn(