mirror of
https://github.com/SigNoz/signoz.git
synced 2025-12-27 15:18:08 +00:00
fix: reset query in quick filters (#8528)
* fix: added fix for reset all * chore: added fix for empty query * fix: fixed value suggestion issues * chore: minor pr review changes * chore: pr review fixes * chore: cleanup for debouncedFetchValueSuggestions
This commit is contained in:
parent
e78ca467fc
commit
4da7d62b0c
@ -26,9 +26,9 @@ import {
|
||||
queryOperatorSuggestions,
|
||||
} from 'constants/antlrQueryConstants';
|
||||
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
|
||||
import { isNull } from 'lodash-es';
|
||||
import { debounce, isNull } from 'lodash-es';
|
||||
import { TriangleAlert } from 'lucide-react';
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import {
|
||||
IDetailedError,
|
||||
IQueryContext,
|
||||
@ -42,6 +42,7 @@ import {
|
||||
getCurrentValueIndexAtCursor,
|
||||
getQueryContextAtCursor,
|
||||
} from 'utils/queryContextUtils';
|
||||
import { unquote } from 'utils/stringUtils';
|
||||
|
||||
import { queryExamples } from './constants';
|
||||
|
||||
@ -109,7 +110,6 @@ function QuerySearch({
|
||||
|
||||
useEffect(() => {
|
||||
setQuery(queryData.filter?.expression || '');
|
||||
handleQueryValidation(queryData.filter?.expression || '');
|
||||
}, [queryData.filter?.expression]);
|
||||
|
||||
const [keySuggestions, setKeySuggestions] = useState<
|
||||
@ -400,6 +400,11 @@ function QuerySearch({
|
||||
[activeKey, dataSource, isLoadingSuggestions],
|
||||
);
|
||||
|
||||
const debouncedFetchValueSuggestions = useMemo(
|
||||
() => debounce(fetchValueSuggestions, 300),
|
||||
[fetchValueSuggestions],
|
||||
);
|
||||
|
||||
const handleUpdate = useCallback((viewUpdate: { view: EditorView }): void => {
|
||||
if (!isMountedRef.current) return;
|
||||
|
||||
@ -465,15 +470,18 @@ function QuerySearch({
|
||||
const handleBlur = (): void => {
|
||||
handleQueryValidation(query);
|
||||
setIsFocused(false);
|
||||
if (editorRef.current) {
|
||||
closeCompletion(editorRef.current);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (query) {
|
||||
handleQueryValidation(query);
|
||||
}
|
||||
|
||||
return (): void => {
|
||||
if (debouncedFetchValueSuggestions) {
|
||||
debouncedFetchValueSuggestions.cancel();
|
||||
}
|
||||
};
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
@ -656,27 +664,38 @@ function QuerySearch({
|
||||
return null;
|
||||
}
|
||||
|
||||
const searchText = word?.text.toLowerCase().trim() ?? '';
|
||||
let searchText = '';
|
||||
|
||||
if (
|
||||
queryContext.currentPair &&
|
||||
queryContext.currentPair.valuesPosition &&
|
||||
queryContext.currentPair.valueList
|
||||
) {
|
||||
const { valuesPosition, valueList } = queryContext.currentPair;
|
||||
const idx = getCurrentValueIndexAtCursor(valuesPosition, cursorPos.ch);
|
||||
searchText = isNull(idx)
|
||||
? ''
|
||||
: unquote(valueList[idx]).toLowerCase().trim();
|
||||
}
|
||||
|
||||
options = (valueSuggestions || []).filter((option) =>
|
||||
option.label.toLowerCase().includes(searchText),
|
||||
);
|
||||
|
||||
if (
|
||||
keyName &&
|
||||
((options.length === 0 &&
|
||||
(((options.length === 0 || searchText === '') &&
|
||||
(!isCompleteValuesList || lastValueRef.current !== searchText) &&
|
||||
!isFetchingCompleteValuesList) ||
|
||||
keyName !== activeKey ||
|
||||
isLoadingSuggestions) &&
|
||||
!(isLoadingSuggestions && lastKeyRef.current === keyName)
|
||||
) {
|
||||
setTimeout(() => {
|
||||
fetchValueSuggestions({
|
||||
key: keyName,
|
||||
searchText,
|
||||
fetchingComplete: true,
|
||||
});
|
||||
}, 300);
|
||||
debouncedFetchValueSuggestions({
|
||||
key: keyName,
|
||||
searchText,
|
||||
fetchingComplete: true,
|
||||
});
|
||||
}
|
||||
|
||||
// For values in bracket list, just add quotes without enclosing in brackets
|
||||
@ -846,7 +865,11 @@ function QuerySearch({
|
||||
if (!keyName) {
|
||||
return null;
|
||||
}
|
||||
const searchText = word?.text.toLowerCase().trim() ?? '';
|
||||
let searchText = '';
|
||||
|
||||
if (queryContext.currentPair && queryContext.currentPair.value) {
|
||||
searchText = unquote(queryContext.currentPair.value).toLowerCase().trim();
|
||||
}
|
||||
|
||||
options = (valueSuggestions || []).filter((option) =>
|
||||
option.label.toLowerCase().includes(searchText),
|
||||
@ -855,7 +878,7 @@ function QuerySearch({
|
||||
// Trigger fetch only if needed
|
||||
if (
|
||||
keyName &&
|
||||
((options.length === 0 &&
|
||||
(((options.length === 0 || searchText === '') &&
|
||||
(!isCompleteValuesList || lastValueRef.current !== searchText) &&
|
||||
!isFetchingCompleteValuesList) ||
|
||||
keyName !== activeKey ||
|
||||
@ -863,13 +886,11 @@ function QuerySearch({
|
||||
!(isLoadingSuggestions && lastKeyRef.current === keyName)
|
||||
) {
|
||||
// eslint-disable-next-line sonarjs/no-identical-functions
|
||||
setTimeout(() => {
|
||||
fetchValueSuggestions({
|
||||
key: keyName,
|
||||
searchText,
|
||||
fetchingComplete: true,
|
||||
});
|
||||
}, 300);
|
||||
debouncedFetchValueSuggestions({
|
||||
key: keyName,
|
||||
searchText,
|
||||
fetchingComplete: true,
|
||||
});
|
||||
}
|
||||
|
||||
// Process options to add appropriate formatting when selected
|
||||
@ -1018,22 +1039,6 @@ function QuerySearch({
|
||||
}
|
||||
}
|
||||
|
||||
// // If no specific context is detected, provide general suggestions
|
||||
// options = [
|
||||
// ...(keySuggestions || []),
|
||||
// { label: 'AND', type: 'conjunction', boost: -10 },
|
||||
// { label: 'OR', type: 'conjunction', boost: -10 },
|
||||
// { label: '(', type: 'parenthesis', info: 'Open group', boost: -20 },
|
||||
// ];
|
||||
|
||||
// // Add space after selection for general context
|
||||
// const optionsWithSpace = addSpaceToOptions(options);
|
||||
|
||||
// return {
|
||||
// from: word?.from ?? 0,
|
||||
// options: optionsWithSpace,
|
||||
// };
|
||||
|
||||
// Don't show anything if no context detected
|
||||
return {
|
||||
from: word?.from ?? 0,
|
||||
@ -1043,8 +1048,12 @@ function QuerySearch({
|
||||
|
||||
// Effect to handle focus state and trigger suggestions
|
||||
useEffect(() => {
|
||||
if (isFocused && editorRef.current) {
|
||||
startCompletion(editorRef.current);
|
||||
if (editorRef.current) {
|
||||
if (!isFocused) {
|
||||
closeCompletion(editorRef.current);
|
||||
} else {
|
||||
startCompletion(editorRef.current);
|
||||
}
|
||||
}
|
||||
}, [isFocused]);
|
||||
|
||||
@ -1174,9 +1183,6 @@ function QuerySearch({
|
||||
}}
|
||||
onFocus={(): void => {
|
||||
setIsFocused(true);
|
||||
if (editorRef.current) {
|
||||
startCompletion(editorRef.current);
|
||||
}
|
||||
}}
|
||||
onBlur={handleBlur}
|
||||
/>
|
||||
|
||||
@ -20,6 +20,7 @@ import {
|
||||
import { EQueryType } from 'types/common/dashboard';
|
||||
import { DataSource } from 'types/common/queryBuilder';
|
||||
import { extractQueryPairs } from 'utils/queryContextUtils';
|
||||
import { unquote } from 'utils/stringUtils';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
|
||||
/**
|
||||
@ -95,21 +96,6 @@ export const convertFiltersToExpression = (
|
||||
};
|
||||
};
|
||||
|
||||
function unquote(str: string): string {
|
||||
if (typeof str !== 'string') return str;
|
||||
|
||||
const startsWithQuote = str.startsWith('"') || str.startsWith("'");
|
||||
const endsWithSameQuote =
|
||||
(str.endsWith('"') && str[0] === '"') ||
|
||||
(str.endsWith("'") && str[0] === "'");
|
||||
|
||||
if (startsWithQuote && endsWithSameQuote && str.length >= 2) {
|
||||
return str.slice(1, -1);
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
const formatValuesForFilter = (value: string | string[]): string | string[] => {
|
||||
if (Array.isArray(value)) {
|
||||
return value.map((v) => (typeof v === 'string' ? unquote(v) : String(v)));
|
||||
@ -398,7 +384,7 @@ export const removeKeysFromExpression = (
|
||||
currentQueryPair.position.operatorEnd ??
|
||||
currentQueryPair.position.keyEnd;
|
||||
// Get the part of the expression that comes after the current query pair
|
||||
const expressionAfterPair = `${expression.slice(queryPairEnd + 1)}`;
|
||||
const expressionAfterPair = `${updatedExpression.slice(queryPairEnd + 1)}`;
|
||||
// Match optional spaces and an optional conjunction (AND/OR), case-insensitive
|
||||
const conjunctionOrSpacesRegex = /^(\s*((AND|OR)\s+)?)/i;
|
||||
const match = expressionAfterPair.match(conjunctionOrSpacesRegex);
|
||||
@ -407,10 +393,10 @@ export const removeKeysFromExpression = (
|
||||
queryPairEnd += match[0].length;
|
||||
}
|
||||
// Remove the full query pair (including any conjunction/whitespace) from the expression
|
||||
updatedExpression = `${expression.slice(
|
||||
updatedExpression = `${updatedExpression.slice(
|
||||
0,
|
||||
queryPairStart,
|
||||
)}${expression.slice(queryPairEnd + 1)}`.trim();
|
||||
)}${updatedExpression.slice(queryPairEnd + 1)}`.trim();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@ -90,6 +90,10 @@ export default function QuickFilters(props: IQuickFiltersProps): JSX.Element {
|
||||
...currentQuery.builder,
|
||||
queryData: currentQuery.builder.queryData.map((item, idx) => ({
|
||||
...item,
|
||||
filter: {
|
||||
...item.filter,
|
||||
expression: '',
|
||||
},
|
||||
filters: {
|
||||
...item.filters,
|
||||
items: idx === lastUsedQuery ? [] : [...(item.filters?.items || [])],
|
||||
|
||||
@ -865,6 +865,13 @@ export function QueryBuilderProvider({
|
||||
...currentQueryData.builder,
|
||||
queryData: currentQueryData.builder.queryData.map((item) => ({
|
||||
...item,
|
||||
filter: {
|
||||
...item.filter,
|
||||
expression:
|
||||
item.filter?.expression.trim() === ''
|
||||
? ''
|
||||
: item.filter?.expression ?? '',
|
||||
},
|
||||
filters: {
|
||||
items: [],
|
||||
op: 'AND',
|
||||
|
||||
13
frontend/src/utils/stringUtils.ts
Normal file
13
frontend/src/utils/stringUtils.ts
Normal file
@ -0,0 +1,13 @@
|
||||
export function unquote(str: string): string {
|
||||
if (typeof str !== 'string') return str;
|
||||
|
||||
const trimmed = str.trim();
|
||||
const firstChar = trimmed[0];
|
||||
const lastChar = trimmed[trimmed.length - 1];
|
||||
|
||||
if ((firstChar === '"' || firstChar === "'") && firstChar === lastChar) {
|
||||
return trimmed.slice(1, -1);
|
||||
}
|
||||
|
||||
return trimmed;
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user