Skip to content

Commit 2c8ea97

Browse files
committed
feat(TopQueries): filter by query text
1 parent b9a8e95 commit 2c8ea97

File tree

6 files changed

+32
-15
lines changed

6 files changed

+32
-15
lines changed

src/containers/Tenant/Diagnostics/TopQueries/TopQueries.scss

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,15 @@
1616
&__controls {
1717
display: flex;
1818
flex-wrap: wrap;
19-
align-items: baseline;
2019
gap: 16px;
2120

2221
margin-bottom: 10px;
2322
}
2423

24+
&__search {
25+
@include search();
26+
}
27+
2528
&__result {
2629
overflow: auto;
2730
flex-grow: 1;

src/containers/Tenant/Diagnostics/TopQueries/TopQueries.tsx

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import DataTable, {Column} from '@yandex-cloud/react-data-table';
66
import {Loader} from '@gravity-ui/uikit';
77

88
import {DateRange, DateRangeValues} from '../../../../components/DateRange';
9+
import {Search} from '../../../../components/Search';
910
import TruncatedQuery from '../../../../components/TruncatedQuery/TruncatedQuery';
1011

1112
import {changeUserInput} from '../../../../store/reducers/executeQuery';
@@ -68,14 +69,14 @@ export const TopQueries = ({path, type, changeSchemaTab}: TopQueriesProps) => {
6869

6970
const preventFetch = useRef(false);
7071

71-
// filters sync between redux state and URL
72+
// some filters sync between redux state and URL
7273
// component state is for default values,
7374
// default values are determined from the query response, and should not propagate to URL
74-
const [dateRangeFilters, setDateRangeFilters] = useState<ITopQueriesFilters>(storeFilters);
75+
const [filters, setFilters] = useState<ITopQueriesFilters>(storeFilters);
7576

7677
useEffect(() => {
77-
dispatch(setTopQueriesFilters(dateRangeFilters));
78-
}, [dispatch, dateRangeFilters]);
78+
dispatch(setTopQueriesFilters(filters));
79+
}, [dispatch, filters]);
7980

8081
const setDefaultFiltersFromResponse = (responseData?: IQueryResult) => {
8182
const intervalEnd = responseData?.result?.[0]?.IntervalEnd;
@@ -84,7 +85,7 @@ export const TopQueries = ({path, type, changeSchemaTab}: TopQueriesProps) => {
8485
const to = new Date(intervalEnd).getTime();
8586
const from = new Date(to - HOUR_IN_SECONDS * 1000).getTime();
8687

87-
setDateRangeFilters((currentFilters) => {
88+
setFilters((currentFilters) => {
8889
// request without filters returns the latest interval with data
8990
// only in this case should update filters in ui
9091
// also don't update if user already interacted with controls
@@ -119,11 +120,11 @@ export const TopQueries = ({path, type, changeSchemaTab}: TopQueriesProps) => {
119120

120121
// @ts-expect-error
121122
// typed dispatch required, remove error expectation after adding it
122-
dispatch(fetchTopQueries({database: path, filters: dateRangeFilters})).then(
123+
dispatch(fetchTopQueries({database: path, filters})).then(
123124
setDefaultFiltersFromResponse,
124125
);
125126
},
126-
[dispatch, dateRangeFilters, path],
127+
[dispatch, filters, path],
127128
autorefresh,
128129
);
129130

@@ -137,8 +138,12 @@ export const TopQueries = ({path, type, changeSchemaTab}: TopQueriesProps) => {
137138
[changeSchemaTab, dispatch],
138139
);
139140

141+
const handleTextSearchUpdate = (text: string) => {
142+
setFilters((currentFilters) => ({...currentFilters, text}));
143+
};
144+
140145
const handleDateRangeChange = (value: DateRangeValues) => {
141-
setDateRangeFilters((currentFilters) => ({...currentFilters, ...value}));
146+
setFilters((currentFilters) => ({...currentFilters, ...value}));
142147
};
143148

144149
const renderLoader = () => {
@@ -178,11 +183,13 @@ export const TopQueries = ({path, type, changeSchemaTab}: TopQueriesProps) => {
178183
return (
179184
<div className={b()}>
180185
<div className={b('controls')}>
181-
<DateRange
182-
from={dateRangeFilters.from}
183-
to={dateRangeFilters.to}
184-
onChange={handleDateRangeChange}
186+
<Search
187+
value={filters.text}
188+
onChange={handleTextSearchUpdate}
189+
placeholder={i18n('filter.text.placeholder')}
190+
className={b('search')}
185191
/>
192+
<DateRange from={filters.from} to={filters.to} onChange={handleDateRangeChange} />
186193
</div>
187194
{renderContent()}
188195
</div>
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
{
2-
"no-data": "No data"
2+
"no-data": "No data",
3+
"filter.text.placeholder": "Search by query text..."
34
}
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
{
2-
"no-data": "Нет данных"
2+
"no-data": "Нет данных",
3+
"filter.text.placeholder": "Искать по тексту запроса..."
34
}

src/store/reducers/executeTopQueries.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ function getFiltersConditions(path: string, filters?: ITopQueriesFilters) {
5353
conditions.push(`IntervalEnd IN ${getMaxIntervalSubquery(path)}`);
5454
}
5555

56+
if (filters?.text) {
57+
conditions.push(`QueryText ILIKE '%${filters.text}%'`);
58+
}
59+
5660
return conditions.join(' AND ');
5761
}
5862

src/types/store/executeTopQueries.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ export interface ITopQueriesFilters {
88
from?: number;
99
/** ms from epoch */
1010
to?: number;
11+
text?: string;
1112
}
1213

1314
export interface ITopQueriesState {

0 commit comments

Comments
 (0)