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.
Files changed (67) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/dist/components/Icon/Icon.tsx +6 -0
  3. package/dist/components/InfoViewer/InfoViewer.tsx +2 -2
  4. package/dist/components/InfoViewer/formatters/index.ts +0 -1
  5. package/dist/components/InfoViewer/formatters/table.ts +6 -0
  6. package/dist/components/LabelWithPopover/LabelWithPopover.tsx +3 -7
  7. package/dist/components/LagPopoverContent/LagPopoverContent.scss +13 -0
  8. package/dist/components/LagPopoverContent/LagPopoverContent.tsx +19 -0
  9. package/dist/components/LagPopoverContent/index.ts +1 -0
  10. package/dist/components/Tooltips/NodeEndpointsTooltip/NodeEndpointsTooltip.scss +5 -0
  11. package/dist/components/Tooltips/NodeEndpointsTooltip/NodeEndpointsTooltip.tsx +31 -0
  12. package/dist/components/TruncatedQuery/TruncatedQuery.js +1 -1
  13. package/dist/components/TruncatedQuery/TruncatedQuery.scss +7 -3
  14. package/dist/containers/Node/{NodePages.js → NodePages.ts} +1 -1
  15. package/dist/containers/Nodes/Nodes.tsx +2 -6
  16. package/dist/containers/Nodes/NodesTable.scss +11 -10
  17. package/dist/containers/Nodes/getNodesColumns.tsx +29 -24
  18. package/dist/containers/Storage/PDisk/PDisk.scss +2 -0
  19. package/dist/containers/Storage/PDiskPopup/PDiskPopup.tsx +6 -9
  20. package/dist/containers/Storage/Storage.js +12 -5
  21. package/dist/containers/Storage/StorageGroups/StorageGroups.tsx +3 -1
  22. package/dist/containers/Storage/StorageNodes/StorageNodes.scss +20 -7
  23. package/dist/containers/Storage/StorageNodes/StorageNodes.tsx +43 -7
  24. package/dist/containers/Storage/VDisk/VDisk.tsx +3 -2
  25. package/dist/containers/Storage/VDiskPopup/VDiskPopup.tsx +4 -2
  26. package/dist/containers/Tablet/TabletControls/TabletControls.tsx +2 -2
  27. package/dist/containers/Tenant/Diagnostics/Consumers/Headers/Headers.scss +0 -8
  28. package/dist/containers/Tenant/Diagnostics/Consumers/Headers/Headers.tsx +3 -10
  29. package/dist/containers/Tenant/Diagnostics/Consumers/i18n/ru.json +1 -1
  30. package/dist/containers/Tenant/Diagnostics/Overview/Overview.tsx +11 -43
  31. package/dist/containers/Tenant/Diagnostics/Overview/TableInfo/TableInfo.tsx +19 -17
  32. package/dist/containers/Tenant/Diagnostics/Overview/TableInfo/prepareTableInfo.ts +192 -37
  33. package/dist/containers/Tenant/Diagnostics/Overview/TopicStats/TopicStats.tsx +51 -32
  34. package/dist/containers/Tenant/Diagnostics/Overview/TopicStats/i18n/en.json +2 -1
  35. package/dist/containers/Tenant/Diagnostics/Overview/TopicStats/i18n/ru.json +2 -1
  36. package/dist/containers/Tenant/Diagnostics/Partitions/Headers/Headers.scss +0 -8
  37. package/dist/containers/Tenant/Diagnostics/Partitions/Headers/Headers.tsx +7 -21
  38. package/dist/containers/Tenant/Diagnostics/TopQueries/TopQueries.scss +20 -14
  39. package/dist/containers/Tenant/Diagnostics/TopQueries/TopQueries.tsx +49 -12
  40. package/dist/containers/Tenant/Diagnostics/TopShards/TopShards.tsx +37 -18
  41. package/dist/containers/Tenant/QueryEditor/QueryEditor.js +1 -0
  42. package/dist/routes.ts +1 -1
  43. package/dist/services/api.d.ts +4 -0
  44. package/dist/services/api.js +3 -3
  45. package/dist/store/reducers/{executeQuery.js → executeQuery.ts} +51 -21
  46. package/dist/store/reducers/executeTopQueries.ts +5 -1
  47. package/dist/store/reducers/{nodesList.js → nodesList.ts} +19 -7
  48. package/dist/store/reducers/{olapStats.js → olapStats.ts} +8 -18
  49. package/dist/store/reducers/settings.js +1 -1
  50. package/dist/store/reducers/storage.js +8 -18
  51. package/dist/types/api/nodesList.ts +25 -0
  52. package/dist/types/api/query.ts +4 -1
  53. package/dist/types/api/schema.ts +523 -3
  54. package/dist/types/common.ts +1 -0
  55. package/dist/types/store/executeQuery.ts +42 -0
  56. package/dist/types/store/nodesList.ts +24 -0
  57. package/dist/types/store/olapStats.ts +14 -0
  58. package/dist/utils/index.js +9 -1
  59. package/dist/utils/nodes.ts +4 -0
  60. package/dist/utils/query.test.ts +42 -29
  61. package/dist/utils/query.ts +34 -22
  62. package/dist/utils/timeParsers/formatDuration.ts +30 -12
  63. package/dist/utils/timeParsers/i18n/en.json +4 -0
  64. package/dist/utils/timeParsers/i18n/ru.json +4 -0
  65. package/dist/utils/tooltip.js +2 -28
  66. package/package.json +1 -1
  67. package/dist/components/InfoViewer/formatters/topicStats.tsx +0 -29
@@ -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(response.result);
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
- name: 'id',
103
- type: 'Uint64?'
104
- }, {
105
- name: 'value',
106
- type: 'Utf8?'
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
- id: '42',
112
- value: 'hello world'
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(response.result);
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(response.result);
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
- name: 'id',
143
- type: 'Uint64?'
144
- }, {
145
- name: 'value',
146
- type: 'Utf8?'
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
- id: '42',
153
- value: 'hello world'
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
  });
@@ -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: 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
- }),
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 = (data?: DeprecatedExecuteResponsePlain | ExecuteClassicResponsePlain): KeyValueRow[] | undefined => {
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 => Boolean(
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 => Boolean(
94
- response &&
95
- !Array.isArray(response) &&
96
- Array.isArray((response as ExecuteModernResponse).result) &&
97
- Array.isArray((response as ExecuteModernResponse).columns)
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 => Boolean(
101
- data && typeof data === 'object' && ('ast' in data || 'plan' in data || 'stats' in data)
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 error.data?.error?.message || error.message || error.data || error.statusText || JSON.stringify(error);
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
- * 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);
@@ -3,5 +3,9 @@
3
3
  "hoursMin": "{{hours}}h {{minutes}}m",
4
4
  "minSec": "{{minutes}}m {{seconds}}s",
5
5
  "secMs": "{{seconds}}s {{ms}}ms",
6
+ "days": "{{days}}d",
7
+ "hours": "{{hours}}h",
8
+ "min": "{{minutes}}m",
9
+ "sec": "{{seconds}}s",
6
10
  "ms": "{{ms}}ms"
7
11
  }
@@ -3,5 +3,9 @@
3
3
  "hoursMin": "{{hours}}ч {{minutes}}м",
4
4
  "minSec": "{{minutes}}м {{seconds}}с",
5
5
  "secMs": "{{seconds}}с {{ms}}мс",
6
+ "days": "{{days}}д",
7
+ "hours": "{{hours}}ч",
8
+ "min": "{{minutes}}м",
9
+ "sec": "{{seconds}}с",
6
10
  "ms": "{{ms}}мс"
7
11
  }
@@ -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,6 +1,6 @@
1
1
  {
2
2
  "name": "ydb-embedded-ui",
3
- "version": "3.4.4",
3
+ "version": "3.5.0",
4
4
  "files": [
5
5
  "dist"
6
6
  ],
@@ -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
- });