Skip to content
This repository was archived by the owner on May 13, 2025. It is now read-only.

Commit 3b98fc1

Browse files
authored
feat: add saved filters SQL query to the dashboard tile editor (#361)
1 parent dce6ffd commit 3b98fc1

File tree

5 files changed

+81
-37
lines changed

5 files changed

+81
-37
lines changed

src/pages/Dashboards/CreateTileForm.tsx

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import classes from './styles/Form.module.css';
33
import { useForm } from '@mantine/form';
44
import { useDashboardsStore, dashboardsStoreReducers } from './providers/DashboardsProvider';
55
import { MutableRefObject, useCallback, useEffect, useMemo, useRef, useState } from 'react';
6-
import { useAppStore } from '@/layouts/MainLayout/providers/AppProvider';
6+
import { appStoreReducers, useAppStore } from '@/layouts/MainLayout/providers/AppProvider';
77
import _ from 'lodash';
88
import { getLogStreamSchema } from '@/api/logStream';
99
import { Field } from '@/@types/parseable/dataType';
@@ -29,6 +29,7 @@ import TimeRange from '@/components/Header/TimeRange';
2929
import { colors, isCircularChart, isGraph, normalizeGraphColorConfig } from './Charts';
3030
import { usePostLLM } from '@/hooks/usePostLLM';
3131
import { notify } from '@/utils/notification';
32+
import { filterStoreReducers, useFilterStore } from '../Stream/providers/FilterProvider';
3233

3334
const selectDashboardWarningText = 'Select a dashboard to continue';
3435
const validateQueryWarningText = 'Validate query to continue';
@@ -37,6 +38,8 @@ const noDataWarning = 'No data available for the query';
3738
const invalidVizConfig = 'Invalid visualization config';
3839

3940
const { toggleVizEditorModal, toggleCreateTileModal } = dashboardsStoreReducers;
41+
const { toggleSavedFiltersModal, setAppliedFilterQuery } = filterStoreReducers;
42+
const { changeStream } = appStoreReducers;
4043

4144
const getErrorMsg = (form: TileFormType, configType: 'basic' | 'data' | 'viz'): string | null => {
4245
const { dashboardId, isQueryValidated, data, visualization } = form.values;
@@ -289,14 +292,20 @@ const Query = (props: { form: TileFormType; onChangeValue: (key: string, value:
289292
const [initialHeight, setInitialHeight] = useState(0);
290293
const [dashboards] = useDashboardsStore((store) => store.dashboards);
291294
const [timeRange] = useLogsStore((store) => store.timeRange);
295+
const [appliedFilterQuery, setLogsStore] = useFilterStore((store) => store.appliedFilterQuery);
292296
const [aiQuery, setAiQuery] = useState('');
293297
const [userSpecificStreams] = useAppStore((store) => store.userSpecificStreams);
298+
const [, setAppStore] = useAppStore((store) => store.maximized);
294299
const allStreams = useMemo(
295300
() => _.map(userSpecificStreams, (stream) => ({ label: stream.name, value: stream.name })),
296301
[userSpecificStreams],
297302
);
298303
const { data: resAIQuery, postLLMQuery } = usePostLLM();
299304

305+
useEffect(() => {
306+
onEditorChange(appliedFilterQuery);
307+
}, [appliedFilterQuery]);
308+
300309
const onEditorChange = useCallback((query: string | undefined) => {
301310
onChangeValue('query', query || '');
302311
onChangeValue('isQueryValidated', false);
@@ -348,10 +357,15 @@ const Query = (props: { form: TileFormType; onChangeValue: (key: string, value:
348357
});
349358
}, [query, dashboardId, dashboards, timeRange]);
350359

351-
const onStreamSelect = useCallback((val: string | null) => {
352-
setLocalStream(val || '');
360+
const onStreamSelect = useCallback((stream: string | null) => {
361+
if (stream) {
362+
setAppStore((store) => changeStream(store, stream));
363+
setLogsStore((store) => setAppliedFilterQuery(store, ''));
364+
}
365+
setLocalStream(stream || '');
353366
}, []);
354367

368+
const onClick = useCallback(() => setLogsStore((store) => toggleSavedFiltersModal(store, true)), []);
355369
const isValidStream = !_.isEmpty(localStream);
356370
const handleAIGenerate = useCallback(() => {
357371
if (!aiQuery?.length) {
@@ -375,6 +389,9 @@ const Query = (props: { form: TileFormType; onChangeValue: (key: string, value:
375389
key="stream"
376390
placeholder="Select Stream"
377391
/>
392+
<Button disabled={!localStream} className={classes.savedFiltersBtn} h="100%" onClick={onClick}>
393+
Saved Filters
394+
</Button>
378395
</Stack>
379396
</Stack>
380397
{errorMsg && <Text className={classes.warningText}>{errorMsg}</Text>}

src/pages/Dashboards/index.tsx

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { useSyncTimeRange } from './hooks';
1212
import _ from 'lodash';
1313
import useParamsController from './hooks/useParamsController';
1414
import { useDocumentTitle } from '@mantine/hooks';
15+
import SavedFiltersModal from '../Stream/components/Querier/SavedFiltersModal';
1516

1617
const LoadingView = () => {
1718
return (
@@ -35,27 +36,30 @@ const Dashboards = () => {
3536
}, [isStoreSynced]);
3637

3738
return (
38-
<Box
39-
style={{
40-
flex: 1,
41-
display: 'flex',
42-
position: 'relative',
43-
flexDirection: 'row',
44-
width: '100%',
45-
overflow: 'hidden',
46-
}}>
47-
{dashboards === null || !isStoreSynced ? (
48-
<LoadingView />
49-
) : createTileFormOpen ? (
50-
<CreateTileForm />
51-
) : (
52-
<>
53-
<SideBar updateTimeRange={updateTimeRange} />
54-
<CreateDashboardModal />
55-
<Dashboard />
56-
</>
57-
)}
58-
</Box>
39+
<>
40+
<SavedFiltersModal />
41+
<Box
42+
style={{
43+
flex: 1,
44+
display: 'flex',
45+
position: 'relative',
46+
flexDirection: 'row',
47+
width: '100%',
48+
overflow: 'hidden',
49+
}}>
50+
{dashboards === null || !isStoreSynced ? (
51+
<LoadingView />
52+
) : createTileFormOpen ? (
53+
<CreateTileForm />
54+
) : (
55+
<>
56+
<SideBar updateTimeRange={updateTimeRange} />
57+
<CreateDashboardModal />
58+
<Dashboard />
59+
</>
60+
)}
61+
</Box>
62+
</>
5963
);
6064
};
6165

src/pages/Stream/components/Querier/SavedFiltersModal.tsx

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,10 @@ import { EmptySimple } from '@/components/Empty';
1313
import { useAppStore } from '@/layouts/MainLayout/providers/AppProvider';
1414
import useSavedFiltersQuery from '@/hooks/useSavedFilters';
1515
import { generateQueryBuilderASTFromSQL } from '../../utils';
16+
import { useLocation } from 'react-router-dom';
1617

17-
const { toggleSavedFiltersModal, resetFilters, parseQuery, applySavedFilters } = filterStoreReducers;
18+
const { toggleSavedFiltersModal, resetFilters, parseQuery, applySavedFilters, setAppliedFilterQuery } =
19+
filterStoreReducers;
1820
const { applyCustomQuery, updateSavedFilterId, getCleanStoreForRefetch, setTimeRange } = logsStoreReducers;
1921

2022
const renderDeleteIcon = () => <IconTrash size={px('1rem')} stroke={1.5} />;
@@ -58,6 +60,9 @@ const SavedFilterItem = (props: {
5860
const [showDeletePropmt, setShowDeletePrompt] = useState<boolean>(false);
5961
const { deleteSavedFilterMutation, isDeleting, isRefetching } = useSavedFiltersQuery();
6062

63+
const location = useLocation();
64+
const [, setFilterStore] = useFilterStore((_store) => null);
65+
6166
const toggleShowQuery = useCallback(() => {
6267
return setShowQuery((prev) => !prev);
6368
}, []);
@@ -78,22 +83,27 @@ const SavedFilterItem = (props: {
7883
}, [time_filter, isStoredAndCurrentTimeRangeAreSame, hardRefresh, changeTimerange]);
7984

8085
const onApplyFilters = useCallback(() => {
81-
if (query.filter_query) {
82-
if (query.filter_type === 'sql') {
83-
props.onSqlSearchApply(query.filter_query, filter_id, time_filter);
84-
} else {
86+
if (location.pathname.includes('dashboard')) {
87+
setFilterStore((store) => setAppliedFilterQuery(store, query.filter_query));
88+
setFilterStore((store) => toggleSavedFiltersModal(store, false));
89+
} else {
90+
if (query.filter_query) {
91+
if (query.filter_type === 'sql') {
92+
props.onSqlSearchApply(query.filter_query, filter_id, time_filter);
93+
} else {
94+
if (filter_id !== savedFilterId) {
95+
props.onFilterBuilderQueryApply(generateQueryBuilderASTFromSQL(query.filter_query), filter_id);
96+
} else {
97+
handleTimeFilter();
98+
}
99+
}
100+
} else if (query.filter_builder) {
85101
if (filter_id !== savedFilterId) {
86-
props.onFilterBuilderQueryApply(generateQueryBuilderASTFromSQL(query.filter_query), filter_id);
102+
props.onFilterBuilderQueryApply(query.filter_builder, filter_id);
87103
} else {
88104
handleTimeFilter();
89105
}
90106
}
91-
} else if (query.filter_builder) {
92-
if (filter_id !== savedFilterId) {
93-
props.onFilterBuilderQueryApply(query.filter_builder, filter_id);
94-
} else {
95-
handleTimeFilter();
96-
}
97107
}
98108
}, [savedFilterId, isStoredAndCurrentTimeRangeAreSame, hardRefresh, changeTimerange]);
99109

src/pages/Stream/providers/FilterProvider.tsx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ type UpdateRuleType = {
6565
type FilterStore = {
6666
fields: Field[];
6767
query: QueryType;
68+
appliedFilterQuery: string;
6869
fieldTypeMap: FieldTypeMap;
6970
fieldNames: string[];
7071
isSumbitDisabled: boolean;
@@ -88,6 +89,7 @@ const defaultQuery = {
8889
const initialState: FilterStore = {
8990
fields: [],
9091
query: defaultQuery,
92+
appliedFilterQuery: '',
9193
fieldTypeMap: {},
9294
fieldNames: [],
9395
isSumbitDisabled: true,
@@ -139,6 +141,7 @@ type FilterStoreReducers = {
139141
toggleSaveFiltersModal: (_store: FilterStore, val: boolean) => ReducerOutput;
140142
toggleSavedFiltersModal: (_store: FilterStore, val: boolean) => ReducerOutput;
141143
applySavedFilters: (store: FilterStore, query: QueryType) => ReducerOutput;
144+
setAppliedFilterQuery: (store: FilterStore, query: string | undefined) => ReducerOutput;
142145
};
143146

144147
const { Provider: FilterProvider, useStore: useFilterStore } = initContext(initialState);
@@ -234,6 +237,13 @@ const updateParentCombinator = (store: FilterStore, combinator: Combinator) => {
234237
return { query: { ...query, combinator: combinator } };
235238
};
236239

240+
const setAppliedFilterQuery = (_store: FilterStore, query: string | undefined) => {
241+
return {
242+
..._store,
243+
appliedFilterQuery: query ?? '',
244+
};
245+
};
246+
237247
export const noValueOperators = ['null', 'notNull'];
238248

239249
const toggleSubmitBtn = (_store: FilterStore, val: boolean) => {
@@ -354,6 +364,7 @@ const filterStoreReducers: FilterStoreReducers = {
354364
toggleSaveFiltersModal,
355365
toggleSavedFiltersModal,
356366
applySavedFilters,
367+
setAppliedFilterQuery,
357368
};
358369

359370
export { FilterProvider, useFilterStore, filterStoreReducers };

src/routes/elements.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@ export const DashboardsElement: FC = () => {
2424
<SuspensePage>
2525
<LogsProvider>
2626
<DashbaordsProvider>
27-
<Dashboards />
27+
<FilterProvider>
28+
<Dashboards />
29+
</FilterProvider>
2830
</DashbaordsProvider>
2931
</LogsProvider>
3032
</SuspensePage>

0 commit comments

Comments
 (0)