ydb-embedded-ui 3.4.5 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/dist/components/InfoViewer/formatters/table.ts +6 -0
  3. package/dist/components/TruncatedQuery/TruncatedQuery.js +1 -1
  4. package/dist/components/TruncatedQuery/TruncatedQuery.scss +7 -3
  5. package/dist/containers/Node/{NodePages.js → NodePages.ts} +1 -1
  6. package/dist/containers/Tablet/TabletControls/TabletControls.tsx +2 -2
  7. package/dist/containers/Tenant/Diagnostics/Overview/Overview.tsx +11 -43
  8. package/dist/containers/Tenant/Diagnostics/Overview/TableInfo/TableInfo.tsx +19 -17
  9. package/dist/containers/Tenant/Diagnostics/Overview/TableInfo/prepareTableInfo.ts +192 -37
  10. package/dist/containers/Tenant/Diagnostics/TopQueries/TopQueries.scss +20 -14
  11. package/dist/containers/Tenant/Diagnostics/TopQueries/TopQueries.tsx +49 -12
  12. package/dist/containers/Tenant/Diagnostics/TopShards/TopShards.tsx +37 -18
  13. package/dist/containers/Tenant/QueryEditor/QueriesHistory/QueriesHistory.tsx +3 -3
  14. package/dist/containers/Tenant/QueryEditor/QueryDuration/QueryDuration.scss +8 -0
  15. package/dist/containers/Tenant/QueryEditor/QueryDuration/QueryDuration.tsx +21 -0
  16. package/dist/containers/Tenant/QueryEditor/QueryEditor.js +58 -82
  17. package/dist/containers/Tenant/QueryEditor/QueryEditor.scss +0 -33
  18. package/dist/containers/Tenant/QueryEditor/QueryEditorControls/OldQueryEditorControls.tsx +83 -0
  19. package/dist/containers/Tenant/QueryEditor/QueryEditorControls/QueryEditorControls.scss +57 -0
  20. package/dist/containers/Tenant/QueryEditor/QueryEditorControls/QueryEditorControls.tsx +84 -0
  21. package/dist/containers/Tenant/QueryEditor/QueryEditorControls/shared.ts +23 -0
  22. package/dist/containers/Tenant/QueryEditor/QueryExplain/QueryExplain.js +12 -23
  23. package/dist/containers/Tenant/QueryEditor/QueryResult/QueryResult.js +4 -6
  24. package/dist/containers/Tenant/QueryEditor/i18n/en.json +3 -0
  25. package/dist/containers/Tenant/QueryEditor/i18n/index.ts +11 -0
  26. package/dist/containers/Tenant/QueryEditor/i18n/ru.json +3 -0
  27. package/dist/containers/UserSettings/UserSettings.tsx +30 -1
  28. package/dist/routes.ts +1 -1
  29. package/dist/services/api.d.ts +4 -3
  30. package/dist/services/api.js +5 -5
  31. package/dist/store/reducers/{executeQuery.js → executeQuery.ts} +48 -43
  32. package/dist/store/reducers/executeTopQueries.ts +5 -1
  33. package/dist/store/reducers/{explainQuery.js → explainQuery.ts} +44 -59
  34. package/dist/store/reducers/{olapStats.js → olapStats.ts} +8 -18
  35. package/dist/store/reducers/settings.js +19 -4
  36. package/dist/store/reducers/storage.js +5 -7
  37. package/dist/types/api/error.ts +14 -0
  38. package/dist/types/api/query.ts +227 -115
  39. package/dist/types/api/schema.ts +523 -3
  40. package/dist/types/common.ts +1 -0
  41. package/dist/types/store/executeQuery.ts +38 -0
  42. package/dist/types/store/explainQuery.ts +38 -0
  43. package/dist/types/store/olapStats.ts +14 -0
  44. package/dist/types/store/query.ts +23 -3
  45. package/dist/utils/constants.ts +2 -1
  46. package/dist/utils/error.ts +25 -0
  47. package/dist/utils/index.js +0 -49
  48. package/dist/utils/prepareQueryExplain.ts +7 -24
  49. package/dist/utils/query.test.ts +148 -213
  50. package/dist/utils/query.ts +68 -90
  51. package/dist/utils/timeParsers/formatDuration.ts +30 -12
  52. package/dist/utils/timeParsers/i18n/en.json +9 -5
  53. package/dist/utils/timeParsers/i18n/ru.json +9 -5
  54. package/dist/utils/timeParsers/parsers.ts +9 -0
  55. package/dist/utils/utils.js +1 -2
  56. package/package.json +1 -1
@@ -2,13 +2,10 @@ import {YQLType} from '../types';
2
2
  import type {
3
3
  AnyExecuteResponse,
4
4
  AnyExplainResponse,
5
- AnyResponse,
6
- CommonFields,
7
- DeepExecuteResponse,
8
- DeprecatedExecuteResponsePlain,
9
- ExecuteClassicResponsePlain,
10
5
  ExecuteModernResponse,
11
6
  KeyValueRow,
7
+ ScanPlan,
8
+ ScriptPlan,
12
9
  } from '../types/api/query';
13
10
  import type {IQueryResult} from '../types/store/query';
14
11
 
@@ -47,119 +44,94 @@ export const getColumnType = (type: string) => {
47
44
  default:
48
45
  return undefined;
49
46
  }
50
- }
47
+ };
51
48
 
49
+ /** parse response result field from ArrayRow to KeyValueRow */
52
50
  const parseExecuteModernResponse = (data: ExecuteModernResponse): IQueryResult => {
53
51
  const {result, columns, ...restData} = data;
54
52
 
55
53
  return {
56
- result: result && columns && result.map((row) => {
57
- return row.reduce((newRow: KeyValueRow, cellData, columnIndex) => {
58
- const {name} = columns[columnIndex];
59
- newRow[name] = cellData;
60
- return newRow;
61
- }, {});
62
- }),
54
+ result:
55
+ result &&
56
+ columns &&
57
+ result.map((row) => {
58
+ return row.reduce((newRow, cellData, columnIndex) => {
59
+ const {name} = columns[columnIndex];
60
+ newRow[name] = cellData;
61
+ return newRow;
62
+ }, {} as KeyValueRow);
63
+ }),
63
64
  columns,
64
65
  ...restData,
65
66
  };
66
67
  };
67
68
 
68
- const parseDeprecatedExecuteResponseValue = (data?: DeprecatedExecuteResponsePlain | ExecuteClassicResponsePlain): KeyValueRow[] | undefined => {
69
- if (!data) {
70
- return undefined;
71
- }
72
-
73
- if (typeof data === 'string') {
74
- try {
75
- return JSON.parse(data);
76
- } catch (e) {
77
- return undefined;
78
- }
79
- }
80
-
81
- if (Array.isArray(data)) {
82
- return data;
83
- }
84
-
85
- // Plan is not a valid response in this case
86
- return undefined;
69
+ const isModern = (response: AnyExecuteResponse): response is ExecuteModernResponse =>
70
+ Boolean(
71
+ response &&
72
+ !Array.isArray(response) &&
73
+ Array.isArray((response as ExecuteModernResponse).result) &&
74
+ Array.isArray((response as ExecuteModernResponse).columns),
75
+ );
76
+
77
+ type UnsupportedQueryResponseFormat =
78
+ | Array<unknown>
79
+ | string
80
+ | null
81
+ | undefined
82
+ | {result: string | Record<string, unknown>};
83
+
84
+ const isUnsupportedType = (
85
+ data: AnyExecuteResponse | AnyExplainResponse | UnsupportedQueryResponseFormat,
86
+ ): data is UnsupportedQueryResponseFormat => {
87
+ return Boolean(
88
+ !data ||
89
+ typeof data !== 'object' ||
90
+ Array.isArray(data) ||
91
+ ('result' in data && !Array.isArray(data.result)),
92
+ );
87
93
  };
88
94
 
89
- const hasResult = (data: AnyExecuteResponse): data is DeepExecuteResponse => Boolean(
90
- data && typeof data === 'object' && 'result' in data
91
- );
92
-
93
- const isModern = (response: AnyExecuteResponse): response is ExecuteModernResponse => Boolean(
94
- response &&
95
- !Array.isArray(response) &&
96
- Array.isArray((response as ExecuteModernResponse).result) &&
97
- Array.isArray((response as ExecuteModernResponse).columns)
98
- );
99
-
100
- const hasCommonFields = (data: AnyResponse): data is CommonFields => Boolean(
101
- data && typeof data === 'object' && ('ast' in data || 'plan' in data || 'stats' in data)
102
- );
103
-
104
- // complex logic because of the variety of possible responses
105
- // after all backends are updated to the latest version, it can be simplified
106
- export const parseQueryAPIExecuteResponse = (data: AnyExecuteResponse): IQueryResult => {
107
- if (!data) {
95
+ export const parseQueryAPIExecuteResponse = (
96
+ data: AnyExecuteResponse | UnsupportedQueryResponseFormat,
97
+ ): IQueryResult => {
98
+ if (isUnsupportedType(data)) {
108
99
  return {};
109
100
  }
110
-
111
- if (hasResult(data)) {
112
- if (isModern(data)) {
113
- return parseExecuteModernResponse(data);
114
- }
115
-
116
- return {
117
- ...data,
118
- result: parseDeprecatedExecuteResponseValue(data.result),
119
- };
101
+ if (isModern(data)) {
102
+ return parseExecuteModernResponse(data);
120
103
  }
121
104
 
122
- if (hasCommonFields(data)) {
123
- return data;
124
- }
125
-
126
- return {
127
- result: parseDeprecatedExecuteResponseValue(data),
128
- };
105
+ return data;
129
106
  };
130
107
 
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) {
108
+ export const parseQueryAPIExplainResponse = (
109
+ data: AnyExplainResponse | UnsupportedQueryResponseFormat,
110
+ ): IQueryResult => {
111
+ if (isUnsupportedType(data)) {
135
112
  return {};
136
113
  }
137
114
 
138
- if ('ast' in data) {
139
- return data;
140
- }
115
+ return data;
116
+ };
141
117
 
142
- if ('result' in data) {
143
- const {result, ...restData} = data;
118
+ const isExplainScriptPlan = (plan: ScriptPlan | ScanPlan): plan is ScriptPlan =>
119
+ Boolean(plan && 'queries' in plan);
144
120
 
145
- if ('ast' in data.result) {
146
- return {
147
- ast: result.ast,
148
- ...restData,
149
- };
121
+ export const parseQueryExplainPlan = (plan: ScriptPlan | ScanPlan): ScanPlan => {
122
+ if (isExplainScriptPlan(plan)) {
123
+ if (!plan.queries || !plan.queries.length) {
124
+ return {meta: plan.meta};
150
125
  }
151
126
 
152
127
  return {
153
- plan: data.result,
154
- ...restData,
128
+ Plan: plan.queries[0].Plan,
129
+ tables: plan.queries[0].tables,
130
+ meta: plan.meta,
155
131
  };
156
132
  }
157
133
 
158
- if (hasCommonFields(data)) {
159
- return data;
160
- }
161
-
162
- return {plan: data};
134
+ return plan;
163
135
  };
164
136
 
165
137
  export const prepareQueryResponse = (data?: KeyValueRow[]) => {
@@ -186,5 +158,11 @@ export const prepareQueryResponse = (data?: KeyValueRow[]) => {
186
158
  };
187
159
 
188
160
  export function prepareQueryError(error: any) {
189
- return error.data?.error?.message || error.message || error.data || error.statusText || JSON.stringify(error);
161
+ return (
162
+ error.data?.error?.message ||
163
+ error.message ||
164
+ error.data ||
165
+ error.statusText ||
166
+ JSON.stringify(error)
167
+ );
190
168
  }
@@ -4,9 +4,10 @@ import i18n from './i18n';
4
4
 
5
5
  /**
6
6
  * Process time difference in ms and returns formated time.
7
- * Only two major values are returned (days & hours, hours & minutes, minutes & seconds, etc.)
7
+ * By default only two major values are returned (days & hours, hours & minutes, minutes & seconds, etc.).
8
+ * It can be altered with valuesCount arg
8
9
  */
9
- export const formatDurationToShortTimeFormat = (value: number) => {
10
+ export const formatDurationToShortTimeFormat = (value: number, valuesCount: 1 | 2 = 2) => {
10
11
  const ms = value % 1000;
11
12
  let remain = Math.floor(value / 1000);
12
13
 
@@ -29,17 +30,34 @@ export const formatDurationToShortTimeFormat = (value: number) => {
29
30
  ms,
30
31
  };
31
32
 
32
- if (days > 0) {
33
- return i18n('daysHours', duration);
33
+ if (valuesCount === 2) {
34
+ if (days > 0) {
35
+ return i18n('daysHours', duration);
36
+ }
37
+ if (hours > 0) {
38
+ return i18n('hoursMin', duration);
39
+ }
40
+ if (minutes > 0) {
41
+ return i18n('minSec', duration);
42
+ }
43
+ if (seconds > 0) {
44
+ return i18n('secMs', duration);
45
+ }
34
46
  }
35
- if (hours > 0) {
36
- return i18n('hoursMin', duration);
37
- }
38
- if (minutes > 0) {
39
- return i18n('minSec', duration);
40
- }
41
- if (seconds > 0) {
42
- return i18n('secMs', duration);
47
+
48
+ if (valuesCount === 1) {
49
+ if (days > 0) {
50
+ return i18n('days', duration);
51
+ }
52
+ if (hours > 0) {
53
+ return i18n('hours', duration);
54
+ }
55
+ if (minutes > 0) {
56
+ return i18n('min', duration);
57
+ }
58
+ if (seconds > 0) {
59
+ return i18n('sec', duration);
60
+ }
43
61
  }
44
62
 
45
63
  return i18n('ms', duration);
@@ -1,7 +1,11 @@
1
1
  {
2
- "daysHours": "{{days}}d {{hours}}h",
3
- "hoursMin": "{{hours}}h {{minutes}}m",
4
- "minSec": "{{minutes}}m {{seconds}}s",
5
- "secMs": "{{seconds}}s {{ms}}ms",
6
- "ms": "{{ms}}ms"
2
+ "daysHours": "{{days}}\u00a0d\u00a0{{hours}}\u00a0h",
3
+ "hoursMin": "{{hours}}\u00a0h\u00a0{{minutes}}\u00a0m",
4
+ "minSec": "{{minutes}}\u00a0m\u00a0{{seconds}}\u00a0s",
5
+ "secMs": "{{seconds}}\u00a0s\u00a0{{ms}}\u00a0ms",
6
+ "days": "{{days}}\u00a0d",
7
+ "hours": "{{hours}}\u00a0h",
8
+ "min": "{{minutes}}\u00a0m",
9
+ "sec": "{{seconds}}\u00a0s",
10
+ "ms": "{{ms}}\u00a0ms"
7
11
  }
@@ -1,7 +1,11 @@
1
1
  {
2
- "daysHours": "{{days}}д {{hours}}ч",
3
- "hoursMin": "{{hours}}ч {{minutes}}м",
4
- "minSec": "{{minutes}}м {{seconds}}с",
5
- "secMs": "{{seconds}}с {{ms}}мс",
6
- "ms": "{{ms}}мс"
2
+ "daysHours": "{{days}}\u00a0д\u00a0{{hours}}\u00a0ч",
3
+ "hoursMin": "{{hours}}\u00a0ч\u00a0{{minutes}}\u00a0м",
4
+ "minSec": "{{minutes}}\u00a0м\u00a0{{seconds}}\u00a0с",
5
+ "secMs": "{{seconds}}\u00a0с\u00a0{{ms}}\u00a0мс",
6
+ "days": "{{days}}\u00a0д",
7
+ "hours": "{{hours}}\u00a0ч",
8
+ "min": "{{minutes}}\u00a0м",
9
+ "sec": "{{seconds}}\u00a0с",
10
+ "ms": "{{ms}}\u00a0мс"
7
11
  }
@@ -1,5 +1,6 @@
1
1
  import type {IProtobufTimeObject} from '../../types/api/common';
2
2
 
3
+ import {isNumeric} from '../utils';
3
4
  import {parseProtobufDurationToMs, parseProtobufTimestampToMs} from '.';
4
5
 
5
6
  export const parseLag = (value: string | IProtobufTimeObject | undefined) =>
@@ -16,3 +17,11 @@ export const parseTimestampToIdleTime = (value: string | IProtobufTimeObject | u
16
17
  // Usually it below 100ms, so it could be omitted
17
18
  return duration < 0 ? 0 : duration;
18
19
  };
20
+
21
+ export const parseUsToMs = (value: string | number | undefined) => {
22
+ if (!value || !isNumeric(value)) {
23
+ return 0;
24
+ }
25
+
26
+ return Math.round(Number(value) / 1000);
27
+ };
@@ -1,11 +1,10 @@
1
1
  export function parseJson(value) {
2
2
  if (!value) {
3
- return;
3
+ return undefined;
4
4
  }
5
5
  try {
6
6
  return JSON.parse(value);
7
7
  } catch (err) {
8
- console.log(err);
9
8
  return value;
10
9
  }
11
10
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ydb-embedded-ui",
3
- "version": "3.4.5",
3
+ "version": "4.0.0",
4
4
  "files": [
5
5
  "dist"
6
6
  ],