ydb-embedded-ui 4.15.1 → 4.16.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/components/DiagnosticCard/DiagnosticCard.scss +5 -0
  3. package/dist/components/DiagnosticCard/DiagnosticCard.tsx +17 -0
  4. package/dist/components/EntityStatus/EntityStatus.js +2 -2
  5. package/dist/components/EntityStatus/EntityStatus.scss +15 -0
  6. package/dist/containers/Tenant/Diagnostics/DetailedOverview/DetailedOverview.tsx +3 -11
  7. package/dist/containers/Tenant/Diagnostics/Healthcheck/Details/Details.tsx +20 -11
  8. package/dist/containers/Tenant/Diagnostics/Healthcheck/Healthcheck.scss +14 -1
  9. package/dist/containers/Tenant/Diagnostics/Healthcheck/Healthcheck.tsx +26 -37
  10. package/dist/containers/Tenant/Diagnostics/Healthcheck/Preview/Preview.tsx +37 -25
  11. package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.tsx +154 -0
  12. package/dist/containers/Tenant/Diagnostics/TenantOverview/i18n/en.json +7 -0
  13. package/dist/containers/Tenant/Diagnostics/TenantOverview/i18n/index.ts +11 -0
  14. package/dist/containers/Tenant/Diagnostics/TenantOverview/i18n/ru.json +7 -0
  15. package/dist/containers/Tenant/Query/QueriesHistory/QueriesHistory.scss +4 -1
  16. package/dist/containers/Tenant/Query/QueriesHistory/QueriesHistory.tsx +42 -11
  17. package/dist/containers/Tenant/Query/QueryEditor/QueryEditor.js +1 -1
  18. package/dist/containers/Tenant/Query/QueryEditorControls/QueryEditorControls.tsx +11 -7
  19. package/dist/containers/Tenant/Query/i18n/en.json +3 -0
  20. package/dist/containers/Tenant/Query/i18n/ru.json +3 -0
  21. package/dist/containers/Tenants/Tenants.tsx +3 -1
  22. package/dist/containers/UserSettings/Setting.tsx +9 -2
  23. package/dist/containers/UserSettings/i18n/en.json +5 -1
  24. package/dist/containers/UserSettings/i18n/ru.json +5 -1
  25. package/dist/containers/UserSettings/settings.ts +25 -0
  26. package/dist/services/api.ts +16 -16
  27. package/dist/store/reducers/executeQuery.ts +33 -7
  28. package/dist/store/reducers/explainQuery.ts +12 -4
  29. package/dist/store/reducers/healthcheckInfo.ts +27 -11
  30. package/dist/store/reducers/settings/settings.ts +4 -10
  31. package/dist/store/reducers/tenant/tenant.ts +19 -1
  32. package/dist/store/reducers/tenant/types.ts +3 -1
  33. package/dist/store/reducers/tenants/selectors.ts +1 -1
  34. package/dist/store/reducers/tenants/utils.ts +2 -2
  35. package/dist/types/api/tenant.ts +19 -20
  36. package/dist/types/store/executeQuery.ts +11 -1
  37. package/dist/types/store/query.ts +2 -1
  38. package/dist/utils/autofetcher.ts +7 -7
  39. package/dist/utils/constants.ts +2 -1
  40. package/dist/utils/hooks/i18n/en.json +1 -1
  41. package/dist/utils/hooks/i18n/ru.json +1 -1
  42. package/dist/utils/hooks/useQueryModes.ts +4 -2
  43. package/dist/utils/i18n/i18n.ts +10 -4
  44. package/dist/utils/query.ts +14 -0
  45. package/dist/utils/settings.ts +10 -0
  46. package/package.json +1 -1
  47. package/dist/containers/Tenant/Diagnostics/Healthcheck/Preview/PreviewItem/PreviewItem.tsx +0 -33
  48. package/dist/containers/Tenant/Diagnostics/Healthcheck/Preview/PreviewItem/index.ts +0 -1
  49. 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.split('/');
6
- const defaultValue = parts.length ? parts[parts.length - 1] : '—';
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;
@@ -22,38 +22,38 @@ export interface TTenantInfo {
22
22
  }
23
23
 
24
24
  export interface TTenant {
25
- Name: string;
26
- Id: string;
27
- Type: ETenantType;
28
- State: State;
25
+ Name?: string;
26
+ Id?: string;
27
+ Type?: ETenantType;
28
+ State?: State;
29
29
  StateStats?: THiveDomainStatsStateCount[];
30
- Metrics: TMetrics;
30
+ Metrics?: TMetrics;
31
31
  NodeIds?: number[];
32
- AliveNodes: number;
33
- Resources: TTenantResources;
32
+ AliveNodes?: number;
33
+ Resources?: TTenantResources;
34
34
  /** uint64 */
35
- CreateTime: string;
36
- Owner: string;
35
+ CreateTime?: string;
36
+ Owner?: string;
37
37
  Users?: string[];
38
38
  PoolStats?: TPoolStats[];
39
- UserAttributes: Record<string, string>;
40
- Overall: EFlag;
39
+ UserAttributes?: Record<string, string>;
40
+ Overall?: EFlag;
41
41
  SystemTablets?: TTabletStateInfo[];
42
- ResourceId: string;
42
+ ResourceId?: string;
43
43
  Tablets?: TTabletStateInfo[];
44
44
  /** uint64 */
45
- StorageAllocatedSize: string;
45
+ StorageAllocatedSize?: string;
46
46
  /** uint64 */
47
- StorageMinAvailableSize: string;
47
+ StorageMinAvailableSize?: string;
48
48
  Nodes?: TSystemStateInfo[];
49
49
  /** uint64 */
50
- MemoryUsed: string;
50
+ MemoryUsed?: string;
51
51
  /** uint64 */
52
- MemoryLimit: string;
52
+ MemoryLimit?: string;
53
53
  /** double */
54
- CoresUsed: number;
54
+ CoresUsed?: number;
55
55
  /** uint64 */
56
- StorageGroups: string;
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
- queries: string[];
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
  }
@@ -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 \"{{mode}}\" cannot be set. You need to turn in additional query modes in settings to enable it"
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": "Режим выполнения запроса \"{{mode}}\" недоступен. Вам необходимо включить дополнительные режимы выполнения запросов в настройках"
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: errorMessage ?? i18n('useQueryModes.queryModeCannotBeSet', {mode: value}),
21
+ title:
22
+ errorMessage ??
23
+ i18n('useQueryModes.queryModeCannotBeSet', {mode: QUERY_MODES_TITLES[value]}),
22
24
  type: 'error',
23
25
  });
24
26
 
@@ -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(Lang.En);
13
- configureYdbUiComponents({lang: Lang.En});
14
- configureUiKit({lang: Lang.En});
18
+ i18n.setLang(currentLang);
19
+ configureYdbUiComponents({lang: currentLang});
20
+ configureUiKit({lang: currentLang});
15
21
 
16
- export {i18n, Lang};
22
+ export {i18n, Lang, currentLang, defaultLang};
@@ -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,6 +1,6 @@
1
1
  {
2
2
  "name": "ydb-embedded-ui",
3
- "version": "4.15.1",
3
+ "version": "4.16.0",
4
4
  "files": [
5
5
  "dist"
6
6
  ],
@@ -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);