ydb-embedded-ui 22.2.0-hotfix.1 → 22.3.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.
- package/dist/components/Graph/GravityGraph.js +9 -2
- package/dist/components/Graph/GravityGraph.js.map +1 -1
- package/dist/components/Graph/utils.d.ts +2 -1
- package/dist/components/Graph/utils.js +7 -0
- package/dist/components/Graph/utils.js.map +1 -1
- package/dist/containers/Authentication/Authentication.js +29 -30
- package/dist/containers/Authentication/Authentication.js.map +1 -1
- package/dist/containers/Authentication/utils.d.ts +2 -2
- package/dist/containers/Authentication/utils.js +1 -1
- package/dist/containers/Authentication/utils.js.map +1 -1
- package/dist/containers/Tenant/Diagnostics/DiagnosticsPages.js +5 -1
- package/dist/containers/Tenant/Diagnostics/DiagnosticsPages.js.map +1 -1
- package/dist/containers/Tenant/Diagnostics/Overview/Overview.js +7 -1
- package/dist/containers/Tenant/Diagnostics/Overview/Overview.js.map +1 -1
- package/dist/containers/Tenant/Diagnostics/Overview/ResourcePoolInfo/ResourcePoolInfo.scss +24 -0
- package/dist/containers/Tenant/Diagnostics/Overview/ResourcePoolInfo/ResourcePoolUsage.d.ts +8 -0
- package/dist/containers/Tenant/Diagnostics/Overview/ResourcePoolInfo/ResourcePoolUsage.js +34 -0
- package/dist/containers/Tenant/Diagnostics/Overview/ResourcePoolInfo/ResourcePoolUsage.js.map +1 -0
- package/dist/containers/Tenant/Diagnostics/Overview/ResourcePoolInfo/i18n/en.json +4 -1
- package/dist/containers/Tenant/Diagnostics/Overview/ResourcePoolInfo/i18n/index.d.ts +1 -1
- package/dist/containers/Tenant/Diagnostics/Overview/ResourcePoolInfo/index.d.ts +1 -0
- package/dist/containers/Tenant/Diagnostics/Overview/ResourcePoolInfo/index.js +1 -0
- package/dist/containers/Tenant/Diagnostics/Overview/ResourcePoolInfo/index.js.map +1 -1
- package/dist/containers/Tenant/Diagnostics/Overview/SchemaObjectInfo/SchemaObjectInfo.js +1 -1
- package/dist/containers/Tenant/Diagnostics/Overview/SchemaObjectInfo/SchemaObjectInfo.js.map +1 -1
- package/dist/containers/Tenant/Diagnostics/Overview/StreamingQueryInfo/StreamingQueryInfo.js +2 -17
- package/dist/containers/Tenant/Diagnostics/Overview/StreamingQueryInfo/StreamingQueryInfo.js.map +1 -1
- package/dist/containers/Tenant/Diagnostics/Overview/TableInfo/i18n/en.json +4 -0
- package/dist/containers/Tenant/Diagnostics/Overview/TableInfo/i18n/index.d.ts +1 -1
- package/dist/containers/Tenant/Diagnostics/Overview/TableInfo/prepareTableInfo/prepareColumnTableInfo.js +4 -1
- package/dist/containers/Tenant/Diagnostics/Overview/TableInfo/prepareTableInfo/prepareColumnTableInfo.js.map +1 -1
- package/dist/containers/Tenant/Diagnostics/Overview/TableInfo/prepareTableInfo/prepareRowTableInfo.js +4 -1
- package/dist/containers/Tenant/Diagnostics/Overview/TableInfo/prepareTableInfo/prepareRowTableInfo.js.map +1 -1
- package/dist/containers/Tenant/Diagnostics/Overview/TableInfo/prepareTableInfo/prepareTTL.js +41 -3
- package/dist/containers/Tenant/Diagnostics/Overview/TableInfo/prepareTableInfo/prepareTTL.js.map +1 -1
- package/dist/containers/Tenant/Diagnostics/StreamingQueryGraph/StreamingQueryGraph.d.ts +7 -0
- package/dist/containers/Tenant/Diagnostics/StreamingQueryGraph/StreamingQueryGraph.js +38 -0
- package/dist/containers/Tenant/Diagnostics/StreamingQueryGraph/StreamingQueryGraph.js.map +1 -0
- package/dist/containers/Tenant/Diagnostics/StreamingQueryGraph/StreamingQueryGraph.scss +18 -0
- package/dist/containers/Tenant/Diagnostics/StreamingQueryGraph/i18n/en.json +5 -0
- package/dist/containers/Tenant/Diagnostics/StreamingQueryGraph/i18n/index.d.ts +2 -0
- package/dist/containers/Tenant/Diagnostics/StreamingQueryGraph/i18n/index.js +5 -0
- package/dist/containers/Tenant/Diagnostics/StreamingQueryGraph/i18n/index.js.map +1 -0
- package/dist/containers/Tenant/Diagnostics/StreamingQueryGraph/index.d.ts +1 -0
- package/dist/containers/Tenant/Diagnostics/StreamingQueryGraph/index.js +2 -0
- package/dist/containers/Tenant/Diagnostics/StreamingQueryGraph/index.js.map +1 -0
- package/dist/containers/Tenant/Diagnostics/i18n/en.json +1 -0
- package/dist/containers/Tenant/Diagnostics/i18n/index.d.ts +1 -1
- package/dist/containers/Tenant/Diagnostics/tabsContent.js +2 -0
- package/dist/containers/Tenant/Diagnostics/tabsContent.js.map +1 -1
- package/dist/containers/Tenant/Query/QueryEditor/YqlEditor/YqlEditor.js +8 -1
- package/dist/containers/Tenant/Query/QueryEditor/YqlEditor/YqlEditor.js.map +1 -1
- package/dist/store/reducers/executeTopQueries/executeTopQueries.d.ts +7 -0
- package/dist/store/reducers/executeTopQueries/executeTopQueries.js +38 -0
- package/dist/store/reducers/executeTopQueries/executeTopQueries.js.map +1 -1
- package/dist/store/reducers/query/parsers/prepareStreamingQueryPlan.d.ts +8 -0
- package/dist/store/reducers/query/parsers/prepareStreamingQueryPlan.js +53 -0
- package/dist/store/reducers/query/parsers/prepareStreamingQueryPlan.js.map +1 -0
- package/dist/store/reducers/streamingQuery/streamingQuery.d.ts +5 -1
- package/dist/store/reducers/streamingQuery/streamingQuery.js +35 -10
- package/dist/store/reducers/streamingQuery/streamingQuery.js.map +1 -1
- package/dist/store/reducers/tenant/constants.d.ts +1 -0
- package/dist/store/reducers/tenant/constants.js +1 -0
- package/dist/store/reducers/tenant/constants.js.map +1 -1
- package/dist/types/api/schema/columnEntity.d.ts +2 -1
- package/dist/types/api/schema/sysView.d.ts +59 -2
- package/dist/types/api/schema/sysView.js +53 -1
- package/dist/types/api/schema/sysView.js.map +1 -1
- package/dist/types/api/schema/table.d.ts +8 -0
- package/dist/types/api/schema/table.js.map +1 -1
- package/dist/utils/query.d.ts +1 -0
- package/dist/utils/query.js +40 -0
- package/dist/utils/query.js.map +1 -1
- package/dist/utils/schema.d.ts +6 -2
- package/dist/utils/schema.js +14 -4
- package/dist/utils/schema.js.map +1 -1
- package/package.json +1 -1
- package/src/components/Graph/GravityGraph.tsx +9 -2
- package/src/components/Graph/utils.ts +9 -1
- package/src/containers/Authentication/Authentication.tsx +29 -34
- package/src/containers/Authentication/utils.ts +3 -3
- package/src/containers/Tenant/Diagnostics/DiagnosticsPages.ts +6 -1
- package/src/containers/Tenant/Diagnostics/Overview/Overview.tsx +17 -1
- package/src/containers/Tenant/Diagnostics/Overview/ResourcePoolInfo/ResourcePoolInfo.scss +24 -0
- package/src/containers/Tenant/Diagnostics/Overview/ResourcePoolInfo/ResourcePoolUsage.tsx +53 -0
- package/src/containers/Tenant/Diagnostics/Overview/ResourcePoolInfo/i18n/en.json +4 -1
- package/src/containers/Tenant/Diagnostics/Overview/ResourcePoolInfo/index.ts +1 -0
- package/src/containers/Tenant/Diagnostics/Overview/SchemaObjectInfo/SchemaObjectInfo.tsx +7 -1
- package/src/containers/Tenant/Diagnostics/Overview/StreamingQueryInfo/StreamingQueryInfo.tsx +2 -20
- package/src/containers/Tenant/Diagnostics/Overview/TableInfo/i18n/en.json +4 -0
- package/src/containers/Tenant/Diagnostics/Overview/TableInfo/prepareTableInfo/prepareColumnTableInfo.tsx +11 -1
- package/src/containers/Tenant/Diagnostics/Overview/TableInfo/prepareTableInfo/prepareRowTableInfo.tsx +11 -1
- package/src/containers/Tenant/Diagnostics/Overview/TableInfo/prepareTableInfo/prepareTTL.ts +45 -3
- package/src/containers/Tenant/Diagnostics/StreamingQueryGraph/StreamingQueryGraph.scss +18 -0
- package/src/containers/Tenant/Diagnostics/StreamingQueryGraph/StreamingQueryGraph.tsx +79 -0
- package/src/containers/Tenant/Diagnostics/StreamingQueryGraph/i18n/en.json +5 -0
- package/src/containers/Tenant/Diagnostics/StreamingQueryGraph/i18n/index.ts +7 -0
- package/src/containers/Tenant/Diagnostics/StreamingQueryGraph/index.ts +1 -0
- package/src/containers/Tenant/Diagnostics/i18n/en.json +1 -0
- package/src/containers/Tenant/Diagnostics/tabsContent.tsx +4 -0
- package/src/containers/Tenant/Query/QueryEditor/YqlEditor/YqlEditor.tsx +8 -1
- package/src/store/reducers/executeTopQueries/executeTopQueries.ts +46 -0
- package/src/store/reducers/query/parsers/prepareStreamingQueryPlan.ts +74 -0
- package/src/store/reducers/streamingQuery/streamingQuery.ts +43 -16
- package/src/store/reducers/tenant/constants.ts +1 -0
- package/src/types/api/schema/columnEntity.ts +2 -1
- package/src/types/api/schema/sysView.ts +60 -37
- package/src/types/api/schema/table.ts +7 -0
- package/src/utils/query.ts +55 -0
- package/src/utils/schema.ts +22 -5
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import type {QueryPlan} from '../../../../types/api/query';
|
|
2
|
+
import type {PreparedQueryData} from '../types';
|
|
3
|
+
|
|
4
|
+
import {preparePlanData} from './preparePlanData';
|
|
5
|
+
|
|
6
|
+
// empty: nothing has been published yet; unparsed: a plan arrived but cannot be read,
|
|
7
|
+
// for instance truncated by the backend; unsupported: a readable plan of an unknown version.
|
|
8
|
+
export type StreamingQueryPlanState = 'empty' | 'unparsed' | 'unsupported' | 'ready';
|
|
9
|
+
|
|
10
|
+
interface StreamingQueryPlan {
|
|
11
|
+
state: StreamingQueryPlanState;
|
|
12
|
+
prepared?: PreparedQueryData['preparedPlan'];
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function isObject(value: unknown): value is Record<string, unknown> {
|
|
16
|
+
return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function isPlanNode(value: unknown) {
|
|
20
|
+
return isObject(value) && typeof value['Node Type'] === 'string';
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function isStringList(value: unknown) {
|
|
24
|
+
return (
|
|
25
|
+
value === undefined || (Array.isArray(value) && value.every((i) => typeof i === 'string'))
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// The graph blocks render these fields directly, so anything else would throw while drawing.
|
|
30
|
+
function isRenderable(prepared: PreparedQueryData['preparedPlan']) {
|
|
31
|
+
return (prepared?.nodes ?? []).every(({data}) => {
|
|
32
|
+
return (
|
|
33
|
+
(data?.id === undefined || typeof data.id === 'number') &&
|
|
34
|
+
(data?.name === undefined || typeof data.name === 'string') &&
|
|
35
|
+
isStringList(data?.operators) &&
|
|
36
|
+
isStringList(data?.tables)
|
|
37
|
+
);
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function prepareStreamingQueryPlan(planText?: string): StreamingQueryPlan {
|
|
42
|
+
if (!planText) {
|
|
43
|
+
return {state: 'empty'};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
let parsed: unknown;
|
|
47
|
+
try {
|
|
48
|
+
parsed = JSON.parse(planText);
|
|
49
|
+
} catch {
|
|
50
|
+
return {state: 'unparsed'};
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (!isObject(parsed) || !isObject(parsed.meta)) {
|
|
54
|
+
return {state: 'empty'};
|
|
55
|
+
}
|
|
56
|
+
if (!parsed.Plan) {
|
|
57
|
+
return {state: 'empty'};
|
|
58
|
+
}
|
|
59
|
+
if (!isPlanNode(parsed.Plan)) {
|
|
60
|
+
return {state: 'unparsed'};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
try {
|
|
64
|
+
const {simplifiedPlan: _simplifiedPlan, ...prepared} = preparePlanData(
|
|
65
|
+
parsed as unknown as QueryPlan,
|
|
66
|
+
);
|
|
67
|
+
if (!isRenderable(prepared)) {
|
|
68
|
+
return {state: 'unparsed'};
|
|
69
|
+
}
|
|
70
|
+
return prepared.nodes?.length ? {state: 'ready', prepared} : {state: 'unsupported'};
|
|
71
|
+
} catch {
|
|
72
|
+
return {state: 'unparsed'};
|
|
73
|
+
}
|
|
74
|
+
}
|
|
@@ -14,27 +14,54 @@ WHERE Path = '${safePath}'
|
|
|
14
14
|
LIMIT 1`;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
+
function getStreamingQueryPlanSQL(path: string) {
|
|
18
|
+
const safePath = path.replace(/'/g, "''");
|
|
19
|
+
return `${QUERY_TECHNICAL_MARK}
|
|
20
|
+
SELECT
|
|
21
|
+
Status,
|
|
22
|
+
Issues,
|
|
23
|
+
Plan
|
|
24
|
+
FROM \`.sys/streaming_queries\`
|
|
25
|
+
WHERE Path = '${safePath}'
|
|
26
|
+
LIMIT 1`;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async function execStreamingSQL(
|
|
30
|
+
sql: string,
|
|
31
|
+
{database, signal}: {database: string; signal: AbortSignal},
|
|
32
|
+
) {
|
|
33
|
+
const response = await window.api.viewer.sendQuery(
|
|
34
|
+
{query: sql, database, action: 'execute-query', internal_call: true},
|
|
35
|
+
{signal, withRetries: true},
|
|
36
|
+
);
|
|
37
|
+
if (isQueryErrorResponse(response)) {
|
|
38
|
+
return {error: response};
|
|
39
|
+
}
|
|
40
|
+
return {data: parseQueryAPIResponse(response)};
|
|
41
|
+
}
|
|
42
|
+
|
|
17
43
|
export const streamingQueriesApi = api.injectEndpoints({
|
|
18
44
|
endpoints: (build) => ({
|
|
19
45
|
getStreamingQueryInfo: build.query({
|
|
20
46
|
queryFn: async ({database, path}: {database: string; path: string}, {signal}) => {
|
|
21
47
|
try {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
48
|
+
return await execStreamingSQL(getStreamingQueryInfoSQL(path), {
|
|
49
|
+
database,
|
|
50
|
+
signal,
|
|
51
|
+
});
|
|
52
|
+
} catch (error) {
|
|
53
|
+
return {error};
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
providesTags: ['All'],
|
|
57
|
+
}),
|
|
58
|
+
getStreamingQueryPlan: build.query({
|
|
59
|
+
queryFn: async ({database, path}: {database: string; path: string}, {signal}) => {
|
|
60
|
+
try {
|
|
61
|
+
return await execStreamingSQL(getStreamingQueryPlanSQL(path), {
|
|
62
|
+
database,
|
|
63
|
+
signal,
|
|
64
|
+
});
|
|
38
65
|
} catch (error) {
|
|
39
66
|
return {error};
|
|
40
67
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type {EColumnCodec, EUnit, TPathID, TStorageSettings, TTypeInfo} from './shared';
|
|
2
|
-
import type {TFamilyDescription} from './table';
|
|
2
|
+
import type {TFamilyDescription, TTTLTier} from './table';
|
|
3
3
|
|
|
4
4
|
export interface TColumnTableDescription {
|
|
5
5
|
Name?: string;
|
|
@@ -71,6 +71,7 @@ interface TTtl {
|
|
|
71
71
|
ExpireAfterBytes?: string;
|
|
72
72
|
|
|
73
73
|
ColumnUnit?: EUnit;
|
|
74
|
+
Tiers?: TTTLTier[];
|
|
74
75
|
}
|
|
75
76
|
|
|
76
77
|
interface TColumnTableSchema {
|
|
@@ -2,43 +2,66 @@ import type {TPathID} from './shared';
|
|
|
2
2
|
|
|
3
3
|
export interface TSysViewDescription {
|
|
4
4
|
Name?: string;
|
|
5
|
-
|
|
5
|
+
/**
|
|
6
|
+
* ESysViewType: enum name ("EVSlots") on YDB <= 26.3.1.x,
|
|
7
|
+
* numeric value (13) since ydb-platform/ydb#54332
|
|
8
|
+
*/
|
|
9
|
+
Type?: ESysViewType | number;
|
|
6
10
|
SourceObject?: TPathID;
|
|
7
11
|
}
|
|
8
12
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
13
|
+
/**
|
|
14
|
+
* Numeric ESysViewType values
|
|
15
|
+
* source: https://github.com/ydb-platform/ydb/blob/main/ydb/core/protos/sys_view_types.proto
|
|
16
|
+
*/
|
|
17
|
+
export const SYS_VIEW_TYPE_IDS = {
|
|
18
|
+
EPartitionStats: 1,
|
|
19
|
+
ENodes: 2,
|
|
20
|
+
ETopQueriesByDurationOneMinute: 3,
|
|
21
|
+
ETopQueriesByDurationOneHour: 4,
|
|
22
|
+
ETopQueriesByReadBytesOneMinute: 5,
|
|
23
|
+
ETopQueriesByReadBytesOneHour: 6,
|
|
24
|
+
ETopQueriesByCpuTimeOneMinute: 7,
|
|
25
|
+
ETopQueriesByCpuTimeOneHour: 8,
|
|
26
|
+
ETopQueriesByRequestUnitsOneMinute: 9,
|
|
27
|
+
ETopQueriesByRequestUnitsOneHour: 10,
|
|
28
|
+
EQuerySessions: 11,
|
|
29
|
+
EPDisks: 12,
|
|
30
|
+
EVSlots: 13,
|
|
31
|
+
EGroups: 14,
|
|
32
|
+
EStoragePools: 15,
|
|
33
|
+
EStorageStats: 16,
|
|
34
|
+
ETablets: 17,
|
|
35
|
+
EQueryMetricsOneMinute: 18,
|
|
36
|
+
ETopPartitionsByCpuOneMinute: 19,
|
|
37
|
+
ETopPartitionsByCpuOneHour: 20,
|
|
38
|
+
ETopPartitionsByTliOneMinute: 21,
|
|
39
|
+
ETopPartitionsByTliOneHour: 22,
|
|
40
|
+
EResourcePoolClassifiers: 23,
|
|
41
|
+
EResourcePools: 24,
|
|
42
|
+
EAuthUsers: 25,
|
|
43
|
+
EAuthGroups: 26,
|
|
44
|
+
EAuthGroupMembers: 27,
|
|
45
|
+
EAuthOwners: 28,
|
|
46
|
+
EAuthPermissions: 29,
|
|
47
|
+
EAuthEffectivePermissions: 30,
|
|
48
|
+
EPgTables: 31,
|
|
49
|
+
EInformationSchemaTables: 32,
|
|
50
|
+
EPgClass: 33,
|
|
51
|
+
EShowCreate: 34,
|
|
52
|
+
ECompileCacheQueries: 35,
|
|
53
|
+
EStorePrimaryIndexStats: 36,
|
|
54
|
+
EStorePrimaryIndexSchemaStats: 37,
|
|
55
|
+
EStorePrimaryIndexPortionStats: 38,
|
|
56
|
+
EStorePrimaryIndexGranuleStats: 39,
|
|
57
|
+
EStorePrimaryIndexOptimizerStats: 40,
|
|
58
|
+
ETablePrimaryIndexStats: 41,
|
|
59
|
+
ETablePrimaryIndexSchemaStats: 42,
|
|
60
|
+
ETablePrimaryIndexPortionStats: 43,
|
|
61
|
+
ETablePrimaryIndexGranuleStats: 44,
|
|
62
|
+
ETablePrimaryIndexOptimizerStats: 45,
|
|
63
|
+
EStreamingQueries: 46,
|
|
64
|
+
EUdfModules: 47,
|
|
65
|
+
} as const;
|
|
66
|
+
|
|
67
|
+
export type ESysViewType = keyof typeof SYS_VIEW_TYPE_IDS;
|
|
@@ -66,6 +66,13 @@ interface TEnabled {
|
|
|
66
66
|
ExpireAfterSeconds?: number;
|
|
67
67
|
ColumnUnit?: EUnit;
|
|
68
68
|
SysSettings?: TSysSettings;
|
|
69
|
+
Tiers?: TTTLTier[];
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export interface TTTLTier {
|
|
73
|
+
ApplyAfterSeconds?: number;
|
|
74
|
+
Delete?: {};
|
|
75
|
+
EvictToExternalStorage?: {Storage?: string};
|
|
69
76
|
}
|
|
70
77
|
|
|
71
78
|
interface TSysSettings {
|
package/src/utils/query.ts
CHANGED
|
@@ -253,6 +253,61 @@ export function isErrorResponse(data: unknown): data is ErrorResponse {
|
|
|
253
253
|
return Boolean(data && typeof data === 'object' && 'issues' in data);
|
|
254
254
|
}
|
|
255
255
|
|
|
256
|
+
function hasIssueContent(data: ErrorResponse) {
|
|
257
|
+
return Boolean(data.error || data.issues?.length);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// The issues view walks this tree and renders these fields, so anything else would throw while drawing.
|
|
261
|
+
function isIssueTree(value: unknown): boolean {
|
|
262
|
+
return (
|
|
263
|
+
Array.isArray(value) &&
|
|
264
|
+
value.every((issue) => {
|
|
265
|
+
if (!issue || typeof issue !== 'object' || Array.isArray(issue)) {
|
|
266
|
+
return false;
|
|
267
|
+
}
|
|
268
|
+
const {
|
|
269
|
+
message,
|
|
270
|
+
issue_code: issueCode,
|
|
271
|
+
issues,
|
|
272
|
+
} = issue as {
|
|
273
|
+
message?: unknown;
|
|
274
|
+
issue_code?: unknown;
|
|
275
|
+
issues?: unknown;
|
|
276
|
+
};
|
|
277
|
+
return (
|
|
278
|
+
(message === undefined || typeof message === 'string') &&
|
|
279
|
+
(issueCode === undefined || typeof issueCode === 'number') &&
|
|
280
|
+
(issues === undefined || issues === null || isIssueTree(issues))
|
|
281
|
+
);
|
|
282
|
+
})
|
|
283
|
+
);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
function hasRenderableIssues(data: ErrorResponse) {
|
|
287
|
+
const message: unknown = data.error?.message;
|
|
288
|
+
return (
|
|
289
|
+
(message === undefined || typeof message === 'string') &&
|
|
290
|
+
(data.issues === undefined || data.issues === null || isIssueTree(data.issues))
|
|
291
|
+
);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
export function parseIssuesData(raw: unknown): ErrorResponse | string | undefined {
|
|
295
|
+
if (typeof raw === 'string' && raw) {
|
|
296
|
+
try {
|
|
297
|
+
const parsed: unknown = JSON.parse(raw);
|
|
298
|
+
return isErrorResponse(parsed) && hasIssueContent(parsed) && hasRenderableIssues(parsed)
|
|
299
|
+
? parsed
|
|
300
|
+
: undefined;
|
|
301
|
+
} catch {
|
|
302
|
+
return raw;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
if (isErrorResponse(raw) && hasIssueContent(raw) && hasRenderableIssues(raw)) {
|
|
306
|
+
return raw;
|
|
307
|
+
}
|
|
308
|
+
return undefined;
|
|
309
|
+
}
|
|
310
|
+
|
|
256
311
|
// Although schema is set in request, if schema is not supported default schema for the version will be used
|
|
257
312
|
// So we should additionally parse response
|
|
258
313
|
export function parseQueryAPIResponse(
|
package/src/utils/schema.ts
CHANGED
|
@@ -1,14 +1,31 @@
|
|
|
1
1
|
import type {ESysViewType} from '../types/api/schema/sysView';
|
|
2
|
+
import {SYS_VIEW_TYPE_IDS} from '../types/api/schema/sysView';
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
|
|
4
|
+
const SYS_VIEW_TYPE_NAMES_BY_ID = new Map<number, ESysViewType>(
|
|
5
|
+
(Object.keys(SYS_VIEW_TYPE_IDS) as ESysViewType[]).map(
|
|
6
|
+
(name) => [SYS_VIEW_TYPE_IDS[name], name] as const,
|
|
7
|
+
),
|
|
8
|
+
);
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Normalizes SysViewDescription.Type for display.
|
|
12
|
+
* YDB <= 26.3.1.x returns the enum name ("EVSlots"),
|
|
13
|
+
* YDB with ydb-platform/ydb#54332 returns the numeric value (13).
|
|
14
|
+
*/
|
|
15
|
+
export function prepareSystemViewType(type?: string | number | null): string | undefined {
|
|
16
|
+
if (type === undefined || type === null || type === '') {
|
|
5
17
|
return undefined;
|
|
6
18
|
}
|
|
19
|
+
|
|
20
|
+
// Ids unknown to this UI version are shown as-is instead of hiding the row
|
|
21
|
+
const name =
|
|
22
|
+
typeof type === 'number' ? (SYS_VIEW_TYPE_NAMES_BY_ID.get(type) ?? String(type)) : type;
|
|
23
|
+
|
|
7
24
|
// System view type is enum, its format from backend is EType
|
|
8
25
|
// We need to display only Type, remove redundant E
|
|
9
26
|
// EStoragePools -> StoragePools, EStorageStats -> StorageStats
|
|
10
|
-
if (
|
|
11
|
-
return
|
|
27
|
+
if (name.startsWith('E')) {
|
|
28
|
+
return name.slice(1);
|
|
12
29
|
}
|
|
13
|
-
return
|
|
30
|
+
return name;
|
|
14
31
|
}
|