ydb-embedded-ui 1.14.2 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (133) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/dist/assets/illustrations/dark/thumbsUp.svg +15 -0
  3. package/dist/assets/illustrations/light/thumbsUp.svg +15 -0
  4. package/dist/components/AsideNavigation/AsideHeader.tsx +1 -1
  5. package/dist/components/AsideNavigation/AsideHeaderFooterItem/AsideHeaderFooterItem.tsx +1 -1
  6. package/dist/components/AsideNavigation/AsideHeaderTooltip/AsideHeaderTooltip.tsx +1 -1
  7. package/dist/components/AsideNavigation/CompositeBar/CompositeBar.tsx +1 -1
  8. package/dist/components/AsideNavigation/Logo/Logo.tsx +1 -1
  9. package/dist/components/AsideNavigation/Settings/Settings.tsx +1 -1
  10. package/dist/components/AsideNavigation/Settings/SettingsMenu/SettingsMenu.tsx +1 -1
  11. package/dist/components/AsideNavigation/Settings/SettingsSearch/SettingsSearch.tsx +1 -1
  12. package/dist/components/AsideNavigation/Settings/collect-settings.ts +1 -1
  13. package/dist/components/Breadcrumbs/Breadcrumbs.js +1 -1
  14. package/dist/components/ClusterInfo/ClusterInfo.tsx +1 -1
  15. package/dist/components/Collapse/Collapse.js +1 -1
  16. package/dist/components/CopyToClipboard/CopyToClipboard.tsx +1 -1
  17. package/dist/components/CriticalActionDialog/CriticalActionDialog.js +1 -1
  18. package/dist/components/EmptyState/EmptyState.scss +0 -1
  19. package/dist/components/EnableFullscreenButton/EnableFullscreenButton.tsx +1 -1
  20. package/dist/components/EntityStatus/EntityStatus.js +28 -3
  21. package/dist/components/EntityStatus/EntityStatus.scss +22 -1
  22. package/dist/components/Fullscreen/Fullscreen.tsx +1 -1
  23. package/dist/components/Icon/Icon.js +1 -1
  24. package/dist/components/Illustration/Illustration.tsx +3 -1
  25. package/dist/components/Loader/Loader.tsx +1 -1
  26. package/dist/components/NodesViewer/NodesViewer.js +5 -2
  27. package/dist/components/Pagination/Pagination.js +1 -1
  28. package/dist/components/ProblemFilter/ProblemFilter.js +1 -1
  29. package/dist/components/ShortyString/ShortyString.tsx +1 -1
  30. package/dist/components/TableSkeleton/TableSkeleton.tsx +1 -1
  31. package/dist/components/TabletsOverall/TabletsOverall.tsx +1 -1
  32. package/dist/containers/App/App.js +1 -1
  33. package/dist/containers/App/App.scss +0 -10
  34. package/dist/containers/App/Content.js +1 -1
  35. package/dist/containers/App/TipPopup/TipPopup.js +1 -1
  36. package/dist/containers/AsideNavigation/AsideNavigation.tsx +1 -1
  37. package/dist/containers/Authentication/Authentication.tsx +1 -1
  38. package/dist/containers/Group/Group.js +1 -1
  39. package/dist/containers/Header/Header.tsx +1 -1
  40. package/dist/containers/Header/Host/Host.js +1 -1
  41. package/dist/containers/Heatmap/Heatmap.js +1 -1
  42. package/dist/containers/Node/Node.tsx +1 -1
  43. package/dist/containers/Node/NodeStructure/Pdisk.tsx +1 -1
  44. package/dist/containers/Nodes/Nodes.js +4 -2
  45. package/dist/containers/Pdisk/Pdisk.js +1 -1
  46. package/dist/containers/Pool/Pool.js +3 -2
  47. package/dist/containers/ReduxTooltip/ReduxTooltip.js +1 -1
  48. package/dist/containers/Storage/EmptyFilter/EmptyFilter.tsx +34 -0
  49. package/dist/containers/Storage/EmptyFilter/i18n/en.json +4 -0
  50. package/dist/containers/Storage/EmptyFilter/i18n/index.ts +11 -0
  51. package/dist/containers/Storage/EmptyFilter/i18n/ru.json +4 -0
  52. package/dist/containers/Storage/Pdisk/Pdisk.tsx +1 -1
  53. package/dist/containers/Storage/Storage.js +3 -1
  54. package/dist/containers/Storage/StorageFilter/StorageFilter.tsx +2 -1
  55. package/dist/containers/Storage/StorageGroups/StorageGroups.tsx +27 -6
  56. package/dist/containers/Storage/StorageGroups/i18n/en.json +6 -0
  57. package/dist/containers/Storage/StorageGroups/i18n/index.ts +11 -0
  58. package/dist/containers/Storage/StorageGroups/i18n/ru.json +6 -0
  59. package/dist/containers/Storage/StorageNodes/StorageNodes.tsx +24 -7
  60. package/dist/containers/Storage/StorageNodes/i18n/en.json +6 -0
  61. package/dist/containers/Storage/StorageNodes/i18n/index.ts +11 -0
  62. package/dist/containers/Storage/StorageNodes/i18n/ru.json +6 -0
  63. package/dist/containers/Storage/UsageFilter/UsageFilter.tsx +1 -1
  64. package/dist/containers/Storage/Vdisk/Vdisk.js +1 -1
  65. package/dist/containers/Tablet/Tablet.js +1 -1
  66. package/dist/containers/Tablets/Tablets.js +1 -1
  67. package/dist/containers/TabletsFilters/TabletsFilters.js +1 -1
  68. package/dist/containers/Tenant/Acl/Acl.js +1 -1
  69. package/dist/containers/Tenant/Diagnostics/Compute/Compute.js +1 -1
  70. package/dist/containers/Tenant/Diagnostics/Describe/Describe.js +1 -1
  71. package/dist/containers/Tenant/Diagnostics/DetailedOverview/DetailedOverview.tsx +3 -4
  72. package/dist/containers/Tenant/Diagnostics/Diagnostics.tsx +1 -1
  73. package/dist/containers/Tenant/Diagnostics/Healthcheck/Healthcheck.scss +7 -1
  74. package/dist/containers/Tenant/Diagnostics/Healthcheck/Healthcheck.tsx +86 -0
  75. package/dist/containers/Tenant/Diagnostics/Healthcheck/IssuePreview/IssuePreview.tsx +34 -0
  76. package/dist/containers/Tenant/Diagnostics/Healthcheck/IssuePreview/index.ts +1 -0
  77. package/dist/containers/Tenant/Diagnostics/Healthcheck/IssuesList/IssuesList.tsx +69 -0
  78. package/dist/containers/Tenant/Diagnostics/Healthcheck/IssuesList/index.ts +1 -0
  79. package/dist/containers/Tenant/Diagnostics/Healthcheck/Preview/Preview.tsx +80 -0
  80. package/dist/containers/Tenant/Diagnostics/Healthcheck/Preview/index.ts +1 -0
  81. package/dist/containers/Tenant/Diagnostics/Healthcheck/i18n/en.json +11 -0
  82. package/dist/containers/Tenant/Diagnostics/Healthcheck/i18n/index.ts +11 -0
  83. package/dist/containers/Tenant/Diagnostics/Healthcheck/i18n/ru.json +11 -0
  84. package/dist/containers/Tenant/Diagnostics/Healthcheck/index.ts +1 -0
  85. package/dist/containers/Tenant/Diagnostics/HotKeys/HotKeys.js +1 -1
  86. package/dist/containers/Tenant/Diagnostics/Network/Network.js +3 -2
  87. package/dist/containers/Tenant/Diagnostics/Network/Network.scss +1 -1
  88. package/dist/containers/Tenant/Diagnostics/Overview/Overview.tsx +17 -35
  89. package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.js +1 -1
  90. package/dist/containers/Tenant/Diagnostics/TopQueries/TopQueries.js +3 -3
  91. package/dist/containers/Tenant/Diagnostics/TopShards/TopShards.js +3 -3
  92. package/dist/containers/Tenant/ObjectGeneral/ObjectGeneral.tsx +1 -1
  93. package/dist/containers/Tenant/ObjectGeneralTabs/ObjectGeneralTabs.tsx +1 -1
  94. package/dist/containers/Tenant/ObjectSummary/ObjectSummary.tsx +1 -1
  95. package/dist/containers/Tenant/Preview/Preview.js +1 -1
  96. package/dist/containers/Tenant/QueryEditor/Issues/Issues.scss +2 -3
  97. package/dist/containers/Tenant/QueryEditor/Issues/Issues.tsx +1 -1
  98. package/dist/containers/Tenant/QueryEditor/QueriesHistory/QueriesHistory.tsx +1 -1
  99. package/dist/containers/Tenant/QueryEditor/QueryEditor.js +2 -2
  100. package/dist/containers/Tenant/QueryEditor/QueryExplain/QueryExplain.js +63 -45
  101. package/dist/containers/Tenant/QueryEditor/QueryExplain/QueryExplain.scss +8 -4
  102. package/dist/containers/Tenant/QueryEditor/QueryResult/QueryResult.js +1 -1
  103. package/dist/containers/Tenant/QueryEditor/QueryResult/QueryResult.scss +1 -0
  104. package/dist/containers/Tenant/QueryEditor/SaveQuery/SaveQuery.js +1 -1
  105. package/dist/containers/Tenant/QueryEditor/SavedQueries/SavedQueries.js +1 -1
  106. package/dist/containers/Tenant/Schema/SchemaInfoViewer/SchemaInfoViewer.scss +2 -2
  107. package/dist/containers/Tenant/utils/paneVisibilityToggleHelpers.tsx +1 -1
  108. package/dist/containers/Tenants/Tenants.js +4 -2
  109. package/dist/containers/UserSettings/UserSettings.tsx +2 -2
  110. package/dist/containers/Vdisk/Vdisk.js +1 -1
  111. package/dist/containers/VdiskPdiskNode/VdiskPdiskNode.js +1 -1
  112. package/dist/index.js +1 -1
  113. package/dist/services/api.d.ts +9 -0
  114. package/dist/setupTests.js +1 -1
  115. package/dist/store/reducers/executeTopQueries.js +6 -9
  116. package/dist/store/reducers/explainQuery.js +27 -36
  117. package/dist/store/reducers/olapStats.js +6 -8
  118. package/dist/store/reducers/shardsWorkload.js +6 -8
  119. package/dist/types/api/healthcheck.ts +91 -0
  120. package/dist/types/api/query.ts +32 -21
  121. package/dist/types/assets.d.ts +1 -1
  122. package/dist/types/store/healthcheck.ts +3 -0
  123. package/dist/types/store/query.ts +1 -1
  124. package/dist/utils/createToast.tsx +1 -1
  125. package/dist/utils/getNodesColumns.js +1 -1
  126. package/dist/utils/hooks/index.ts +1 -0
  127. package/dist/utils/hooks/useAutofetcher.ts +29 -0
  128. package/dist/utils/i18n/i18n.ts +1 -1
  129. package/dist/utils/prepareQueryExplain.ts +0 -4
  130. package/dist/utils/query.test.ts +59 -1
  131. package/dist/utils/query.ts +38 -4
  132. package/package.json +9 -11
  133. package/dist/containers/Tenant/Diagnostics/Healthcheck/Healthcheck.js +0 -195
@@ -0,0 +1,91 @@
1
+ export enum SelfCheckResult {
2
+ UNSPECIFIED = 'UNSPECIFIED',
3
+ GOOD = 'GOOD',
4
+ DEGRADED = 'DEGRADED',
5
+ MAINTENANCE_REQUIRED = 'MAINTENANCE_REQUIRED',
6
+ EMERGENCY = 'EMERGENCY',
7
+ }
8
+
9
+ enum StatusFlag {
10
+ UNSPECIFIED = 'UNSPECIFIED',
11
+ GREY = 'GREY',
12
+ GREEN = 'GREEN',
13
+ BLUE = 'BLUE',
14
+ YELLOW = 'YELLOW',
15
+ ORANGE = 'ORANGE',
16
+ RED = 'RED',
17
+ }
18
+
19
+ interface LocationNode {
20
+ id: number;
21
+ host: string;
22
+ port: number;
23
+ }
24
+
25
+ interface LocationStoragePDisk {
26
+ id: string;
27
+ path: string;
28
+ }
29
+
30
+ interface LocationStorageVDisk {
31
+ id: string;
32
+ pdisk: LocationStoragePDisk;
33
+ }
34
+
35
+ interface LocationStorageGroup {
36
+ id: string;
37
+ vdisk: LocationStorageVDisk;
38
+ }
39
+
40
+ interface LocationStoragePool {
41
+ name: string;
42
+ group: LocationStorageGroup;
43
+ }
44
+
45
+ interface LocationStorage {
46
+ node: LocationNode;
47
+ pool: LocationStoragePool;
48
+ }
49
+
50
+ interface LocationComputePool {
51
+ name: string;
52
+ }
53
+
54
+ interface LocationComputeTablet {
55
+ type: string;
56
+ id?: string[];
57
+ count: number;
58
+ }
59
+
60
+ interface LocationCompute {
61
+ node: LocationNode;
62
+ pool: LocationComputePool;
63
+ tablet: LocationComputeTablet;
64
+ }
65
+
66
+ interface LocationDatabase {
67
+ name: string;
68
+ }
69
+
70
+ interface Location {
71
+ storage: LocationStorage;
72
+ compute: LocationCompute;
73
+ database: LocationDatabase;
74
+ }
75
+
76
+ export interface IssueLog {
77
+ id: string;
78
+ status: StatusFlag;
79
+ message: string;
80
+ location: Location;
81
+ reason?: string[];
82
+ type: string;
83
+ level: number;
84
+ }
85
+
86
+ export interface HealthCheckAPIResponse {
87
+ // eslint-disable-next-line camelcase
88
+ self_check_result: SelfCheckResult;
89
+ // eslint-disable-next-line camelcase
90
+ issue_log?: IssueLog[];
91
+ }
@@ -46,15 +46,12 @@ export interface ColumnType {
46
46
  // modern response
47
47
 
48
48
  export type ExecuteModernResponse = {
49
- // either both fields exist, or neither one does
50
- // they can be undefined for queries like `insert into`
51
- result?: ArrayRow[];
52
- columns?: ColumnType[];
49
+ result: ArrayRow[];
50
+ columns: ColumnType[];
53
51
  } & CommonFields;
54
52
 
55
53
  export type ExecuteClassicResponseDeep = {
56
- // can be undefined for queries like `insert into`
57
- result?: KeyValueRow[];
54
+ result: KeyValueRow[];
58
55
  } & CommonFields;
59
56
 
60
57
  // can be undefined for queries like `insert into`
@@ -63,19 +60,20 @@ export type ExecuteClassicResponsePlain = KeyValueRow[] | undefined;
63
60
  export type ExecuteClassicResponse = ExecuteClassicResponseDeep | ExecuteClassicResponsePlain;
64
61
 
65
62
  export type ExecuteYdbResponse = {
66
- // can be undefined for queries like `insert into`
67
- result?: KeyValueRow[];
63
+ result: KeyValueRow[];
68
64
  } & CommonFields;
69
65
 
70
- type ExecuteResponse<Schema extends Schemas> = (
71
- Schema extends 'modern'
72
- ? ExecuteModernResponse
73
- : Schema extends 'ydb'
74
- ? ExecuteYdbResponse
75
- : Schema extends 'classic' | undefined
76
- ? ExecuteClassicResponse
77
- : unknown
78
- );
66
+ type ExecuteResponse<Schema extends Schemas> =
67
+ | CommonFields // result can be undefined for queries like `insert into`
68
+ | (
69
+ Schema extends 'modern'
70
+ ? ExecuteModernResponse
71
+ : Schema extends 'ydb'
72
+ ? ExecuteYdbResponse
73
+ : Schema extends 'classic' | undefined
74
+ ? ExecuteClassicResponse
75
+ : unknown
76
+ );
79
77
 
80
78
  // deprecated response from older versions, backward compatibility
81
79
 
@@ -107,9 +105,9 @@ type ExplainResponse = CommonFields;
107
105
 
108
106
  type DeprecatedExplainResponse<Action extends ExplainActions> = (
109
107
  Action extends 'explain-ast'
110
- ? {ast: AST} & DeprecatedCommonFields
111
- : Actions extends 'explain'
112
- ? ({result: Plan} & DeprecatedCommonFields) | Plan
108
+ ? ({result: {ast: AST}} & Required<DeprecatedCommonFields>) | {ast: AST}
109
+ : Action extends 'explain'
110
+ ? ({result: Plan} & Required<DeprecatedCommonFields>) | Plan
113
111
  : unknown
114
112
  );
115
113
 
@@ -138,10 +136,23 @@ export type AnyExecuteResponse =
138
136
  | ExecuteModernResponse
139
137
  | ExecuteClassicResponse
140
138
  | ExecuteYdbResponse
141
- | DeprecatedExecuteResponse;
139
+ | CommonFields
140
+ | DeprecatedExecuteResponse
141
+ | null;
142
142
 
143
143
  export type DeepExecuteResponse =
144
144
  | ExecuteModernResponse
145
145
  | ExecuteClassicResponseDeep
146
146
  | ExecuteYdbResponse
147
147
  | DeprecatedExecuteResponseDeep;
148
+
149
+ export type AnyExplainResponse =
150
+ | ExplainResponse
151
+ | CommonFields
152
+ | DeprecatedExplainResponse<'explain'>
153
+ | DeprecatedExplainResponse<'explain-ast'>
154
+ | null;
155
+
156
+ export type AnyResponse =
157
+ | AnyExecuteResponse
158
+ | AnyExplainResponse;
@@ -9,4 +9,4 @@ declare module '*.jpeg';
9
9
  declare module '*.ico';
10
10
 
11
11
  declare type SVGIconData =
12
- import('@yandex-cloud/uikit/build/esm/components/Icon/types').SVGIconData;
12
+ import('@gravity-ui/uikit/build/esm/components/Icon/types').SVGIconData;
@@ -0,0 +1,3 @@
1
+ import type {HealthCheckAPIResponse} from "../api/healthcheck";
2
+
3
+ export type IHealthCheck = HealthCheckAPIResponse;
@@ -5,5 +5,5 @@ export interface IQueryResult {
5
5
  columns?: ColumnType[];
6
6
  stats?: any;
7
7
  plan?: any;
8
- ast?: any;
8
+ ast?: string;
9
9
  }
@@ -1,4 +1,4 @@
1
- import {Toaster} from '@yandex-cloud/uikit';
1
+ import {Toaster} from '@gravity-ui/uikit';
2
2
 
3
3
  const toaster = new Toaster();
4
4
 
@@ -1,6 +1,6 @@
1
1
  import cn from 'bem-cn-lite';
2
2
  import DataTable from '@yandex-cloud/react-data-table';
3
- import {Button, Popover} from '@yandex-cloud/uikit';
3
+ import {Button, Popover} from '@gravity-ui/uikit';
4
4
 
5
5
  import Icon from '../components/Icon/Icon';
6
6
  import EntityStatus from '../components/EntityStatus/EntityStatus';
@@ -0,0 +1 @@
1
+ export * from './useAutofetcher';
@@ -0,0 +1,29 @@
1
+ import {DependencyList, useEffect, useRef} from 'react';
2
+
3
+ import {AutoFetcher} from '../autofetcher';
4
+
5
+ export const useAutofetcher = (fetchData: VoidFunction, deps: DependencyList, enabled = true) => {
6
+ const ref = useRef<AutoFetcher | null>(null);
7
+
8
+ if (ref.current === null) {
9
+ ref.current = new AutoFetcher();
10
+ }
11
+
12
+ const autofetcher = ref.current;
13
+
14
+ // initial fetch
15
+ useEffect(fetchData, deps); // eslint-disable-line react-hooks/exhaustive-deps
16
+
17
+ useEffect(() => {
18
+ autofetcher.stop();
19
+
20
+ if (enabled) {
21
+ autofetcher.start();
22
+ autofetcher.fetch(fetchData);
23
+ }
24
+
25
+ return () => {
26
+ autofetcher.stop();
27
+ };
28
+ }, [enabled, ...deps]); // eslint-disable-line react-hooks/exhaustive-deps
29
+ };
@@ -1,4 +1,4 @@
1
- import {I18N} from '@yandex-cloud/i18n';
1
+ import {I18N} from '@gravity-ui/i18n';
2
2
 
3
3
  export enum Lang {
4
4
  En = 'en',
@@ -59,8 +59,6 @@ export function preparePlan(plan: Plan) {
59
59
  const nodes: GraphNode[] = [];
60
60
  const links: Link[] = [];
61
61
 
62
- let graphDepth = 0;
63
-
64
62
  function parsePlans(plans: Plan[] = [], from: string, curDepth: number) {
65
63
  const depth = curDepth + 1;
66
64
  plans.forEach((p) => {
@@ -77,7 +75,6 @@ export function preparePlan(plan: Plan) {
77
75
  };
78
76
  nodes.push(node);
79
77
  links.push({from, to: node.name});
80
- graphDepth = Math.max(graphDepth, depth);
81
78
  parsePlans(p.Plans, node.name, depth);
82
79
  });
83
80
  }
@@ -96,6 +93,5 @@ export function preparePlan(plan: Plan) {
96
93
  return {
97
94
  nodes,
98
95
  links,
99
- graphDepth,
100
96
  };
101
97
  }
@@ -1,4 +1,7 @@
1
- import {parseQueryAPIExecuteResponse} from './query';
1
+ import {
2
+ parseQueryAPIExecuteResponse,
3
+ parseQueryAPIExplainResponse,
4
+ } from './query';
2
5
 
3
6
  describe('API utils', () => {
4
7
  describe('json/viewer/query', () => {
@@ -185,5 +188,60 @@ describe('API utils', () => {
185
188
  });
186
189
  });
187
190
  });
191
+
192
+ describe('parseQueryAPIExplainResponse', () => {
193
+ it('should handle empty response', () => {
194
+ expect(parseQueryAPIExplainResponse(null)).toEqual({});
195
+ });
196
+
197
+ it('should accept stats without a plan', () => {
198
+ const stats = {metric: 'good'};
199
+ expect(parseQueryAPIExplainResponse({stats}).stats).toEqual(stats);
200
+ });
201
+
202
+ describe('old format', () => {
203
+ describe('explain', () => {
204
+ it('should parse plan data in the root', () => {
205
+ const plan = {foo: 'bar'};
206
+ expect(parseQueryAPIExplainResponse(plan).plan).toEqual(plan);
207
+ });
208
+
209
+ it('should parse plan in the result field with stats', () => {
210
+ const plan = {foo: 'bar'};
211
+ const stats = {metric: 'good'};
212
+ const actual = parseQueryAPIExplainResponse({result: plan, stats});
213
+ expect(actual.plan).toEqual(plan);
214
+ expect(actual.stats).toEqual(stats);
215
+ });
216
+ });
217
+
218
+ describe('explain-ast', () => {
219
+ it('should parse ast field in the root', () => {
220
+ const ast = 'ast';
221
+ expect(parseQueryAPIExplainResponse({ast}).ast).toBe(ast);
222
+ });
223
+
224
+ it('should parse ast in the result field with stats', () => {
225
+ const ast = 'ast';
226
+ const stats = {metric: 'good'};
227
+ const actual = parseQueryAPIExplainResponse({result: {ast}, stats});
228
+ expect(actual.ast).toBe(ast);
229
+ expect(actual.stats).toEqual(stats);
230
+ });
231
+ });
232
+ });
233
+
234
+ describe('new format', () => {
235
+ it('should parse explain response with stats', () => {
236
+ const plan = {foo: 'bar'};
237
+ const ast = 'ast';
238
+ const stats = {metric: 'good'};
239
+ const actual = parseQueryAPIExplainResponse({plan, ast, stats});
240
+ expect(actual.plan).toEqual(plan);
241
+ expect(actual.ast).toBe(ast);
242
+ expect(actual.stats).toEqual(stats);
243
+ });
244
+ });
245
+ });
188
246
  });
189
247
  });
@@ -1,14 +1,14 @@
1
1
  import {YQLType} from '../types';
2
2
  import type {
3
3
  AnyExecuteResponse,
4
+ AnyExplainResponse,
5
+ AnyResponse,
4
6
  CommonFields,
5
7
  DeepExecuteResponse,
6
8
  DeprecatedExecuteResponsePlain,
7
9
  ExecuteClassicResponsePlain,
8
10
  ExecuteModernResponse,
9
11
  KeyValueRow,
10
- QueryAPIExecuteResponse,
11
- Schemas,
12
12
  } from '../types/api/query';
13
13
  import type {IQueryResult} from '../types/store/query';
14
14
 
@@ -97,13 +97,13 @@ const isModern = (response: AnyExecuteResponse): response is ExecuteModernRespon
97
97
  Array.isArray((response as ExecuteModernResponse).columns)
98
98
  );
99
99
 
100
- const hasCommonFields = (data: AnyExecuteResponse): data is CommonFields => Boolean(
100
+ const hasCommonFields = (data: AnyResponse): data is CommonFields => Boolean(
101
101
  data && typeof data === 'object' && ('ast' in data || 'plan' in data || 'stats' in data)
102
102
  );
103
103
 
104
104
  // complex logic because of the variety of possible responses
105
105
  // after all backends are updated to the latest version, it can be simplified
106
- export const parseQueryAPIExecuteResponse = <T extends Schemas>(data: QueryAPIExecuteResponse<T>): IQueryResult => {
106
+ export const parseQueryAPIExecuteResponse = (data: AnyExecuteResponse): IQueryResult => {
107
107
  if (!data) {
108
108
  return {};
109
109
  }
@@ -128,6 +128,40 @@ export const parseQueryAPIExecuteResponse = <T extends Schemas>(data: QueryAPIEx
128
128
  };
129
129
  };
130
130
 
131
+ // complex logic because of the variety of possible responses
132
+ // after all backends are updated to the latest version, it can be simplified
133
+ export const parseQueryAPIExplainResponse = (data: AnyExplainResponse): IQueryResult => {
134
+ if (!data) {
135
+ return {};
136
+ }
137
+
138
+ if ('ast' in data) {
139
+ return data;
140
+ }
141
+
142
+ if ('result' in data) {
143
+ const {result, ...restData} = data;
144
+
145
+ if ('ast' in data.result) {
146
+ return {
147
+ ast: result.ast,
148
+ ...restData,
149
+ };
150
+ }
151
+
152
+ return {
153
+ plan: data.result,
154
+ ...restData,
155
+ };
156
+ }
157
+
158
+ if (hasCommonFields(data)) {
159
+ return data;
160
+ }
161
+
162
+ return {plan: data};
163
+ };
164
+
131
165
  export const prepareQueryResponse = (data?: KeyValueRow[]) => {
132
166
  if (!Array.isArray(data)) {
133
167
  return [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ydb-embedded-ui",
3
- "version": "1.14.2",
3
+ "version": "2.1.0",
4
4
  "files": [
5
5
  "dist"
6
6
  ],
@@ -9,7 +9,7 @@
9
9
  "url": "git@github.com:ydb-platform/ydb-embedded-ui.git"
10
10
  },
11
11
  "dependencies": {
12
- "@yandex-cloud/i18n": "0.6.0",
12
+ "@gravity-ui/i18n": "^1.0.0",
13
13
  "@yandex-cloud/paranoid": "^1.2.1",
14
14
  "@yandex-cloud/react-data-table": "0.2.1",
15
15
  "axios": "0.19.2",
@@ -36,7 +36,7 @@
36
36
  "reselect": "4.0.0",
37
37
  "sass": "1.32.8",
38
38
  "web-vitals": "1.1.2",
39
- "ydb-ui-components": "2.4.1"
39
+ "ydb-ui-components": "3.0.1"
40
40
  },
41
41
  "scripts": {
42
42
  "start": "react-app-rewired start",
@@ -95,6 +95,11 @@
95
95
  "devDependencies": {
96
96
  "@commitlint/cli": "^15.0.0",
97
97
  "@commitlint/config-conventional": "^15.0.0",
98
+ "@gravity-ui/eslint-config": "^1.0.2",
99
+ "@gravity-ui/prettier-config": "^1.0.1",
100
+ "@gravity-ui/stylelint-config": "^1.0.1",
101
+ "@gravity-ui/tsconfig": "^1.0.0",
102
+ "@gravity-ui/uikit": "^3.0.1",
98
103
  "@testing-library/jest-dom": "^5.15.0",
99
104
  "@testing-library/react": "^11.2.7",
100
105
  "@testing-library/user-event": "^12.8.3",
@@ -107,12 +112,6 @@
107
112
  "@types/react-transition-group": "^4.4.4",
108
113
  "@types/react-virtualized-auto-sizer": "^1.0.1",
109
114
  "@yandex-cloud/axios-wrapper": "^1.0.2",
110
- "@yandex-cloud/browserslist-config": "1.0.1",
111
- "@yandex-cloud/eslint-config": "^1.0.0",
112
- "@yandex-cloud/prettier-config": "^1.0.0",
113
- "@yandex-cloud/stylelint-config": "^1.1.0",
114
- "@yandex-cloud/tsconfig": "^1.0.0",
115
- "@yandex-cloud/uikit": "^2.8.0",
116
115
  "copyfiles": "^2.4.1",
117
116
  "eslint-config-prettier": "^8.3.0",
118
117
  "husky": "^7.0.4",
@@ -128,7 +127,6 @@
128
127
  "typescript": "^4.5.5"
129
128
  },
130
129
  "peerDependencies": {
131
- "@yandex-cloud/browserslist-config": "^1.0.1",
132
- "@yandex-cloud/uikit": "^2.8.0"
130
+ "@gravity-ui/uikit": "^3.0.1"
133
131
  }
134
132
  }
@@ -1,195 +0,0 @@
1
- import React from 'react';
2
- import PropTypes from 'prop-types';
3
- import {connect} from 'react-redux';
4
- import cn from 'bem-cn-lite';
5
-
6
- import {Loader, Button} from '@yandex-cloud/uikit';
7
-
8
- import IssuesViewer from './IssuesViewer/IssuesViewer';
9
-
10
- import {getHealthcheckInfo} from '../../../../store/reducers/healthcheckInfo';
11
- import {hideTooltip, showTooltip} from '../../../../store/reducers/tooltip';
12
- import {AutoFetcher} from '../../../../utils/autofetcher';
13
-
14
- import './Healthcheck.scss';
15
-
16
- const b = cn('healthcheck');
17
-
18
- class Healthcheck extends React.Component {
19
- static propTypes = {
20
- data: PropTypes.object,
21
- loading: PropTypes.bool,
22
- wasLoaded: PropTypes.bool,
23
- error: PropTypes.object,
24
- getHealthcheckInfo: PropTypes.func,
25
- tenant: PropTypes.string,
26
- preview: PropTypes.bool,
27
- showMoreHandler: PropTypes.func,
28
- };
29
-
30
- autofetcher;
31
-
32
- componentDidMount() {
33
- this.autofetcher = new AutoFetcher();
34
- this.fetchHealthcheck();
35
- if (this.props.autorefresh) {
36
- this.autofetcher.start();
37
- this.autofetcher.fetch(() => this.fetchHealthcheck());
38
- }
39
- }
40
-
41
- componentDidUpdate(prevProps) {
42
- const {autorefresh} = this.props;
43
-
44
- if (autorefresh && !prevProps.autorefresh) {
45
- this.fetchHealthcheck();
46
- this.autofetcher.stop();
47
- this.autofetcher.start();
48
- this.autofetcher.fetch(() => this.fetchHealthcheck());
49
- }
50
- if (!autorefresh && prevProps.autorefresh) {
51
- this.autofetcher.stop();
52
- }
53
- }
54
-
55
- componentWillUnmount() {
56
- this.autofetcher.stop();
57
- }
58
-
59
- fetchHealthcheck = () => {
60
- const {tenant, getHealthcheckInfo} = this.props;
61
- getHealthcheckInfo(tenant);
62
- };
63
-
64
- renderLoader() {
65
- return (
66
- <div className={b('loader')}>
67
- <Loader size="m" />
68
- </div>
69
- );
70
- }
71
-
72
- renderUpdateButton() {
73
- const {loading} = this.props;
74
- return (
75
- <Button size="s" onClick={this.fetchHealthcheck} loading={loading}>
76
- Update
77
- </Button>
78
- );
79
- }
80
-
81
- renderPreview = () => {
82
- const {data, showMoreHandler} = this.props;
83
- const {self_check_result: selfCheckResult} = data;
84
- const modifier = selfCheckResult.toLowerCase();
85
-
86
- const statusOk = selfCheckResult === 'GOOD';
87
- const text = statusOk
88
- ? 'No issues have been found on this database.'
89
- : 'Several issues have been found on this database.';
90
-
91
- return (
92
- <div>
93
- <div className={b('status-wrapper')}>
94
- <div className={b('preview-title')}>Healthcheck</div>
95
- <div className={b('self-check-status-indicator', {[modifier]: true})}>
96
- {statusOk ? 'Ok' : 'Error'}
97
- </div>
98
- {this.renderUpdateButton()}
99
- </div>
100
- <div className={b('preview-content')}>
101
- {text}
102
- {!statusOk && (
103
- <Button
104
- view="flat-info"
105
- onClick={showMoreHandler}
106
- size="s"
107
- >
108
- Show details
109
- </Button>
110
- )}
111
- </div>
112
- </div>
113
- );
114
- };
115
-
116
- renderOverviewStatus = () => {
117
- const {data} = this.props;
118
- const {self_check_result: selfCheckResult} = data;
119
- const modifier = selfCheckResult.toLowerCase();
120
-
121
- return (
122
- <div className={b('self-check-status')}>
123
- <h3 className={b('self-check-status-label')}>Self check status</h3>
124
- <div className={b('self-check-status-indicator', {[modifier]: true})} />
125
- {selfCheckResult}
126
- <div className={b('self-check-update')}>{this.renderUpdateButton()}</div>
127
- </div>
128
- );
129
- };
130
-
131
- renderHealthcheckIssues() {
132
- const {data, showTooltip, hideTooltip} = this.props;
133
- const {issue_log: issueLog} = data;
134
-
135
- if (!issueLog) {
136
- return null;
137
- }
138
-
139
- return (
140
- <div className={b('issues')}>
141
- <h3>Issues</h3>
142
- <IssuesViewer
143
- issues={issueLog}
144
- showTooltip={showTooltip}
145
- hideTooltip={hideTooltip}
146
- />
147
- </div>
148
- );
149
- }
150
-
151
- renderContent = () => {
152
- const {preview} = this.props;
153
- return preview ? (
154
- this.renderPreview()
155
- ) : (
156
- <div className={b()}>
157
- {this.renderOverviewStatus()}
158
- {this.renderHealthcheckIssues()}
159
- </div>
160
- );
161
- };
162
-
163
- render() {
164
- const {error, data, loading, wasLoaded} = this.props;
165
-
166
- if (error) {
167
- return <div>{error.statusText}</div>;
168
- } else if (data && data['self_check_result']) {
169
- return this.renderContent();
170
- } else if (loading && !wasLoaded) {
171
- return this.renderLoader();
172
- } else return <div className="error">no healthcheck data</div>;
173
- }
174
- }
175
-
176
- function mapStateToProps(state) {
177
- const {data, loading, wasLoaded, error} = state.healthcheckInfo;
178
- const {autorefresh} = state.schema;
179
-
180
- return {
181
- data,
182
- loading,
183
- wasLoaded,
184
- error,
185
- autorefresh,
186
- };
187
- }
188
-
189
- const mapDispatchToProps = {
190
- getHealthcheckInfo,
191
- hideTooltip,
192
- showTooltip,
193
- };
194
-
195
- export default connect(mapStateToProps, mapDispatchToProps)(Healthcheck);