ydb-embedded-ui 1.6.4 → 1.7.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 CHANGED
@@ -1,5 +1,14 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.7.0](https://github.com/ydb-platform/ydb-embedded-ui/compare/v1.6.4...v1.7.0) (2022-06-29)
4
+
5
+
6
+ ### Features
7
+
8
+ * **Storage:** show total groups count ([5e31cfe](https://github.com/ydb-platform/ydb-embedded-ui/commit/5e31cfee9edc50fa4bc0770c443b136291a3536e))
9
+ * **Storage:** show total nodes count ([b438f70](https://github.com/ydb-platform/ydb-embedded-ui/commit/b438f7075961e878a1412ca185743c4374dd9178))
10
+ * **Tenant:** display tables indexes ([693a100](https://github.com/ydb-platform/ydb-embedded-ui/commit/693a1001db6487b2d43aeca7d8168afcd06f5cbd))
11
+
3
12
  ## [1.6.4](https://github.com/ydb-platform/ydb-embedded-ui/compare/v1.6.3...v1.6.4) (2022-06-24)
4
13
 
5
14
 
@@ -20,6 +20,8 @@ import {
20
20
  StorageTypes,
21
21
  setStorageType,
22
22
  VisibleEntitiesTitles,
23
+ getStoragePoolsGroupsCount,
24
+ getStorageNodesCount,
23
25
  } from '../../store/reducers/storage';
24
26
  import {getNodesList} from '../../store/reducers/clusterNodes';
25
27
  import StorageGroups from './StorageGroups/StorageGroups';
@@ -52,6 +54,8 @@ class Storage extends React.Component {
52
54
  getStorageInfo: PropTypes.func,
53
55
  setInitialState: PropTypes.func,
54
56
  flatListStorageEntities: PropTypes.array,
57
+ groupsCount: PropTypes.object,
58
+ nodesCount: PropTypes.object,
55
59
  setStorageFilter: PropTypes.func,
56
60
  setVisibleEntities: PropTypes.func,
57
61
  visibleEntities: PropTypes.string,
@@ -199,10 +203,39 @@ class Storage extends React.Component {
199
203
  setStorageType(value);
200
204
  };
201
205
 
206
+ renderEntitiesCount() {
207
+ const {
208
+ storageType,
209
+ groupsCount,
210
+ nodesCount,
211
+ loading,
212
+ wasLoaded,
213
+ } = this.props;
214
+
215
+ let label = `${storageType === StorageTypes.groups ? 'Groups' : 'Nodes'}: `;
216
+ const count = storageType === StorageTypes.groups ? groupsCount : nodesCount;
217
+
218
+ if (loading && !wasLoaded) {
219
+ label += '...';
220
+ return label;
221
+ }
222
+
223
+ if (count.total === count.found) {
224
+ label += count.total;
225
+ } else {
226
+ label += `${count.found} of ${count.total}`;
227
+ }
228
+
229
+ return label;
230
+ }
231
+
202
232
  renderControls() {
203
- const {setStorageFilter, visibleEntities, storageType, flatListStorageEntities, loading, wasLoaded} =
204
- this.props;
205
- const showLoader = loading && !wasLoaded;
233
+ const {
234
+ setStorageFilter,
235
+ visibleEntities,
236
+ storageType,
237
+ } = this.props;
238
+
206
239
  return (
207
240
  <div className={b('controls')}>
208
241
  <div className={b('search')}>
@@ -231,9 +264,9 @@ class Storage extends React.Component {
231
264
  {StorageTypes.nodes}
232
265
  </RadioButton.Option>
233
266
  </RadioButton>
234
- <Label theme="info" size="m">{`${
235
- storageType === StorageTypes.groups ? 'Groups' : 'Nodes'
236
- }: ${(showLoader) ? '...' : flatListStorageEntities.length}`}</Label>
267
+ <Label theme="info" size="m">
268
+ {this.renderEntitiesCount()}
269
+ </Label>
237
270
  </div>
238
271
  );
239
272
  }
@@ -270,8 +303,10 @@ function mapStateToProps(state) {
270
303
 
271
304
  return {
272
305
  flatListStorageEntities: getFilteredEntities(state),
306
+ groupsCount: getStoragePoolsGroupsCount(state),
273
307
  autorefresh: state.schema.autorefresh,
274
308
  nodes: getNodesObject(state),
309
+ nodesCount: getStorageNodesCount(state),
275
310
  loading,
276
311
  wasLoaded,
277
312
  error,
@@ -3,6 +3,8 @@ import {useSelector} from 'react-redux';
3
3
  import cn from 'bem-cn-lite';
4
4
 
5
5
  import {Button, Modal} from '@yandex-cloud/uikit';
6
+
7
+ import type {EPathType} from '../../../../types/api/schema';
6
8
  //@ts-ignore
7
9
  import Icon from '../../../../components/Icon/Icon';
8
10
  import Overview from '../Overview/Overview';
@@ -14,7 +16,7 @@ import TenantOverview from '../TenantOverview/TenantOverview';
14
16
  import './DetailedOverview.scss';
15
17
 
16
18
  interface DetailedOverviewProps {
17
- type: string;
19
+ type?: EPathType;
18
20
  className?: string;
19
21
  tenantName: string;
20
22
  additionalTenantInfo?: any;
@@ -29,7 +29,8 @@ import Compute from './Compute/Compute';
29
29
  import Tablets from '../../Tablets/Tablets';
30
30
 
31
31
  import routes, {createHref} from '../../../routes';
32
- import {OLAP_TABLE_TYPE, TABLE_TYPE} from '../Tenant';
32
+ import type {EPathType} from '../../../types/api/schema';
33
+ import {isTableType} from '../utils/schema';
33
34
  import {TenantGeneralTabsIds, TenantTabsGroups} from '../TenantPages';
34
35
  import {GeneralPagesIds, DATABASE_PAGES, TABLE_PAGES, DIR_PAGES} from './DiagnosticsPages';
35
36
  //@ts-ignore
@@ -39,7 +40,7 @@ import {setTopLevelTab, setDiagnosticsTab} from '../../../store/reducers/tenant'
39
40
  import './Diagnostics.scss';
40
41
 
41
42
  interface DiagnosticsProps {
42
- type: string;
43
+ type?: EPathType;
43
44
  additionalTenantInfo?: any;
44
45
  additionalNodesInfo?: any;
45
46
  }
@@ -68,8 +69,7 @@ function Diagnostics(props: DiagnosticsProps) {
68
69
  const isDatabase = currentSchemaPath === tenantName;
69
70
 
70
71
  const pages = useMemo(() => {
71
- const {type} = props;
72
- const isTable = type === TABLE_TYPE || type === OLAP_TABLE_TYPE;
72
+ const isTable = isTableType(props.type);
73
73
 
74
74
  let pages = DIR_PAGES;
75
75
 
@@ -8,7 +8,7 @@ import Icon from '../../../../components/Icon/Icon';
8
8
 
9
9
  import {AutoFetcher} from '../../../../utils/autofetcher';
10
10
  import {getHotKeys, setHotKeysOptions} from '../../../../store/reducers/hotKeys';
11
- import {TABLE_TYPE} from '../../Tenant';
11
+ import {EPathType} from '../../../../types/api/schema';
12
12
  import {prepareQueryError} from '../../../../utils';
13
13
 
14
14
  import './HotKeys.scss';
@@ -42,7 +42,8 @@ function HotKeys({
42
42
  type,
43
43
  }) {
44
44
  const fetchData = () => {
45
- if (type === TABLE_TYPE) {
45
+ // ColumnTables excluded intentionally
46
+ if (type === EPathType.EPathTypeTable) {
46
47
  getHotKeys(currentSchemaPath);
47
48
  }
48
49
  };
@@ -7,7 +7,8 @@ import {Loader} from '@yandex-cloud/uikit';
7
7
  //@ts-ignore
8
8
  import SchemaInfoViewer from '../../Schema/SchemaInfoViewer/SchemaInfoViewer';
9
9
 
10
- import {OLAP_TABLE_TYPE} from '../../Tenant';
10
+ import type {EPathType} from '../../../../types/api/schema';
11
+ import {isColumnEntityType, isTableType} from '../../utils/schema';
11
12
  import {AutoFetcher} from '../../../../utils/autofetcher';
12
13
  //@ts-ignore
13
14
  import {getSchema} from '../../../../store/reducers/schema';
@@ -44,7 +45,7 @@ function prepareOlapTableGeneral(tableData: any, olapStats: any[]) {
44
45
  }
45
46
 
46
47
  interface OverviewProps {
47
- type: string;
48
+ type?: EPathType;
48
49
  className?: string;
49
50
  tenantName?: string;
50
51
  }
@@ -70,7 +71,7 @@ function Overview(props: OverviewProps) {
70
71
  const schemaPath = currentSchemaPath || tenantName;
71
72
  dispatch(getSchema({path: schemaPath}));
72
73
 
73
- if (type === OLAP_TABLE_TYPE) {
74
+ if (isTableType(type) && isColumnEntityType(type)) {
74
75
  dispatch(getOlapStats({path: schemaPath}));
75
76
  }
76
77
  };
@@ -98,7 +99,7 @@ function Overview(props: OverviewProps) {
98
99
  currentItem?.PathDescription?.Table || currentItem?.PathDescription?.ColumnTableDescription;
99
100
 
100
101
  const schemaData = useMemo(() => {
101
- return props.type === OLAP_TABLE_TYPE
102
+ return isTableType(props.type) && isColumnEntityType(props.type)
102
103
  ? prepareOlapTableGeneral(tableSchema, olapStats)
103
104
  : currentItem;
104
105
  }, [props.type, tableSchema, olapStats, currentItem]);
@@ -9,7 +9,7 @@ import {changeUserInput} from '../../../../store/reducers/executeQuery';
9
9
  import {sendQuery, setQueryOptions} from '../../../../store/reducers/executeTopQueries';
10
10
  import TruncatedQuery from '../../../../components/TruncatedQuery/TruncatedQuery';
11
11
  import {AutoFetcher} from '../../../../utils/autofetcher';
12
- import {OLAP_STORE_TYPE, OLAP_TABLE_TYPE} from '../../Tenant';
12
+ import {isColumnEntityType} from '../../utils/schema';
13
13
 
14
14
  import {DEFAULT_TABLE_SETTINGS} from '../../../../utils/constants';
15
15
  import {TenantGeneralTabsIds} from '../../TenantPages';
@@ -149,7 +149,7 @@ class TopQueries extends React.Component {
149
149
 
150
150
  let message;
151
151
 
152
- if (type === OLAP_STORE_TYPE || type === OLAP_TABLE_TYPE) {
152
+ if (isColumnEntityType(type)) {
153
153
  message = 'No data';
154
154
  } else if (error && !error.isCancelled) {
155
155
  message = prepareQueryError(error).slice(0, 300);
@@ -12,7 +12,7 @@ import {setCurrentSchemaPath, getSchema} from '../../../../store/reducers/schema
12
12
  import {AutoFetcher} from '../../../../utils/autofetcher';
13
13
  import HistoryContext from '../../../../contexts/HistoryContext';
14
14
  import {DEFAULT_TABLE_SETTINGS} from '../../../../utils/constants';
15
- import {OLAP_STORE_TYPE, OLAP_TABLE_TYPE} from '../../Tenant';
15
+ import {isColumnEntityType} from '../../utils/schema';
16
16
  import {prepareQueryError} from '../../../../utils';
17
17
 
18
18
  import './TopShards.scss';
@@ -120,7 +120,7 @@ function TopShards({
120
120
  };
121
121
 
122
122
  const renderContent = () => {
123
- if (type === OLAP_STORE_TYPE || type === OLAP_TABLE_TYPE) {
123
+ if (isColumnEntityType(type)) {
124
124
  return 'No data';
125
125
  }
126
126
  if (error) {
@@ -14,13 +14,14 @@ import {TenantGeneralTabsIds, TenantTabsGroups, TENANT_GENERAL_TABS} from '../Te
14
14
  import routes, {createHref} from '../../../routes';
15
15
  import {setSettingValue} from '../../../store/reducers/settings';
16
16
  import {TENANT_INITIAL_TAB_KEY} from '../../../utils/constants';
17
+ import type {EPathType} from '../../../types/api/schema';
17
18
 
18
19
  import './ObjectGeneral.scss';
19
20
 
20
21
  const b = cn('object-general');
21
22
 
22
23
  interface ObjectGeneralProps {
23
- type: string;
24
+ type?: EPathType;
24
25
  additionalTenantInfo?: any;
25
26
  additionalNodesInfo?: any;
26
27
  setSettingValue: (name: string, value: string) => void;
@@ -16,7 +16,8 @@ import CopyToClipboard from '../../../components/CopyToClipboard/CopyToClipboard
16
16
  import InfoViewer from '../../../components/InfoViewer/InfoViewer';
17
17
  import Icon from '../../../components/Icon/Icon';
18
18
 
19
- import {OLAP_TABLE_TYPE, TABLE_TYPE} from '../Tenant';
19
+ import type {EPathType} from '../../../types/api/schema';
20
+ import {isColumnEntityType, isTableType} from '../utils/schema';
20
21
 
21
22
  import {
22
23
  DEFAULT_IS_TENANT_COMMON_INFO_COLLAPSED,
@@ -69,7 +70,7 @@ function prepareOlapTableSchema(tableSchema: any) {
69
70
  }
70
71
 
71
72
  interface ObjectSummaryProps {
72
- type: string;
73
+ type?: EPathType;
73
74
  onCollapseSummary: VoidFunction;
74
75
  onExpandSummary: VoidFunction;
75
76
  isCollapsed: boolean;
@@ -104,12 +105,13 @@ function ObjectSummary(props: ObjectSummaryProps) {
104
105
  const tableSchema =
105
106
  currentItem?.PathDescription?.Table || currentItem?.PathDescription?.ColumnTableDescription;
106
107
 
107
- const schema =
108
- props.type === OLAP_TABLE_TYPE ? prepareOlapTableSchema(tableSchema) : tableSchema;
108
+ const schema = isTableType(props.type) && isColumnEntityType(props.type)
109
+ ? prepareOlapTableSchema(tableSchema)
110
+ : tableSchema;
109
111
 
110
112
  useEffect(() => {
111
113
  const {type} = props;
112
- const isTable = type === TABLE_TYPE || type === OLAP_TABLE_TYPE;
114
+ const isTable = isTableType(type);
113
115
 
114
116
  if (type && !isTable && !TENANT_INFO_TABS.find((el) => el.id === infoTab)) {
115
117
  history.push({
@@ -120,8 +122,7 @@ function ObjectSummary(props: ObjectSummaryProps) {
120
122
  }, [props.type]);
121
123
 
122
124
  const renderTabs = () => {
123
- const {type} = props;
124
- const isTable = type === TABLE_TYPE || type === OLAP_TABLE_TYPE;
125
+ const isTable = isTableType(props.type);
125
126
  const tabsItems = isTable ? [...TENANT_INFO_TABS, ...TENANT_SCHEMA_TAB] : TENANT_INFO_TABS;
126
127
 
127
128
  return (
@@ -228,8 +229,7 @@ function ObjectSummary(props: ObjectSummaryProps) {
228
229
  };
229
230
 
230
231
  const renderCommonInfoControls = () => {
231
- const {type} = props;
232
- const isTable = type === TABLE_TYPE || type === OLAP_TABLE_TYPE;
232
+ const isTable = isTableType(props.type);
233
233
  return (
234
234
  <React.Fragment>
235
235
  {isTable && (
@@ -257,8 +257,8 @@ function ObjectSummary(props: ObjectSummaryProps) {
257
257
  message = `${Status}: ${Reason}`;
258
258
  }
259
259
 
260
- return props.type ? (
261
- <div className={b('entity-type')}>{type}</div>
260
+ return type ? (
261
+ <div className={b('entity-type')}>{type.replace('EPathType', '')}</div>
262
262
  ) : (
263
263
  <div className={b('entity-type', {error: true})}>
264
264
  <HelpPopover content={message} offset={{left: 0}} />
@@ -13,7 +13,7 @@ import {sendQuery, setQueryOptions} from '../../../store/reducers/preview';
13
13
  import {showTooltip, hideTooltip} from '../../../store/reducers/tooltip';
14
14
  import {prepareQueryError, prepareQueryResponse} from '../../../utils/index';
15
15
 
16
- import {OLAP_TABLE_TYPE, TABLE_TYPE} from '../Tenant';
16
+ import {isTableType} from '../utils/schema';
17
17
  import {AutoFetcher} from '../../../utils/autofetcher';
18
18
  import EnableFullscreenButton from '../../../components/EnableFullscreenButton/EnableFullscreenButton';
19
19
  import {DEFAULT_TABLE_SETTINGS} from '../../../utils/constants';
@@ -82,7 +82,7 @@ class Preview extends React.Component {
82
82
  sendQueryForPreview = () => {
83
83
  const {sendQuery, database, table, type} = this.props;
84
84
 
85
- if (type !== TABLE_TYPE && type !== OLAP_TABLE_TYPE) {
85
+ if (!isTableType(type)) {
86
86
  return;
87
87
  }
88
88
 
@@ -150,7 +150,7 @@ class Preview extends React.Component {
150
150
 
151
151
  let message;
152
152
 
153
- if (type !== TABLE_TYPE && type !== OLAP_TABLE_TYPE) {
153
+ if (!isTableType(type)) {
154
154
  message = <div className={b('message-container')}>Not available</div>;
155
155
  }
156
156
 
@@ -35,6 +35,9 @@ export function SchemaTree(props: SchemaTreeProps) {
35
35
  return Children.map(({Name = '', PathType}) => ({
36
36
  name: Name,
37
37
  type: mapPathTypeToNavigationTreeType(PathType),
38
+ // FIXME: should only be explicitly set to true for tables with indexes
39
+ // at the moment of writing there is no property to determine this, fix later
40
+ expandable: true,
38
41
  }));
39
42
  });
40
43
 
@@ -1,4 +1,4 @@
1
- import {useEffect, useMemo, useReducer} from 'react';
1
+ import {useEffect, useReducer} from 'react';
2
2
  import {useDispatch, useSelector} from 'react-redux';
3
3
  import cn from 'bem-cn-lite';
4
4
  import {useLocation} from 'react-router';
@@ -22,28 +22,12 @@ import {
22
22
  //@ts-ignore
23
23
  import {getTenantInfo, clearTenant} from '../../store/reducers/tenant';
24
24
  import routes, {CLUSTER_PAGES, createHref} from '../../routes';
25
+ import type {TEvDescribeSchemeResult} from '../../types/api/schema';
25
26
 
26
27
  import './Tenant.scss';
27
28
 
28
29
  const b = cn('tenant-page');
29
30
 
30
- export const TABLE_TYPE = 'Table';
31
- export const OLAP_TABLE_TYPE = 'ColumnTable';
32
- export const OLAP_STORE_TYPE = 'ColumnStore';
33
-
34
- export function calcEntityType(currentPathType?: string) {
35
- return currentPathType && currentPathType.replace('EPathType', '');
36
- }
37
-
38
- export function isTableType(currentPathType?: string) {
39
- const type = calcEntityType(currentPathType);
40
-
41
- if (type === TABLE_TYPE || type === OLAP_TABLE_TYPE) {
42
- return true;
43
- }
44
- return false;
45
- }
46
-
47
31
  const getInitialIsSummaryCollapsed = () => {
48
32
  return Boolean(localStorage.getItem(DEFAULT_IS_TENANT_SUMMARY_COLLAPSED));
49
33
  };
@@ -114,11 +98,7 @@ function Tenant(props: TenantProps) {
114
98
  };
115
99
  }, [tenantName, dispatch]);
116
100
 
117
- const currentPathType = currentItem.PathDescription?.Self?.PathType;
118
-
119
- const entityType = useMemo(() => {
120
- return calcEntityType(currentPathType);
121
- }, [currentPathType]);
101
+ const currentPathType = (currentItem as TEvDescribeSchemeResult).PathDescription?.Self?.PathType;
122
102
 
123
103
  const onCollapseSummaryHandler = () => {
124
104
  dispatchSummaryVisibilityAction(PaneVisibilityActionTypes.triggerCollapse);
@@ -142,14 +122,14 @@ function Tenant(props: TenantProps) {
142
122
  onSplitStartDragAdditional={onSplitStartDragAdditional}
143
123
  >
144
124
  <ObjectSummary
145
- type={entityType as string}
125
+ type={currentPathType}
146
126
  onCollapseSummary={onCollapseSummaryHandler}
147
127
  onExpandSummary={onExpandSummaryHandler}
148
128
  isCollapsed={summaryVisibilityState.collapsed}
149
129
  additionalTenantInfo={props.additionalTenantInfo}
150
130
  />
151
131
  <ObjectGeneral
152
- type={entityType as string}
132
+ type={currentPathType}
153
133
  additionalTenantInfo={props.additionalTenantInfo}
154
134
  additionalNodesInfo={props.additionalNodesInfo}
155
135
  />
@@ -13,8 +13,16 @@ export const mapPathTypeToNavigationTreeType = (
13
13
  return 'table';
14
14
  case EPathType.EPathTypeDir:
15
15
  case EPathType.EPathTypeColumnStore:
16
+ case EPathType.EPathTypeTableIndex:
16
17
  return 'directory';
17
18
  default:
18
19
  return defaultType;
19
20
  }
20
21
  };
22
+
23
+ export const isTableType = (type?: EPathType) =>
24
+ mapPathTypeToNavigationTreeType(type) === 'table';
25
+
26
+ export const isColumnEntityType = (type?: EPathType) =>
27
+ type === EPathType.EPathTypeColumnStore ||
28
+ type === EPathType.EPathTypeColumnTable;
@@ -83,7 +83,6 @@ export class YdbEmbeddedAPI extends AxiosWrapper {
83
83
  path,
84
84
  enums: true,
85
85
  backup: false,
86
- private: false,
87
86
  partition_config: false,
88
87
  partition_stats: false,
89
88
  partitioning_info: false,
@@ -111,7 +110,6 @@ export class YdbEmbeddedAPI extends AxiosWrapper {
111
110
  path,
112
111
  enums: true,
113
112
  backup: false,
114
- private: false,
115
113
  children: false,
116
114
  partition_config: false,
117
115
  partition_stats: true,
@@ -125,7 +125,15 @@ export function setVisibleEntities(value) {
125
125
  }
126
126
 
127
127
  export const getStoragePools = (state) => state.storage.data?.StoragePools;
128
+ export const getStoragePoolsGroupsCount = (state) => ({
129
+ total: state.storage.data?.TotalGroups || 0,
130
+ found: state.storage.data?.FoundGroups || 0,
131
+ });
128
132
  export const getStorageNodes = (state) => state.storage.data?.Nodes;
133
+ export const getStorageNodesCount = (state) => ({
134
+ total: state.storage.data?.TotalNodes || 0,
135
+ found: state.storage.data?.FoundNodes || 0,
136
+ });
129
137
  export const getStorageFilter = (state) => state.storage.filter;
130
138
  export const getVisibleEntities = (state) => state.storage.visible;
131
139
  export const getStorageType = (state) => state.storage.type;
@@ -88,6 +88,7 @@ export enum EPathType {
88
88
  EPathTypeSubDomain = 'EPathTypeSubDomain',
89
89
  EPathTypeColumnStore = 'EPathTypeColumnStore',
90
90
  EPathTypeColumnTable = 'EPathTypeColumnTable',
91
+ EPathTypeTableIndex = 'EPathTypeTableIndex',
91
92
  }
92
93
 
93
94
  enum EPathSubType {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ydb-embedded-ui",
3
- "version": "1.6.4",
3
+ "version": "1.7.0",
4
4
  "files": [
5
5
  "dist"
6
6
  ],
@@ -40,7 +40,7 @@
40
40
  "reselect": "4.0.0",
41
41
  "sass": "1.32.8",
42
42
  "web-vitals": "1.1.2",
43
- "ydb-ui-components": "2.0.2"
43
+ "ydb-ui-components": "2.1.0"
44
44
  },
45
45
  "scripts": {
46
46
  "start": "react-app-rewired start",