ydb-embedded-ui 4.15.1 → 4.16.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/CHANGELOG.md +14 -0
- package/dist/components/DiagnosticCard/DiagnosticCard.scss +5 -0
- package/dist/components/DiagnosticCard/DiagnosticCard.tsx +17 -0
- package/dist/components/EntityStatus/EntityStatus.js +2 -2
- package/dist/components/EntityStatus/EntityStatus.scss +15 -0
- package/dist/containers/Tenant/Diagnostics/DetailedOverview/DetailedOverview.tsx +3 -11
- package/dist/containers/Tenant/Diagnostics/Healthcheck/Details/Details.tsx +20 -11
- package/dist/containers/Tenant/Diagnostics/Healthcheck/Healthcheck.scss +14 -1
- package/dist/containers/Tenant/Diagnostics/Healthcheck/Healthcheck.tsx +26 -37
- package/dist/containers/Tenant/Diagnostics/Healthcheck/Preview/Preview.tsx +37 -25
- package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.tsx +154 -0
- package/dist/containers/Tenant/Diagnostics/TenantOverview/i18n/en.json +7 -0
- package/dist/containers/Tenant/Diagnostics/TenantOverview/i18n/index.ts +11 -0
- package/dist/containers/Tenant/Diagnostics/TenantOverview/i18n/ru.json +7 -0
- package/dist/containers/Tenant/Query/QueriesHistory/QueriesHistory.scss +4 -1
- package/dist/containers/Tenant/Query/QueriesHistory/QueriesHistory.tsx +42 -11
- package/dist/containers/Tenant/Query/QueryEditor/QueryEditor.js +1 -1
- package/dist/containers/Tenant/Query/QueryEditorControls/QueryEditorControls.tsx +11 -7
- package/dist/containers/Tenant/Query/i18n/en.json +3 -0
- package/dist/containers/Tenant/Query/i18n/ru.json +3 -0
- package/dist/containers/Tenants/Tenants.tsx +3 -1
- package/dist/containers/UserSettings/Setting.tsx +9 -2
- package/dist/containers/UserSettings/i18n/en.json +5 -1
- package/dist/containers/UserSettings/i18n/ru.json +5 -1
- package/dist/containers/UserSettings/settings.ts +25 -0
- package/dist/services/api.ts +16 -16
- package/dist/store/reducers/executeQuery.ts +33 -7
- package/dist/store/reducers/explainQuery.ts +12 -4
- package/dist/store/reducers/healthcheckInfo.ts +27 -11
- package/dist/store/reducers/settings/settings.ts +4 -10
- package/dist/store/reducers/tenant/tenant.ts +19 -1
- package/dist/store/reducers/tenant/types.ts +3 -1
- package/dist/store/reducers/tenants/selectors.ts +1 -1
- package/dist/store/reducers/tenants/utils.ts +2 -2
- package/dist/types/api/tenant.ts +19 -20
- package/dist/types/store/executeQuery.ts +11 -1
- package/dist/types/store/query.ts +2 -1
- package/dist/utils/autofetcher.ts +7 -7
- package/dist/utils/constants.ts +2 -1
- package/dist/utils/hooks/i18n/en.json +1 -1
- package/dist/utils/hooks/i18n/ru.json +1 -1
- package/dist/utils/hooks/useQueryModes.ts +4 -2
- package/dist/utils/i18n/i18n.ts +10 -4
- package/dist/utils/query.ts +14 -0
- package/dist/utils/settings.ts +10 -0
- package/package.json +1 -1
- package/dist/containers/Tenant/Diagnostics/Healthcheck/Preview/PreviewItem/PreviewItem.tsx +0 -33
- package/dist/containers/Tenant/Diagnostics/Healthcheck/Preview/PreviewItem/index.ts +0 -1
- package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.js +0 -213
@@ -20,6 +20,7 @@ const SET_QUERY_TAB = 'tenant/SET_QUERY_TAB';
|
|
20
20
|
const SET_DIAGNOSTICS_TAB = 'tenant/SET_DIAGNOSTICS_TAB';
|
21
21
|
const SET_SUMMARY_TAB = 'tenant/SET_SUMMARY_TAB';
|
22
22
|
const CLEAR_TENANT = 'tenant/CLEAR_TENANT';
|
23
|
+
const SET_DATA_WAS_NOT_LOADED = 'tenant/SET_DATA_WAS_NOT_LOADED';
|
23
24
|
|
24
25
|
const initialState = {loading: false, wasLoaded: false};
|
25
26
|
|
@@ -43,6 +44,10 @@ const tenantReducer: Reducer<TenantState, TenantAction> = (state = initialState,
|
|
43
44
|
}
|
44
45
|
|
45
46
|
case FETCH_TENANT.FAILURE: {
|
47
|
+
if (action.error?.isCancelled) {
|
48
|
+
return state;
|
49
|
+
}
|
50
|
+
|
46
51
|
return {
|
47
52
|
...state,
|
48
53
|
error: action.error,
|
@@ -84,6 +89,13 @@ const tenantReducer: Reducer<TenantState, TenantAction> = (state = initialState,
|
|
84
89
|
};
|
85
90
|
}
|
86
91
|
|
92
|
+
case SET_DATA_WAS_NOT_LOADED: {
|
93
|
+
return {
|
94
|
+
...state,
|
95
|
+
wasLoaded: false,
|
96
|
+
};
|
97
|
+
}
|
98
|
+
|
87
99
|
default:
|
88
100
|
return state;
|
89
101
|
}
|
@@ -91,7 +103,7 @@ const tenantReducer: Reducer<TenantState, TenantAction> = (state = initialState,
|
|
91
103
|
|
92
104
|
export const getTenantInfo = ({path}: {path: string}) => {
|
93
105
|
return createApiRequest({
|
94
|
-
request: window.api.getTenantInfo({path}),
|
106
|
+
request: window.api.getTenantInfo({path}, {concurrentId: 'getTenantInfo'}),
|
95
107
|
actions: FETCH_TENANT,
|
96
108
|
dataHandler: (tenantData): TTenant | undefined => {
|
97
109
|
return tenantData.TenantInfo?.[0];
|
@@ -131,4 +143,10 @@ export function setSummaryTab(tab: TenantSummaryTab) {
|
|
131
143
|
} as const;
|
132
144
|
}
|
133
145
|
|
146
|
+
export const setDataWasNotLoaded = () => {
|
147
|
+
return {
|
148
|
+
type: SET_DATA_WAS_NOT_LOADED,
|
149
|
+
} as const;
|
150
|
+
};
|
151
|
+
|
134
152
|
export default tenantReducer;
|
@@ -16,6 +16,7 @@ import {
|
|
16
16
|
setQueryTab,
|
17
17
|
setSummaryTab,
|
18
18
|
setTenantPage,
|
19
|
+
setDataWasNotLoaded,
|
19
20
|
} from './tenant';
|
20
21
|
|
21
22
|
export type TenantPage = ValueOf<typeof TENANT_PAGES_IDS>;
|
@@ -41,4 +42,5 @@ export type TenantAction =
|
|
41
42
|
| ReturnType<typeof setTenantPage>
|
42
43
|
| ReturnType<typeof setQueryTab>
|
43
44
|
| ReturnType<typeof setDiagnosticsTab>
|
44
|
-
| ReturnType<typeof setSummaryTab
|
45
|
+
| ReturnType<typeof setSummaryTab>
|
46
|
+
| ReturnType<typeof setDataWasNotLoaded>;
|
@@ -24,7 +24,7 @@ const filterTenantsByProblems = (tenants: PreparedTenant[], problemFilter: Probl
|
|
24
24
|
const filteredTenantsBySearch = (tenants: PreparedTenant[], searchQuery: string) => {
|
25
25
|
return tenants.filter((item) => {
|
26
26
|
const re = new RegExp(escapeRegExp(searchQuery), 'i');
|
27
|
-
return re.test(item.Name) || re.test(item.controlPlaneName);
|
27
|
+
return re.test(item.Name || '') || re.test(item.controlPlaneName);
|
28
28
|
});
|
29
29
|
};
|
30
30
|
|
@@ -2,8 +2,8 @@ import type {TTenant} from '../../../types/api/tenant';
|
|
2
2
|
import {isNumeric} from '../../../utils/utils';
|
3
3
|
|
4
4
|
const getControlPlaneValue = (tenant: TTenant) => {
|
5
|
-
const parts = tenant.Name
|
6
|
-
const defaultValue = parts
|
5
|
+
const parts = tenant.Name?.split('/');
|
6
|
+
const defaultValue = parts?.length ? parts[parts.length - 1] : '—';
|
7
7
|
const controlPlaneName = tenant.ControlPlane?.name;
|
8
8
|
|
9
9
|
return controlPlaneName ?? defaultValue;
|
package/dist/types/api/tenant.ts
CHANGED
@@ -22,38 +22,38 @@ export interface TTenantInfo {
|
|
22
22
|
}
|
23
23
|
|
24
24
|
export interface TTenant {
|
25
|
-
Name
|
26
|
-
Id
|
27
|
-
Type
|
28
|
-
State
|
25
|
+
Name?: string;
|
26
|
+
Id?: string;
|
27
|
+
Type?: ETenantType;
|
28
|
+
State?: State;
|
29
29
|
StateStats?: THiveDomainStatsStateCount[];
|
30
|
-
Metrics
|
30
|
+
Metrics?: TMetrics;
|
31
31
|
NodeIds?: number[];
|
32
|
-
AliveNodes
|
33
|
-
Resources
|
32
|
+
AliveNodes?: number;
|
33
|
+
Resources?: TTenantResources;
|
34
34
|
/** uint64 */
|
35
|
-
CreateTime
|
36
|
-
Owner
|
35
|
+
CreateTime?: string;
|
36
|
+
Owner?: string;
|
37
37
|
Users?: string[];
|
38
38
|
PoolStats?: TPoolStats[];
|
39
|
-
UserAttributes
|
40
|
-
Overall
|
39
|
+
UserAttributes?: Record<string, string>;
|
40
|
+
Overall?: EFlag;
|
41
41
|
SystemTablets?: TTabletStateInfo[];
|
42
|
-
ResourceId
|
42
|
+
ResourceId?: string;
|
43
43
|
Tablets?: TTabletStateInfo[];
|
44
44
|
/** uint64 */
|
45
|
-
StorageAllocatedSize
|
45
|
+
StorageAllocatedSize?: string;
|
46
46
|
/** uint64 */
|
47
|
-
StorageMinAvailableSize
|
47
|
+
StorageMinAvailableSize?: string;
|
48
48
|
Nodes?: TSystemStateInfo[];
|
49
49
|
/** uint64 */
|
50
|
-
MemoryUsed
|
50
|
+
MemoryUsed?: string;
|
51
51
|
/** uint64 */
|
52
|
-
MemoryLimit
|
52
|
+
MemoryLimit?: string;
|
53
53
|
/** double */
|
54
|
-
CoresUsed
|
54
|
+
CoresUsed?: number;
|
55
55
|
/** uint64 */
|
56
|
-
StorageGroups
|
56
|
+
StorageGroups?: string;
|
57
57
|
|
58
58
|
MonitoringEndpoint?: string; // additional
|
59
59
|
ControlPlane?: ControlPlane; // additional
|
@@ -139,11 +139,10 @@ enum State {
|
|
139
139
|
'CONFIGURING' = 'CONFIGURING',
|
140
140
|
}
|
141
141
|
|
142
|
-
enum ETabletVolatileState {
|
142
|
+
export enum ETabletVolatileState {
|
143
143
|
'TABLET_VOLATILE_STATE_UNKNOWN' = 'TABLET_VOLATILE_STATE_UNKNOWN',
|
144
144
|
'TABLET_VOLATILE_STATE_STOPPED' = 'TABLET_VOLATILE_STATE_STOPPED',
|
145
145
|
'TABLET_VOLATILE_STATE_BOOTING' = 'TABLET_VOLATILE_STATE_BOOTING',
|
146
146
|
'TABLET_VOLATILE_STATE_STARTING' = 'TABLET_VOLATILE_STATE_STARTING',
|
147
147
|
'TABLET_VOLATILE_STATE_RUNNING' = 'TABLET_VOLATILE_STATE_RUNNING',
|
148
|
-
'_TABLET_VOLATILE_STATE_BLOCKED' = '_TABLET_VOLATILE_STATE_BLOCKED',
|
149
148
|
}
|
@@ -14,11 +14,17 @@ import type {IQueryResult, QueryError, QueryErrorResponse} from './query';
|
|
14
14
|
|
15
15
|
export type MonacoHotKeyAction = ValueOf<typeof MONACO_HOT_KEY_ACTIONS>;
|
16
16
|
|
17
|
+
export interface QueryInHistory {
|
18
|
+
queryText: string;
|
19
|
+
syntax?: string;
|
20
|
+
}
|
21
|
+
|
17
22
|
export interface ExecuteQueryState {
|
18
23
|
loading: boolean;
|
19
24
|
input: string;
|
20
25
|
history: {
|
21
|
-
|
26
|
+
// String type for backward compatibility
|
27
|
+
queries: (QueryInHistory | string)[];
|
22
28
|
currentIndex: number;
|
23
29
|
};
|
24
30
|
monacoHotKey: null | MonacoHotKeyAction;
|
@@ -38,3 +44,7 @@ export type ExecuteQueryAction =
|
|
38
44
|
| ReturnType<typeof saveQueryToHistory>
|
39
45
|
| ReturnType<typeof setMonacoHotKey>
|
40
46
|
| ReturnType<typeof setTenantPath>;
|
47
|
+
|
48
|
+
export interface ExecuteQueryStateSlice {
|
49
|
+
executeQuery: ExecuteQueryState;
|
50
|
+
}
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import {QUERY_ACTIONS, QUERY_MODES} from '../../utils/query';
|
1
|
+
import {QUERY_ACTIONS, QUERY_MODES, QUERY_SYNTAX} from '../../utils/query';
|
2
2
|
|
3
3
|
import type {IResponseError, NetworkError} from '../api/error';
|
4
4
|
import type {
|
@@ -29,6 +29,7 @@ export type QueryError = NetworkError | QueryErrorResponse;
|
|
29
29
|
|
30
30
|
export type QueryAction = ValueOf<typeof QUERY_ACTIONS>;
|
31
31
|
export type QueryMode = ValueOf<typeof QUERY_MODES>;
|
32
|
+
export type QuerySyntax = ValueOf<typeof QUERY_SYNTAX>;
|
32
33
|
|
33
34
|
export interface SavedQuery {
|
34
35
|
name: string;
|
@@ -1,4 +1,11 @@
|
|
1
1
|
export class AutoFetcher {
|
2
|
+
static DEFAULT_TIMEOUT = 30000;
|
3
|
+
static MIN_TIMEOUT = 30000;
|
4
|
+
timeout: number;
|
5
|
+
active: boolean;
|
6
|
+
timer: undefined | ReturnType<typeof setTimeout>;
|
7
|
+
launchCounter: number;
|
8
|
+
|
2
9
|
constructor() {
|
3
10
|
this.timeout = AutoFetcher.DEFAULT_TIMEOUT;
|
4
11
|
this.active = true;
|
@@ -52,11 +59,4 @@ export class AutoFetcher {
|
|
52
59
|
this.launchCounter++;
|
53
60
|
this.active = true;
|
54
61
|
}
|
55
|
-
|
56
|
-
static DEFAULT_TIMEOUT = 30000;
|
57
|
-
static MIN_TIMEOUT = 30000;
|
58
|
-
timeout: number;
|
59
|
-
active: boolean;
|
60
|
-
timer: undefined | ReturnType<typeof setTimeout>;
|
61
|
-
launchCounter: number;
|
62
62
|
}
|
package/dist/utils/constants.ts
CHANGED
@@ -25,7 +25,6 @@ export const TABLET_STATES = {
|
|
25
25
|
TABLET_VOLATILE_STATE_BOOTING: 'booting',
|
26
26
|
TABLET_VOLATILE_STATE_STARTING: 'starting',
|
27
27
|
TABLET_VOLATILE_STATE_RUNNING: 'running',
|
28
|
-
TABLET_VOLATILE_STATE_BLOCKED: 'blocked',
|
29
28
|
};
|
30
29
|
|
31
30
|
export const TABLET_COLORS = {
|
@@ -81,9 +80,11 @@ export const COLORS_PRIORITY = {
|
|
81
80
|
// ==== Titles ====
|
82
81
|
export const DEVELOPER_UI_TITLE = 'Developer UI';
|
83
82
|
export const CLUSTER_DEFAULT_TITLE = 'Cluster';
|
83
|
+
export const TENANT_DEFAULT_TITLE = 'Database';
|
84
84
|
|
85
85
|
// ==== Settings ====
|
86
86
|
export const THEME_KEY = 'theme';
|
87
|
+
export const LANGUAGE_KEY = 'language';
|
87
88
|
export const INVERTED_DISKS_KEY = 'invertedDisks';
|
88
89
|
export const USE_NODES_ENDPOINT_IN_DIAGNOSTICS_KEY = 'useNodesEndpointInDiagnostics';
|
89
90
|
export const ENABLE_ADDITIONAL_QUERY_MODES = 'enableAdditionalQueryModes';
|
@@ -1,3 +1,3 @@
|
|
1
1
|
{
|
2
|
-
"useQueryModes.queryModeCannotBeSet": "Query mode
|
2
|
+
"useQueryModes.queryModeCannotBeSet": "Query mode '{{mode}}' cannot be set. You need to turn in additional query modes in settings to enable it"
|
3
3
|
}
|
@@ -1,3 +1,3 @@
|
|
1
1
|
{
|
2
|
-
"useQueryModes.queryModeCannotBeSet": "Режим выполнения запроса
|
2
|
+
"useQueryModes.queryModeCannotBeSet": "Режим выполнения запроса '{{mode}}' недоступен. Вам необходимо включить дополнительные режимы выполнения запросов в настройках"
|
3
3
|
}
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import type {QueryMode} from '../../types/store/query';
|
2
2
|
import {ENABLE_ADDITIONAL_QUERY_MODES, QUERY_INITIAL_MODE_KEY} from '../constants';
|
3
|
-
import {isNewQueryMode} from '../query';
|
3
|
+
import {QUERY_MODES_TITLES, isNewQueryMode} from '../query';
|
4
4
|
import createToast from '../createToast';
|
5
5
|
import {useSetting} from './useSetting';
|
6
6
|
import i18n from './i18n';
|
@@ -18,7 +18,9 @@ export const useQueryModes = (): [QueryMode, SetQueryModeIfAvailable] => {
|
|
18
18
|
if (isNewQueryMode(value) && !enableAdditionalQueryModes) {
|
19
19
|
createToast({
|
20
20
|
name: 'QueryModeCannotBeSet',
|
21
|
-
title:
|
21
|
+
title:
|
22
|
+
errorMessage ??
|
23
|
+
i18n('useQueryModes.queryModeCannotBeSet', {mode: QUERY_MODES_TITLES[value]}),
|
22
24
|
type: 'error',
|
23
25
|
});
|
24
26
|
|
package/dist/utils/i18n/i18n.ts
CHANGED
@@ -2,15 +2,21 @@ import {I18N} from '@gravity-ui/i18n';
|
|
2
2
|
import {configure as configureUiKit} from '@gravity-ui/uikit';
|
3
3
|
import {configure as configureYdbUiComponents} from 'ydb-ui-components';
|
4
4
|
|
5
|
+
import {LANGUAGE_KEY} from '../constants';
|
6
|
+
import {readSavedSettingsValue} from '../settings';
|
7
|
+
|
5
8
|
enum Lang {
|
6
9
|
En = 'en',
|
7
10
|
Ru = 'ru',
|
8
11
|
}
|
9
12
|
|
13
|
+
const defaultLang = Lang.En;
|
14
|
+
const currentLang = readSavedSettingsValue(LANGUAGE_KEY, defaultLang);
|
15
|
+
|
10
16
|
const i18n = new I18N();
|
11
17
|
|
12
|
-
i18n.setLang(
|
13
|
-
configureYdbUiComponents({lang:
|
14
|
-
configureUiKit({lang:
|
18
|
+
i18n.setLang(currentLang);
|
19
|
+
configureYdbUiComponents({lang: currentLang});
|
20
|
+
configureUiKit({lang: currentLang});
|
15
21
|
|
16
|
-
export {i18n, Lang};
|
22
|
+
export {i18n, Lang, currentLang, defaultLang};
|
package/dist/utils/query.ts
CHANGED
@@ -19,6 +19,20 @@ export const QUERY_MODES = {
|
|
19
19
|
script: 'script',
|
20
20
|
data: 'data',
|
21
21
|
query: 'query',
|
22
|
+
pg: 'pg',
|
23
|
+
} as const;
|
24
|
+
|
25
|
+
export const QUERY_MODES_TITLES: Record<QueryMode, string> = {
|
26
|
+
scan: 'Scan',
|
27
|
+
script: 'YQL Script',
|
28
|
+
data: 'Data',
|
29
|
+
query: 'YQL - QueryService',
|
30
|
+
pg: 'PostgreSQL',
|
31
|
+
} as const;
|
32
|
+
|
33
|
+
export const QUERY_SYNTAX = {
|
34
|
+
yql: 'yql_v1',
|
35
|
+
pg: 'pg',
|
22
36
|
} as const;
|
23
37
|
|
24
38
|
export const isNewQueryMode = (value: QueryMode) => {
|
@@ -0,0 +1,10 @@
|
|
1
|
+
import {getValueFromLS} from './utils';
|
2
|
+
|
3
|
+
export const userSettings = window.userSettings || {};
|
4
|
+
export const systemSettings = window.systemSettings || {};
|
5
|
+
|
6
|
+
export function readSavedSettingsValue(key: string, defaultValue?: string) {
|
7
|
+
const savedValue = window.web_version ? userSettings[key] : getValueFromLS(key);
|
8
|
+
|
9
|
+
return savedValue ?? defaultValue;
|
10
|
+
}
|
package/package.json
CHANGED
@@ -1,33 +0,0 @@
|
|
1
|
-
import cn from 'bem-cn-lite';
|
2
|
-
|
3
|
-
import {Link, Text} from '@gravity-ui/uikit';
|
4
|
-
|
5
|
-
import EntityStatus from '../../../../../../components/EntityStatus/EntityStatus';
|
6
|
-
import {IssueLog} from '../../../../../../types/api/healthcheck';
|
7
|
-
|
8
|
-
import i18n from '../../i18n';
|
9
|
-
|
10
|
-
const b = cn('healthcheck');
|
11
|
-
|
12
|
-
interface PreviewItemProps {
|
13
|
-
data?: IssueLog;
|
14
|
-
onShowMore?: (id: string) => void;
|
15
|
-
}
|
16
|
-
|
17
|
-
export const PreviewItem = (props: PreviewItemProps) => {
|
18
|
-
const {data, onShowMore} = props;
|
19
|
-
|
20
|
-
if (!data) {
|
21
|
-
return null;
|
22
|
-
}
|
23
|
-
|
24
|
-
return (
|
25
|
-
<div className={b('issue-preview')}>
|
26
|
-
<EntityStatus mode="icons" status={data.status} name={data.type} />
|
27
|
-
<Text as="div" color="secondary" variant="body-2">
|
28
|
-
{data.message}
|
29
|
-
</Text>
|
30
|
-
<Link onClick={() => onShowMore?.(data.id)}>{i18n('label.show-details')}</Link>
|
31
|
-
</div>
|
32
|
-
);
|
33
|
-
};
|
@@ -1 +0,0 @@
|
|
1
|
-
export * from './PreviewItem';
|
@@ -1,213 +0,0 @@
|
|
1
|
-
import React from 'react';
|
2
|
-
import {connect} from 'react-redux';
|
3
|
-
import cn from 'bem-cn-lite';
|
4
|
-
import PropTypes from 'prop-types';
|
5
|
-
import {Loader} from '@gravity-ui/uikit';
|
6
|
-
|
7
|
-
import EntityStatus from '../../../../components/EntityStatus/EntityStatus';
|
8
|
-
import InfoViewer from '../../../../components/InfoViewer/InfoViewer';
|
9
|
-
import {PoolUsage} from '../../../../components/PoolUsage/PoolUsage';
|
10
|
-
import {Tablet} from '../../../../components/Tablet';
|
11
|
-
|
12
|
-
import {getTenantInfo} from '../../../../store/reducers/tenant/tenant';
|
13
|
-
|
14
|
-
import {formatCPU} from '../../../../utils';
|
15
|
-
import {bytesToGB} from '../../../../utils/utils';
|
16
|
-
import {TABLET_STATES} from '../../../../utils/constants';
|
17
|
-
import {AutoFetcher} from '../../../../utils/autofetcher';
|
18
|
-
|
19
|
-
import {mapDatabaseTypeToDBName} from '../../utils/schema';
|
20
|
-
|
21
|
-
import './TenantOverview.scss';
|
22
|
-
|
23
|
-
const b = cn('tenant-overview');
|
24
|
-
|
25
|
-
const renderName = (tenant) => {
|
26
|
-
if (tenant) {
|
27
|
-
const {Name} = tenant;
|
28
|
-
return (
|
29
|
-
<div className={b('tenant-name-wrapper')}>
|
30
|
-
<EntityStatus
|
31
|
-
status={tenant.State}
|
32
|
-
name={Name}
|
33
|
-
withLeftTrim
|
34
|
-
hasClipboardButton
|
35
|
-
clipboardButtonAlwaysVisible
|
36
|
-
/>
|
37
|
-
</div>
|
38
|
-
);
|
39
|
-
}
|
40
|
-
|
41
|
-
return <div>no tenant data</div>;
|
42
|
-
};
|
43
|
-
|
44
|
-
class TenantOverview extends React.Component {
|
45
|
-
static propTypes = {
|
46
|
-
loading: PropTypes.bool,
|
47
|
-
autorefresh: PropTypes.bool,
|
48
|
-
tenant: PropTypes.object,
|
49
|
-
systemTablets: PropTypes.array,
|
50
|
-
additionalTenantInfo: PropTypes.func,
|
51
|
-
tenantName: PropTypes.string,
|
52
|
-
};
|
53
|
-
|
54
|
-
autofetcher;
|
55
|
-
|
56
|
-
componentDidMount() {
|
57
|
-
const {tenantName, autorefresh, getTenantInfo} = this.props;
|
58
|
-
getTenantInfo({path: tenantName});
|
59
|
-
this.autofetcher = new AutoFetcher();
|
60
|
-
if (autorefresh) {
|
61
|
-
this.autofetcher.start();
|
62
|
-
this.autofetcher.fetch(() => getTenantInfo({path: tenantName}));
|
63
|
-
}
|
64
|
-
}
|
65
|
-
|
66
|
-
componentDidUpdate(prevProps) {
|
67
|
-
const {autorefresh, tenantName, getTenantInfo} = this.props;
|
68
|
-
|
69
|
-
const restartAutorefresh = () => {
|
70
|
-
this.autofetcher.stop();
|
71
|
-
this.autofetcher.start();
|
72
|
-
this.autofetcher.fetch(() => getTenantInfo({path: tenantName}));
|
73
|
-
};
|
74
|
-
|
75
|
-
if (prevProps.tenantName !== this.props.tenantName) {
|
76
|
-
getTenantInfo({path: tenantName});
|
77
|
-
if (autorefresh) {
|
78
|
-
restartAutorefresh();
|
79
|
-
}
|
80
|
-
}
|
81
|
-
|
82
|
-
if (autorefresh && !prevProps.autorefresh) {
|
83
|
-
getTenantInfo({path: tenantName});
|
84
|
-
restartAutorefresh();
|
85
|
-
}
|
86
|
-
|
87
|
-
if (!autorefresh && prevProps.autorefresh) {
|
88
|
-
this.autofetcher.stop();
|
89
|
-
}
|
90
|
-
}
|
91
|
-
|
92
|
-
componentWillUnmount() {
|
93
|
-
this.autofetcher.stop();
|
94
|
-
}
|
95
|
-
|
96
|
-
renderLoader = () => {
|
97
|
-
return (
|
98
|
-
<div className={b('loader')}>
|
99
|
-
<Loader size="m" />
|
100
|
-
</div>
|
101
|
-
);
|
102
|
-
};
|
103
|
-
|
104
|
-
render() {
|
105
|
-
const {tenant, loading} = this.props;
|
106
|
-
const {
|
107
|
-
Metrics = {},
|
108
|
-
PoolStats,
|
109
|
-
StateStats = [],
|
110
|
-
MemoryUsed,
|
111
|
-
Name,
|
112
|
-
CoresUsed,
|
113
|
-
StorageGroups,
|
114
|
-
StorageAllocatedSize,
|
115
|
-
Type,
|
116
|
-
SystemTablets,
|
117
|
-
} = tenant;
|
118
|
-
|
119
|
-
const tenantName = mapDatabaseTypeToDBName(Type);
|
120
|
-
const memoryRaw = MemoryUsed ?? Metrics.Memory;
|
121
|
-
|
122
|
-
const memory = (memoryRaw && bytesToGB(memoryRaw)) || 'no data';
|
123
|
-
const storage = (Metrics.Storage && bytesToGB(Metrics.Storage)) || 'no data';
|
124
|
-
const storageGroups = StorageGroups ?? 'no data';
|
125
|
-
const blobStorage = (StorageAllocatedSize && bytesToGB(StorageAllocatedSize)) || 'no data';
|
126
|
-
const storageEfficiency =
|
127
|
-
Metrics.Storage && StorageAllocatedSize
|
128
|
-
? `${((Metrics.Storage * 100) / StorageAllocatedSize).toFixed(2)}%`
|
129
|
-
: 'no data';
|
130
|
-
|
131
|
-
const cpuRaw = CoresUsed !== undefined ? Number(CoresUsed) * 1_000_000 : Metrics.CPU;
|
132
|
-
|
133
|
-
const cpu = formatCPU(cpuRaw);
|
134
|
-
|
135
|
-
const metricsInfo = [
|
136
|
-
{label: 'Type', value: Type},
|
137
|
-
{label: 'Memory', value: memory},
|
138
|
-
{label: 'CPU', value: cpu},
|
139
|
-
{label: 'Tablet storage', value: storage},
|
140
|
-
{label: 'Storage groups', value: storageGroups},
|
141
|
-
{label: 'Blob storage', value: blobStorage},
|
142
|
-
{label: 'Storage efficiency', value: storageEfficiency},
|
143
|
-
];
|
144
|
-
|
145
|
-
const tabletsInfo = StateStats.map((info) => ({
|
146
|
-
label: TABLET_STATES[info.VolatileState],
|
147
|
-
value: info.Count,
|
148
|
-
}));
|
149
|
-
|
150
|
-
return loading ? (
|
151
|
-
this.renderLoader()
|
152
|
-
) : (
|
153
|
-
<div className={b()}>
|
154
|
-
<div className={b('top-label')}>{tenantName}</div>
|
155
|
-
<div className={b('top')}>
|
156
|
-
{renderName(tenant)}
|
157
|
-
{this.props.additionalTenantInfo &&
|
158
|
-
this.props.additionalTenantInfo(
|
159
|
-
this.props.tenant.Name,
|
160
|
-
this.props.tenant.Type,
|
161
|
-
)}
|
162
|
-
</div>
|
163
|
-
<div className={b('system-tablets')}>
|
164
|
-
{SystemTablets &&
|
165
|
-
SystemTablets.map((tablet, tabletIndex) => (
|
166
|
-
<Tablet key={tabletIndex} tablet={tablet} tenantName={Name} />
|
167
|
-
))}
|
168
|
-
</div>
|
169
|
-
<div className={b('common-info')}>
|
170
|
-
<div>
|
171
|
-
<div className={b('section-title')}>Pools</div>
|
172
|
-
{PoolStats ? (
|
173
|
-
<div className={b('section', {pools: true})}>
|
174
|
-
{PoolStats.map((pool, poolIndex) => (
|
175
|
-
<PoolUsage key={poolIndex} data={pool} />
|
176
|
-
))}
|
177
|
-
</div>
|
178
|
-
) : (
|
179
|
-
<div className="error">no pools data</div>
|
180
|
-
)}
|
181
|
-
</div>
|
182
|
-
<InfoViewer
|
183
|
-
title="Metrics"
|
184
|
-
className={b('section', {metrics: true})}
|
185
|
-
info={metricsInfo}
|
186
|
-
/>
|
187
|
-
|
188
|
-
<div className={b('section')}>
|
189
|
-
<InfoViewer info={tabletsInfo} title="Tablets" />
|
190
|
-
</div>
|
191
|
-
</div>
|
192
|
-
</div>
|
193
|
-
);
|
194
|
-
}
|
195
|
-
}
|
196
|
-
|
197
|
-
function mapStateToProps(state) {
|
198
|
-
const {tenant = {}, loading, error: {status} = {}} = state.tenant;
|
199
|
-
const {autorefresh} = state.schema;
|
200
|
-
|
201
|
-
return {
|
202
|
-
tenant,
|
203
|
-
loading,
|
204
|
-
status,
|
205
|
-
autorefresh,
|
206
|
-
};
|
207
|
-
}
|
208
|
-
|
209
|
-
const mapDispatchToProps = {
|
210
|
-
getTenantInfo,
|
211
|
-
};
|
212
|
-
|
213
|
-
export default connect(mapStateToProps, mapDispatchToProps)(TenantOverview);
|