ydb-embedded-ui 4.21.0 → 4.22.0
Sign up to get free protection for your applications and to get access to all the features.
- package/CHANGELOG.md +27 -0
- package/dist/components/NodeHostWrapper/NodeHostWrapper.scss +2 -1
- package/dist/components/QueryResultTable/QueryResultTable.tsx +7 -3
- package/dist/components/VirtualTable/TableChunk.tsx +2 -1
- package/dist/components/VirtualTable/VirtualTable.tsx +1 -1
- package/dist/containers/Node/Node.tsx +9 -17
- package/dist/containers/Node/NodeStructure/NodeStructure.tsx +8 -30
- package/dist/containers/Node/NodeStructure/Pdisk.tsx +32 -18
- package/dist/containers/Node/i18n/en.json +4 -0
- package/dist/containers/Node/i18n/index.ts +11 -0
- package/dist/containers/Node/i18n/ru.json +4 -0
- package/dist/containers/Nodes/Nodes.tsx +5 -10
- package/dist/containers/Nodes/getNodesColumns.tsx +57 -13
- package/dist/containers/Tablets/Tablets.tsx +3 -8
- package/dist/containers/Tenant/Diagnostics/Diagnostics.tsx +0 -1
- package/dist/containers/Tenant/Diagnostics/Network/Network.js +5 -10
- package/dist/containers/Tenant/Diagnostics/Network/utils.ts +6 -0
- package/dist/containers/Tenant/Query/ExecuteResult/ExecuteResult.scss +13 -5
- package/dist/containers/Tenant/Query/ExecuteResult/ExecuteResult.tsx +72 -18
- package/dist/containers/Tenant/Query/ExplainResult/ExplainResult.js +2 -1
- package/dist/containers/Tenant/Query/ExplainResult/utils.ts +6 -0
- package/dist/containers/Tenant/Query/QueryEditor/QueryEditor.js +11 -24
- package/dist/containers/Tenant/Query/utils/getPreparedResult.ts +4 -5
- package/dist/containers/UserSettings/i18n/en.json +5 -2
- package/dist/containers/UserSettings/i18n/ru.json +5 -2
- package/dist/containers/UserSettings/settings.ts +12 -6
- package/dist/store/reducers/executeQuery.ts +4 -3
- package/dist/store/reducers/nodes/nodes.ts +2 -2
- package/dist/store/reducers/nodes/types.ts +12 -1
- package/dist/store/reducers/nodes/utils.ts +6 -0
- package/dist/store/reducers/settings/settings.ts +5 -3
- package/dist/types/api/netInfo.ts +1 -1
- package/dist/types/api/nodes.ts +24 -0
- package/dist/types/api/query.ts +23 -8
- package/dist/types/store/query.ts +6 -0
- package/dist/utils/constants.ts +3 -0
- package/dist/utils/developerUI/__test__/developerUI.test.ts +50 -0
- package/dist/utils/developerUI/developerUI.ts +42 -0
- package/dist/utils/diagnostics.ts +1 -0
- package/dist/utils/query.ts +68 -13
- package/package.json +1 -1
- package/dist/utils/index.js +0 -9
- /package/dist/{components/VirtualTable/utils.ts → utils/index.ts} +0 -0
package/dist/types/api/query.ts
CHANGED
@@ -180,7 +180,7 @@ export interface ColumnType {
|
|
180
180
|
}
|
181
181
|
|
182
182
|
/** undefined = 'classic' */
|
183
|
-
export type Schemas = 'classic' | 'modern' | 'ydb' | undefined;
|
183
|
+
export type Schemas = 'classic' | 'modern' | 'ydb' | 'multi' | undefined;
|
184
184
|
|
185
185
|
/** undefined = 'execute' */
|
186
186
|
export type ExecuteActions =
|
@@ -231,16 +231,29 @@ export type ExplainResponse<Action extends ExplainActions> = Action extends 'exp
|
|
231
231
|
? ExplainScriptResponse
|
232
232
|
: ExplainQueryResponse;
|
233
233
|
|
234
|
+
// ==== Execute Results ====
|
235
|
+
|
236
|
+
interface ModernSchemaResult {
|
237
|
+
result?: ArrayRow[];
|
238
|
+
columns?: ColumnType[];
|
239
|
+
}
|
240
|
+
interface MultiSchemaResult {
|
241
|
+
result?: {
|
242
|
+
rows?: ArrayRow[] | null;
|
243
|
+
columns?: ColumnType[];
|
244
|
+
}[];
|
245
|
+
}
|
246
|
+
interface DefaultSchemaResult {
|
247
|
+
result?: KeyValueRow[];
|
248
|
+
}
|
249
|
+
|
234
250
|
// ==== Execute Responses ====
|
235
251
|
|
236
252
|
type ResultFields<Schema extends Schemas> = Schema extends 'modern'
|
237
|
-
?
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
: {
|
242
|
-
result?: KeyValueRow[];
|
243
|
-
};
|
253
|
+
? ModernSchemaResult
|
254
|
+
: Schema extends 'multi'
|
255
|
+
? MultiSchemaResult
|
256
|
+
: DefaultSchemaResult;
|
244
257
|
|
245
258
|
/**
|
246
259
|
* meta.type = 'query'
|
@@ -287,6 +300,7 @@ export type AnyExplainResponse = ExplainQueryResponse | ExplainScriptResponse;
|
|
287
300
|
export type ExecuteModernResponse =
|
288
301
|
| ExecuteQueryResponse<'modern'>
|
289
302
|
| ExecuteScriptResponse<'modern'>;
|
303
|
+
export type ExecuteMultiResponse = ExecuteQueryResponse<'multi'> | ExecuteScriptResponse<'multi'>;
|
290
304
|
export type ExecuteClassicResponse =
|
291
305
|
| ExecuteQueryResponse<'classic'>
|
292
306
|
| ExecuteScriptResponse<'classic'>;
|
@@ -294,5 +308,6 @@ export type ExecuteYdbResponse = ExecuteQueryResponse<'ydb'> | ExecuteScriptResp
|
|
294
308
|
|
295
309
|
export type AnyExecuteResponse =
|
296
310
|
| ExecuteModernResponse
|
311
|
+
| ExecuteMultiResponse
|
297
312
|
| ExecuteClassicResponse
|
298
313
|
| ExecuteYdbResponse;
|
@@ -11,7 +11,13 @@ import type {
|
|
11
11
|
} from '../api/query';
|
12
12
|
import type {ValueOf} from '../common';
|
13
13
|
|
14
|
+
export interface ParsedResultSet {
|
15
|
+
columns?: ColumnType[];
|
16
|
+
result?: KeyValueRow[];
|
17
|
+
}
|
18
|
+
|
14
19
|
export interface IQueryResult {
|
20
|
+
resultSets?: ParsedResultSet[];
|
15
21
|
result?: KeyValueRow[];
|
16
22
|
columns?: ColumnType[];
|
17
23
|
stats?: TKqpStatsQuery;
|
package/dist/utils/constants.ts
CHANGED
@@ -133,3 +133,6 @@ export const TENANT_INITIAL_PAGE_KEY = 'saved_tenant_initial_tab';
|
|
133
133
|
|
134
134
|
// Send filters and sort params to backend for Nodes and Storage tables
|
135
135
|
export const USE_BACKEND_PARAMS_FOR_TABLES_KEY = 'useBackendParamsForTables';
|
136
|
+
|
137
|
+
// Enable schema that supports multiple resultsets
|
138
|
+
export const QUERY_USE_MULTI_SCHEMA_KEY = 'queryUseMultiSchema';
|
@@ -0,0 +1,50 @@
|
|
1
|
+
import {
|
2
|
+
createDeveloperUILinkWithNodeId,
|
3
|
+
createPDiskDeveloperUILink,
|
4
|
+
createVDiskDeveloperUILink,
|
5
|
+
} from '../developerUI';
|
6
|
+
|
7
|
+
describe('Developer UI links generators', () => {
|
8
|
+
describe('createDeveloperUILinkWithNodeId', () => {
|
9
|
+
it('should create relative link with no host', () => {
|
10
|
+
expect(createDeveloperUILinkWithNodeId(1)).toBe('/node/1/');
|
11
|
+
});
|
12
|
+
it('should create relative link with existing relative path with nodeId', () => {
|
13
|
+
expect(createDeveloperUILinkWithNodeId(1, '/node/3/')).toBe('/node/1/');
|
14
|
+
});
|
15
|
+
it('should create full link with host', () => {
|
16
|
+
expect(
|
17
|
+
createDeveloperUILinkWithNodeId(
|
18
|
+
1,
|
19
|
+
'http://ydb-vla-dev02-001.search.yandex.net:8765',
|
20
|
+
),
|
21
|
+
).toBe('http://ydb-vla-dev02-001.search.yandex.net:8765/node/1/');
|
22
|
+
});
|
23
|
+
it('should create full link with host with existing node path with nodeId', () => {
|
24
|
+
expect(
|
25
|
+
createDeveloperUILinkWithNodeId(
|
26
|
+
1,
|
27
|
+
'http://ydb-vla-dev02-001.search.yandex.net:8765/node/3',
|
28
|
+
),
|
29
|
+
).toBe('http://ydb-vla-dev02-001.search.yandex.net:8765/node/1/');
|
30
|
+
});
|
31
|
+
});
|
32
|
+
describe('createPDiskDeveloperUILink', () => {
|
33
|
+
it('should create link with pDiskId and nodeId', () => {
|
34
|
+
expect(createPDiskDeveloperUILink({nodeId: 1, pDiskId: 1})).toBe(
|
35
|
+
'/node/1/actors/pdisks/pdisk000000001',
|
36
|
+
);
|
37
|
+
});
|
38
|
+
});
|
39
|
+
describe('createVDiskDeveloperUILink', () => {
|
40
|
+
it('should create link with pDiskId, vDiskSlotId nodeId', () => {
|
41
|
+
expect(
|
42
|
+
createVDiskDeveloperUILink({
|
43
|
+
nodeId: 1,
|
44
|
+
pDiskId: 1,
|
45
|
+
vDiskSlotId: 1,
|
46
|
+
}),
|
47
|
+
).toBe('/node/1/actors/vdisks/vdisk000000001_000000001');
|
48
|
+
});
|
49
|
+
});
|
50
|
+
});
|
@@ -0,0 +1,42 @@
|
|
1
|
+
import {backend} from '../../store';
|
2
|
+
import {pad9} from '../utils';
|
3
|
+
|
4
|
+
// Current node connects with target node by itself using nodeId
|
5
|
+
export const createDeveloperUILinkWithNodeId = (nodeId: number | string, host = backend) => {
|
6
|
+
const nodePathRegexp = /\/node\/\d+\/?$/g;
|
7
|
+
|
8
|
+
// In case current backend is already relative node path ({host}/node/{nodeId})
|
9
|
+
// We replace existing nodeId path with new nodeId path
|
10
|
+
if (nodePathRegexp.test(String(host))) {
|
11
|
+
return String(host).replace(nodePathRegexp, `/node/${nodeId}/`);
|
12
|
+
}
|
13
|
+
|
14
|
+
return `${host ?? ''}/node/${nodeId}/`;
|
15
|
+
};
|
16
|
+
|
17
|
+
interface PDiskDeveloperUILinkParams {
|
18
|
+
nodeId: number | string;
|
19
|
+
pDiskId: number | string;
|
20
|
+
host?: string;
|
21
|
+
}
|
22
|
+
|
23
|
+
export const createPDiskDeveloperUILink = ({nodeId, pDiskId, host}: PDiskDeveloperUILinkParams) => {
|
24
|
+
const pdiskPath = 'actors/pdisks/pdisk' + pad9(pDiskId);
|
25
|
+
|
26
|
+
return createDeveloperUILinkWithNodeId(nodeId, host) + pdiskPath;
|
27
|
+
};
|
28
|
+
|
29
|
+
interface VDiskDeveloperUILinkParams extends PDiskDeveloperUILinkParams {
|
30
|
+
vDiskSlotId: number | string;
|
31
|
+
}
|
32
|
+
|
33
|
+
export const createVDiskDeveloperUILink = ({
|
34
|
+
nodeId,
|
35
|
+
pDiskId,
|
36
|
+
vDiskSlotId,
|
37
|
+
host,
|
38
|
+
}: VDiskDeveloperUILinkParams) => {
|
39
|
+
const vdiskPath = 'actors/vdisks/vdisk' + pad9(pDiskId) + '_' + pad9(vDiskSlotId);
|
40
|
+
|
41
|
+
return createDeveloperUILinkWithNodeId(nodeId, host) + vdiskPath;
|
42
|
+
};
|
package/dist/utils/query.ts
CHANGED
@@ -2,7 +2,10 @@ import {YQLType} from '../types';
|
|
2
2
|
import type {
|
3
3
|
AnyExecuteResponse,
|
4
4
|
AnyExplainResponse,
|
5
|
+
ArrayRow,
|
6
|
+
ColumnType,
|
5
7
|
ExecuteModernResponse,
|
8
|
+
ExecuteMultiResponse,
|
6
9
|
KeyValueRow,
|
7
10
|
QueryPlan,
|
8
11
|
ScriptPlan,
|
@@ -76,34 +79,74 @@ export const getColumnType = (type: string) => {
|
|
76
79
|
}
|
77
80
|
};
|
78
81
|
|
79
|
-
/** parse response result
|
82
|
+
/** parse response result from ArrayRow to KeyValueRow */
|
83
|
+
const parseModernResult = (rows: ArrayRow[], columns: ColumnType[]) => {
|
84
|
+
return rows.map((row) => {
|
85
|
+
return row.reduce<KeyValueRow>((newRow, cellData, columnIndex) => {
|
86
|
+
const {name} = columns[columnIndex];
|
87
|
+
newRow[name] = cellData;
|
88
|
+
return newRow;
|
89
|
+
}, {});
|
90
|
+
});
|
91
|
+
};
|
92
|
+
|
80
93
|
const parseExecuteModernResponse = (data: ExecuteModernResponse): IQueryResult => {
|
81
94
|
const {result, columns, ...restData} = data;
|
82
95
|
|
83
96
|
return {
|
84
|
-
result:
|
85
|
-
result &&
|
86
|
-
columns &&
|
87
|
-
result.map((row) => {
|
88
|
-
return row.reduce((newRow, cellData, columnIndex) => {
|
89
|
-
const {name} = columns[columnIndex];
|
90
|
-
newRow[name] = cellData;
|
91
|
-
return newRow;
|
92
|
-
}, {} as KeyValueRow);
|
93
|
-
}),
|
97
|
+
result: result && columns && parseModernResult(result, columns),
|
94
98
|
columns,
|
95
99
|
...restData,
|
96
100
|
};
|
97
101
|
};
|
98
102
|
|
103
|
+
const parseExecuteMultiResponse = (data: ExecuteMultiResponse): IQueryResult => {
|
104
|
+
const {result, ...restData} = data;
|
105
|
+
|
106
|
+
const parsedResult = result?.map((resultSet) => {
|
107
|
+
const {rows, columns} = resultSet;
|
108
|
+
|
109
|
+
let parsedRows: KeyValueRow[] | undefined;
|
110
|
+
|
111
|
+
if (columns) {
|
112
|
+
// Result shouldn't be null if there are columns
|
113
|
+
parsedRows = [];
|
114
|
+
}
|
115
|
+
|
116
|
+
if (rows && columns) {
|
117
|
+
parsedRows = parseModernResult(rows, columns);
|
118
|
+
}
|
119
|
+
|
120
|
+
return {
|
121
|
+
columns: columns,
|
122
|
+
result: parsedRows,
|
123
|
+
};
|
124
|
+
});
|
125
|
+
|
126
|
+
return {
|
127
|
+
resultSets: parsedResult, // use a separate field to make result compatible
|
128
|
+
...restData,
|
129
|
+
};
|
130
|
+
};
|
131
|
+
|
99
132
|
const isModern = (response: AnyExecuteResponse): response is ExecuteModernResponse =>
|
100
133
|
Boolean(
|
101
134
|
response &&
|
102
135
|
!Array.isArray(response) &&
|
103
|
-
Array.isArray(
|
136
|
+
Array.isArray(response.result) &&
|
104
137
|
Array.isArray((response as ExecuteModernResponse).columns),
|
105
138
|
);
|
106
139
|
|
140
|
+
const isMulti = (response: AnyExecuteResponse): response is ExecuteMultiResponse =>
|
141
|
+
Boolean(
|
142
|
+
response &&
|
143
|
+
!Array.isArray(response) &&
|
144
|
+
Array.isArray(response.result) &&
|
145
|
+
typeof response.result[0] === 'object' &&
|
146
|
+
'rows' in response.result[0] &&
|
147
|
+
'columns' in response.result[0],
|
148
|
+
);
|
149
|
+
|
107
150
|
type UnsupportedQueryResponseFormat =
|
108
151
|
| Array<unknown>
|
109
152
|
| string
|
@@ -122,12 +165,17 @@ const isUnsupportedType = (
|
|
122
165
|
);
|
123
166
|
};
|
124
167
|
|
168
|
+
// Although schema is set in request, if schema is not supported default schema for the version will be used
|
169
|
+
// So we should additionally parse response
|
125
170
|
export const parseQueryAPIExecuteResponse = (
|
126
171
|
data: AnyExecuteResponse | UnsupportedQueryResponseFormat,
|
127
172
|
): IQueryResult => {
|
128
173
|
if (isUnsupportedType(data)) {
|
129
174
|
return {};
|
130
175
|
}
|
176
|
+
if (isMulti(data)) {
|
177
|
+
return parseExecuteMultiResponse(data);
|
178
|
+
}
|
131
179
|
if (isModern(data)) {
|
132
180
|
return parseExecuteModernResponse(data);
|
133
181
|
}
|
@@ -175,7 +223,14 @@ export const prepareQueryResponse = (data?: KeyValueRow[]) => {
|
|
175
223
|
for (const field in row) {
|
176
224
|
if (Object.prototype.hasOwnProperty.call(row, field)) {
|
177
225
|
const type = typeof row[field];
|
178
|
-
|
226
|
+
|
227
|
+
// Although typeof null == 'object'
|
228
|
+
// null result should be preserved
|
229
|
+
if (
|
230
|
+
(row[field] !== null && type === 'object') ||
|
231
|
+
type === 'boolean' ||
|
232
|
+
Array.isArray(row[field])
|
233
|
+
) {
|
179
234
|
formattedData[field] = JSON.stringify(row[field]);
|
180
235
|
} else {
|
181
236
|
formattedData[field] = row[field];
|
package/package.json
CHANGED
package/dist/utils/index.js
DELETED
@@ -1,9 +0,0 @@
|
|
1
|
-
// determine how many nodes have status Connected "true"
|
2
|
-
export const getConnectedNodesCount = (nodeStateInfo) => {
|
3
|
-
return nodeStateInfo?.reduce((acc, item) => (item.Connected ? acc + 1 : acc), 0);
|
4
|
-
};
|
5
|
-
|
6
|
-
export const renderExplainNode = (node) => {
|
7
|
-
const parts = node.name.split('|');
|
8
|
-
return parts.length > 1 ? parts[1] : node.name;
|
9
|
-
};
|
File without changes
|