Extract PowerSearchTerm

Summary: Project doc: https://docs.google.com/document/d/1miofxds9DJgWScj0zFyBbdpRH5Rj0T9FqiCapof5-vU

Reviewed By: lblasa

Differential Revision: D48599166

fbshipit-source-id: 13b447b55408a8673928489312c4d22cf864c232
This commit is contained in:
Andrey Goncharov
2023-08-30 07:26:35 -07:00
committed by Facebook GitHub Bot
parent 2c5bcb373d
commit c9ab951e84
4 changed files with 105 additions and 70 deletions

View File

@@ -7,7 +7,7 @@
* @format * @format
*/ */
import {OperatorConfig, PowerSearchConfig} from './PowerSearchTypes'; import {OperatorConfig, PowerSearchConfig} from './PowerSearchConfig';
const MyStatusEnum = { const MyStatusEnum = {
NEEDS_REVIEW: 'Needs review', NEEDS_REVIEW: 'Needs review',

View File

@@ -0,0 +1,74 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
import {CloseOutlined} from '@ant-design/icons';
import {Button, Input, Space} from 'antd';
import * as React from 'react';
import {FieldConfig, OperatorConfig} from './PowerSearchConfig';
export type SearchExpressionTerm = {
field: FieldConfig;
operator: OperatorConfig;
searchValue?: string;
};
type PowerSearchTermProps = {
searchTerm: SearchExpressionTerm;
searchValueRenderer: 'input' | 'button';
onCancel: () => void;
onFinalize: (completeSearchTerm: Required<SearchExpressionTerm>) => void;
};
export const PowerSearchTerm: React.FC<PowerSearchTermProps> = ({
searchTerm,
searchValueRenderer,
onCancel,
onFinalize,
}) => {
return (
<Space.Compact block size="small">
<Button>{searchTerm.field.label}</Button>
<Button>{searchTerm.operator.label}</Button>
{searchValueRenderer === 'button' ? (
<Button>{searchTerm.searchValue ?? '...'}</Button>
) : (
// TODO: Fix width
<Input
autoFocus
style={{width: 100}}
placeholder="..."
onBlur={(event) => {
const newValue = event.target.value;
if (!newValue) {
onCancel();
return;
}
onFinalize({
...searchTerm,
searchValue: newValue,
});
}}
onKeyDown={(event) => {
if (event.key === 'Enter' || event.key === 'Escape') {
event.currentTarget.blur();
}
}}
/>
)}
<Button
icon={<CloseOutlined />}
onClick={() => {
onCancel();
}}
/>
</Space.Compact>
);
};

View File

@@ -8,14 +8,10 @@
*/ */
import * as React from 'react'; import * as React from 'react';
import {AutoComplete, Button, Input, Space} from 'antd'; import {AutoComplete, Space} from 'antd';
import { import {PowerSearchConfig} from './PowerSearchConfig';
PowerSearchConfig,
FieldConfig,
OperatorConfig,
} from './PowerSearchTypes';
import {CloseOutlined} from '@ant-design/icons';
import {PowerSearchContainer} from './PowerSearchContainer'; import {PowerSearchContainer} from './PowerSearchContainer';
import {PowerSearchTerm, SearchExpressionTerm} from './PowerSearchTerm';
export {PowerSearchConfig}; export {PowerSearchConfig};
@@ -32,12 +28,6 @@ type AutocompleteOptionGroup = {
const OPTION_KEY_DELIMITER = '::'; const OPTION_KEY_DELIMITER = '::';
type SearchExpressionTerm = {
field: FieldConfig;
operator: OperatorConfig;
searchValue?: string;
};
export const PowerSearch: React.FC<PowerSearchProps> = ({config}) => { export const PowerSearch: React.FC<PowerSearchProps> = ({config}) => {
const [searchExpression, setSearchExpression] = React.useState< const [searchExpression, setSearchExpression] = React.useState<
SearchExpressionTerm[] SearchExpressionTerm[]
@@ -88,62 +78,33 @@ export const PowerSearch: React.FC<PowerSearchProps> = ({config}) => {
const isLastTerm = i === searchExpression.length - 1; const isLastTerm = i === searchExpression.length - 1;
return ( return (
<Space.Compact block size="small" key={i.toString()}> <PowerSearchTerm
<Button>{searchTerm.field.label}</Button> key={i.toString()}
<Button>{searchTerm.operator.label}</Button> searchTerm={searchTerm}
{lastSearchTermHasSearchValue || !isLastTerm ? ( searchValueRenderer={
<Button>{searchTerm.searchValue ?? '...'}</Button> lastSearchTermHasSearchValue || !isLastTerm ? 'button' : 'input'
) : ( }
// TODO: Fix width onCancel={() => {
<Input setSearchExpression((prevSearchExpression) => {
autoFocus if (prevSearchExpression[i]) {
style={{width: 100}} return [
placeholder="..." ...prevSearchExpression.slice(0, i),
onBlur={(event) => { ...prevSearchExpression.slice(i + 1),
const newValue = event.target.value; ];
}
if (!newValue) { return prevSearchExpression;
setSearchExpression((prevSearchExpression) => { });
return prevSearchExpression.slice(0, -1); }}
}); onFinalize={(finalSearchTerm) => {
return; setSearchExpression((prevSearchExpression) => {
} return [
...prevSearchExpression.slice(0, -1),
setSearchExpression((prevSearchExpression) => { finalSearchTerm,
return [ ];
...prevSearchExpression.slice(0, -1), });
{ searchTermFinderRef.current?.focus();
...prevSearchExpression[ }}
prevSearchExpression.length - 1 />
],
searchValue: newValue,
},
];
});
searchTermFinderRef.current?.focus();
}}
onKeyDown={(event) => {
if (event.key === 'Enter' || event.key === 'Escape') {
event.currentTarget.blur();
}
}}
/>
)}
<Button
icon={<CloseOutlined />}
onClick={() => {
setSearchExpression((prevSearchExpression) => {
if (prevSearchExpression[i]) {
return [
...prevSearchExpression.slice(0, i),
...prevSearchExpression.slice(i + 1),
];
}
return prevSearchExpression;
});
}}
/>
</Space.Compact>
); );
})} })}
</Space> </Space>