ydb-embedded-ui 1.10.1 → 1.10.2
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/CHANGELOG.md +14 -0
- package/dist/components/IndexInfoViewer/IndexInfoViewer.tsx +10 -7
- package/dist/components/InfoViewer/InfoViewer.scss +1 -2
- package/dist/components/InfoViewer/utils.ts +18 -10
- package/dist/containers/Tenant/Diagnostics/DetailedOverview/DetailedOverview.tsx +15 -14
- package/dist/containers/Tenant/QueryEditor/QueryEditor.js +12 -2
- package/dist/containers/Tenant/Schema/SchemaInfoViewer/SchemaInfoViewer.js +164 -42
- package/dist/containers/Tenant/Schema/SchemaInfoViewer/SchemaInfoViewer.scss +18 -0
- package/dist/services/api.js +0 -1
- package/dist/store/reducers/executeQuery.js +3 -2
- package/dist/store/reducers/settings.js +20 -13
- package/dist/types/api/schema.ts +117 -4
- package/dist/utils/constants.js +4 -0
- package/dist/utils/index.js +7 -3
- package/dist/utils/pdisk.ts +2 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
@@ -1,5 +1,19 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## [1.10.2](https://github.com/ydb-platform/ydb-embedded-ui/compare/v1.10.1...v1.10.2) (2022-08-17)
|
4
|
+
|
5
|
+
|
6
|
+
### Bug Fixes
|
7
|
+
|
8
|
+
* convert bytes on decimal scale ([db9b0a7](https://github.com/ydb-platform/ydb-embedded-ui/commit/db9b0a71fc5334f5a40992cc6abc0688782ad5d2))
|
9
|
+
* display HDD instead of ROT as pdisk type ([bd9e5ba](https://github.com/ydb-platform/ydb-embedded-ui/commit/bd9e5ba4e594cb3a1f6a964f619f9824e083ae7c))
|
10
|
+
* **InfoViewer:** accept default value formatter ([e03d8cc](https://github.com/ydb-platform/ydb-embedded-ui/commit/e03d8cc5de76e4ac00b05586ae6f6522a9708fb0))
|
11
|
+
* **InfoViewer:** allow longer labels ([89060a3](https://github.com/ydb-platform/ydb-embedded-ui/commit/89060a381858b5beaa3c3cf3402c13c917705676))
|
12
|
+
* **Overview:** display table r/o replicas ([6dbe0b4](https://github.com/ydb-platform/ydb-embedded-ui/commit/6dbe0b45fc5e3867f9d6141d270c15508a693e35))
|
13
|
+
* **Overview:** format & group table info in overview ([1a35cfc](https://github.com/ydb-platform/ydb-embedded-ui/commit/1a35cfcd2075454c4a1f1fc4961a4b3106b6d225))
|
14
|
+
* **QueryEditor:** save chosen run action ([b0fb436](https://github.com/ydb-platform/ydb-embedded-ui/commit/b0fb43651e0c6d1dc5d6a25f92716703402b556d))
|
15
|
+
* use current i18n lang for numeral formatting ([5d58fcf](https://github.com/ydb-platform/ydb-embedded-ui/commit/5d58fcffde21924f3cbe6c28946c7a9f755a8490))
|
16
|
+
|
3
17
|
## [1.10.1](https://github.com/ydb-platform/ydb-embedded-ui/compare/v1.10.0...v1.10.1) (2022-08-10)
|
4
18
|
|
5
19
|
|
@@ -10,13 +10,16 @@ const DISPLAYED_FIELDS: Set<keyof TIndexDescription> = new Set([
|
|
10
10
|
]);
|
11
11
|
|
12
12
|
const formatItem = createInfoFormatter<TIndexDescription>({
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
13
|
+
values: {
|
14
|
+
Type: (value) => value?.substring(10), // trims EIndexType prefix
|
15
|
+
State: (value) => value?.substring(11), // trims EIndexState prefix
|
16
|
+
KeyColumnNames: (value) => value?.join(', '),
|
17
|
+
DataColumnNames: (value) => value?.join(', '),
|
18
|
+
},
|
19
|
+
labels: {
|
20
|
+
KeyColumnNames: 'Columns',
|
21
|
+
DataColumnNames: 'Includes',
|
22
|
+
},
|
20
23
|
});
|
21
24
|
|
22
25
|
interface IndexInfoViewerProps {
|
@@ -2,7 +2,7 @@ type LabelMap<T> = {
|
|
2
2
|
[label in keyof T]?: string;
|
3
3
|
}
|
4
4
|
|
5
|
-
type
|
5
|
+
type ValueFormatters<T> = {
|
6
6
|
[label in keyof T]?: (value: T[label]) => string | undefined;
|
7
7
|
}
|
8
8
|
|
@@ -13,20 +13,28 @@ function formatLabel<Shape>(label: keyof Shape, map: LabelMap<Shape>) {
|
|
13
13
|
function formatValue<Shape, Key extends keyof Shape>(
|
14
14
|
label: Key,
|
15
15
|
value: Shape[Key],
|
16
|
-
|
16
|
+
formatters: ValueFormatters<Shape>,
|
17
|
+
defaultFormatter?: (value: Shape[Key]) => string | undefined,
|
17
18
|
) {
|
18
|
-
const
|
19
|
-
const
|
19
|
+
const formatter = formatters[label] || defaultFormatter;
|
20
|
+
const formattedValue = formatter ? formatter(value) : value;
|
20
21
|
|
21
|
-
return String(
|
22
|
+
return String(formattedValue ?? '');
|
22
23
|
}
|
23
24
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
)
|
25
|
+
interface CreateInfoFormatterOptions<Shape> {
|
26
|
+
values?: ValueFormatters<Shape>,
|
27
|
+
labels?: LabelMap<Shape>,
|
28
|
+
defaultValueFormatter?: (value: Shape[keyof Shape]) => string | undefined,
|
29
|
+
}
|
30
|
+
|
31
|
+
export function createInfoFormatter<Shape extends Record<string, any>>({
|
32
|
+
values: valueFormatters,
|
33
|
+
labels: labelMap,
|
34
|
+
defaultValueFormatter,
|
35
|
+
}: CreateInfoFormatterOptions<Shape>) {
|
28
36
|
return <Key extends keyof Shape>(label: Key, value: Shape[Key]) => ({
|
29
37
|
label: formatLabel(label, labelMap || {}),
|
30
|
-
value: formatValue(label, value,
|
38
|
+
value: formatValue(label, value, valueFormatters || {}, defaultValueFormatter),
|
31
39
|
});
|
32
40
|
}
|
@@ -60,20 +60,21 @@ function DetailedOverview(props: DetailedOverviewProps) {
|
|
60
60
|
const isTenant = tenantName === currentSchemaPath;
|
61
61
|
return (
|
62
62
|
<div className={b()}>
|
63
|
-
|
64
|
-
|
65
|
-
<
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
63
|
+
{isTenant ? (
|
64
|
+
<>
|
65
|
+
<div className={b('section')}>
|
66
|
+
<TenantOverview tenantName={tenantName} additionalTenantInfo={additionalTenantInfo} />
|
67
|
+
</div>
|
68
|
+
<div className={b('section')}>
|
69
|
+
<Healthcheck
|
70
|
+
tenant={tenantName}
|
71
|
+
preview={true}
|
72
|
+
showMoreHandler={openModalHandler}
|
73
|
+
/>
|
74
|
+
</div>
|
75
|
+
</>
|
76
|
+
) : (
|
77
|
+
<Overview type={type} tenantName={tenantName} />
|
77
78
|
)}
|
78
79
|
</div>
|
79
80
|
);
|
@@ -33,6 +33,7 @@ import {
|
|
33
33
|
DEFAULT_SIZE_RESULT_PANE_KEY,
|
34
34
|
DEFAULT_TABLE_SETTINGS,
|
35
35
|
SAVED_QUERIES_KEY,
|
36
|
+
QUERY_INITIAL_RUN_ACTION_KEY,
|
36
37
|
} from '../../../utils/constants';
|
37
38
|
import {prepareQueryResponse} from '../../../utils/index';
|
38
39
|
|
@@ -538,7 +539,13 @@ function QueryEditor(props) {
|
|
538
539
|
};
|
539
540
|
|
540
541
|
const renderControls = () => {
|
541
|
-
const {
|
542
|
+
const {
|
543
|
+
executeQuery,
|
544
|
+
explainQuery,
|
545
|
+
savedQueries,
|
546
|
+
selectRunAction,
|
547
|
+
setSettingValue,
|
548
|
+
} = props;
|
542
549
|
const {runAction} = executeQuery;
|
543
550
|
const runIsDisabled = !executeQuery.input || executeQuery.loading;
|
544
551
|
const runText = _.find(RUN_ACTIONS, {value: runAction}).content;
|
@@ -546,7 +553,10 @@ function QueryEditor(props) {
|
|
546
553
|
const menuItems = RUN_ACTIONS.map((action) => {
|
547
554
|
return {
|
548
555
|
text: action.content,
|
549
|
-
action: () =>
|
556
|
+
action: () => {
|
557
|
+
selectRunAction(action.value);
|
558
|
+
setSettingValue(QUERY_INITIAL_RUN_ACTION_KEY, action.value);
|
559
|
+
},
|
550
560
|
};
|
551
561
|
});
|
552
562
|
|
@@ -3,63 +3,185 @@ import PropTypes from 'prop-types';
|
|
3
3
|
import cn from 'bem-cn-lite';
|
4
4
|
import './SchemaInfoViewer.scss';
|
5
5
|
|
6
|
-
import {formatCPU, formatBytes} from '../../../../utils';
|
6
|
+
import {formatCPU, formatBytes, formatNumber, formatBps} from '../../../../utils';
|
7
7
|
|
8
|
-
import InfoViewer from '../../../../components/InfoViewer
|
8
|
+
import {InfoViewer, createInfoFormatter} from '../../../../components/InfoViewer';
|
9
9
|
|
10
10
|
const b = cn('schema-info-viewer');
|
11
11
|
|
12
|
+
const formatTabletMetricsItem = createInfoFormatter({
|
13
|
+
values: {
|
14
|
+
CPU: formatCPU,
|
15
|
+
Memory: formatBytes,
|
16
|
+
Storage: formatBytes,
|
17
|
+
Network: formatBps,
|
18
|
+
ReadThroughput: formatBps,
|
19
|
+
WriteThroughput: formatBps,
|
20
|
+
},
|
21
|
+
defaultValueFormatter: formatNumber,
|
22
|
+
});
|
23
|
+
|
24
|
+
const formatFollowerGroupItem = createInfoFormatter({
|
25
|
+
values: {
|
26
|
+
FollowerCount: formatNumber,
|
27
|
+
},
|
28
|
+
});
|
29
|
+
|
30
|
+
const formatPartitionConfigItem = createInfoFormatter({
|
31
|
+
values: {
|
32
|
+
FollowerCount: formatNumber,
|
33
|
+
CrossDataCenterFollowerCount: formatNumber,
|
34
|
+
},
|
35
|
+
});
|
36
|
+
|
37
|
+
const formatTableStatsItem = createInfoFormatter({
|
38
|
+
values: {
|
39
|
+
DataSize: formatBytes,
|
40
|
+
IndexSize: formatBytes,
|
41
|
+
LastAccessTime: (value) => value > 0 ? new Date(Number(value)).toUTCString() : 'N/A',
|
42
|
+
LastUpdateTime: (value) => value > 0 ? new Date(Number(value)).toUTCString() : 'N/A',
|
43
|
+
},
|
44
|
+
defaultValueFormatter: formatNumber,
|
45
|
+
});
|
46
|
+
|
47
|
+
const formatTableStats = (fields) => Object.entries(fields)
|
48
|
+
.map(([label, value]) => formatTableStatsItem(label, value))
|
49
|
+
.filter(({value}) => Boolean(value));
|
50
|
+
|
12
51
|
class SchemaInfoViewer extends React.Component {
|
13
52
|
static propTypes = {
|
14
53
|
data: PropTypes.object.isRequired,
|
15
54
|
};
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
return formatBytes(value);
|
21
|
-
} else {
|
22
|
-
return value;
|
55
|
+
|
56
|
+
renderItem(itemData, title) {
|
57
|
+
if (!Array.isArray(itemData) || !itemData.length) {
|
58
|
+
return null;
|
23
59
|
}
|
24
|
-
|
60
|
+
|
61
|
+
return (
|
62
|
+
<div className={b('item')}>
|
63
|
+
<InfoViewer
|
64
|
+
title={title}
|
65
|
+
info={itemData}
|
66
|
+
/>
|
67
|
+
</div>
|
68
|
+
);
|
69
|
+
}
|
70
|
+
|
71
|
+
renderContent(data) {
|
72
|
+
const {PathDescription = {}} = data;
|
73
|
+
const {TableStats = {}, TabletMetrics = {}, Table: {PartitionConfig = {}} = {}} = PathDescription;
|
74
|
+
const {
|
75
|
+
PartCount,
|
76
|
+
RowCount,
|
77
|
+
DataSize,
|
78
|
+
IndexSize,
|
79
|
+
|
80
|
+
LastAccessTime,
|
81
|
+
LastUpdateTime,
|
82
|
+
|
83
|
+
ImmediateTxCompleted,
|
84
|
+
PlannedTxCompleted,
|
85
|
+
TxRejectedByOverload,
|
86
|
+
TxRejectedBySpace,
|
87
|
+
TxCompleteLagMsec,
|
88
|
+
InFlightTxCount,
|
89
|
+
|
90
|
+
RowUpdates,
|
91
|
+
RowDeletes,
|
92
|
+
RowReads,
|
93
|
+
RangeReads,
|
94
|
+
RangeReadRows,
|
95
|
+
|
96
|
+
...restTableStats
|
97
|
+
} = TableStats;
|
98
|
+
const {FollowerGroups, FollowerCount, CrossDataCenterFollowerCount} = PartitionConfig;
|
99
|
+
|
100
|
+
const tableStatsInfo = [
|
101
|
+
formatTableStats({
|
102
|
+
PartCount,
|
103
|
+
RowCount,
|
104
|
+
DataSize,
|
105
|
+
IndexSize,
|
106
|
+
}),
|
107
|
+
formatTableStats({
|
108
|
+
LastAccessTime,
|
109
|
+
LastUpdateTime,
|
110
|
+
}),
|
111
|
+
formatTableStats({
|
112
|
+
ImmediateTxCompleted,
|
113
|
+
PlannedTxCompleted,
|
114
|
+
TxRejectedByOverload,
|
115
|
+
TxRejectedBySpace,
|
116
|
+
TxCompleteLagMsec,
|
117
|
+
InFlightTxCount,
|
118
|
+
}),
|
119
|
+
formatTableStats({
|
120
|
+
RowUpdates,
|
121
|
+
RowDeletes,
|
122
|
+
RowReads,
|
123
|
+
RangeReads,
|
124
|
+
RangeReadRows,
|
125
|
+
}),
|
126
|
+
formatTableStats(restTableStats),
|
127
|
+
];
|
128
|
+
|
129
|
+
const tabletMetricsInfo = Object.keys(TabletMetrics).map((key) =>
|
130
|
+
formatTabletMetricsItem(key, TabletMetrics[key])
|
131
|
+
);
|
132
|
+
|
133
|
+
const partitionConfigInfo = [];
|
134
|
+
|
135
|
+
if (Array.isArray(FollowerGroups) && FollowerGroups.length > 0) {
|
136
|
+
partitionConfigInfo.push(...Object.keys(FollowerGroups[0]).map((key) =>
|
137
|
+
formatFollowerGroupItem(key, FollowerGroups[0][key])
|
138
|
+
));
|
139
|
+
} else if (FollowerCount !== undefined) {
|
140
|
+
partitionConfigInfo.push(
|
141
|
+
formatPartitionConfigItem('FollowerCount', FollowerCount)
|
142
|
+
);
|
143
|
+
} else if (CrossDataCenterFollowerCount !== undefined) {
|
144
|
+
partitionConfigInfo.push(
|
145
|
+
formatPartitionConfigItem('CrossDataCenterFollowerCount', CrossDataCenterFollowerCount)
|
146
|
+
);
|
147
|
+
}
|
148
|
+
|
149
|
+
if ([
|
150
|
+
tabletMetricsInfo,
|
151
|
+
partitionConfigInfo,
|
152
|
+
tableStatsInfo.flat(),
|
153
|
+
].flat().length === 0) {
|
154
|
+
return (
|
155
|
+
<div className={b('item')}>Empty</div>
|
156
|
+
);
|
157
|
+
}
|
158
|
+
|
159
|
+
return (
|
160
|
+
<div className={b('row')}>
|
161
|
+
{tabletMetricsInfo.length > 0 || partitionConfigInfo.length > 0 ? (
|
162
|
+
<div className={b('col')}>
|
163
|
+
{this.renderItem(tabletMetricsInfo, 'Tablet Metrics')}
|
164
|
+
{this.renderItem(partitionConfigInfo, 'Partition Config')}
|
165
|
+
</div>
|
166
|
+
) : null}
|
167
|
+
<div className={b('col')}>
|
168
|
+
{tableStatsInfo.map((info, index) => (
|
169
|
+
<React.Fragment key={index}>
|
170
|
+
{this.renderItem(info, index === 0 ? 'Table Stats' : undefined)}
|
171
|
+
</React.Fragment>
|
172
|
+
))}
|
173
|
+
</div>
|
174
|
+
</div>
|
175
|
+
);
|
176
|
+
}
|
177
|
+
|
25
178
|
render() {
|
26
179
|
const {data} = this.props;
|
27
180
|
|
28
181
|
if (data) {
|
29
|
-
const {PathDescription = {}} = data;
|
30
|
-
const {TableStats = {}, TabletMetrics = {}} = PathDescription;
|
31
|
-
const {PartCount, ...restTableStats} = TableStats;
|
32
|
-
|
33
|
-
const priorityInfo = [{
|
34
|
-
label: 'PartCount',
|
35
|
-
value: PartCount,
|
36
|
-
}].filter(({value}) => value !== undefined);
|
37
|
-
|
38
|
-
const tableStatsInfo = Object.keys(restTableStats).map((key) => ({
|
39
|
-
label: key,
|
40
|
-
value: TableStats[key].toString(),
|
41
|
-
}));
|
42
|
-
|
43
|
-
const tabletMetricsInfo = Object.keys(TabletMetrics).map((key) => ({
|
44
|
-
label: key,
|
45
|
-
value: this.formatTabletMetricsValue(key, TabletMetrics[key].toString()),
|
46
|
-
}));
|
47
|
-
|
48
|
-
const generalInfo = [
|
49
|
-
...priorityInfo,
|
50
|
-
...tabletMetricsInfo,
|
51
|
-
...tableStatsInfo,
|
52
|
-
];
|
53
|
-
|
54
182
|
return (
|
55
183
|
<div className={b()}>
|
56
|
-
|
57
|
-
{generalInfo.length ? (
|
58
|
-
<InfoViewer info={generalInfo}></InfoViewer>
|
59
|
-
) : (
|
60
|
-
<div>Empty</div>
|
61
|
-
)}
|
62
|
-
</div>
|
184
|
+
{this.renderContent(data)}
|
63
185
|
</div>
|
64
186
|
);
|
65
187
|
} else {
|
@@ -1,6 +1,24 @@
|
|
1
1
|
.schema-info-viewer {
|
2
2
|
overflow: auto;
|
3
3
|
|
4
|
+
&__row {
|
5
|
+
display: flex;
|
6
|
+
flex-wrap: wrap;
|
7
|
+
justify-content: flex-start;
|
8
|
+
align-items: flex-start;
|
9
|
+
}
|
10
|
+
|
11
|
+
&__col {
|
12
|
+
display: flex;
|
13
|
+
flex-direction: column;
|
14
|
+
justify-content: flex-start;
|
15
|
+
align-items: flex-start;
|
16
|
+
|
17
|
+
& + & {
|
18
|
+
margin-left: 50px;
|
19
|
+
}
|
20
|
+
}
|
21
|
+
|
4
22
|
&__item {
|
5
23
|
margin-bottom: 20px;
|
6
24
|
|
package/dist/services/api.js
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
import {createRequestActionTypes, createApiRequest} from '../utils';
|
2
2
|
import '../../services/api';
|
3
3
|
import {getValueFromLS, parseJson} from '../../utils/utils';
|
4
|
-
import {QUERIES_HISTORY_KEY} from '../../utils/constants';
|
4
|
+
import {QUERIES_HISTORY_KEY, QUERY_INITIAL_RUN_ACTION_KEY} from '../../utils/constants';
|
5
|
+
import {readSavedSettingsValue} from './settings';
|
5
6
|
|
6
7
|
const MAXIMUM_QUERIES_IN_HISTORY = 20;
|
7
8
|
|
@@ -39,7 +40,7 @@ const initialState = {
|
|
39
40
|
? MAXIMUM_QUERIES_IN_HISTORY - 1
|
40
41
|
: queriesHistoryInitial.length - 1,
|
41
42
|
},
|
42
|
-
runAction: RUN_ACTIONS_VALUES.script,
|
43
|
+
runAction: readSavedSettingsValue(QUERY_INITIAL_RUN_ACTION_KEY, RUN_ACTIONS_VALUES.script),
|
43
44
|
monacoHotKey: null,
|
44
45
|
};
|
45
46
|
|
@@ -1,4 +1,11 @@
|
|
1
|
-
import {
|
1
|
+
import {
|
2
|
+
defaultUserSettings,
|
3
|
+
ALL,
|
4
|
+
SAVED_QUERIES_KEY,
|
5
|
+
THEME_KEY,
|
6
|
+
TENANT_INITIAL_TAB_KEY,
|
7
|
+
QUERY_INITIAL_RUN_ACTION_KEY,
|
8
|
+
} from '../../utils/constants';
|
2
9
|
import '../../services/api';
|
3
10
|
import {getValueFromLS} from '../../utils/utils';
|
4
11
|
|
@@ -7,24 +14,24 @@ const SET_SETTING_VALUE = 'settings/SET_VALUE';
|
|
7
14
|
|
8
15
|
const userSettings = window.userSettings || {};
|
9
16
|
const systemSettings = window.systemSettings || {};
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
: getValueFromLS(TENANT_INITIAL_TAB_KEY);
|
17
|
+
|
18
|
+
export function readSavedSettingsValue(key, defaultValue) {
|
19
|
+
const savedValue = window.web_version
|
20
|
+
? userSettings[key]
|
21
|
+
: getValueFromLS(key);
|
22
|
+
|
23
|
+
return savedValue ?? defaultValue;
|
24
|
+
}
|
19
25
|
|
20
26
|
export const initialState = {
|
21
27
|
problemFilter: ALL,
|
22
28
|
userSettings: {
|
23
29
|
...defaultUserSettings,
|
24
30
|
...userSettings,
|
25
|
-
theme,
|
26
|
-
[SAVED_QUERIES_KEY]:
|
27
|
-
[TENANT_INITIAL_TAB_KEY]:
|
31
|
+
theme: readSavedSettingsValue(THEME_KEY, 'light'),
|
32
|
+
[SAVED_QUERIES_KEY]: readSavedSettingsValue(SAVED_QUERIES_KEY, '[]'),
|
33
|
+
[TENANT_INITIAL_TAB_KEY]: readSavedSettingsValue(TENANT_INITIAL_TAB_KEY),
|
34
|
+
[QUERY_INITIAL_RUN_ACTION_KEY]: readSavedSettingsValue(QUERY_INITIAL_RUN_ACTION_KEY),
|
28
35
|
},
|
29
36
|
systemSettings,
|
30
37
|
};
|
package/dist/types/api/schema.ts
CHANGED
@@ -16,7 +16,7 @@ export interface TEvDescribeSchemeResult {
|
|
16
16
|
PathOwnerId?: string;
|
17
17
|
}
|
18
18
|
|
19
|
-
enum EStatus
|
19
|
+
enum EStatus {
|
20
20
|
StatusSuccess = 'StatusSuccess',
|
21
21
|
StatusAccepted = 'StatusAccepted',
|
22
22
|
StatusPathDoesNotExist = 'StatusPathDoesNotExist',
|
@@ -47,8 +47,8 @@ interface TPathDescription {
|
|
47
47
|
Children?: TDirEntry[];
|
48
48
|
|
49
49
|
// for table
|
50
|
-
Table?:
|
51
|
-
TableStats?:
|
50
|
+
Table?: TTableDescription;
|
51
|
+
TableStats?: TTableStats;
|
52
52
|
TabletMetrics?: unknown;
|
53
53
|
TablePartitions?: unknown[];
|
54
54
|
|
@@ -82,6 +82,119 @@ interface TDirEntry {
|
|
82
82
|
Version?: TPathVersion;
|
83
83
|
}
|
84
84
|
|
85
|
+
// incomplete
|
86
|
+
export interface TTableDescription {
|
87
|
+
PartitionConfig?: TPartitionConfig;
|
88
|
+
}
|
89
|
+
|
90
|
+
// incomplete
|
91
|
+
export interface TPartitionConfig {
|
92
|
+
/** uint64 */
|
93
|
+
FollowerCount?: string;
|
94
|
+
/**
|
95
|
+
* uint32
|
96
|
+
* @deprecated use FollowerGroups
|
97
|
+
*/
|
98
|
+
CrossDataCenterFollowerCount?: string;
|
99
|
+
/** 0 or 1 items */
|
100
|
+
FollowerGroups?: TFollowerGroup[];
|
101
|
+
}
|
102
|
+
|
103
|
+
export interface TFollowerGroup {
|
104
|
+
/** uint32 */
|
105
|
+
FollowerCount?: string;
|
106
|
+
AllowLeaderPromotion?: boolean;
|
107
|
+
AllowClientRead?: boolean;
|
108
|
+
/** uint32[] */
|
109
|
+
AllowedNodeIDs?: string[];
|
110
|
+
/**
|
111
|
+
* uint32[]
|
112
|
+
* @deprecated use AllowedDataCenters
|
113
|
+
*/
|
114
|
+
AllowedDataCenterNumIDs?: string[];
|
115
|
+
RequireAllDataCenters?: boolean;
|
116
|
+
LocalNodeOnly?: boolean;
|
117
|
+
RequireDifferentNodes?: boolean;
|
118
|
+
FollowerCountPerDataCenter?: boolean; // multiplies FollowerCount by number of DataCenters
|
119
|
+
AllowedDataCenters?: string[];
|
120
|
+
}
|
121
|
+
|
122
|
+
interface TTableStats {
|
123
|
+
/** uint64 */
|
124
|
+
DataSize?: string;
|
125
|
+
/** uint64 */
|
126
|
+
RowCount?: string;
|
127
|
+
/** uint64 */
|
128
|
+
IndexSize?: string;
|
129
|
+
/** uint64 */
|
130
|
+
InMemSize?: string;
|
131
|
+
|
132
|
+
/**
|
133
|
+
* uint64
|
134
|
+
* unix time in millisec
|
135
|
+
*/
|
136
|
+
LastAccessTime?: string;
|
137
|
+
/**
|
138
|
+
* uint64
|
139
|
+
* unix time in millisec
|
140
|
+
*/
|
141
|
+
LastUpdateTime?: string;
|
142
|
+
|
143
|
+
RowCountHistogram?: THistogram;
|
144
|
+
DataSizeHistogram?: THistogram;
|
145
|
+
|
146
|
+
/** uint64 */
|
147
|
+
ImmediateTxCompleted?: string;
|
148
|
+
/** uint64 */
|
149
|
+
PlannedTxCompleted?: string;
|
150
|
+
/** uint64 */
|
151
|
+
TxRejectedByOverload?: string;
|
152
|
+
/** uint64 */
|
153
|
+
TxRejectedBySpace?: string;
|
154
|
+
/** uint64 */
|
155
|
+
TxCompleteLagMsec?: string;
|
156
|
+
/** uint64 */
|
157
|
+
InFlightTxCount?: string;
|
158
|
+
|
159
|
+
/** uint64 */
|
160
|
+
RowUpdates?: string;
|
161
|
+
/** uint64 */
|
162
|
+
RowDeletes?: string;
|
163
|
+
/** uint64 */
|
164
|
+
RowReads?: string;
|
165
|
+
/** uint64 */
|
166
|
+
RangeReads?: string;
|
167
|
+
/** uint64 */
|
168
|
+
RangeReadRows?: string;
|
169
|
+
|
170
|
+
/** uint64 */
|
171
|
+
PartCount?: string;
|
172
|
+
|
173
|
+
KeyAccessSample?: THistogram;
|
174
|
+
|
175
|
+
/** uint64 */
|
176
|
+
SearchHeight?: string;
|
177
|
+
|
178
|
+
/**
|
179
|
+
* uint64
|
180
|
+
* seconds since epoch
|
181
|
+
*/
|
182
|
+
LastFullCompactionTs?: string;
|
183
|
+
|
184
|
+
// i.e. this shard lent to other shards
|
185
|
+
HasLoanedParts?: boolean;
|
186
|
+
}
|
187
|
+
|
188
|
+
interface THistogram {
|
189
|
+
Buckets?: THistogramBucket[];
|
190
|
+
}
|
191
|
+
|
192
|
+
interface THistogramBucket {
|
193
|
+
Key?: string;
|
194
|
+
/** uint64 */
|
195
|
+
Value?: string;
|
196
|
+
}
|
197
|
+
|
85
198
|
export interface TIndexDescription {
|
86
199
|
Name?: string;
|
87
200
|
/** uint64 */
|
@@ -111,7 +224,7 @@ export enum EPathType {
|
|
111
224
|
|
112
225
|
EPathTypeSubDomain = 'EPathTypeSubDomain',
|
113
226
|
|
114
|
-
EPathTypeTableIndex = 'EPathTypeTableIndex',
|
227
|
+
EPathTypeTableIndex = 'EPathTypeTableIndex',
|
115
228
|
EPathTypeExtSubDomain = 'EPathTypeExtSubDomain',
|
116
229
|
|
117
230
|
EPathTypeColumnStore = 'EPathTypeColumnStore',
|
package/dist/utils/constants.js
CHANGED
@@ -6,6 +6,9 @@ export const GROUP_AUTO_RELOAD_INTERVAL = 10 * SECOND;
|
|
6
6
|
export const PDISK_AUTO_RELOAD_INTERVAL = 10 * SECOND;
|
7
7
|
export const VDISK_AUTO_RELOAD_INTERVAL = 10 * SECOND;
|
8
8
|
export const AUTO_RELOAD_INTERVAL = 10 * SECOND;
|
9
|
+
// by agreement, display all byte values in decimal scale
|
10
|
+
// values in data are always in bytes, never in higher units,
|
11
|
+
// therefore there is no issue arbitrary converting them in UI
|
9
12
|
export const MEGABYTE = 1_000_000;
|
10
13
|
export const GIGABYTE = 1_000_000_000;
|
11
14
|
export const TERABYTE = 1_000_000_000_000;
|
@@ -139,3 +142,4 @@ export const DEFAULT_TABLE_SETTINGS = {
|
|
139
142
|
};
|
140
143
|
|
141
144
|
export const TENANT_INITIAL_TAB_KEY = 'saved_tenant_initial_tab';
|
145
|
+
export const QUERY_INITIAL_RUN_ACTION_KEY = 'query_initial_run_action';
|
package/dist/utils/index.js
CHANGED
@@ -1,16 +1,20 @@
|
|
1
1
|
import numeral from 'numeral';
|
2
2
|
import _ from 'lodash';
|
3
3
|
|
4
|
+
import {i18n} from './i18n';
|
4
5
|
import {MEGABYTE, TERABYTE, DAY_IN_SECONDS, GIGABYTE} from './constants';
|
5
6
|
|
6
7
|
import locales from 'numeral/locales'; // eslint-disable-line no-unused-vars
|
7
|
-
|
8
|
-
numeral.
|
8
|
+
|
9
|
+
numeral.locale(i18n.lang);
|
9
10
|
|
10
11
|
export const formatBytes = (bytes) => {
|
11
|
-
|
12
|
+
// by agreement, display byte values in decimal scale
|
13
|
+
return numeral(bytes).format('0 b');
|
12
14
|
};
|
13
15
|
|
16
|
+
export const formatBps = (bytes) => formatBytes(bytes) + '/s';
|
17
|
+
|
14
18
|
export const formatBytesToGigabyte = (bytes) => {
|
15
19
|
return `${Math.floor(bytes / GIGABYTE)} GB`;
|
16
20
|
};
|
package/dist/utils/pdisk.ts
CHANGED
@@ -28,7 +28,7 @@ export const parseBitField = <T extends Record<string, number>>(
|
|
28
28
|
};
|
29
29
|
|
30
30
|
export enum IPDiskType {
|
31
|
-
|
31
|
+
HDD = 'HDD', // ROT (Rotation?) = HDD
|
32
32
|
SSD = 'SSD',
|
33
33
|
MVME = 'NVME',
|
34
34
|
}
|
@@ -67,7 +67,7 @@ export const getPDiskType = (data: TPDiskStateInfo): IPDiskType | undefined => {
|
|
67
67
|
return IPDiskType.MVME;
|
68
68
|
}
|
69
69
|
} else if (categoryBitField.typeExt === '0') {
|
70
|
-
return IPDiskType.
|
70
|
+
return IPDiskType.HDD;
|
71
71
|
}
|
72
72
|
|
73
73
|
return undefined;
|