From d83a5dadf751f8fce4008325d041b403764b4289 Mon Sep 17 00:00:00 2001 From: Yunus M Date: Tue, 17 Jun 2025 15:39:30 +0530 Subject: [PATCH] feat: fetch more keys is complete list not already fetched --- .../api/querySuggestions/getKeySuggestions.ts | 2 +- .../QueryV2/QuerySearch/QuerySearch.tsx | 109 +++++++++++------- .../QueryBuilderV2/QueryV2/QueryV2.tsx | 6 +- .../useGetQueryKeySuggestions.ts | 6 +- .../src/types/api/querySuggestions/types.ts | 14 ++- 5 files changed, 92 insertions(+), 45 deletions(-) diff --git a/frontend/src/api/querySuggestions/getKeySuggestions.ts b/frontend/src/api/querySuggestions/getKeySuggestions.ts index 3bd9d723a90a..293defaf76ef 100644 --- a/frontend/src/api/querySuggestions/getKeySuggestions.ts +++ b/frontend/src/api/querySuggestions/getKeySuggestions.ts @@ -8,4 +8,4 @@ import { export const getKeySuggestions = ( props: QueryKeyRequestProps, ): Promise> => - axios.get(`/fields/keys?signal=${props.signal}`); + axios.get(`/fields/keys?signal=${props.signal}&name=${props.name}`); diff --git a/frontend/src/components/QueryBuilderV2/QueryV2/QuerySearch/QuerySearch.tsx b/frontend/src/components/QueryBuilderV2/QueryV2/QuerySearch/QuerySearch.tsx index 50f6206bb822..026cf045a989 100644 --- a/frontend/src/components/QueryBuilderV2/QueryV2/QuerySearch/QuerySearch.tsx +++ b/frontend/src/components/QueryBuilderV2/QueryV2/QuerySearch/QuerySearch.tsx @@ -18,9 +18,9 @@ import CodeMirror, { keymap, } from '@uiw/react-codemirror'; import { Button, Card, Collapse, Popover, Tag } from 'antd'; +import { getKeySuggestions } from 'api/querySuggestions/getKeySuggestions'; import { getValueSuggestions } from 'api/querySuggestions/getValueSuggestion'; import cx from 'classnames'; -import { useGetQueryKeySuggestions } from 'hooks/querySuggestions/useGetQueryKeySuggestions'; import { TriangleAlert } from 'lucide-react'; import { useCallback, useEffect, useRef, useState } from 'react'; import { @@ -29,7 +29,8 @@ import { IValidationResult, } from 'types/antlrQueryTypes'; import { IBuilderQuery } from 'types/api/queryBuilder/queryBuilderData'; -import { QueryKeySuggestionsProps } from 'types/api/querySuggestions/types'; +import { QueryKeyDataSuggestionsProps } from 'types/api/querySuggestions/types'; +import { DataSource } from 'types/common/queryBuilder'; import { queryOperatorSuggestions, validateQuery } from 'utils/antlrQueryUtils'; import { getQueryContextAtCursor } from 'utils/queryContextUtils'; @@ -65,9 +66,11 @@ const disallowMultipleSpaces: Extension = EditorView.inputHandler.of( function QuerySearch({ onChange, queryData, + dataSource, }: { onChange: (value: string) => void; queryData: IBuilderQuery; + dataSource: DataSource; }): JSX.Element { const [query, setQuery] = useState(queryData.filter?.expression || ''); const [valueSuggestions, setValueSuggestions] = useState([ @@ -84,7 +87,7 @@ function QuerySearch({ }); const [keySuggestions, setKeySuggestions] = useState< - QueryKeySuggestionsProps[] | null + QueryKeyDataSuggestionsProps[] | null >(null); const [showExamples] = useState(false); @@ -92,6 +95,8 @@ function QuerySearch({ const [cursorPos, setCursorPos] = useState({ line: 0, ch: 0 }); const [isFocused, setIsFocused] = useState(false); + const [isCompleteKeysList, setIsCompleteKeysList] = useState(false); + const lastPosRef = useRef<{ line: number; ch: number }>({ line: 0, ch: 0 }); // Reference to the editor view for programmatic autocompletion @@ -99,9 +104,45 @@ function QuerySearch({ const lastKeyRef = useRef(''); const isMountedRef = useRef(true); - const { data: queryKeySuggestions } = useGetQueryKeySuggestions({ - signal: 'traces', - }); + // const { + // data: queryKeySuggestions, + // refetch: refetchQueryKeySuggestions, + // } = useGetQueryKeySuggestions({ + // signal: dataSource, + // name: searchText || '', + // }); + + // Add back the generateOptions function and useEffect + const generateOptions = (keys: { + [key: string]: QueryKeyDataSuggestionsProps[]; + }): any[] => + Object.values(keys).flatMap((items: QueryKeyDataSuggestionsProps[]) => + items.map(({ name, fieldDataType }) => ({ + label: name, + type: fieldDataType === 'string' ? 'keyword' : fieldDataType, + info: '', + details: '', + })), + ); + + const fetchKeySuggestions = async (searchText?: string): Promise => { + const response = await getKeySuggestions({ + signal: dataSource, + name: searchText || '', + }); + + if (response.data.data) { + const { complete, keys } = response.data.data; + const options = generateOptions(keys); + setKeySuggestions((prev) => [...(prev || []), ...options]); + setIsCompleteKeysList(complete); + } + }; + + useEffect(() => { + fetchKeySuggestions(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); // Add a state for tracking editing mode const [editingMode, setEditingMode] = useState< @@ -202,7 +243,7 @@ function QuerySearch({ try { const response = await getValueSuggestions({ key, - signal: 'traces', + signal: dataSource, }); // Skip updates if component unmounted or key changed @@ -287,7 +328,7 @@ function QuerySearch({ } } }, - [activeKey, isLoadingSuggestions], + [activeKey, dataSource, isLoadingSuggestions], ); const handleUpdate = useCallback((viewUpdate: { view: EditorView }): void => { @@ -519,6 +560,12 @@ function QuerySearch({ option.label.toLowerCase().includes(searchText), ); + if (!isCompleteKeysList && options.length === 0) { + setTimeout(() => { + fetchKeySuggestions(searchText); + }, 300); + } + // If we have previous pairs, we can prioritize keys that haven't been used yet if (queryContext.queryPairs && queryContext.queryPairs.length > 0) { const usedKeys = queryContext.queryPairs.map((pair) => pair.key); @@ -790,17 +837,6 @@ function QuerySearch({ }; } - // Add back the generateOptions function and useEffect - const generateOptions = (data: any): any[] => - Object.values(data.keys).flatMap((items: any) => - items.map(({ name, fieldDataType }: any) => ({ - label: name, - type: fieldDataType === 'string' ? 'keyword' : fieldDataType, - info: '', - details: '', - })), - ); - // Effect to handle focus state and trigger suggestions useEffect(() => { if (isFocused && editorRef.current) { @@ -808,13 +844,6 @@ function QuerySearch({ } }, [isFocused]); - useEffect(() => { - if (queryKeySuggestions) { - const options = generateOptions(queryKeySuggestions.data.data); - setKeySuggestions(options); - } - }, [queryKeySuggestions]); - useEffect(() => { if (!queryContext) return; @@ -1009,42 +1038,44 @@ function QuerySearch({ )} - - {/* {queryContext && ( + {/* + {queryContext && (
- Token: - {queryContext.currentToken || '-'} + Token: + + {queryContext.currentToken || '-'} + - Type: - {queryContext.tokenType || '-'} + Type: + {queryContext.tokenType || '-'} - Context: + Context: {renderContextBadge()} {queryContext.keyToken && ( - Key: - {queryContext.keyToken} + Key: + {queryContext.keyToken} )} {queryContext.operatorToken && ( - Operator: - {queryContext.operatorToken} + Operator: + {queryContext.operatorToken} )} {queryContext.valueToken && ( - Value: - {queryContext.valueToken} + Value: + {queryContext.valueToken} )} diff --git a/frontend/src/components/QueryBuilderV2/QueryV2/QueryV2.tsx b/frontend/src/components/QueryBuilderV2/QueryV2/QueryV2.tsx index 59048513fac6..d3584d761d29 100644 --- a/frontend/src/components/QueryBuilderV2/QueryV2/QueryV2.tsx +++ b/frontend/src/components/QueryBuilderV2/QueryV2/QueryV2.tsx @@ -175,7 +175,11 @@ export const QueryV2 = memo(function QueryV2({
- +
{showSpanScopeSelector && ( diff --git a/frontend/src/hooks/querySuggestions/useGetQueryKeySuggestions.ts b/frontend/src/hooks/querySuggestions/useGetQueryKeySuggestions.ts index 4bc6f0f15ac2..85fb7914e504 100644 --- a/frontend/src/hooks/querySuggestions/useGetQueryKeySuggestions.ts +++ b/frontend/src/hooks/querySuggestions/useGetQueryKeySuggestions.ts @@ -5,13 +5,15 @@ import { QueryKeySuggestionsResponseProps } from 'types/api/querySuggestions/typ export const useGetQueryKeySuggestions = ({ signal, + name, }: { signal: string; + name: string; }): UseQueryResult< AxiosResponse, AxiosError > => useQuery, AxiosError>({ - queryKey: ['queryKeySuggestions'], - queryFn: () => getKeySuggestions({ signal }), + queryKey: ['queryKeySuggestions', signal, name], + queryFn: () => getKeySuggestions({ signal, name }), }); diff --git a/frontend/src/types/api/querySuggestions/types.ts b/frontend/src/types/api/querySuggestions/types.ts index a54300a7684b..219692a0a9d5 100644 --- a/frontend/src/types/api/querySuggestions/types.ts +++ b/frontend/src/types/api/querySuggestions/types.ts @@ -1,18 +1,28 @@ -export interface QueryKeySuggestionsProps { +export interface QueryKeyDataSuggestionsProps { label: string; type: string; info?: string; apply?: string; detail?: string; + fieldContext: string; + fieldDataType: string; + name: string; + signal: string; } export interface QueryKeySuggestionsResponseProps { status: string; - data: QueryKeySuggestionsProps[]; + data: { + complete: boolean; + keys: { + [key: string]: QueryKeyDataSuggestionsProps[]; + }; + }; } export interface QueryKeyRequestProps { signal: string; + name: string; } export interface QueryKeyValueSuggestionsProps {