Skip to content

Commit 1c07728

Browse files
authored
Merge branch 'main' into astandrik.display-a-list-of-operations-1414
2 parents 081c130 + d4f528c commit 1c07728

File tree

11 files changed

+48
-32
lines changed

11 files changed

+48
-32
lines changed

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

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {ResponseError} from '../../../../components/Errors/ResponseError';
44
import {ResizeableDataTable} from '../../../../components/ResizeableDataTable/ResizeableDataTable';
55
import {TableWithControlsLayout} from '../../../../components/TableWithControlsLayout/TableWithControlsLayout';
66
import {topQueriesApi} from '../../../../store/reducers/executeTopQueries/executeTopQueries';
7+
import type {KeyValueRow} from '../../../../types/api/query';
78
import {useAutoRefreshInterval, useTypedSelector} from '../../../../utils/hooks';
89
import {parseQueryErrorToString} from '../../../../utils/query';
910
import {QUERY_TABLE_SETTINGS} from '../../utils/constants';
@@ -16,12 +17,14 @@ import i18n from './i18n';
1617

1718
interface Props {
1819
database: string;
20+
onRowClick: (query: string) => void;
21+
rowClassName: string;
1922
}
2023

21-
export const RunningQueriesData = ({database}: Props) => {
24+
export const RunningQueriesData = ({database, onRowClick, rowClassName}: Props) => {
2225
const [autoRefreshInterval] = useAutoRefreshInterval();
2326
const filters = useTypedSelector((state) => state.executeTopQueries);
24-
const {currentData, isFetching, error} = topQueriesApi.useGetRunningQueriesQuery(
27+
const {currentData, isLoading, error} = topQueriesApi.useGetRunningQueriesQuery(
2528
{
2629
database,
2730
filters,
@@ -31,16 +34,22 @@ export const RunningQueriesData = ({database}: Props) => {
3134

3235
const data = currentData?.resultSets?.[0].result || [];
3336

37+
const handleRowClick = (row: KeyValueRow) => {
38+
return onRowClick(row.QueryText as string);
39+
};
40+
3441
return (
3542
<React.Fragment>
3643
{error ? <ResponseError error={parseQueryErrorToString(error)} /> : null}
37-
<TableWithControlsLayout.Table loading={isFetching && data === undefined}>
44+
<TableWithControlsLayout.Table loading={isLoading}>
3845
<ResizeableDataTable
3946
emptyDataMessage={i18n('no-data')}
4047
columnsWidthLSKey={RUNNING_QUERIES_COLUMNS_WIDTH_LS_KEY}
4148
columns={RUNNING_QUERIES_COLUMNS}
4249
data={data}
4350
settings={QUERY_TABLE_SETTINGS}
51+
onRowClick={handleRowClick}
52+
rowClassName={() => rowClassName}
4453
/>
4554
</TableWithControlsLayout.Table>
4655
</React.Fragment>

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

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,8 @@ export const TopQueries = ({tenantName}: TopQueriesProps) => {
9393
dispatch(setTopQueriesFilters(value));
9494
};
9595

96+
const DataComponent = isTopQueries ? TopQueriesData : RunningQueriesData;
97+
9698
return (
9799
<TableWithControlsLayout>
98100
<TableWithControlsLayout.Controls>
@@ -115,11 +117,7 @@ export const TopQueries = ({tenantName}: TopQueriesProps) => {
115117
/>
116118
) : null}
117119
</TableWithControlsLayout.Controls>
118-
{isTopQueries ? (
119-
<TopQueriesData database={tenantName} onRowClick={onRowClick} />
120-
) : (
121-
<RunningQueriesData database={tenantName} />
122-
)}
120+
<DataComponent database={tenantName} onRowClick={onRowClick} rowClassName={b('row')} />
123121
</TableWithControlsLayout>
124122
);
125123
};

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

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import {ResizeableDataTable} from '../../../../components/ResizeableDataTable/Re
55
import {TableWithControlsLayout} from '../../../../components/TableWithControlsLayout/TableWithControlsLayout';
66
import {topQueriesApi} from '../../../../store/reducers/executeTopQueries/executeTopQueries';
77
import type {KeyValueRow} from '../../../../types/api/query';
8-
import {cn} from '../../../../utils/cn';
98
import {isSortableTopQueriesProperty} from '../../../../utils/diagnostics';
109
import {useAutoRefreshInterval, useTypedSelector} from '../../../../utils/hooks';
1110
import {parseQueryErrorToString} from '../../../../utils/query';
@@ -14,17 +13,16 @@ import {QUERY_TABLE_SETTINGS} from '../../utils/constants';
1413
import {TOP_QUERIES_COLUMNS, TOP_QUERIES_COLUMNS_WIDTH_LS_KEY} from './getTopQueriesColumns';
1514
import i18n from './i18n';
1615

17-
const b = cn('kv-top-queries');
18-
1916
interface Props {
2017
database: string;
2118
onRowClick: (query: string) => void;
19+
rowClassName: string;
2220
}
2321

24-
export const TopQueriesData = ({database, onRowClick}: Props) => {
22+
export const TopQueriesData = ({database, onRowClick, rowClassName}: Props) => {
2523
const [autoRefreshInterval] = useAutoRefreshInterval();
2624
const filters = useTypedSelector((state) => state.executeTopQueries);
27-
const {currentData, isFetching, error} = topQueriesApi.useGetTopQueriesQuery(
25+
const {currentData, isLoading, error} = topQueriesApi.useGetTopQueriesQuery(
2826
{
2927
database,
3028
filters,
@@ -46,15 +44,15 @@ export const TopQueriesData = ({database, onRowClick}: Props) => {
4644
return (
4745
<React.Fragment>
4846
{error ? <ResponseError error={parseQueryErrorToString(error)} /> : null}
49-
<TableWithControlsLayout.Table loading={isFetching && currentData === undefined}>
47+
<TableWithControlsLayout.Table loading={isLoading}>
5048
<ResizeableDataTable
5149
emptyDataMessage={i18n('no-data')}
5250
columnsWidthLSKey={TOP_QUERIES_COLUMNS_WIDTH_LS_KEY}
5351
columns={columns}
5452
data={data || []}
5553
settings={QUERY_TABLE_SETTINGS}
5654
onRowClick={handleRowClick}
57-
rowClassName={() => b('row')}
55+
rowClassName={() => rowClassName}
5856
/>
5957
</TableWithControlsLayout.Table>
6058
</React.Fragment>

src/containers/Tenant/Diagnostics/TopQueries/i18n/en.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"no-data": "No data",
3-
"filter.text.placeholder": "Search by query text...",
3+
"filter.text.placeholder": "Search by query text or userSID...",
44
"mode_top": "Top",
55
"mode_running": "Running",
66
"col_user": "User",

src/services/settings.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ export const DEFAULT_USER_SETTINGS = {
3636
[LAST_USED_QUERY_ACTION_KEY]: QUERY_ACTIONS.execute,
3737
[ASIDE_HEADER_COMPACT_KEY]: true,
3838
[PARTITIONS_HIDDEN_COLUMNS_KEY]: [],
39-
[USE_PAGINATED_TABLES_KEY]: true,
39+
[USE_PAGINATED_TABLES_KEY]: false,
4040
[USE_CLUSTER_BALANCER_AS_BACKEND_KEY]: true,
4141
[ENABLE_AUTOCOMPLETE]: true,
4242
[AUTOCOMPLETE_ON_ENTER]: true,

src/store/reducers/executeTopQueries/executeTopQueries.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -94,10 +94,11 @@ export const topQueriesApi = api.injectEndpoints({
9494
{signal},
9595
) => {
9696
try {
97-
const filterConditions = filters?.text ? `Query ILIKE '%${filters.text}%'` : '';
98-
const commonQueryPart = `SELECT UserSID, QueryStartAt, Query as QueryText, ApplicationName from \`.sys/query_sessions\` WHERE ${filterConditions || 'true'}`;
97+
const filterConditions = filters?.text
98+
? `Query ILIKE '%${filters.text}%' OR UserSID ILIKE '%${filters.text}%'`
99+
: '';
99100

100-
const queryText = `${commonQueryPart} AND Query NOT LIKE '${commonQueryPart}%' ORDER BY SessionStartAt limit 100`;
101+
const queryText = `SELECT UserSID, QueryStartAt, Query as QueryText, ApplicationName from \`.sys/query_sessions\` WHERE ${filterConditions || 'true'} ORDER BY SessionStartAt limit 100`;
101102

102103
const response = await window.api.sendQuery(
103104
{
@@ -114,6 +115,13 @@ export const topQueriesApi = api.injectEndpoints({
114115

115116
const data = parseQueryAPIExecuteResponse(response);
116117

118+
/* filter running queries query itself */
119+
if (data?.resultSets?.[0]?.result) {
120+
data.resultSets[0].result = data.resultSets[0].result.filter(
121+
(item) => item.QueryText !== queryText,
122+
);
123+
}
124+
117125
return {data};
118126
} catch (error) {
119127
return {error};

src/store/reducers/executeTopQueries/utils.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,9 @@ export function getFiltersConditions(path: string, filters?: TopQueriesFilters)
3737
}
3838

3939
if (filters?.text) {
40-
conditions.push(`QueryText ILIKE '%${filters.text}%'`);
40+
conditions.push(
41+
`(QueryText ILIKE '%${filters.text}%' OR UserSID ILIKE '%${filters.text}%')`,
42+
);
4143
}
4244

4345
return conditions.join(' AND ');

tests/suites/nodes/NodesPage.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,14 @@ import type {Locator, Page} from '@playwright/test';
22

33
import {PageModel} from '../../models/PageModel';
44
import {nodesPage} from '../../utils/constants';
5+
import {selectContentTable} from '../../utils/selectContentTable';
56

67
export class NodesPage extends PageModel {
78
readonly table: Locator;
89

910
constructor(page: Page) {
1011
super(page, nodesPage);
1112

12-
this.table = this.selector.locator('.ydb-paginated-table__table');
13+
this.table = selectContentTable(this.selector);
1314
}
1415
}

tests/suites/storage/StoragePage.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import type {Locator, Page} from '@playwright/test';
22

33
import {PageModel} from '../../models/PageModel';
44
import {storagePage} from '../../utils/constants';
5+
import {selectContentTable} from '../../utils/selectContentTable';
56

67
type EntityType = 'Groups' | 'Nodes';
78

@@ -14,7 +15,7 @@ export class StoragePage extends PageModel {
1415
constructor(page: Page) {
1516
super(page, storagePage);
1617

17-
this.table = this.selector.locator('.ydb-paginated-table__table');
18+
this.table = selectContentTable(this.selector);
1819

1920
this.entityTypeSelector = this.selector.getByTestId(storageTypeFilterQa);
2021
}

tests/suites/tenant/diagnostics/Diagnostics.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -88,15 +88,15 @@ export class Table {
8888
}
8989

9090
async waitForCellValueByHeader(row: number, header: string, value: string) {
91-
const headers = await this.getHeaders();
92-
const colIndex = headers.indexOf(header);
93-
if (colIndex === -1) {
94-
throw new Error(`Header "${header}" not found`);
95-
}
96-
const cell = this.table.locator(
97-
`tr.data-table__row:nth-child(${row}) td:nth-child(${colIndex + 1})`,
98-
);
9991
await retryAction(async () => {
92+
const headers = await this.getHeaders();
93+
const colIndex = headers.indexOf(header);
94+
if (colIndex === -1) {
95+
throw new Error(`Header "${header}" not found`);
96+
}
97+
const cell = this.table.locator(
98+
`tr.data-table__row:nth-child(${row}) td:nth-child(${colIndex + 1})`,
99+
);
100100
const cellValue = (await cell.innerText()).trim();
101101
if (cellValue === value) {
102102
return true;

0 commit comments

Comments
 (0)