ydb-embedded-ui 3.4.5 → 4.0.0
Sign up to get free protection for your applications and to get access to all the features.
- package/CHANGELOG.md +41 -0
- package/dist/components/InfoViewer/formatters/table.ts +6 -0
- package/dist/components/TruncatedQuery/TruncatedQuery.js +1 -1
- package/dist/components/TruncatedQuery/TruncatedQuery.scss +7 -3
- package/dist/containers/Node/{NodePages.js → NodePages.ts} +1 -1
- package/dist/containers/Tablet/TabletControls/TabletControls.tsx +2 -2
- package/dist/containers/Tenant/Diagnostics/Overview/Overview.tsx +11 -43
- package/dist/containers/Tenant/Diagnostics/Overview/TableInfo/TableInfo.tsx +19 -17
- package/dist/containers/Tenant/Diagnostics/Overview/TableInfo/prepareTableInfo.ts +192 -37
- package/dist/containers/Tenant/Diagnostics/TopQueries/TopQueries.scss +20 -14
- package/dist/containers/Tenant/Diagnostics/TopQueries/TopQueries.tsx +49 -12
- package/dist/containers/Tenant/Diagnostics/TopShards/TopShards.tsx +37 -18
- package/dist/containers/Tenant/QueryEditor/QueriesHistory/QueriesHistory.tsx +3 -3
- package/dist/containers/Tenant/QueryEditor/QueryDuration/QueryDuration.scss +8 -0
- package/dist/containers/Tenant/QueryEditor/QueryDuration/QueryDuration.tsx +21 -0
- package/dist/containers/Tenant/QueryEditor/QueryEditor.js +58 -82
- package/dist/containers/Tenant/QueryEditor/QueryEditor.scss +0 -33
- package/dist/containers/Tenant/QueryEditor/QueryEditorControls/OldQueryEditorControls.tsx +83 -0
- package/dist/containers/Tenant/QueryEditor/QueryEditorControls/QueryEditorControls.scss +57 -0
- package/dist/containers/Tenant/QueryEditor/QueryEditorControls/QueryEditorControls.tsx +84 -0
- package/dist/containers/Tenant/QueryEditor/QueryEditorControls/shared.ts +23 -0
- package/dist/containers/Tenant/QueryEditor/QueryExplain/QueryExplain.js +12 -23
- package/dist/containers/Tenant/QueryEditor/QueryResult/QueryResult.js +4 -6
- package/dist/containers/Tenant/QueryEditor/i18n/en.json +3 -0
- package/dist/containers/Tenant/QueryEditor/i18n/index.ts +11 -0
- package/dist/containers/Tenant/QueryEditor/i18n/ru.json +3 -0
- package/dist/containers/UserSettings/UserSettings.tsx +30 -1
- package/dist/routes.ts +1 -1
- package/dist/services/api.d.ts +4 -3
- package/dist/services/api.js +5 -5
- package/dist/store/reducers/{executeQuery.js → executeQuery.ts} +48 -43
- package/dist/store/reducers/executeTopQueries.ts +5 -1
- package/dist/store/reducers/{explainQuery.js → explainQuery.ts} +44 -59
- package/dist/store/reducers/{olapStats.js → olapStats.ts} +8 -18
- package/dist/store/reducers/settings.js +19 -4
- package/dist/store/reducers/storage.js +5 -7
- package/dist/types/api/error.ts +14 -0
- package/dist/types/api/query.ts +227 -115
- package/dist/types/api/schema.ts +523 -3
- package/dist/types/common.ts +1 -0
- package/dist/types/store/executeQuery.ts +38 -0
- package/dist/types/store/explainQuery.ts +38 -0
- package/dist/types/store/olapStats.ts +14 -0
- package/dist/types/store/query.ts +23 -3
- package/dist/utils/constants.ts +2 -1
- package/dist/utils/error.ts +25 -0
- package/dist/utils/index.js +0 -49
- package/dist/utils/prepareQueryExplain.ts +7 -24
- package/dist/utils/query.test.ts +148 -213
- package/dist/utils/query.ts +68 -90
- package/dist/utils/timeParsers/formatDuration.ts +30 -12
- package/dist/utils/timeParsers/i18n/en.json +9 -5
- package/dist/utils/timeParsers/i18n/ru.json +9 -5
- package/dist/utils/timeParsers/parsers.ts +9 -0
- package/dist/utils/utils.js +1 -2
- package/package.json +1 -1
package/dist/utils/query.ts
CHANGED
@@ -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:
|
57
|
-
|
58
|
-
|
59
|
-
|
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
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
return
|
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
|
90
|
-
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
|
-
|
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
|
-
|
123
|
-
return data;
|
124
|
-
}
|
125
|
-
|
126
|
-
return {
|
127
|
-
result: parseDeprecatedExecuteResponseValue(data),
|
128
|
-
};
|
105
|
+
return data;
|
129
106
|
};
|
130
107
|
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
if (
|
108
|
+
export const parseQueryAPIExplainResponse = (
|
109
|
+
data: AnyExplainResponse | UnsupportedQueryResponseFormat,
|
110
|
+
): IQueryResult => {
|
111
|
+
if (isUnsupportedType(data)) {
|
135
112
|
return {};
|
136
113
|
}
|
137
114
|
|
138
|
-
|
139
|
-
|
140
|
-
}
|
115
|
+
return data;
|
116
|
+
};
|
141
117
|
|
142
|
-
|
143
|
-
|
118
|
+
const isExplainScriptPlan = (plan: ScriptPlan | ScanPlan): plan is ScriptPlan =>
|
119
|
+
Boolean(plan && 'queries' in plan);
|
144
120
|
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
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
|
-
|
154
|
-
|
128
|
+
Plan: plan.queries[0].Plan,
|
129
|
+
tables: plan.queries[0].tables,
|
130
|
+
meta: plan.meta,
|
155
131
|
};
|
156
132
|
}
|
157
133
|
|
158
|
-
|
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
|
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
|
-
*
|
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 (
|
33
|
-
|
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
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
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}}
|
3
|
-
"hoursMin": "{{hours}}
|
4
|
-
"minSec": "{{minutes}}
|
5
|
-
"secMs": "{{seconds}}
|
6
|
-
"
|
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}}
|
3
|
-
"hoursMin": "{{hours}}
|
4
|
-
"minSec": "{{minutes}}
|
5
|
-
"secMs": "{{seconds}}
|
6
|
-
"
|
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
|
+
};
|
package/dist/utils/utils.js
CHANGED