ydb-embedded-ui 3.1.0 → 3.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (124) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/README.md +2 -0
  3. package/dist/components/DateRange/DateRange.scss +11 -0
  4. package/dist/{containers/Tenant/Diagnostics/TopShards → components}/DateRange/DateRange.tsx +7 -7
  5. package/dist/{containers/Tenant/Diagnostics/TopShards → components}/DateRange/index.ts +0 -0
  6. package/dist/components/EntitiesCount/EntitiesCount.tsx +34 -0
  7. package/dist/components/EntitiesCount/i18n/en.json +3 -0
  8. package/dist/components/{AsideNavigation/Settings → EntitiesCount}/i18n/index.ts +2 -2
  9. package/dist/components/EntitiesCount/i18n/ru.json +3 -0
  10. package/dist/components/EntitiesCount/index.ts +1 -0
  11. package/dist/components/Fullscreen/Fullscreen.scss +7 -5
  12. package/dist/components/Illustration/Illustration.tsx +4 -11
  13. package/dist/components/InfoViewer/InfoViewer.scss +2 -0
  14. package/dist/components/TabletsOverall/TabletsOverall.tsx +4 -4
  15. package/dist/components/TabletsStatistic/TabletsStatistic.tsx +56 -0
  16. package/dist/components/TabletsStatistic/index.ts +1 -0
  17. package/dist/containers/App/App.scss +4 -12
  18. package/dist/containers/AsideNavigation/AsideNavigation.scss +0 -18
  19. package/dist/containers/AsideNavigation/AsideNavigation.tsx +95 -33
  20. package/dist/containers/Heatmap/Heatmap.scss +0 -7
  21. package/dist/containers/Heatmap/Heatmap.tsx +203 -0
  22. package/dist/containers/Heatmap/HeatmapCanvas/HeatmapCanvas.js +2 -1
  23. package/dist/containers/Heatmap/index.ts +1 -0
  24. package/dist/containers/Node/Node.tsx +1 -1
  25. package/dist/containers/Storage/DiskStateProgressBar/DiskStateProgressBar.tsx +1 -1
  26. package/dist/containers/Storage/Storage.js +12 -19
  27. package/dist/containers/Storage/StorageNodes/StorageNodes.tsx +16 -0
  28. package/dist/containers/Tablets/Tablets.scss +0 -5
  29. package/dist/containers/Tablets/Tablets.tsx +172 -0
  30. package/dist/containers/Tablets/i18n/en.json +6 -0
  31. package/dist/{components/AsideNavigation → containers/Tablets}/i18n/index.ts +1 -1
  32. package/dist/containers/Tablets/i18n/ru.json +6 -0
  33. package/dist/containers/Tablets/index.ts +1 -0
  34. package/dist/containers/TabletsFilters/TabletsFilters.js +4 -8
  35. package/dist/containers/TabletsFilters/TabletsFilters.scss +6 -2
  36. package/dist/containers/Tenant/Diagnostics/Diagnostics.tsx +8 -13
  37. package/dist/containers/Tenant/Diagnostics/DiagnosticsPages.ts +7 -7
  38. package/dist/containers/Tenant/Diagnostics/{TopShards/TopShards.scss → OverloadedShards/OverloadedShards.scss} +1 -1
  39. package/dist/containers/Tenant/Diagnostics/{TopShards/TopShards.tsx → OverloadedShards/OverloadedShards.tsx} +10 -11
  40. package/dist/containers/Tenant/Diagnostics/{TopShards → OverloadedShards}/i18n/en.json +0 -0
  41. package/dist/containers/Tenant/Diagnostics/OverloadedShards/i18n/index.ts +11 -0
  42. package/dist/containers/Tenant/Diagnostics/{TopShards → OverloadedShards}/i18n/ru.json +0 -0
  43. package/dist/containers/Tenant/Diagnostics/OverloadedShards/index.ts +1 -0
  44. package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.js +7 -7
  45. package/dist/containers/Tenant/Diagnostics/TopQueries/TopQueries.scss +16 -19
  46. package/dist/containers/Tenant/Diagnostics/TopQueries/TopQueries.tsx +202 -0
  47. package/dist/containers/Tenant/Diagnostics/TopQueries/i18n/en.json +4 -0
  48. package/dist/containers/Tenant/Diagnostics/{TopShards → TopQueries}/i18n/index.ts +1 -1
  49. package/dist/containers/Tenant/Diagnostics/TopQueries/i18n/ru.json +4 -0
  50. package/dist/containers/Tenant/Diagnostics/TopQueries/index.ts +1 -0
  51. package/dist/containers/Tenants/Tenants.js +1 -1
  52. package/dist/containers/UserSettings/UserSettings.tsx +5 -4
  53. package/dist/routes.ts +1 -1
  54. package/dist/services/api.d.ts +7 -0
  55. package/dist/store/reducers/describe.ts +4 -1
  56. package/dist/store/reducers/executeTopQueries.ts +170 -0
  57. package/dist/store/reducers/{heatmap.js → heatmap.ts} +33 -18
  58. package/dist/store/reducers/settings.js +13 -3
  59. package/dist/store/reducers/shardsWorkload.ts +9 -9
  60. package/dist/store/reducers/storage.js +2 -0
  61. package/dist/store/reducers/{tablets.js → tablets.ts} +30 -17
  62. package/dist/store/state-url-mapping.js +10 -2
  63. package/dist/types/api/compute.ts +52 -0
  64. package/dist/types/api/consumer.ts +257 -0
  65. package/dist/types/api/enums.ts +2 -2
  66. package/dist/types/api/nodes.ts +5 -2
  67. package/dist/types/api/pdisk.ts +3 -0
  68. package/dist/types/api/schema.ts +17 -3
  69. package/dist/types/api/storage.ts +31 -28
  70. package/dist/types/api/tablet.ts +18 -2
  71. package/dist/types/api/tenant.ts +4 -1
  72. package/dist/types/api/topic.ts +157 -0
  73. package/dist/types/api/vdisk.ts +3 -0
  74. package/dist/types/store/executeTopQueries.ts +29 -0
  75. package/dist/types/store/heatmap.ts +51 -0
  76. package/dist/types/store/schema.ts +3 -3
  77. package/dist/types/store/shardsWorkload.ts +3 -3
  78. package/dist/types/store/tablets.ts +42 -0
  79. package/dist/utils/constants.ts +1 -37
  80. package/dist/utils/getNodesColumns.js +14 -2
  81. package/dist/utils/tablet.ts +53 -0
  82. package/package.json +4 -3
  83. package/dist/components/AsideNavigation/AsideHeader.scss +0 -147
  84. package/dist/components/AsideNavigation/AsideHeader.tsx +0 -389
  85. package/dist/components/AsideNavigation/AsideHeaderFooterItem/AsideHeaderFooterItem.scss +0 -82
  86. package/dist/components/AsideNavigation/AsideHeaderFooterItem/AsideHeaderFooterItem.tsx +0 -138
  87. package/dist/components/AsideNavigation/AsideHeaderFooterSlot/AsideHeaderFooterSlot.tsx +0 -33
  88. package/dist/components/AsideNavigation/AsideHeaderFooterSlot/SlotsContext.tsx +0 -49
  89. package/dist/components/AsideNavigation/AsideHeaderTooltip/AsideHeaderTooltip.scss +0 -16
  90. package/dist/components/AsideNavigation/AsideHeaderTooltip/AsideHeaderTooltip.tsx +0 -37
  91. package/dist/components/AsideNavigation/CompositeBar/CompositeBar.scss +0 -108
  92. package/dist/components/AsideNavigation/CompositeBar/CompositeBar.tsx +0 -282
  93. package/dist/components/AsideNavigation/Content/Content.tsx +0 -35
  94. package/dist/components/AsideNavigation/Drawer/Drawer.scss +0 -76
  95. package/dist/components/AsideNavigation/Drawer/Drawer.tsx +0 -134
  96. package/dist/components/AsideNavigation/Drawer/index.ts +0 -1
  97. package/dist/components/AsideNavigation/Logo/Logo.scss +0 -43
  98. package/dist/components/AsideNavigation/Logo/Logo.tsx +0 -82
  99. package/dist/components/AsideNavigation/Settings/README.md +0 -92
  100. package/dist/components/AsideNavigation/Settings/Settings.scss +0 -128
  101. package/dist/components/AsideNavigation/Settings/Settings.tsx +0 -270
  102. package/dist/components/AsideNavigation/Settings/SettingsMenu/SettingsMenu.scss +0 -78
  103. package/dist/components/AsideNavigation/Settings/SettingsMenu/SettingsMenu.tsx +0 -141
  104. package/dist/components/AsideNavigation/Settings/SettingsSearch/SettingsSearch.tsx +0 -57
  105. package/dist/components/AsideNavigation/Settings/collect-settings.ts +0 -156
  106. package/dist/components/AsideNavigation/Settings/filter-settings.ts +0 -38
  107. package/dist/components/AsideNavigation/Settings/helpers.ts +0 -39
  108. package/dist/components/AsideNavigation/Settings/i18n/en.json +0 -5
  109. package/dist/components/AsideNavigation/Settings/i18n/ru.json +0 -5
  110. package/dist/components/AsideNavigation/Settings/index.ts +0 -1
  111. package/dist/components/AsideNavigation/constants.ts +0 -28
  112. package/dist/components/AsideNavigation/helpers.ts +0 -34
  113. package/dist/components/AsideNavigation/i18n/en.json +0 -4
  114. package/dist/components/AsideNavigation/i18n/ru.json +0 -4
  115. package/dist/components/AsideNavigation/icons.ts +0 -32
  116. package/dist/components/AsideNavigation/types.ts +0 -23
  117. package/dist/components/TabletsStatistic/TabletsStatistic.js +0 -58
  118. package/dist/containers/Heatmap/Heatmap.js +0 -244
  119. package/dist/containers/Tablets/Tablets.js +0 -228
  120. package/dist/containers/Tenant/Diagnostics/TopQueries/TopQueries.js +0 -188
  121. package/dist/containers/Tenant/Diagnostics/TopShards/DateRange/DateRange.scss +0 -13
  122. package/dist/containers/Tenant/Diagnostics/TopShards/index.ts +0 -1
  123. package/dist/store/reducers/executeTopQueries.js +0 -66
  124. package/dist/types/api/consumers.ts +0 -3
@@ -9,11 +9,10 @@ import {Switch, Tabs} from '@gravity-ui/uikit';
9
9
 
10
10
  import {Loader} from '../../../components/Loader';
11
11
 
12
- //@ts-ignore
13
- import TopQueries from './TopQueries/TopQueries';
12
+ import {TopQueries} from './TopQueries';
14
13
  //@ts-ignore
15
14
  import DetailedOverview from './DetailedOverview/DetailedOverview';
16
- import {TopShards} from './TopShards';
15
+ import {OverloadedShards} from './OverloadedShards';
17
16
  //@ts-ignore
18
17
  import Storage from '../../Storage/Storage';
19
18
  //@ts-ignore
@@ -23,11 +22,11 @@ import Describe from './Describe/Describe';
23
22
  //@ts-ignore
24
23
  import HotKeys from './HotKeys/HotKeys';
25
24
  //@ts-ignore
26
- import Heatmap from '../../Heatmap/Heatmap';
25
+ import {Heatmap} from '../../Heatmap';
27
26
  //@ts-ignore
28
27
  import Compute from './Compute/Compute';
29
28
  //@ts-ignore
30
- import Tablets from '../../Tablets/Tablets';
29
+ import {Tablets} from '../../Tablets';
31
30
  import {Consumers} from './Consumers';
32
31
 
33
32
  import routes, {createHref} from '../../../routes';
@@ -51,11 +50,7 @@ const b = cn('kv-tenant-diagnostics');
51
50
 
52
51
  function Diagnostics(props: DiagnosticsProps) {
53
52
  const dispatch = useDispatch();
54
- const {
55
- currentSchemaPath,
56
- currentSchema: currentItem = {},
57
- autorefresh,
58
- } = useSelector((state: any) => state.schema);
53
+ const {currentSchemaPath, autorefresh} = useSelector((state: any) => state.schema);
59
54
  const {diagnosticsTab = GeneralPagesIds.overview, wasLoaded} = useSelector(
60
55
  (state: any) => state.tenant,
61
56
  );
@@ -130,8 +125,8 @@ function Diagnostics(props: DiagnosticsProps) {
130
125
  />
131
126
  );
132
127
  }
133
- case GeneralPagesIds.topShards: {
134
- return <TopShards tenantPath={tenantNameString} type={type} />;
128
+ case GeneralPagesIds.overloadedShards: {
129
+ return <OverloadedShards tenantPath={tenantNameString} type={type} />;
135
130
  }
136
131
  case GeneralPagesIds.nodes: {
137
132
  return (
@@ -157,7 +152,7 @@ function Diagnostics(props: DiagnosticsProps) {
157
152
  return <HotKeys type={type} />;
158
153
  }
159
154
  case GeneralPagesIds.graph: {
160
- return <Heatmap path={currentItem.Path} />;
155
+ return <Heatmap path={currentSchemaPath} />;
161
156
  }
162
157
  case GeneralPagesIds.consumers: {
163
158
  return <Consumers path={currentSchemaPath} type={type} />;
@@ -3,7 +3,7 @@ import {EPathType} from '../../../types/api/schema';
3
3
  export enum GeneralPagesIds {
4
4
  'overview' = 'Overview',
5
5
  'topQueries' = 'topQueries',
6
- 'topShards' = 'topShards',
6
+ 'overloadedShards' = 'overloadedShards',
7
7
  'nodes' = 'Nodes',
8
8
  'tablets' = 'Tablets',
9
9
  'storage' = 'Storage',
@@ -29,9 +29,9 @@ const topQueries = {
29
29
  title: 'Top queries',
30
30
  };
31
31
 
32
- const topShards = {
33
- id: GeneralPagesIds.topShards,
34
- title: 'Top shards',
32
+ const overloadedShards = {
33
+ id: GeneralPagesIds.overloadedShards,
34
+ title: 'Overloaded shards',
35
35
  };
36
36
 
37
37
  const nodes = {
@@ -75,7 +75,7 @@ const consumers = {
75
75
  export const DATABASE_PAGES = [
76
76
  overview,
77
77
  topQueries,
78
- topShards,
78
+ overloadedShards,
79
79
  nodes,
80
80
  tablets,
81
81
  storage,
@@ -83,9 +83,9 @@ export const DATABASE_PAGES = [
83
83
  describe,
84
84
  ];
85
85
 
86
- export const TABLE_PAGES = [overview, topShards, graph, tablets, hotKeys, describe];
86
+ export const TABLE_PAGES = [overview, overloadedShards, graph, tablets, hotKeys, describe];
87
87
 
88
- export const DIR_PAGES = [overview, topShards, describe];
88
+ export const DIR_PAGES = [overview, overloadedShards, describe];
89
89
 
90
90
  export const CDC_STREAM_PAGES = [overview, consumers, describe];
91
91
  export const TOPIC_PAGES = [overview, consumers, describe];
@@ -1,4 +1,4 @@
1
- .top-shards {
1
+ .overloaded-shards {
2
2
  display: flex;
3
3
  flex-direction: column;
4
4
 
@@ -5,6 +5,7 @@ import cn from 'bem-cn-lite';
5
5
  import DataTable, {Column, Settings, SortOrder} from '@yandex-cloud/react-data-table';
6
6
  import {Loader} from '@gravity-ui/uikit';
7
7
 
8
+ import {DateRange, DateRangeValues} from '../../../../components/DateRange';
8
9
  import InternalLink from '../../../../components/InternalLink/InternalLink';
9
10
 
10
11
  import HistoryContext from '../../../../contexts/HistoryContext';
@@ -13,8 +14,8 @@ import routes, {createHref} from '../../../../routes';
13
14
 
14
15
  import {
15
16
  sendShardQuery,
16
- setShardQueryOptions,
17
- setTopShardFilters,
17
+ setShardsState,
18
+ setShardsQueryFilters,
18
19
  } from '../../../../store/reducers/shardsWorkload';
19
20
  import {setCurrentSchemaPath, getSchema} from '../../../../store/reducers/schema';
20
21
  import type {IShardsWorkloadFilters} from '../../../../types/store/shardsWorkload';
@@ -30,12 +31,10 @@ import {getDefaultNodePath} from '../../../Node/NodePages';
30
31
 
31
32
  import {isColumnEntityType} from '../../utils/schema';
32
33
 
33
- import {DateRange, DateRangeValues} from './DateRange';
34
-
35
34
  import i18n from './i18n';
36
- import './TopShards.scss';
35
+ import './OverloadedShards.scss';
37
36
 
38
- const b = cn('top-shards');
37
+ const b = cn('overloaded-shards');
39
38
  const bLink = cn('yc-link');
40
39
 
41
40
  const TABLE_SETTINGS: Settings = {
@@ -83,12 +82,12 @@ function dataTableToStringSortOrder(value: SortOrder | SortOrder[] = []) {
83
82
  return sortOrders.map(({columnId}) => columnId).join(',');
84
83
  }
85
84
 
86
- interface TopShardsProps {
85
+ interface OverloadedShardsProps {
87
86
  tenantPath: string;
88
87
  type?: EPathType;
89
88
  }
90
89
 
91
- export const TopShards = ({tenantPath, type}: TopShardsProps) => {
90
+ export const OverloadedShards = ({tenantPath, type}: OverloadedShardsProps) => {
92
91
  const dispatch = useDispatch();
93
92
 
94
93
  const {autorefresh, currentSchemaPath} = useTypedSelector((state) => state.schema);
@@ -134,7 +133,7 @@ export const TopShards = ({tenantPath, type}: TopShardsProps) => {
134
133
  // don't show loader for requests triggered by table sort, only for path change
135
134
  useEffect(() => {
136
135
  dispatch(
137
- setShardQueryOptions({
136
+ setShardsState({
138
137
  wasLoaded: false,
139
138
  data: undefined,
140
139
  }),
@@ -144,14 +143,14 @@ export const TopShards = ({tenantPath, type}: TopShardsProps) => {
144
143
  const history = useContext(HistoryContext);
145
144
 
146
145
  const onSort = (newSortOrder?: SortOrder | SortOrder[]) => {
147
- // omit information about sort order to disable ASC order, only DESC makes sense for top shards
146
+ // omit information about sort order to disable ASC order, only DESC makes sense for overloaded shards
148
147
  // use a string (and not the DataTable default format) to prevent reference change,
149
148
  // which would cause an excess state change, to avoid repeating requests
150
149
  setSortOrder(dataTableToStringSortOrder(newSortOrder));
151
150
  };
152
151
 
153
152
  const handleDateRangeChange = (value: DateRangeValues) => {
154
- dispatch(setTopShardFilters(value));
153
+ dispatch(setShardsQueryFilters(value));
155
154
  setFilters(value);
156
155
  };
157
156
 
@@ -0,0 +1,11 @@
1
+ import {i18n, Lang} from '../../../../../utils/i18n';
2
+
3
+ import en from './en.json';
4
+ import ru from './ru.json';
5
+
6
+ const COMPONENT = 'ydb-diagnostics-overloaded-shards';
7
+
8
+ i18n.registerKeyset(Lang.En, COMPONENT, en);
9
+ i18n.registerKeyset(Lang.Ru, COMPONENT, ru);
10
+
11
+ export default i18n.keyset(COMPONENT);
@@ -0,0 +1 @@
1
+ export * from './OverloadedShards';
@@ -171,18 +171,18 @@ class TenantOverview extends React.Component {
171
171
  ))}
172
172
  </div>
173
173
  <div className={b('common-info')}>
174
- {PoolStats ? (
175
- <div>
176
- <div className={b('section-title')}>Pools</div>
174
+ <div>
175
+ <div className={b('section-title')}>Pools</div>
176
+ {PoolStats ? (
177
177
  <div className={b('section', {pools: true})}>
178
178
  {PoolStats.map((pool, poolIndex) => (
179
179
  <PoolUsage key={poolIndex} data={pool} />
180
180
  ))}
181
181
  </div>
182
- </div>
183
- ) : (
184
- <div className="error">no pools data</div>
185
- )}
182
+ ) : (
183
+ <div className="error">no pools data</div>
184
+ )}
185
+ </div>
186
186
  <InfoViewer
187
187
  title="Metrics"
188
188
  className={b('section', {metrics: true})}
@@ -1,43 +1,40 @@
1
1
  @import '../../../../styles/mixins.scss';
2
2
 
3
3
  .kv-top-queries {
4
+ display: flex;
5
+ flex-direction: column;
6
+
4
7
  height: 100%;
5
8
 
6
9
  @include query-data-table;
7
- &__message-container {
8
- padding: 15px 0;
9
- }
10
10
 
11
11
  &__loader {
12
12
  display: flex;
13
13
  justify-content: center;
14
14
  }
15
15
 
16
- &__owner-container {
17
- margin: 10px;
16
+ &__controls {
17
+ display: flex;
18
+ flex-wrap: wrap;
19
+ gap: 16px;
18
20
 
19
- .yc-staff-card {
20
- display: inline-block;
21
- }
21
+ margin-bottom: 10px;
22
22
  }
23
23
 
24
- &__text {
25
- font-size: var(--yc-text-body-1-font-size);
26
- line-height: var(--yc-text-body-1-line-height);
27
-
28
- color: var(--yc-color-text-primary);
29
-
30
- &::first-letter {
31
- color: var(--yc-color-text-danger);
32
- }
24
+ &__search {
25
+ @include search();
33
26
  }
34
27
 
35
- &__result &__table-content {
36
- & .data-table {
28
+ &__result {
29
+ overflow: auto;
30
+ flex-grow: 1;
31
+
32
+ .data-table {
37
33
  &,
38
34
  &__table {
39
35
  width: 100%;
40
36
  }
37
+
41
38
  &__td {
42
39
  vertical-align: top;
43
40
  white-space: pre;
@@ -0,0 +1,202 @@
1
+ import {useCallback, useEffect, useRef, useState} from 'react';
2
+ import {useDispatch} from 'react-redux';
3
+ import cn from 'bem-cn-lite';
4
+
5
+ import DataTable, {Column, Settings} from '@yandex-cloud/react-data-table';
6
+ import {Loader} from '@gravity-ui/uikit';
7
+
8
+ import {DateRange, DateRangeValues} from '../../../../components/DateRange';
9
+ import {Search} from '../../../../components/Search';
10
+ import TruncatedQuery from '../../../../components/TruncatedQuery/TruncatedQuery';
11
+
12
+ import {changeUserInput} from '../../../../store/reducers/executeQuery';
13
+ import {
14
+ fetchTopQueries,
15
+ setTopQueriesFilters,
16
+ setTopQueriesState,
17
+ } from '../../../../store/reducers/executeTopQueries';
18
+
19
+ import type {KeyValueRow} from '../../../../types/api/query';
20
+ import type {EPathType} from '../../../../types/api/schema';
21
+ import type {ITopQueriesFilters} from '../../../../types/store/executeTopQueries';
22
+ import type {IQueryResult} from '../../../../types/store/query';
23
+
24
+ import {DEFAULT_TABLE_SETTINGS, HOUR_IN_SECONDS} from '../../../../utils/constants';
25
+ import {useAutofetcher, useTypedSelector} from '../../../../utils/hooks';
26
+ import {prepareQueryError} from '../../../../utils/query';
27
+
28
+ import {isColumnEntityType} from '../../utils/schema';
29
+ import {TenantGeneralTabsIds} from '../../TenantPages';
30
+
31
+ import i18n from './i18n';
32
+ import './TopQueries.scss';
33
+
34
+ const b = cn('kv-top-queries');
35
+
36
+ const TABLE_SETTINGS: Settings = {
37
+ ...DEFAULT_TABLE_SETTINGS,
38
+ dynamicRenderType: 'variable',
39
+ };
40
+
41
+ const MAX_QUERY_HEIGHT = 10;
42
+ const COLUMNS: Column<KeyValueRow>[] = [
43
+ {
44
+ name: 'CPUTimeUs',
45
+ width: 140,
46
+ sortAccessor: (row) => Number(row['CPUTimeUs']),
47
+ },
48
+ {
49
+ name: 'QueryText',
50
+ width: 500,
51
+ sortable: false,
52
+ render: ({value}) => <TruncatedQuery value={value} maxQueryHeight={MAX_QUERY_HEIGHT} />,
53
+ },
54
+ ];
55
+
56
+ interface TopQueriesProps {
57
+ path: string;
58
+ changeSchemaTab: (tab: TenantGeneralTabsIds) => void;
59
+ type?: EPathType;
60
+ }
61
+
62
+ export const TopQueries = ({path, type, changeSchemaTab}: TopQueriesProps) => {
63
+ const dispatch = useDispatch();
64
+
65
+ const {autorefresh} = useTypedSelector((state) => state.schema);
66
+
67
+ const {
68
+ loading,
69
+ wasLoaded,
70
+ error,
71
+ data: {result: data = undefined} = {},
72
+ filters: storeFilters,
73
+ } = useTypedSelector((state) => state.executeTopQueries);
74
+
75
+ const preventFetch = useRef(false);
76
+
77
+ // some filters sync between redux state and URL
78
+ // component state is for default values,
79
+ // default values are determined from the query response, and should not propagate to URL
80
+ const [filters, setFilters] = useState<ITopQueriesFilters>(storeFilters);
81
+
82
+ useEffect(() => {
83
+ dispatch(setTopQueriesFilters(filters));
84
+ }, [dispatch, filters]);
85
+
86
+ const setDefaultFiltersFromResponse = (responseData?: IQueryResult) => {
87
+ const intervalEnd = responseData?.result?.[0]?.IntervalEnd;
88
+
89
+ if (intervalEnd) {
90
+ const to = new Date(intervalEnd).getTime();
91
+ const from = new Date(to - HOUR_IN_SECONDS * 1000).getTime();
92
+
93
+ setFilters((currentFilters) => {
94
+ // request without filters returns the latest interval with data
95
+ // only in this case should update filters in ui
96
+ // also don't update if user already interacted with controls
97
+ const shouldUpdateFilters = !currentFilters.from && !currentFilters.to;
98
+
99
+ if (!shouldUpdateFilters) {
100
+ return currentFilters;
101
+ }
102
+
103
+ preventFetch.current = true;
104
+
105
+ return {...currentFilters, from, to};
106
+ });
107
+ }
108
+ };
109
+
110
+ useAutofetcher(
111
+ (isBackground) => {
112
+ if (preventFetch.current) {
113
+ preventFetch.current = false;
114
+ return;
115
+ }
116
+
117
+ if (!isBackground) {
118
+ dispatch(
119
+ setTopQueriesState({
120
+ wasLoaded: false,
121
+ data: undefined,
122
+ }),
123
+ );
124
+ }
125
+
126
+ // @ts-expect-error
127
+ // typed dispatch required, remove error expectation after adding it
128
+ dispatch(fetchTopQueries({database: path, filters})).then(
129
+ setDefaultFiltersFromResponse,
130
+ );
131
+ },
132
+ [dispatch, filters, path],
133
+ autorefresh,
134
+ );
135
+
136
+ const handleRowClick = useCallback(
137
+ (row) => {
138
+ const {QueryText: input} = row;
139
+
140
+ dispatch(changeUserInput({input}));
141
+ changeSchemaTab(TenantGeneralTabsIds.query);
142
+ },
143
+ [changeSchemaTab, dispatch],
144
+ );
145
+
146
+ const handleTextSearchUpdate = (text: string) => {
147
+ setFilters((currentFilters) => ({...currentFilters, text}));
148
+ };
149
+
150
+ const handleDateRangeChange = (value: DateRangeValues) => {
151
+ setFilters((currentFilters) => ({...currentFilters, ...value}));
152
+ };
153
+
154
+ const renderLoader = () => {
155
+ return (
156
+ <div className={b('loader')}>
157
+ <Loader size="m" />
158
+ </div>
159
+ );
160
+ };
161
+
162
+ const renderContent = () => {
163
+ if (loading && !wasLoaded) {
164
+ return renderLoader();
165
+ }
166
+
167
+ if (error && !error.isCancelled) {
168
+ return <div className="error">{prepareQueryError(error)}</div>;
169
+ }
170
+
171
+ if (!data || isColumnEntityType(type)) {
172
+ return i18n('no-data');
173
+ }
174
+
175
+ return (
176
+ <div className={b('result')}>
177
+ <DataTable
178
+ columns={COLUMNS}
179
+ data={data}
180
+ settings={TABLE_SETTINGS}
181
+ onRowClick={handleRowClick}
182
+ theme="yandex-cloud"
183
+ />
184
+ </div>
185
+ );
186
+ };
187
+
188
+ return (
189
+ <div className={b()}>
190
+ <div className={b('controls')}>
191
+ <Search
192
+ value={filters.text}
193
+ onChange={handleTextSearchUpdate}
194
+ placeholder={i18n('filter.text.placeholder')}
195
+ className={b('search')}
196
+ />
197
+ <DateRange from={filters.from} to={filters.to} onChange={handleDateRangeChange} />
198
+ </div>
199
+ {renderContent()}
200
+ </div>
201
+ );
202
+ };
@@ -0,0 +1,4 @@
1
+ {
2
+ "no-data": "No data",
3
+ "filter.text.placeholder": "Search by query text..."
4
+ }
@@ -3,7 +3,7 @@ import {i18n, Lang} from '../../../../../utils/i18n';
3
3
  import en from './en.json';
4
4
  import ru from './ru.json';
5
5
 
6
- const COMPONENT = 'ydb-diagnostics-top-shards';
6
+ const COMPONENT = 'ydb-diagnostics-top-queries';
7
7
 
8
8
  i18n.registerKeyset(Lang.En, COMPONENT, en);
9
9
  i18n.registerKeyset(Lang.Ru, COMPONENT, ru);
@@ -0,0 +1,4 @@
1
+ {
2
+ "no-data": "Нет данных",
3
+ "filter.text.placeholder": "Искать по тексту запроса..."
4
+ }
@@ -0,0 +1 @@
1
+ export * from './TopQueries';
@@ -9,7 +9,7 @@ import {Loader, TextInput, Button} from '@gravity-ui/uikit';
9
9
 
10
10
  import EntityStatus from '../../components/EntityStatus/EntityStatus';
11
11
  import PoolsGraph from '../../components/PoolsGraph/PoolsGraph';
12
- import TabletsStatistic from '../../components/TabletsStatistic/TabletsStatistic';
12
+ import {TabletsStatistic} from '../../components/TabletsStatistic';
13
13
  import {ProblemFilter} from '../../components/ProblemFilter';
14
14
  import {Illustration} from '../../components/Illustration';
15
15
  import {AutoFetcher} from '../../utils/autofetcher';
@@ -1,12 +1,13 @@
1
1
  import {connect} from 'react-redux';
2
2
 
3
3
  import {RadioButton, Switch} from '@gravity-ui/uikit';
4
- import {Settings} from '../../components/AsideNavigation/Settings';
4
+ import {Settings} from '@gravity-ui/navigation';
5
+
5
6
  import favoriteFilledIcon from '../../assets/icons/star.svg';
6
7
  import flaskIcon from '../../assets/icons/flask.svg';
7
- //@ts-ignore
8
+
8
9
  import {INVERTED_DISKS_KEY, THEME_KEY} from '../../utils/constants';
9
- //@ts-ignore
10
+
10
11
  import {setSettingValue} from '../../store/reducers/settings';
11
12
 
12
13
  enum Theme {
@@ -67,7 +68,7 @@ const mapStateToProps = (state: any) => {
67
68
 
68
69
  return {
69
70
  theme,
70
- invertedDisks,
71
+ invertedDisks: JSON.parse(invertedDisks),
71
72
  };
72
73
  };
73
74
 
package/dist/routes.ts CHANGED
@@ -28,7 +28,7 @@ export const CLUSTER_PAGES = {
28
28
  export function createHref(
29
29
  route: string,
30
30
  params?: object,
31
- query: Record<string | number, string | number> = {},
31
+ query: Record<string | number, string | number | string[] | number[] | undefined> = {},
32
32
  ) {
33
33
  let extendedQuery = query;
34
34
 
@@ -48,6 +48,13 @@ interface Window {
48
48
  getTenantInfo: (params: {
49
49
  path: string;
50
50
  }) => Promise<import('../types/api/tenant').TTenantInfo>;
51
+ getTabletsInfo: (params: {
52
+ nodes?: string[];
53
+ path?: string;
54
+ }) => Promise<import('../types/api/tablet').TEvTabletStateResponse>;
55
+ getHeatmapData: (params: {
56
+ path: string;
57
+ }) => Promise<import('../types/api/schema').TEvDescribeSchemeResult>;
51
58
  [method: string]: Function;
52
59
  };
53
60
  }
@@ -2,7 +2,6 @@ import {createSelector, Selector} from 'reselect';
2
2
  import {Reducer} from 'redux';
3
3
 
4
4
  import '../../services/api';
5
- import {IConsumer} from '../../types/api/consumers';
6
5
  import {
7
6
  IDescribeRootStateSlice,
8
7
  IDescribeState,
@@ -100,6 +99,10 @@ const selectConsumersNames = (state: IDescribeRootStateSlice, path?: string) =>
100
99
  ? state.describe.data[path]?.PathDescription?.PersQueueGroup?.PQTabletConfig?.ReadRules
101
100
  : undefined;
102
101
 
102
+ interface IConsumer {
103
+ name: string;
104
+ }
105
+
103
106
  export const selectConsumers: Selector<IDescribeRootStateSlice, IConsumer[], [string | undefined]> =
104
107
  createSelector(selectConsumersNames, (names = []) => names.map((name) => ({name})));
105
108