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.
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);