1- import { Box , Stack } from '@mantine/core' ;
1+ import { Box , Button , Loader , Stack , TextInput , Text } from '@mantine/core' ;
22import { ReactNode , useCallback , useEffect , useRef , useState } from 'react' ;
33import classes from '../../Stream/styles/JSONView.module.css' ;
44import EmptyBox from '@/components/Empty' ;
@@ -10,12 +10,14 @@ import {
1010} from '@/constants/theme' ;
1111import { Log } from '@/@types/parseable/api/query' ;
1212import _ from 'lodash' ;
13- import { IconCheck , IconCopy , IconDotsVertical } from '@tabler/icons-react' ;
13+ import { IconCheck , IconCopy , IconDotsVertical , IconSearch } from '@tabler/icons-react' ;
1414import { copyTextToClipboard } from '@/utils' ;
1515import timeRangeUtils from '@/utils/timeRangeUtils' ;
16- import { useCorrelationStore } from '../providers/CorrelationProvider' ;
16+ import { correlationStoreReducers , useCorrelationStore } from '../providers/CorrelationProvider' ;
1717import { ErrorView , LoadingView } from '@/pages/Stream/Views/Explore/LoadingViews' ;
1818import { formatLogTs , isJqSearch } from '@/pages/Stream/providers/LogsProvider' ;
19+ import jqSearch from '@/utils/jqSearch' ;
20+ import { useHotkeys } from '@mantine/hooks' ;
1921
2022type ContextMenuState = {
2123 visible : boolean ;
@@ -24,7 +26,7 @@ type ContextMenuState = {
2426 row : Log | null ;
2527} ;
2628
27- // const { setInstantSearchValue, applyInstantSearch, applyJqSearch } = correlationStoreReducers;
29+ const { setInstantSearchValue, applyInstantSearch, applyJqSearch } = correlationStoreReducers ;
2830
2931const Item = ( props : { header : string | null ; value : string ; highlight : boolean } ) => {
3032 return (
@@ -171,105 +173,104 @@ const JsonRows = (props: { isSearching: boolean; setContextMenu: any }) => {
171173 ) ;
172174} ;
173175
174- // const Toolbar = ({
175- // isSearching,
176- // setSearching,
177- // }: {
178- // isSearching: boolean;
179- // setSearching: React.Dispatch<React.SetStateAction<boolean>>;
180- // }) => {
181- // const [localSearchValue, setLocalSearchValue] = useState<string>('');
182- // const searchInputRef = useRef<HTMLInputElement>(null);
183-
184- // const [searchValue, setCorrelationData] = useCorrelationStore((store) => store.tableOpts.instantSearchValue);
185- // const [{ rawData, filteredData }] = useCorrelationStore((store) => store.data);
176+ const Toolbar = ( {
177+ isSearching,
178+ setSearching,
179+ } : {
180+ isSearching : boolean ;
181+ setSearching : React . Dispatch < React . SetStateAction < boolean > > ;
182+ } ) => {
183+ const [ localSearchValue , setLocalSearchValue ] = useState < string > ( '' ) ;
184+ const searchInputRef = useRef < HTMLInputElement > ( null ) ;
186185
187- // const debouncedSearch = useCallback(
188- // _.debounce(async (val: string) => {
189- // if (val.trim() === '') {
190- // setCorrelationData((store) => setInstantSearchValue(store, ''));
191- // setCorrelationData(applyInstantSearch);
192- // } else {
193- // const isJq = isJqSearch(val);
194- // if (isJq) {
195- // const jqResult = await jqSearch(rawData, val);
196- // setCorrelationData((store) => applyJqSearch(store, jqResult));
197- // } else {
198- // setCorrelationData(applyInstantSearch);
199- // }
200- // }
201- // setSearching(false);
202- // }, 500),
203- // [rawData],
204- // );
186+ const [ searchValue , setCorrelationData ] = useCorrelationStore ( ( store ) => store . tableOpts . instantSearchValue ) ;
187+ const [ pageData ] = useCorrelationStore ( ( store ) => store . tableOpts ) ;
188+ const debouncedSearch = useCallback (
189+ _ . debounce ( async ( val : string ) => {
190+ if ( val . trim ( ) === '' ) {
191+ setCorrelationData ( ( store ) => setInstantSearchValue ( store , '' ) ) ;
192+ setCorrelationData ( applyInstantSearch ) ;
193+ } else {
194+ const isJq = isJqSearch ( val ) ;
195+ if ( isJq ) {
196+ const jqResult = await jqSearch ( pageData , val ) ;
197+ setCorrelationData ( ( store ) => applyJqSearch ( store , jqResult ) ) ;
198+ } else {
199+ setCorrelationData ( applyInstantSearch ) ;
200+ }
201+ }
202+ setSearching ( false ) ;
203+ } , 500 ) ,
204+ [ pageData ] ,
205+ ) ;
205206
206- // const handleSearch = useCallback(() => {
207- // if (localSearchValue.trim()) {
208- // setSearching(true);
209- // setCorrelationData((store) => setInstantSearchValue(store, localSearchValue));
210- // debouncedSearch(localSearchValue);
211- // }
212- // }, [localSearchValue, debouncedSearch, setSearching]);
207+ const handleSearch = useCallback ( ( ) => {
208+ if ( localSearchValue . trim ( ) ) {
209+ setSearching ( true ) ;
210+ setCorrelationData ( ( store ) => setInstantSearchValue ( store , localSearchValue ) ) ;
211+ debouncedSearch ( localSearchValue ) ;
212+ }
213+ } , [ localSearchValue , debouncedSearch , setSearching ] ) ;
213214
214- // const handleInputChange = useCallback(
215- // (e: React.ChangeEvent<HTMLInputElement>) => {
216- // const value = e.target.value;
217- // setLocalSearchValue(value);
218- // if (value.trim() === '') {
219- // debouncedSearch(value);
220- // }
221- // },
222- // [debouncedSearch],
223- // );
215+ const handleInputChange = useCallback (
216+ ( e : React . ChangeEvent < HTMLInputElement > ) => {
217+ const value = e . target . value ;
218+ setLocalSearchValue ( value ) ;
219+ if ( value . trim ( ) === '' ) {
220+ debouncedSearch ( value ) ;
221+ }
222+ } ,
223+ [ debouncedSearch ] ,
224+ ) ;
224225
225- // useHotkeys([['mod+K', () => searchInputRef.current?.focus()]]);
226+ useHotkeys ( [ [ 'mod+K' , ( ) => searchInputRef . current ?. focus ( ) ] ] ) ;
226227
227- // const handleKeyDown = useCallback(
228- // (e: React.KeyboardEvent<HTMLInputElement>) => {
229- // if (e.key === 'Enter' && !isSearching && localSearchValue.trim()) {
230- // handleSearch();
231- // }
232- // },
233- // [isSearching, localSearchValue],
234- // );
228+ const handleKeyDown = useCallback (
229+ ( e : React . KeyboardEvent < HTMLInputElement > ) => {
230+ if ( e . key === 'Enter' && ! isSearching && localSearchValue . trim ( ) ) {
231+ handleSearch ( ) ;
232+ }
233+ } ,
234+ [ isSearching , localSearchValue ] ,
235+ ) ;
235236
236- // if (_.isEmpty(rawData )) return null;
237+ if ( _ . isEmpty ( pageData ) ) return null ;
237238
238- // const inputStyles = {
239- // '--input-left-section-width': '2rem',
240- // '--input-right-section-width': '6rem',
241- // width: '100%',
242- // } as React.CSSProperties;
239+ const inputStyles = {
240+ '--input-left-section-width' : '2rem' ,
241+ '--input-right-section-width' : '6rem' ,
242+ width : '100%' ,
243+ } as React . CSSProperties ;
243244
244- // return (
245- // <div className={classes.headerWrapper}>
246- // <TextInput
247- // leftSection={isSearching ? <Loader size="sm" /> : <IconSearch stroke={2.5} size="0.9rem" />}
248- // placeholder="Search loaded data with text or jq. For jq input try `jq .[]`"
249- // value={localSearchValue}
250- // onChange={handleInputChange}
251- // onKeyDown={handleKeyDown}
252- // ref={searchInputRef}
253- // classNames={{ input: classes.inputField }}
254- // style={inputStyles}
255- // rightSection={
256- // searchValue && !isSearching ? (
257- // <Text style={{ fontSize: '0.7rem', textAlign: 'end' }} lineClamp={1}>
258- // {filteredData.length} Matches
259- // </Text>
260- // ) : null
261- // }
262- // />
263- // <Button
264- // onClick={handleSearch}
265- // disabled={!localSearchValue.trim() || isSearching}
266- // style={{ width: '10%' }}
267- // leftSection={<IconSearch stroke={2.5} size="0.9rem" />}>
268- // Search
269- // </Button>
270- // </div>
271- // );
272- // };
245+ return (
246+ < div className = { classes . headerWrapper } >
247+ < TextInput
248+ leftSection = { isSearching ? < Loader size = "sm" /> : < IconSearch stroke = { 2.5 } size = "0.9rem" /> }
249+ placeholder = "Search loaded data with text or jq. For jq input try `jq .[]`"
250+ value = { localSearchValue }
251+ onChange = { handleInputChange }
252+ onKeyDown = { handleKeyDown }
253+ ref = { searchInputRef }
254+ classNames = { { input : classes . inputField } }
255+ style = { inputStyles }
256+ rightSection = {
257+ searchValue && ! isSearching ? (
258+ < Text style = { { fontSize : '0.7rem' , textAlign : 'end' } } lineClamp = { 1 } >
259+ Matches
260+ </ Text >
261+ ) : null
262+ }
263+ />
264+ < Button
265+ onClick = { handleSearch }
266+ disabled = { ! localSearchValue . trim ( ) || isSearching }
267+ style = { { width : '10%' } }
268+ leftSection = { < IconSearch stroke = { 2.5 } size = "0.9rem" /> } >
269+ Search
270+ </ Button >
271+ </ div >
272+ ) ;
273+ } ;
273274
274275const TableContainer = ( props : { children : ReactNode } ) => {
275276 return < Box className = { classes . container } > { props . children } </ Box > ;
@@ -286,11 +287,13 @@ const CorrleationJSONView = (props: { errorMessage: string | null; hasNoData: bo
286287
287288 const contextMenuRef = useRef < HTMLDivElement > ( null ) ;
288289 const { errorMessage, hasNoData, showTable } = props ;
289- const [ isSearching ] = useState ( false ) ;
290+ const [ isSearching , setSearching ] = useState ( false ) ;
290291 const primaryHeaderHeight = ! maximized
291292 ? PRIMARY_HEADER_HEIGHT + STREAM_PRIMARY_TOOLBAR_CONTAINER_HEIGHT + STREAM_SECONDARY_TOOLBAR_HRIGHT
292293 : 0 ;
293294
295+ // const showTableOrLoader = logsLoading || streamsLoading || showTable || !errorMessage || !hasNoData;
296+
294297 useEffect ( ( ) => {
295298 const handleClickOutside = ( event : MouseEvent ) => {
296299 if ( contextMenuRef . current && ! contextMenuRef . current . contains ( event . target as Node ) ) {
@@ -311,7 +314,7 @@ const CorrleationJSONView = (props: { errorMessage: string | null; hasNoData: bo
311314
312315 return (
313316 < TableContainer >
314- { /* <Toolbar isSearching={isSearching} setSearching={setSearching} /> */ }
317+ < Toolbar isSearching = { isSearching } setSearching = { setSearching } />
315318 { ! errorMessage ? (
316319 showTable ? (
317320 < Box className = { classes . innerContainer } style = { { maxHeight : `calc(100vh - ${ primaryHeaderHeight } px )` } } >
0 commit comments