feat: added blur event to having input in query section (#5684)

* feat: added blur event to having input in query section

* feat: added a error message for incomplete having clause and improved handleBlur

* feat: added focus event to remove error message

---------

Co-authored-by: Srikanth Chekuri <srikanth.chekuri92@gmail.com>
This commit is contained in:
rahulkeswani101 2024-09-26 16:12:49 +05:30 committed by GitHub
parent fc8391c5aa
commit 6e3141a4ce
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -1,3 +1,4 @@
import { Color } from '@signozhq/design-tokens';
import { Select } from 'antd'; import { Select } from 'antd';
import { ENTITY_VERSION_V4 } from 'constants/app'; import { ENTITY_VERSION_V4 } from 'constants/app';
// ** Constants // ** Constants
@ -34,6 +35,7 @@ export function HavingFilter({
const [currentFormValue, setCurrentFormValue] = useState<HavingForm>( const [currentFormValue, setCurrentFormValue] = useState<HavingForm>(
initialHavingValues, initialHavingValues,
); );
const [errorMessage, setErrorMessage] = useState<string | null>(null);
const { isMulti } = useTagValidation( const { isMulti } = useTagValidation(
currentFormValue.op, currentFormValue.op,
@ -198,6 +200,29 @@ export function HavingFilter({
resetChanges(); resetChanges();
}; };
const handleFocus = useCallback(() => {
setErrorMessage(null);
}, []);
const handleBlur = useCallback((): void => {
if (searchText) {
const { columnName, op, value } = getHavingObject(searchText);
const isCompleteHavingClause =
columnName && op && value.every((v) => v !== '');
if (isCompleteHavingClause && isValidHavingValue(searchText)) {
setLocalValues((prev) => {
const updatedValues = [...prev, searchText];
onChange(updatedValues.map(transformFromStringToHaving));
return updatedValues;
});
setSearchText('');
} else {
setErrorMessage('Invalid HAVING clause');
}
}
}, [searchText, onChange]);
useEffect(() => { useEffect(() => {
parseSearchText(searchText); parseSearchText(searchText);
}, [searchText, parseSearchText]); }, [searchText, parseSearchText]);
@ -209,28 +234,36 @@ export function HavingFilter({
const isMetricsDataSource = query.dataSource === DataSource.METRICS; const isMetricsDataSource = query.dataSource === DataSource.METRICS;
return ( return (
<Select <>
getPopupContainer={popupContainer} <Select
autoClearSearchValue={false} getPopupContainer={popupContainer}
mode="multiple" autoClearSearchValue={false}
onSearch={handleSearch} mode="multiple"
searchValue={searchText} onSearch={handleSearch}
tagRender={tagRender} searchValue={searchText}
value={localValues} tagRender={tagRender}
data-testid="havingSelect" value={localValues}
disabled={isMetricsDataSource && !query.aggregateAttribute.key} data-testid="havingSelect"
style={{ width: '100%' }} disabled={isMetricsDataSource && !query.aggregateAttribute.key}
notFoundContent={currentFormValue.value.length === 0 ? undefined : null} style={{ width: '100%' }}
placeholder="GroupBy(operation) > 5" notFoundContent={currentFormValue.value.length === 0 ? undefined : null}
onDeselect={handleDeselect} placeholder="GroupBy(operation) > 5"
onChange={handleChange} onDeselect={handleDeselect}
onSelect={handleSelect} onChange={handleChange}
> onSelect={handleSelect}
{options.map((opt) => ( onFocus={handleFocus}
<Select.Option key={opt.value} value={opt.value} title="havingOption"> onBlur={handleBlur}
{opt.label} status={errorMessage ? 'error' : undefined}
</Select.Option> >
))} {options.map((opt) => (
</Select> <Select.Option key={opt.value} value={opt.value} title="havingOption">
{opt.label}
</Select.Option>
))}
</Select>
{errorMessage && (
<div style={{ color: Color.BG_CHERRY_500 }}>{errorMessage}</div>
)}
</>
); );
} }