ydb-embedded-ui 4.19.2 → 4.20.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/dist/components/LinkToSchemaObject/LinkToSchemaObject.tsx +20 -0
  3. package/dist/components/ProgressViewer/ProgressViewer.tsx +2 -1
  4. package/dist/components/QueryExecutionStatus/QueryExecutionStatus.tsx +3 -2
  5. package/dist/components/UsageLabel/UsageLabel.scss +6 -0
  6. package/dist/components/UsageLabel/UsageLabel.tsx +22 -0
  7. package/dist/containers/AsideNavigation/AsideNavigation.tsx +13 -8
  8. package/dist/containers/AsideNavigation/i18n/en.json +13 -0
  9. package/dist/containers/AsideNavigation/i18n/index.ts +11 -0
  10. package/dist/containers/AsideNavigation/i18n/ru.json +13 -0
  11. package/dist/containers/Node/NodeStructure/Pdisk.tsx +74 -68
  12. package/dist/containers/Node/NodeStructure/Vdisk.tsx +9 -33
  13. package/dist/containers/Nodes/Nodes.tsx +10 -2
  14. package/dist/containers/Nodes/getNodesColumns.tsx +206 -122
  15. package/dist/containers/Storage/Storage.tsx +9 -2
  16. package/dist/containers/Storage/utils/index.ts +1 -22
  17. package/dist/containers/Tenant/Diagnostics/Describe/Describe.tsx +2 -3
  18. package/dist/containers/Tenant/Diagnostics/DetailedOverview/DetailedOverview.scss +0 -1
  19. package/dist/containers/Tenant/Diagnostics/DetailedOverview/DetailedOverview.tsx +4 -2
  20. package/dist/containers/Tenant/Diagnostics/Diagnostics.tsx +1 -0
  21. package/dist/containers/Tenant/Diagnostics/TenantOverview/Healthcheck/HealthcheckDetails.tsx +8 -1
  22. package/dist/containers/Tenant/Diagnostics/TenantOverview/Healthcheck/HealthcheckPreview.tsx +11 -1
  23. package/dist/containers/Tenant/Diagnostics/TenantOverview/Healthcheck/IssuesViewer/IssueTree.tsx +0 -1
  24. package/dist/containers/Tenant/Diagnostics/TenantOverview/MetricsCards/MetricsCards.tsx +3 -0
  25. package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantCpu/TenantCpu.tsx +21 -0
  26. package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantCpu/TopNodesByCpu.tsx +53 -0
  27. package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantCpu/TopNodesByLoad.tsx +53 -0
  28. package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantCpu/TopQueries.tsx +85 -0
  29. package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantCpu/TopShards.tsx +53 -0
  30. package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantMemory/TenantMemory.tsx +9 -0
  31. package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantMemory/TopNodesByMemory.tsx +55 -0
  32. package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.scss +40 -0
  33. package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.tsx +35 -19
  34. package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantOverviewTableLayout.tsx +53 -0
  35. package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantStorage/TopTables.tsx +15 -7
  36. package/dist/containers/Tenant/Diagnostics/TenantOverview/i18n/en.json +3 -3
  37. package/dist/containers/Tenant/Diagnostics/TenantOverview/i18n/ru.json +3 -3
  38. package/dist/containers/Tenant/Diagnostics/TopQueries/TopQueries.scss +0 -2
  39. package/dist/containers/Tenant/Diagnostics/TopQueries/TopQueries.tsx +13 -61
  40. package/dist/containers/Tenant/Diagnostics/TopQueries/getTopQueriesColumns.tsx +82 -0
  41. package/dist/containers/Tenant/Diagnostics/TopShards/Filters/Filters.tsx +2 -2
  42. package/dist/containers/Tenant/Diagnostics/TopShards/TopShards.tsx +18 -97
  43. package/dist/containers/Tenant/Diagnostics/TopShards/getTopShardsColumns.tsx +138 -0
  44. package/dist/containers/Tenant/Info/ExternalTable/ExternalTable.tsx +2 -4
  45. package/dist/containers/Tenant/Query/ExecuteResult/{ExecuteResult.js → ExecuteResult.tsx} +51 -31
  46. package/dist/containers/Tenant/Query/Issues/Issues.tsx +4 -6
  47. package/dist/containers/Tenant/Query/QueryDuration/QueryDuration.tsx +1 -1
  48. package/dist/containers/Tenant/utils/paneVisibilityToggleHelpers.tsx +1 -1
  49. package/dist/routes.ts +6 -0
  50. package/dist/store/reducers/{executeTopQueries.ts → executeTopQueries/executeTopQueries.ts} +23 -75
  51. package/dist/{types/store/executeTopQueries.ts → store/reducers/executeTopQueries/types.ts} +3 -7
  52. package/dist/store/reducers/executeTopQueries/utils.ts +36 -0
  53. package/dist/store/reducers/index.ts +12 -2
  54. package/dist/store/reducers/nodes/types.ts +1 -0
  55. package/dist/store/reducers/nodes/utils.ts +16 -6
  56. package/dist/store/reducers/{shardsWorkload.ts → shardsWorkload/shardsWorkload.ts} +5 -11
  57. package/dist/{types/store/shardsWorkload.ts → store/reducers/shardsWorkload/types.ts} +3 -7
  58. package/dist/store/reducers/storage/storage.ts +1 -1
  59. package/dist/store/reducers/tenantOverview/topNodesByCpu/topNodesByCpu.ts +87 -0
  60. package/dist/store/reducers/tenantOverview/topNodesByCpu/types.ts +29 -0
  61. package/dist/store/reducers/tenantOverview/topNodesByLoad/topNodesByLoad.ts +87 -0
  62. package/dist/store/reducers/tenantOverview/topNodesByLoad/types.ts +29 -0
  63. package/dist/store/reducers/tenantOverview/topNodesByMemory/topNodesByMemory.ts +87 -0
  64. package/dist/store/reducers/tenantOverview/topNodesByMemory/types.ts +29 -0
  65. package/dist/store/reducers/tenantOverview/topQueries/tenantOverviewTopQueries.ts +93 -0
  66. package/dist/store/reducers/tenantOverview/topQueries/types.ts +14 -0
  67. package/dist/store/reducers/tenantOverview/topShards/tenantOverviewTopShards.ts +103 -0
  68. package/dist/store/reducers/tenantOverview/topShards/types.ts +14 -0
  69. package/dist/store/reducers/tenantOverview/topShards/utils.ts +3 -0
  70. package/dist/styles/mixins.scss +4 -0
  71. package/dist/types/additionalProps.ts +3 -1
  72. package/dist/types/api/compute.ts +1 -1
  73. package/dist/types/react-json-inspector.d.ts +21 -0
  74. package/dist/utils/diagnostics.ts +11 -0
  75. package/dist/utils/generateEvaluator.ts +21 -0
  76. package/package.json +1 -1
@@ -0,0 +1,29 @@
1
+ import type {IResponseError} from '../../../../types/api/error';
2
+ import type {ApiRequestAction} from '../../../utils';
3
+ import type {NodesPreparedEntity} from '../../nodes/types';
4
+ import {FETCH_TOP_NODES_BY_CPU, setDataWasNotLoaded} from './topNodesByCpu';
5
+
6
+ export interface TopNodesByCpuState {
7
+ loading: boolean;
8
+ wasLoaded: boolean;
9
+ data?: NodesPreparedEntity[];
10
+ error?: IResponseError;
11
+ }
12
+
13
+ export interface TopNodesByCpuHandledResponse {
14
+ Nodes?: NodesPreparedEntity[];
15
+ }
16
+
17
+ type TopNodesByCpuApiRequestAction = ApiRequestAction<
18
+ typeof FETCH_TOP_NODES_BY_CPU,
19
+ TopNodesByCpuHandledResponse,
20
+ IResponseError
21
+ >;
22
+
23
+ export type TopNodesByCpuAction =
24
+ | TopNodesByCpuApiRequestAction
25
+ | ReturnType<typeof setDataWasNotLoaded>;
26
+
27
+ export interface TopPoolsStateSlice {
28
+ topNodesByCpu: TopNodesByCpuState;
29
+ }
@@ -0,0 +1,87 @@
1
+ import type {Reducer} from 'redux';
2
+
3
+ import {TENANT_OVERVIEW_TABLES_LIMIT} from '../../../../utils/constants';
4
+ import {createApiRequest, createRequestActionTypes} from '../../../utils';
5
+ import {prepareNodesData} from '../../nodes/utils';
6
+ import type {NodesApiRequestParams} from '../../nodes/types';
7
+ import type {TopNodesByLoadAction, TopNodesByLoadState, TopNodesByLoadStateSlice} from './types';
8
+
9
+ export const FETCH_TOP_NODES_BY_LOAD = createRequestActionTypes(
10
+ 'topNodesByLoad',
11
+ 'FETCH_TOP_NODES_BY_LOAD',
12
+ );
13
+ const SET_DATA_WAS_NOT_LOADED = 'topNodesByLoad/SET_DATA_WAS_NOT_LOADED';
14
+
15
+ const initialState = {
16
+ loading: false,
17
+ wasLoaded: false,
18
+ };
19
+
20
+ export const topNodesByLoad: Reducer<TopNodesByLoadState, TopNodesByLoadAction> = (
21
+ state = initialState,
22
+ action,
23
+ ) => {
24
+ switch (action.type) {
25
+ case FETCH_TOP_NODES_BY_LOAD.REQUEST: {
26
+ return {
27
+ ...state,
28
+ loading: true,
29
+ };
30
+ }
31
+ case FETCH_TOP_NODES_BY_LOAD.SUCCESS: {
32
+ return {
33
+ ...state,
34
+ data: action.data?.Nodes,
35
+ loading: false,
36
+ wasLoaded: true,
37
+ error: undefined,
38
+ };
39
+ }
40
+ case FETCH_TOP_NODES_BY_LOAD.FAILURE: {
41
+ if (action.error?.isCancelled) {
42
+ return state;
43
+ }
44
+
45
+ return {
46
+ ...state,
47
+ error: action.error,
48
+ loading: false,
49
+ };
50
+ }
51
+ case SET_DATA_WAS_NOT_LOADED: {
52
+ return {
53
+ ...state,
54
+ wasLoaded: false,
55
+ };
56
+ }
57
+ default:
58
+ return state;
59
+ }
60
+ };
61
+
62
+ const concurrentId = 'getTopNodesByLoad';
63
+
64
+ export function getTopNodesByLoad({
65
+ type = 'any',
66
+ sortOrder = -1,
67
+ sortValue = 'LoadAverage',
68
+ limit = TENANT_OVERVIEW_TABLES_LIMIT,
69
+ ...params
70
+ }: NodesApiRequestParams) {
71
+ return createApiRequest({
72
+ request: window.api.getNodes(
73
+ {type, sortOrder, sortValue, limit, ...params},
74
+ {concurrentId},
75
+ ),
76
+ actions: FETCH_TOP_NODES_BY_LOAD,
77
+ dataHandler: prepareNodesData,
78
+ });
79
+ }
80
+
81
+ export const selectTopNodesByLoad = (state: TopNodesByLoadStateSlice) => state.topNodesByLoad.data;
82
+
83
+ export const setDataWasNotLoaded = () => {
84
+ return {
85
+ type: SET_DATA_WAS_NOT_LOADED,
86
+ } as const;
87
+ };
@@ -0,0 +1,29 @@
1
+ import type {IResponseError} from '../../../../types/api/error';
2
+ import type {ApiRequestAction} from '../../../utils';
3
+ import type {NodesPreparedEntity} from '../../nodes/types';
4
+ import {FETCH_TOP_NODES_BY_LOAD, setDataWasNotLoaded} from './topNodesByLoad';
5
+
6
+ export interface TopNodesByLoadState {
7
+ loading: boolean;
8
+ wasLoaded: boolean;
9
+ data?: NodesPreparedEntity[];
10
+ error?: IResponseError;
11
+ }
12
+
13
+ export interface TopNodesByLoadHandledResponse {
14
+ Nodes?: NodesPreparedEntity[];
15
+ }
16
+
17
+ type TopNodesByLoadApiRequestAction = ApiRequestAction<
18
+ typeof FETCH_TOP_NODES_BY_LOAD,
19
+ TopNodesByLoadHandledResponse,
20
+ IResponseError
21
+ >;
22
+
23
+ export type TopNodesByLoadAction =
24
+ | TopNodesByLoadApiRequestAction
25
+ | ReturnType<typeof setDataWasNotLoaded>;
26
+
27
+ export interface TopNodesByLoadStateSlice {
28
+ topNodesByLoad: TopNodesByLoadState;
29
+ }
@@ -0,0 +1,87 @@
1
+ import type {Reducer} from 'redux';
2
+
3
+ import {TENANT_OVERVIEW_TABLES_LIMIT} from '../../../../utils/constants';
4
+ import {createApiRequest, createRequestActionTypes} from '../../../utils';
5
+ import {prepareNodesData} from '../../nodes/utils';
6
+ import type {NodesApiRequestParams} from '../../nodes/types';
7
+ import type {TopNodesByMemoryAction, TopNodesByMemoryState, TopNodesByMemorySlice} from './types';
8
+
9
+ export const FETCH_TOP_NODES_BY_MEMORY = createRequestActionTypes(
10
+ 'topNodesByMemory',
11
+ 'FETCH_TOP_NODES_BY_MEMORY',
12
+ );
13
+ const SET_DATA_WAS_NOT_LOADED = 'topNodesByMemory/SET_DATA_WAS_NOT_LOADED';
14
+
15
+ const initialState = {
16
+ loading: false,
17
+ wasLoaded: false,
18
+ };
19
+
20
+ export const topNodesByMemory: Reducer<TopNodesByMemoryState, TopNodesByMemoryAction> = (
21
+ state = initialState,
22
+ action,
23
+ ) => {
24
+ switch (action.type) {
25
+ case FETCH_TOP_NODES_BY_MEMORY.REQUEST: {
26
+ return {
27
+ ...state,
28
+ loading: true,
29
+ };
30
+ }
31
+ case FETCH_TOP_NODES_BY_MEMORY.SUCCESS: {
32
+ return {
33
+ ...state,
34
+ data: action.data?.Nodes,
35
+ loading: false,
36
+ wasLoaded: true,
37
+ error: undefined,
38
+ };
39
+ }
40
+ case FETCH_TOP_NODES_BY_MEMORY.FAILURE: {
41
+ if (action.error?.isCancelled) {
42
+ return state;
43
+ }
44
+
45
+ return {
46
+ ...state,
47
+ error: action.error,
48
+ loading: false,
49
+ };
50
+ }
51
+ case SET_DATA_WAS_NOT_LOADED: {
52
+ return {
53
+ ...state,
54
+ wasLoaded: false,
55
+ };
56
+ }
57
+ default:
58
+ return state;
59
+ }
60
+ };
61
+
62
+ const concurrentId = 'getTopNodeByMemory';
63
+
64
+ export function getTopNodesByMemory({
65
+ type = 'any',
66
+ sortOrder = -1,
67
+ sortValue = 'Memory',
68
+ limit = TENANT_OVERVIEW_TABLES_LIMIT,
69
+ ...params
70
+ }: NodesApiRequestParams) {
71
+ return createApiRequest({
72
+ request: window.api.getNodes(
73
+ {type, sortOrder, sortValue, limit, ...params},
74
+ {concurrentId},
75
+ ),
76
+ actions: FETCH_TOP_NODES_BY_MEMORY,
77
+ dataHandler: prepareNodesData,
78
+ });
79
+ }
80
+
81
+ export const selectTopNodesByMemory = (state: TopNodesByMemorySlice) => state.topNodesByMemory.data;
82
+
83
+ export const setDataWasNotLoaded = () => {
84
+ return {
85
+ type: SET_DATA_WAS_NOT_LOADED,
86
+ } as const;
87
+ };
@@ -0,0 +1,29 @@
1
+ import type {IResponseError} from '../../../../types/api/error';
2
+ import type {ApiRequestAction} from '../../../utils';
3
+ import type {NodesPreparedEntity} from '../../nodes/types';
4
+ import {FETCH_TOP_NODES_BY_MEMORY, setDataWasNotLoaded} from './topNodesByMemory';
5
+
6
+ export interface TopNodesByMemoryState {
7
+ loading: boolean;
8
+ wasLoaded: boolean;
9
+ data?: NodesPreparedEntity[];
10
+ error?: IResponseError;
11
+ }
12
+
13
+ export interface TopNodesByMemoryHandledResponse {
14
+ Nodes?: NodesPreparedEntity[];
15
+ }
16
+
17
+ type TopNodesByMemoryApiRequestAction = ApiRequestAction<
18
+ typeof FETCH_TOP_NODES_BY_MEMORY,
19
+ TopNodesByMemoryHandledResponse,
20
+ IResponseError
21
+ >;
22
+
23
+ export type TopNodesByMemoryAction =
24
+ | TopNodesByMemoryApiRequestAction
25
+ | ReturnType<typeof setDataWasNotLoaded>;
26
+
27
+ export interface TopNodesByMemorySlice {
28
+ topNodesByMemory: TopNodesByMemoryState;
29
+ }
@@ -0,0 +1,93 @@
1
+ import type {Reducer} from 'redux';
2
+
3
+ import '../../../../services/api';
4
+ import {TENANT_OVERVIEW_TABLES_LIMIT} from '../../../../utils/constants';
5
+ import {parseQueryAPIExecuteResponse} from '../../../../utils/query';
6
+
7
+ import {createRequestActionTypes, createApiRequest} from '../../../utils';
8
+ import type {TenantOverviewTopQueriesAction, TenantOverviewTopQueriesState} from './types';
9
+
10
+ export const FETCH_TENANT_OVERVIEW_TOP_QUERIES = createRequestActionTypes(
11
+ 'tenantOverviewTopQueries',
12
+ 'FETCH_TOP_QUERIES',
13
+ );
14
+ const SET_DATA_WAS_NOT_LOADED = 'tenantOverviewTopQueries/SET_DATA_WAS_NOT_LOADED';
15
+
16
+ const initialState = {
17
+ loading: false,
18
+ wasLoaded: false,
19
+ filters: {},
20
+ };
21
+
22
+ const getQueryText = (path: string) => {
23
+ return `
24
+ SELECT
25
+ CPUTime as CPUTimeUs,
26
+ QueryText,
27
+ FROM \`${path}/.sys/top_queries_by_cpu_time_one_hour\`
28
+ ORDER BY CPUTimeUs DESC
29
+ LIMIT ${TENANT_OVERVIEW_TABLES_LIMIT}
30
+ `;
31
+ };
32
+
33
+ export const tenantOverviewTopQueries: Reducer<
34
+ TenantOverviewTopQueriesState,
35
+ TenantOverviewTopQueriesAction
36
+ > = (state = initialState, action) => {
37
+ switch (action.type) {
38
+ case FETCH_TENANT_OVERVIEW_TOP_QUERIES.REQUEST: {
39
+ return {
40
+ ...state,
41
+ loading: true,
42
+ error: undefined,
43
+ };
44
+ }
45
+ case FETCH_TENANT_OVERVIEW_TOP_QUERIES.SUCCESS: {
46
+ return {
47
+ ...state,
48
+ data: action.data,
49
+ loading: false,
50
+ error: undefined,
51
+ wasLoaded: true,
52
+ };
53
+ }
54
+ // 401 Unauthorized error is handled by GenericAPI
55
+ case FETCH_TENANT_OVERVIEW_TOP_QUERIES.FAILURE: {
56
+ return {
57
+ ...state,
58
+ error: action.error || 'Unauthorized',
59
+ loading: false,
60
+ };
61
+ }
62
+ case SET_DATA_WAS_NOT_LOADED:
63
+ return {
64
+ ...state,
65
+ wasLoaded: false,
66
+ };
67
+ default:
68
+ return state;
69
+ }
70
+ };
71
+
72
+ export const fetchTenantOverviewTopQueries = (database: string) =>
73
+ createApiRequest({
74
+ request: window.api.sendQuery(
75
+ {
76
+ schema: 'modern',
77
+ query: getQueryText(database),
78
+ database,
79
+ action: 'execute-scan',
80
+ },
81
+ {
82
+ concurrentId: 'executeTopQueries',
83
+ },
84
+ ),
85
+ actions: FETCH_TENANT_OVERVIEW_TOP_QUERIES,
86
+ dataHandler: parseQueryAPIExecuteResponse,
87
+ });
88
+
89
+ export function setDataWasNotLoaded() {
90
+ return {
91
+ type: SET_DATA_WAS_NOT_LOADED,
92
+ } as const;
93
+ }
@@ -0,0 +1,14 @@
1
+ import type {IQueryResult, QueryErrorResponse} from '../../../../types/store/query';
2
+ import type {ApiRequestAction} from '../../../utils';
3
+ import {FETCH_TENANT_OVERVIEW_TOP_QUERIES, setDataWasNotLoaded} from './tenantOverviewTopQueries';
4
+
5
+ export interface TenantOverviewTopQueriesState {
6
+ loading: boolean;
7
+ wasLoaded: boolean;
8
+ data?: IQueryResult;
9
+ error?: QueryErrorResponse;
10
+ }
11
+
12
+ export type TenantOverviewTopQueriesAction =
13
+ | ApiRequestAction<typeof FETCH_TENANT_OVERVIEW_TOP_QUERIES, IQueryResult, QueryErrorResponse>
14
+ | ReturnType<typeof setDataWasNotLoaded>;
@@ -0,0 +1,103 @@
1
+ import type {Reducer} from 'redux';
2
+
3
+ import '../../../../services/api';
4
+ import {TENANT_OVERVIEW_TABLES_LIMIT} from '../../../../utils/constants';
5
+ import {parseQueryAPIExecuteResponse} from '../../../../utils/query';
6
+ import {createRequestActionTypes, createApiRequest} from '../../../utils';
7
+ import {TenantOverviewTopShardsAction, TenantOverviewTopShardsState} from './types';
8
+
9
+ export const FETCH_TENANT_OVERVIEW_TOP_SHARDS = createRequestActionTypes(
10
+ 'tenantOverviewTopShards',
11
+ 'FETCH_TENANT_OVERVIEW_TOP_SHARDS',
12
+ );
13
+ const SET_DATA_WAS_NOT_LOADED = 'tenantOverviewTopShards/SET_DATA_WAS_NOT_LOADED';
14
+
15
+ const initialState = {
16
+ loading: false,
17
+ wasLoaded: false,
18
+ };
19
+
20
+ function createShardQuery(path: string, tenantName?: string) {
21
+ const pathSelect = tenantName
22
+ ? `CAST(SUBSTRING(CAST(Path AS String), ${tenantName.length}) AS Utf8) AS Path`
23
+ : 'Path';
24
+
25
+ return `SELECT
26
+ ${pathSelect},
27
+ TabletId,
28
+ CPUCores,
29
+ FROM \`.sys/partition_stats\`
30
+ WHERE
31
+ Path='${path}'
32
+ OR Path LIKE '${path}/%'
33
+ ORDER BY CPUCores DESC
34
+ LIMIT ${TENANT_OVERVIEW_TABLES_LIMIT}`;
35
+ }
36
+
37
+ const queryAction = 'execute-scan';
38
+
39
+ export const tenantOverviewTopShards: Reducer<
40
+ TenantOverviewTopShardsState,
41
+ TenantOverviewTopShardsAction
42
+ > = (state = initialState, action) => {
43
+ switch (action.type) {
44
+ case FETCH_TENANT_OVERVIEW_TOP_SHARDS.REQUEST: {
45
+ return {
46
+ ...state,
47
+ loading: true,
48
+ error: undefined,
49
+ };
50
+ }
51
+ case FETCH_TENANT_OVERVIEW_TOP_SHARDS.SUCCESS: {
52
+ return {
53
+ ...state,
54
+ data: action.data,
55
+ loading: false,
56
+ error: undefined,
57
+ wasLoaded: true,
58
+ };
59
+ }
60
+ // 401 Unauthorized error is handled by GenericAPI
61
+ case FETCH_TENANT_OVERVIEW_TOP_SHARDS.FAILURE: {
62
+ if (action.error?.isCancelled) {
63
+ return state;
64
+ }
65
+
66
+ return {
67
+ ...state,
68
+ error: action.error || 'Unauthorized',
69
+ loading: false,
70
+ };
71
+ }
72
+ case SET_DATA_WAS_NOT_LOADED:
73
+ return {
74
+ ...state,
75
+ wasLoaded: false,
76
+ };
77
+ default:
78
+ return state;
79
+ }
80
+ };
81
+
82
+ export const sendTenantOverviewTopShardsQuery = (database: string, path = '') =>
83
+ createApiRequest({
84
+ request: window.api.sendQuery(
85
+ {
86
+ schema: 'modern',
87
+ query: createShardQuery(path, database),
88
+ database,
89
+ action: queryAction,
90
+ },
91
+ {
92
+ concurrentId: 'executeTopShards',
93
+ },
94
+ ),
95
+ actions: FETCH_TENANT_OVERVIEW_TOP_SHARDS,
96
+ dataHandler: parseQueryAPIExecuteResponse,
97
+ });
98
+
99
+ export function setDataWasNotLoaded() {
100
+ return {
101
+ type: SET_DATA_WAS_NOT_LOADED,
102
+ } as const;
103
+ }
@@ -0,0 +1,14 @@
1
+ import type {IQueryResult, QueryErrorResponse} from '../../../../types/store/query';
2
+ import type {ApiRequestAction} from '../../../utils';
3
+ import {FETCH_TENANT_OVERVIEW_TOP_SHARDS, setDataWasNotLoaded} from './tenantOverviewTopShards';
4
+
5
+ export interface TenantOverviewTopShardsState {
6
+ loading: boolean;
7
+ wasLoaded: boolean;
8
+ data?: IQueryResult;
9
+ error?: QueryErrorResponse;
10
+ }
11
+
12
+ export type TenantOverviewTopShardsAction =
13
+ | ApiRequestAction<typeof FETCH_TENANT_OVERVIEW_TOP_SHARDS, IQueryResult, QueryErrorResponse>
14
+ | ReturnType<typeof setDataWasNotLoaded>;
@@ -0,0 +1,3 @@
1
+ import {generateEvaluator} from '../../../../utils/generateEvaluator';
2
+
3
+ export const getLoadSeverityForShard = generateEvaluator(60, 80, ['success', 'warning', 'danger']);
@@ -177,6 +177,10 @@
177
177
  .data-table__table-wrapper {
178
178
  padding-bottom: 20px;
179
179
  }
180
+
181
+ &_sticky-head_fixed {
182
+ overflow: initial;
183
+ }
180
184
  }
181
185
  }
182
186
  }
@@ -26,6 +26,8 @@ export interface AdditionalTenantsProps {
26
26
 
27
27
  export type NodeAddress = Pick<TSystemStateInfo, 'Host' | 'Endpoints' | 'NodeId'>;
28
28
 
29
+ export type GetNodeRefFunc = (node?: NodeAddress) => string | null;
30
+
29
31
  export interface AdditionalNodesProps extends Record<string, unknown> {
30
- getNodeRef?: (node?: NodeAddress) => string | null;
32
+ getNodeRef?: GetNodeRefFunc;
31
33
  }
@@ -20,7 +20,7 @@ export interface TComputeInfo {
20
20
  Nodes?: TComputeNodeInfo[]; // v2
21
21
  }
22
22
 
23
- interface TComputeTenantInfo {
23
+ export interface TComputeTenantInfo {
24
24
  Overall: EFlag;
25
25
  Name: string;
26
26
  Nodes?: TComputeNodeInfo[];
@@ -0,0 +1,21 @@
1
+ declare module 'react-json-inspector' {
2
+ // This typing is sufficient for current use cases, but some types are incompelete
3
+ class JSONTree extends React.Component<{
4
+ data?: object;
5
+ search?: boolean;
6
+ searchOptions?: {
7
+ debounceTime?: number;
8
+ };
9
+ onClick?: ({path: string, key: string, value: object}) => void;
10
+ validateQuery?: (query: string) => boolean;
11
+ isExpanded?: (keypath: string) => boolean;
12
+ filterOptions?: {
13
+ cacheResults?: bool;
14
+ ignoreCase?: bool;
15
+ };
16
+ query?: string;
17
+ verboseShowOriginal?: boolean;
18
+ className?: string;
19
+ }> {}
20
+ export default JSONTree;
21
+ }
@@ -0,0 +1,11 @@
1
+ import {ValueOf} from '../types/common';
2
+
3
+ export const TOP_SHARDS_SORT_VALUES = {
4
+ CPUCores: 'CPUCores',
5
+ DataSize: 'DataSize',
6
+ } as const;
7
+
8
+ export type TopShardsSortValue = ValueOf<typeof TOP_SHARDS_SORT_VALUES>;
9
+
10
+ export const isSortableTopShardsProperty = (value: string): value is TopShardsSortValue =>
11
+ Object.values(TOP_SHARDS_SORT_VALUES).includes(value as TopShardsSortValue);
@@ -0,0 +1,21 @@
1
+ export const generateEvaluator =
2
+ <OkLevel extends string, WarnLevel extends string, CritLevel extends string>(
3
+ warn: number,
4
+ crit: number,
5
+ levels: [OkLevel, WarnLevel, CritLevel],
6
+ ) =>
7
+ (value: number) => {
8
+ if (0 <= value && value < warn) {
9
+ return levels[0];
10
+ }
11
+
12
+ if (warn <= value && value < crit) {
13
+ return levels[1];
14
+ }
15
+
16
+ if (crit <= value) {
17
+ return levels[2];
18
+ }
19
+
20
+ return undefined;
21
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ydb-embedded-ui",
3
- "version": "4.19.2",
3
+ "version": "4.20.0",
4
4
  "files": [
5
5
  "dist"
6
6
  ],