ydb-embedded-ui 3.4.4 → 3.5.0
Sign up to get free protection for your applications and to get access to all the features.
- package/CHANGELOG.md +31 -0
- package/dist/components/Icon/Icon.tsx +6 -0
- package/dist/components/InfoViewer/InfoViewer.tsx +2 -2
- package/dist/components/InfoViewer/formatters/index.ts +0 -1
- package/dist/components/InfoViewer/formatters/table.ts +6 -0
- package/dist/components/LabelWithPopover/LabelWithPopover.tsx +3 -7
- package/dist/components/LagPopoverContent/LagPopoverContent.scss +13 -0
- package/dist/components/LagPopoverContent/LagPopoverContent.tsx +19 -0
- package/dist/components/LagPopoverContent/index.ts +1 -0
- package/dist/components/Tooltips/NodeEndpointsTooltip/NodeEndpointsTooltip.scss +5 -0
- package/dist/components/Tooltips/NodeEndpointsTooltip/NodeEndpointsTooltip.tsx +31 -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/Nodes/Nodes.tsx +2 -6
- package/dist/containers/Nodes/NodesTable.scss +11 -10
- package/dist/containers/Nodes/getNodesColumns.tsx +29 -24
- package/dist/containers/Storage/PDisk/PDisk.scss +2 -0
- package/dist/containers/Storage/PDiskPopup/PDiskPopup.tsx +6 -9
- package/dist/containers/Storage/Storage.js +12 -5
- package/dist/containers/Storage/StorageGroups/StorageGroups.tsx +3 -1
- package/dist/containers/Storage/StorageNodes/StorageNodes.scss +20 -7
- package/dist/containers/Storage/StorageNodes/StorageNodes.tsx +43 -7
- package/dist/containers/Storage/VDisk/VDisk.tsx +3 -2
- package/dist/containers/Storage/VDiskPopup/VDiskPopup.tsx +4 -2
- package/dist/containers/Tablet/TabletControls/TabletControls.tsx +2 -2
- package/dist/containers/Tenant/Diagnostics/Consumers/Headers/Headers.scss +0 -8
- package/dist/containers/Tenant/Diagnostics/Consumers/Headers/Headers.tsx +3 -10
- package/dist/containers/Tenant/Diagnostics/Consumers/i18n/ru.json +1 -1
- 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/Overview/TopicStats/TopicStats.tsx +51 -32
- package/dist/containers/Tenant/Diagnostics/Overview/TopicStats/i18n/en.json +2 -1
- package/dist/containers/Tenant/Diagnostics/Overview/TopicStats/i18n/ru.json +2 -1
- package/dist/containers/Tenant/Diagnostics/Partitions/Headers/Headers.scss +0 -8
- package/dist/containers/Tenant/Diagnostics/Partitions/Headers/Headers.tsx +7 -21
- 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/QueryEditor.js +1 -0
- package/dist/routes.ts +1 -1
- package/dist/services/api.d.ts +4 -0
- package/dist/services/api.js +3 -3
- package/dist/store/reducers/{executeQuery.js → executeQuery.ts} +51 -21
- package/dist/store/reducers/executeTopQueries.ts +5 -1
- package/dist/store/reducers/{nodesList.js → nodesList.ts} +19 -7
- package/dist/store/reducers/{olapStats.js → olapStats.ts} +8 -18
- package/dist/store/reducers/settings.js +1 -1
- package/dist/store/reducers/storage.js +8 -18
- package/dist/types/api/nodesList.ts +25 -0
- package/dist/types/api/query.ts +4 -1
- package/dist/types/api/schema.ts +523 -3
- package/dist/types/common.ts +1 -0
- package/dist/types/store/executeQuery.ts +42 -0
- package/dist/types/store/nodesList.ts +24 -0
- package/dist/types/store/olapStats.ts +14 -0
- package/dist/utils/index.js +9 -1
- package/dist/utils/nodes.ts +4 -0
- package/dist/utils/query.test.ts +42 -29
- package/dist/utils/query.ts +34 -22
- package/dist/utils/timeParsers/formatDuration.ts +30 -12
- package/dist/utils/timeParsers/i18n/en.json +4 -0
- package/dist/utils/timeParsers/i18n/ru.json +4 -0
- package/dist/utils/tooltip.js +2 -28
- package/package.json +1 -1
- package/dist/components/InfoViewer/formatters/topicStats.tsx +0 -29
package/dist/utils/query.test.ts
CHANGED
@@ -1,7 +1,4 @@
|
|
1
|
-
import {
|
2
|
-
parseQueryAPIExecuteResponse,
|
3
|
-
parseQueryAPIExplainResponse,
|
4
|
-
} from './query';
|
1
|
+
import {parseQueryAPIExecuteResponse, parseQueryAPIExplainResponse} from './query';
|
5
2
|
|
6
3
|
describe('API utils', () => {
|
7
4
|
describe('json/viewer/query', () => {
|
@@ -45,7 +42,9 @@ describe('API utils', () => {
|
|
45
42
|
|
46
43
|
it('should accept key-value rows in the result field', () => {
|
47
44
|
const response = {result: [{foo: 'bar'}]};
|
48
|
-
expect(parseQueryAPIExecuteResponse(response).result).toEqual(
|
45
|
+
expect(parseQueryAPIExecuteResponse(response).result).toEqual(
|
46
|
+
response.result,
|
47
|
+
);
|
49
48
|
});
|
50
49
|
});
|
51
50
|
|
@@ -98,19 +97,24 @@ describe('API utils', () => {
|
|
98
97
|
it('should parse modern schema', () => {
|
99
98
|
const response = {
|
100
99
|
result: [['42', 'hello world']],
|
101
|
-
columns: [
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
100
|
+
columns: [
|
101
|
+
{
|
102
|
+
name: 'id',
|
103
|
+
type: 'Uint64?',
|
104
|
+
},
|
105
|
+
{
|
106
|
+
name: 'value',
|
107
|
+
type: 'Utf8?',
|
108
|
+
},
|
109
|
+
],
|
108
110
|
};
|
109
111
|
const actual = parseQueryAPIExecuteResponse(response);
|
110
|
-
expect(actual.result).toEqual([
|
111
|
-
|
112
|
-
|
113
|
-
|
112
|
+
expect(actual.result).toEqual([
|
113
|
+
{
|
114
|
+
id: '42',
|
115
|
+
value: 'hello world',
|
116
|
+
},
|
117
|
+
]);
|
114
118
|
expect(actual.columns).toEqual(response.columns);
|
115
119
|
});
|
116
120
|
|
@@ -125,12 +129,16 @@ describe('API utils', () => {
|
|
125
129
|
|
126
130
|
it('should parse deep classic schema', () => {
|
127
131
|
const response = {result: [{foo: 'bar'}]};
|
128
|
-
expect(parseQueryAPIExecuteResponse(response).result).toEqual(
|
132
|
+
expect(parseQueryAPIExecuteResponse(response).result).toEqual(
|
133
|
+
response.result,
|
134
|
+
);
|
129
135
|
});
|
130
136
|
|
131
137
|
it('should parse ydb schema', () => {
|
132
138
|
const response = {result: [{foo: 'bar'}]};
|
133
|
-
expect(parseQueryAPIExecuteResponse(response).result).toEqual(
|
139
|
+
expect(parseQueryAPIExecuteResponse(response).result).toEqual(
|
140
|
+
response.result,
|
141
|
+
);
|
134
142
|
});
|
135
143
|
});
|
136
144
|
|
@@ -138,20 +146,25 @@ describe('API utils', () => {
|
|
138
146
|
it('should parse modern schema', () => {
|
139
147
|
const response = {
|
140
148
|
result: [['42', 'hello world']],
|
141
|
-
columns: [
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
149
|
+
columns: [
|
150
|
+
{
|
151
|
+
name: 'id',
|
152
|
+
type: 'Uint64?',
|
153
|
+
},
|
154
|
+
{
|
155
|
+
name: 'value',
|
156
|
+
type: 'Utf8?',
|
157
|
+
},
|
158
|
+
],
|
148
159
|
stats: {metric: 'good'},
|
149
160
|
};
|
150
161
|
const actual = parseQueryAPIExecuteResponse(response);
|
151
|
-
expect(actual.result).toEqual([
|
152
|
-
|
153
|
-
|
154
|
-
|
162
|
+
expect(actual.result).toEqual([
|
163
|
+
{
|
164
|
+
id: '42',
|
165
|
+
value: 'hello world',
|
166
|
+
},
|
167
|
+
]);
|
155
168
|
expect(actual.columns).toEqual(response.columns);
|
156
169
|
expect(actual.stats).toEqual(response.stats);
|
157
170
|
});
|
package/dist/utils/query.ts
CHANGED
@@ -47,25 +47,30 @@ export const getColumnType = (type: string) => {
|
|
47
47
|
default:
|
48
48
|
return undefined;
|
49
49
|
}
|
50
|
-
}
|
50
|
+
};
|
51
51
|
|
52
52
|
const parseExecuteModernResponse = (data: ExecuteModernResponse): IQueryResult => {
|
53
53
|
const {result, columns, ...restData} = data;
|
54
54
|
|
55
55
|
return {
|
56
|
-
result:
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
return newRow
|
61
|
-
|
62
|
-
|
56
|
+
result:
|
57
|
+
result &&
|
58
|
+
columns &&
|
59
|
+
result.map((row) => {
|
60
|
+
return row.reduce((newRow: KeyValueRow, cellData, columnIndex) => {
|
61
|
+
const {name} = columns[columnIndex];
|
62
|
+
newRow[name] = cellData;
|
63
|
+
return newRow;
|
64
|
+
}, {});
|
65
|
+
}),
|
63
66
|
columns,
|
64
67
|
...restData,
|
65
68
|
};
|
66
69
|
};
|
67
70
|
|
68
|
-
const parseDeprecatedExecuteResponseValue = (
|
71
|
+
const parseDeprecatedExecuteResponseValue = (
|
72
|
+
data?: DeprecatedExecuteResponsePlain | ExecuteClassicResponsePlain,
|
73
|
+
): KeyValueRow[] | undefined => {
|
69
74
|
if (!data) {
|
70
75
|
return undefined;
|
71
76
|
}
|
@@ -86,20 +91,21 @@ const parseDeprecatedExecuteResponseValue = (data?: DeprecatedExecuteResponsePla
|
|
86
91
|
return undefined;
|
87
92
|
};
|
88
93
|
|
89
|
-
const hasResult = (data: AnyExecuteResponse): data is DeepExecuteResponse =>
|
90
|
-
data && typeof data === 'object' && 'result' in data
|
91
|
-
);
|
94
|
+
const hasResult = (data: AnyExecuteResponse): data is DeepExecuteResponse =>
|
95
|
+
Boolean(data && typeof data === 'object' && 'result' in data);
|
92
96
|
|
93
|
-
const isModern = (response: AnyExecuteResponse): response is ExecuteModernResponse =>
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
)
|
97
|
+
const isModern = (response: AnyExecuteResponse): response is ExecuteModernResponse =>
|
98
|
+
Boolean(
|
99
|
+
response &&
|
100
|
+
!Array.isArray(response) &&
|
101
|
+
Array.isArray((response as ExecuteModernResponse).result) &&
|
102
|
+
Array.isArray((response as ExecuteModernResponse).columns),
|
103
|
+
);
|
99
104
|
|
100
|
-
const hasCommonFields = (data: AnyResponse): data is CommonFields =>
|
101
|
-
|
102
|
-
)
|
105
|
+
const hasCommonFields = (data: AnyResponse): data is CommonFields =>
|
106
|
+
Boolean(
|
107
|
+
data && typeof data === 'object' && ('ast' in data || 'plan' in data || 'stats' in data),
|
108
|
+
);
|
103
109
|
|
104
110
|
// complex logic because of the variety of possible responses
|
105
111
|
// after all backends are updated to the latest version, it can be simplified
|
@@ -186,5 +192,11 @@ export const prepareQueryResponse = (data?: KeyValueRow[]) => {
|
|
186
192
|
};
|
187
193
|
|
188
194
|
export function prepareQueryError(error: any) {
|
189
|
-
return
|
195
|
+
return (
|
196
|
+
error.data?.error?.message ||
|
197
|
+
error.message ||
|
198
|
+
error.data ||
|
199
|
+
error.statusText ||
|
200
|
+
JSON.stringify(error)
|
201
|
+
);
|
190
202
|
}
|
@@ -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);
|
package/dist/utils/tooltip.js
CHANGED
@@ -2,6 +2,8 @@ import cn from 'bem-cn-lite';
|
|
2
2
|
import {calcUptime} from '.';
|
3
3
|
import JSONTree from 'react-json-inspector';
|
4
4
|
|
5
|
+
import {NodeEndpointsTooltip} from '../components/Tooltips/NodeEndpointsTooltip/NodeEndpointsTooltip';
|
6
|
+
|
5
7
|
const poolB = cn('pool-tooltip');
|
6
8
|
|
7
9
|
const PoolTooltip = (props) => {
|
@@ -109,34 +111,6 @@ const NodeTooltip = (props) => {
|
|
109
111
|
);
|
110
112
|
};
|
111
113
|
|
112
|
-
const NodeEndpointsTooltip = (props) => {
|
113
|
-
const {data} = props;
|
114
|
-
return (
|
115
|
-
data && (
|
116
|
-
<div className={nodeB()}>
|
117
|
-
<table>
|
118
|
-
<tbody>
|
119
|
-
{data.Rack && (
|
120
|
-
<tr>
|
121
|
-
<td className={nodeB('label')}>Rack</td>
|
122
|
-
<td className={nodeB('value')}>{data.Rack}</td>
|
123
|
-
</tr>
|
124
|
-
)}
|
125
|
-
{data.Endpoints &&
|
126
|
-
data.Endpoints.length &&
|
127
|
-
data.Endpoints.map(({Name, Address}) => (
|
128
|
-
<tr key={Name}>
|
129
|
-
<td className={nodeB('label')}>{Name}</td>
|
130
|
-
<td className={nodeB('value')}>{Address}</td>
|
131
|
-
</tr>
|
132
|
-
))}
|
133
|
-
</tbody>
|
134
|
-
</table>
|
135
|
-
</div>
|
136
|
-
)
|
137
|
-
);
|
138
|
-
};
|
139
|
-
|
140
114
|
const tabletsOverallB = cn('tabletsOverall-tooltip');
|
141
115
|
|
142
116
|
const TabletsOverallTooltip = (props) => {
|
package/package.json
CHANGED
@@ -1,29 +0,0 @@
|
|
1
|
-
import type {TopicStats} from '../../../types/api/topic';
|
2
|
-
import {formatBytes} from '../../../utils';
|
3
|
-
import {
|
4
|
-
parseLag,
|
5
|
-
parseTimestampToIdleTime,
|
6
|
-
formatDurationToShortTimeFormat,
|
7
|
-
} from '../../../utils/timeParsers';
|
8
|
-
import {convertBytesObjectToSpeed} from '../../../utils/bytesParsers';
|
9
|
-
|
10
|
-
import {SpeedMultiMeter} from '../../SpeedMultiMeter';
|
11
|
-
|
12
|
-
import {createInfoFormatter} from '../utils';
|
13
|
-
|
14
|
-
export const formatTopicStats = createInfoFormatter<TopicStats>({
|
15
|
-
values: {
|
16
|
-
store_size_bytes: formatBytes,
|
17
|
-
min_last_write_time: (value) =>
|
18
|
-
formatDurationToShortTimeFormat(parseTimestampToIdleTime(value)),
|
19
|
-
max_write_time_lag: (value) => formatDurationToShortTimeFormat(parseLag(value)),
|
20
|
-
bytes_written: (value) =>
|
21
|
-
value && <SpeedMultiMeter data={convertBytesObjectToSpeed(value)} withValue={false} />,
|
22
|
-
},
|
23
|
-
labels: {
|
24
|
-
store_size_bytes: 'Store size',
|
25
|
-
min_last_write_time: 'Partitions max time since last write',
|
26
|
-
max_write_time_lag: 'Partitions max write time lag',
|
27
|
-
bytes_written: 'Average write speed',
|
28
|
-
},
|
29
|
-
});
|