ydb-embedded-ui 6.7.0 → 6.8.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 (37) hide show
  1. package/dist/package.json +30 -30
  2. package/dist/src/components/InfoViewer/InfoViewer.d.ts +1 -1
  3. package/dist/src/components/InfoViewer/InfoViewer.js +2 -1
  4. package/dist/src/components/InfoViewer/i18n/en.json +2 -1
  5. package/dist/src/components/InfoViewer/i18n/index.d.ts +1 -1
  6. package/dist/src/components/InfoViewer/i18n/index.js +1 -2
  7. package/dist/src/containers/AppWithClusters/AppWithClusters.js +1 -1
  8. package/dist/src/containers/Storage/StorageGroups/getStorageGroupsColumns.js +4 -3
  9. package/dist/src/containers/Tenant/Acl/Acl.js +80 -54
  10. package/dist/src/containers/Tenant/Acl/Acl.scss +14 -9
  11. package/dist/src/containers/Tenant/Diagnostics/Overview/TableInfo/TableInfo.js +3 -3
  12. package/dist/src/containers/Tenant/Diagnostics/TenantOverview/i18n/index.d.ts +1 -1
  13. package/dist/src/containers/Tenant/EntityTitle/EntityTitle.d.ts +6 -0
  14. package/dist/src/containers/Tenant/EntityTitle/EntityTitle.js +11 -0
  15. package/dist/src/containers/Tenant/ObjectSummary/ObjectSummary.js +2 -2
  16. package/dist/src/containers/Tenant/TenantNavigation/TenantNavigation.js +1 -1
  17. package/dist/src/containers/Tenant/i18n/en.json +5 -1
  18. package/dist/src/containers/Tenant/i18n/index.d.ts +1 -1
  19. package/dist/src/containers/Tenant/utils/index.d.ts +1 -0
  20. package/dist/src/containers/Tenant/utils/index.js +6 -0
  21. package/dist/src/containers/Tenant/utils/queryTemplates.d.ts +3 -0
  22. package/dist/src/containers/Tenant/utils/queryTemplates.js +20 -0
  23. package/dist/src/containers/Tenant/utils/schemaActions.js +16 -2
  24. package/dist/src/containers/UserSettings/Setting.d.ts +7 -9
  25. package/dist/src/containers/UserSettings/Setting.js +13 -28
  26. package/dist/src/containers/UserSettings/UserSettings.d.ts +0 -2
  27. package/dist/src/containers/UserSettings/UserSettings.js +3 -6
  28. package/dist/src/containers/UserSettings/i18n/en.json +2 -2
  29. package/dist/src/containers/UserSettings/settings.js +3 -3
  30. package/dist/src/services/api.js +1 -0
  31. package/dist/src/styles/mixins.scss +5 -0
  32. package/dist/src/styles/themes.scss +1 -1
  33. package/dist/src/types/api/acl.d.ts +2 -1
  34. package/dist/src/types/api/schema/schema.d.ts +5 -0
  35. package/package.json +30 -30
  36. package/dist/src/components/InfoViewer/i18n/ru.json +0 -4
  37. package/dist/src/containers/UserSettings/UserSettings.scss +0 -9
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ydb-embedded-ui",
3
- "version": "6.7.0",
3
+ "version": "6.8.0",
4
4
  "files": [
5
5
  "dist"
6
6
  ],
@@ -12,18 +12,18 @@
12
12
  "dependencies": {
13
13
  "@bem-react/classname": "^1.6.0",
14
14
  "@gravity-ui/axios-wrapper": "^1.4.1",
15
- "@gravity-ui/chartkit": "^5.5.0",
16
- "@gravity-ui/components": "^3.6.2",
17
- "@gravity-ui/date-utils": "^2.4.0",
18
- "@gravity-ui/i18n": "^1.5.0",
19
- "@gravity-ui/icons": "^2.9.1",
20
- "@gravity-ui/navigation": "^2.10.0",
15
+ "@gravity-ui/chartkit": "^5.9.0",
16
+ "@gravity-ui/components": "^3.7.0",
17
+ "@gravity-ui/date-utils": "^2.5.3",
18
+ "@gravity-ui/i18n": "^1.5.1",
19
+ "@gravity-ui/icons": "^2.10.0",
20
+ "@gravity-ui/navigation": "^2.16.0",
21
21
  "@gravity-ui/paranoid": "^2.0.1",
22
22
  "@gravity-ui/react-data-table": "^2.1.1",
23
- "@gravity-ui/uikit": "^6.15.0",
23
+ "@gravity-ui/uikit": "^6.20.1",
24
24
  "@gravity-ui/websql-autocomplete": "^9.1.0",
25
25
  "@reduxjs/toolkit": "^2.2.3",
26
- "axios": "^1.6.8",
26
+ "axios": "^1.7.2",
27
27
  "axios-retry": "^4.4.0",
28
28
  "colord": "^2.9.3",
29
29
  "copy-to-clipboard": "^3.3.3",
@@ -35,17 +35,17 @@
35
35
  "path-to-regexp": "^3.0.0",
36
36
  "qs": "^6.12.0",
37
37
  "react-error-boundary": "^4.0.13",
38
- "react-helmet-async": "2.0.4",
38
+ "react-helmet-async": "^2.0.5",
39
39
  "react-json-inspector": "^7.1.1",
40
40
  "react-list": "^0.8.17",
41
41
  "react-monaco-editor": "^0.55.0",
42
- "react-redux": "^9.1.0",
42
+ "react-redux": "^9.1.2",
43
43
  "react-router": "^5.3.4",
44
44
  "react-router-dom": "^5.3.4",
45
45
  "react-split": "^2.0.14",
46
46
  "redux": "^5.0.1",
47
47
  "redux-location-state": "^2.8.2",
48
- "tslib": "^2.6.2",
48
+ "tslib": "^2.6.3",
49
49
  "url": "^0.11.3",
50
50
  "use-query-params": "^2.2.1",
51
51
  "web-vitals": "^1.1.2",
@@ -122,54 +122,54 @@
122
122
  ]
123
123
  },
124
124
  "devDependencies": {
125
- "@commitlint/cli": "^19.2.1",
126
- "@commitlint/config-conventional": "^19.1.0",
125
+ "@commitlint/cli": "^19.3.0",
126
+ "@commitlint/config-conventional": "^19.2.2",
127
127
  "@gravity-ui/eslint-config": "^3.2.0",
128
128
  "@gravity-ui/prettier-config": "^1.1.0",
129
129
  "@gravity-ui/stylelint-config": "^4.0.1",
130
130
  "@gravity-ui/tsconfig": "^1.0.0",
131
131
  "@playwright/test": "^1.42.1",
132
- "@testing-library/jest-dom": "^6.4.2",
132
+ "@testing-library/jest-dom": "^6.4.6",
133
133
  "@testing-library/react": "^14.2.2",
134
134
  "@testing-library/user-event": "^14.5.2",
135
135
  "@types/jest": "^29.5.12",
136
136
  "@types/lodash": "^4.17.0",
137
137
  "@types/numeral": "^2.0.5",
138
- "@types/qs": "^6.9.14",
139
- "@types/react": "^18.2.73",
140
- "@types/react-dom": "^18.2.23",
138
+ "@types/qs": "^6.9.15",
139
+ "@types/react": "^18.3.3",
140
+ "@types/react-dom": "^18.3.0",
141
141
  "@types/react-router": "^5.1.20",
142
142
  "@types/react-router-dom": "^5.3.3",
143
143
  "copyfiles": "^2.4.1",
144
144
  "http-proxy-middleware": "^2.0.6",
145
145
  "husky": "^9.0.11",
146
146
  "jest-transform-css": "^6.0.1",
147
- "lint-staged": "^15.2.2",
147
+ "lint-staged": "^15.2.7",
148
148
  "npm-run-all": "^4.1.5",
149
149
  "postcss": "^8.4.38",
150
150
  "prettier": "^3.2.5",
151
151
  "prop-types": "^15.8.1",
152
- "react": "^18.2.0",
152
+ "react": "^18.3.1",
153
153
  "react-app-rewired": "^2.2.1",
154
- "react-dom": "^18.2.0",
154
+ "react-dom": "^18.3.1",
155
155
  "react-scripts": "^5.0.1",
156
156
  "sass": "^1.72.0",
157
157
  "source-map-explorer": "^2.5.3",
158
- "stylelint": "^15.0.0",
159
- "ts-jest": "^29.1.2",
158
+ "stylelint": "^15.11.0",
159
+ "ts-jest": "^29.1.5",
160
160
  "typescript": "^5.4.3"
161
161
  },
162
162
  "peerDependencies": {
163
163
  "prop-types": "^15.8.1",
164
- "react": "^18.2.0",
165
- "react-dom": "^18.2.0"
164
+ "react": "^18.3.1",
165
+ "react-dom": "^18.3.1"
166
166
  },
167
167
  "overrides": {
168
168
  "fork-ts-checker-webpack-plugin": "^9.0.2",
169
- "react": "^18.2.0",
170
- "react-dom": "^18.2.0",
171
- "redux": "^5.0.1",
172
- "typescript": "^5.4.3",
173
- "monaco-editor": "^0.48.0"
169
+ "react": "$react",
170
+ "react-dom": "$react-dom",
171
+ "redux": "$redux",
172
+ "typescript": "$typescript",
173
+ "monaco-editor": "$monaco-editor"
174
174
  }
175
175
  }
@@ -5,7 +5,7 @@ export interface InfoViewerItem {
5
5
  value: React.ReactNode;
6
6
  }
7
7
  export interface InfoViewerProps {
8
- title?: string;
8
+ title?: React.ReactNode;
9
9
  info?: InfoViewerItem[];
10
10
  dots?: boolean;
11
11
  size?: 's';
@@ -1,12 +1,13 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import React from 'react';
3
3
  import { cn } from '../../utils/cn';
4
+ import i18n from './i18n';
4
5
  import './InfoViewer.scss';
5
6
  const b = cn('info-viewer');
6
7
  export const InfoViewer = ({ title, info, dots = true, size, className, multilineLabels, renderEmptyState, }) => {
7
8
  if ((!info || !info.length) && renderEmptyState) {
8
9
  return _jsx(React.Fragment, { children: renderEmptyState({ title, size }) });
9
10
  }
10
- return (_jsxs("div", { className: b({ size }, className), children: [title && _jsx("div", { className: b('title'), children: title }), info && info.length > 0 ? (_jsx("div", { className: b('items'), children: info.map((data, infoIndex) => (_jsxs("div", { className: b('row'), children: [_jsxs("div", { className: b('label'), children: [_jsx("div", { className: b('label-text', { multiline: multilineLabels }), children: data.label }), dots && _jsx("div", { className: b('dots') })] }), _jsx("div", { className: b('value'), children: data.value })] }, infoIndex))) })) : (_jsxs(React.Fragment, { children: ["No ", title, " data"] }))] }));
11
+ return (_jsxs("div", { className: b({ size }, className), children: [title && _jsx("div", { className: b('title'), children: title }), info && info.length > 0 ? (_jsx("div", { className: b('items'), children: info.map((data, infoIndex) => (_jsxs("div", { className: b('row'), children: [_jsxs("div", { className: b('label'), children: [_jsx("div", { className: b('label-text', { multiline: multilineLabels }), children: data.label }), dots && _jsx("div", { className: b('dots') })] }), _jsx("div", { className: b('value'), children: data.value })] }, infoIndex))) })) : (i18n('no-data'))] }));
11
12
  };
12
13
  export default InfoViewer;
@@ -1,4 +1,5 @@
1
1
  {
2
2
  "common.created": "Created",
3
- "common.type": "Type"
3
+ "common.type": "Type",
4
+ "no-data": "No data"
4
5
  }
@@ -1,2 +1,2 @@
1
- declare const _default: (key: "common.created" | "common.type", params?: import("@gravity-ui/i18n").Params | undefined) => string;
1
+ declare const _default: (key: "common.created" | "common.type" | "no-data", params?: import("@gravity-ui/i18n").Params | undefined) => string;
2
2
  export default _default;
@@ -1,5 +1,4 @@
1
1
  import { registerKeysets } from '../../../utils/i18n';
2
2
  import en from './en.json';
3
- import ru from './ru.json';
4
3
  const COMPONENT = 'ydb-components-info-viewer';
5
- export default registerKeysets(COMPONENT, { ru, en });
4
+ export default registerKeysets(COMPONENT, { en });
@@ -10,7 +10,7 @@ import i18n from './i18n';
10
10
  const defaultUserSettings = settings;
11
11
  defaultUserSettings[2].sections[0].settings.push({
12
12
  title: i18n('settings.useClusterBalancerAsBackend.title'),
13
- helpPopoverContent: i18n('settings.useClusterBalancerAsBackend.popover'),
13
+ description: i18n('settings.useClusterBalancerAsBackend.popover'),
14
14
  settingKey: USE_CLUSTER_BALANCER_AS_BACKEND_KEY,
15
15
  });
16
16
  export function AppWithClusters({ store, history, getMonitoringLink = getMonitoringLinkDefault, getMonitoringClusterLink = getMonitoringClusterLinkDefault, userSettings = defaultUserSettings, children, }) {
@@ -63,7 +63,8 @@ const erasureColumn = {
63
63
  const degradedColumn = {
64
64
  name: GROUPS_COLUMNS_IDS.Degraded,
65
65
  header: 'Degraded',
66
- width: 100,
66
+ width: 110,
67
+ resizeMinWidth: 110,
67
68
  render: ({ row }) => row.Degraded ? (_jsxs(Label, { theme: getDegradedSeverity(row), children: ["Degraded: ", row.Degraded] })) : ('-'),
68
69
  align: DataTable.LEFT,
69
70
  defaultOrder: DataTable.DESCENDING,
@@ -71,8 +72,8 @@ const degradedColumn = {
71
72
  const usageColumn = {
72
73
  name: GROUPS_COLUMNS_IDS.Usage,
73
74
  header: 'Usage',
74
- width: 100,
75
- resizeMinWidth: 70,
75
+ width: 75,
76
+ resizeMinWidth: 75,
76
77
  render: ({ row }) => {
77
78
  // without a limit the usage can be evaluated as 0,
78
79
  // but the absence of a value is more clear
@@ -1,16 +1,14 @@
1
+ import { __rest } from "tslib";
1
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
3
  import React from 'react';
4
+ import { DefinitionList } from '@gravity-ui/components';
3
5
  import { ResponseError } from '../../../components/Errors/ResponseError';
4
6
  import { Loader } from '../../../components/Loader';
5
- import { ResizeableDataTable } from '../../../components/ResizeableDataTable/ResizeableDataTable';
6
7
  import { schemaAclApi } from '../../../store/reducers/schemaAcl/schemaAcl';
7
8
  import { cn } from '../../../utils/cn';
8
- import { DEFAULT_TABLE_SETTINGS } from '../../../utils/constants';
9
9
  import i18n from '../i18n';
10
10
  import './Acl.scss';
11
11
  const b = cn('ydb-acl');
12
- const ACL_COLUMNS_WIDTH_LS_KEY = 'aclTableColumnsWidth';
13
- const TABLE_SETTINGS = Object.assign(Object.assign({}, DEFAULT_TABLE_SETTINGS), { dynamicRender: false, stickyTop: 36 });
14
12
  const prepareLogin = (value) => {
15
13
  if (value && value.endsWith('@staff') && !value.startsWith('svc_')) {
16
14
  const login = value.split('@')[0];
@@ -18,60 +16,88 @@ const prepareLogin = (value) => {
18
16
  }
19
17
  return value;
20
18
  };
21
- const columns = [
22
- {
23
- name: 'AccessType',
24
- header: 'Access Type',
25
- sortable: false,
26
- render: ({ row }) => row.AccessType,
27
- },
28
- {
29
- name: 'AccessRights',
30
- header: 'Access Rights',
31
- render: ({ row }) => {
32
- var _a;
33
- return (_a = row.AccessRights) === null || _a === void 0 ? void 0 : _a.map((item, index) => {
34
- return _jsx("div", { children: item }, index);
35
- });
36
- },
37
- sortable: false,
38
- },
39
- {
40
- name: 'Subject',
41
- sortable: false,
42
- render: ({ row }) => {
43
- return prepareLogin(row.Subject);
44
- },
45
- width: 140,
46
- },
47
- {
48
- name: 'InheritanceType',
49
- header: 'Inheritance Type',
50
- render: ({ row }) => {
51
- var _a;
52
- return (_a = row.InheritanceType) === null || _a === void 0 ? void 0 : _a.map((item, index) => {
53
- return _jsx("div", { children: item }, index);
54
- });
19
+ const aclParams = ['access', 'type', 'inheritance'];
20
+ const aclParamToName = {
21
+ access: 'Access',
22
+ type: 'Access type',
23
+ inheritance: 'Inheritance type',
24
+ };
25
+ const defaultInheritanceType = ['Object', 'Container'];
26
+ const defaultAccessType = 'Allow';
27
+ const defaultInheritanceTypeSet = new Set(defaultInheritanceType);
28
+ function normalizeAcl(acl) {
29
+ return acl.map((ace) => {
30
+ const { AccessRules = [], AccessRights = [], AccessType, InheritanceType, Subject } = ace;
31
+ const access = AccessRules.concat(AccessRights);
32
+ //"Allow" is default access type. We want to show it only if it isn't default
33
+ const type = AccessType === defaultAccessType ? undefined : AccessType;
34
+ let inheritance;
35
+ // ['Object', 'Container'] - is default inheritance type. We want to show it only if it isn't default
36
+ if ((InheritanceType === null || InheritanceType === void 0 ? void 0 : InheritanceType.length) !== defaultInheritanceTypeSet.size ||
37
+ InheritanceType.some((t) => !defaultInheritanceTypeSet.has(t))) {
38
+ inheritance = InheritanceType;
39
+ }
40
+ return {
41
+ access: access.length ? access : undefined,
42
+ type,
43
+ inheritance,
44
+ Subject,
45
+ };
46
+ });
47
+ }
48
+ function DefinitionValue({ value }) {
49
+ const normalizedValue = typeof value === 'string' ? [value] : value;
50
+ return (_jsx("div", { className: b('definition-content'), children: normalizedValue.map((el) => (_jsx("span", { children: el }, el))) }));
51
+ }
52
+ function getAclListItems(acl) {
53
+ if (!acl || !acl.length) {
54
+ return [];
55
+ }
56
+ const normalizedAcl = normalizeAcl(acl);
57
+ return normalizedAcl.map((_a) => {
58
+ var { Subject } = _a, data = __rest(_a, ["Subject"]);
59
+ const definedDataEntries = Object.entries(data).filter(([_key, value]) => Boolean(value));
60
+ if (definedDataEntries.length === 1 && definedDataEntries[0][0] === 'access') {
61
+ return {
62
+ name: Subject,
63
+ content: _jsx(DefinitionValue, { value: definedDataEntries[0][1] }),
64
+ };
65
+ }
66
+ return {
67
+ label: _jsx("span", { className: b('group-label'), children: Subject }),
68
+ items: aclParams
69
+ .map((key) => {
70
+ const value = data[key];
71
+ if (value) {
72
+ return {
73
+ name: aclParamToName[key],
74
+ content: _jsx(DefinitionValue, { value: value }),
75
+ };
76
+ }
77
+ return undefined;
78
+ })
79
+ .filter(Boolean),
80
+ };
81
+ });
82
+ }
83
+ function getOwnerItem(owner) {
84
+ const preparedOwner = prepareLogin(owner);
85
+ if (!preparedOwner) {
86
+ return [];
87
+ }
88
+ return [
89
+ {
90
+ name: _jsx("span", { className: b('owner'), children: preparedOwner }),
91
+ content: _jsx("span", { className: b('owner'), children: i18n('acl.owner') }),
55
92
  },
56
- sortable: false,
57
- },
58
- ];
93
+ ];
94
+ }
59
95
  export const Acl = ({ path }) => {
60
96
  const { currentData, isFetching, error } = schemaAclApi.useGetSchemaAclQuery({ path });
61
97
  const loading = isFetching && !currentData;
62
98
  const { acl, owner } = currentData || {};
63
- const renderTable = () => {
64
- if (!acl || !acl.length) {
65
- return null;
66
- }
67
- return (_jsx(ResizeableDataTable, { columnsWidthLSKey: ACL_COLUMNS_WIDTH_LS_KEY, columns: columns, data: acl, settings: TABLE_SETTINGS }));
68
- };
69
- const renderOwner = () => {
70
- if (!owner) {
71
- return null;
72
- }
73
- return (_jsxs("div", { className: b('owner-container'), children: [_jsx("span", { className: b('owner-label'), children: `${i18n('acl.owner')}: ` }), prepareLogin(owner)] }));
74
- };
99
+ const aclListItems = getAclListItems(acl);
100
+ const ownerItem = getOwnerItem(owner);
75
101
  if (loading) {
76
102
  return _jsx(Loader, {});
77
103
  }
@@ -81,5 +107,5 @@ export const Acl = ({ path }) => {
81
107
  if (!acl && !owner) {
82
108
  return _jsx(React.Fragment, { children: i18n('acl.empty') });
83
109
  }
84
- return (_jsx("div", { className: b(), children: _jsxs("div", { className: b('result'), children: [renderOwner(), renderTable()] }) }));
110
+ return (_jsxs("div", { className: b(), children: [ownerItem.length ? (_jsx(DefinitionList, { items: ownerItem, nameMaxWidth: 200, className: b('owner-container') })) : null, aclListItems.length ? (_jsx(DefinitionList, { items: aclListItems, nameMaxWidth: 200, className: b('result') })) : null] }));
85
111
  };
@@ -1,17 +1,22 @@
1
1
  @import '../../../styles/mixins.scss';
2
2
 
3
3
  .ydb-acl {
4
- &__result {
5
- align-self: flex-start;
6
- }
7
-
4
+ width: 100%;
8
5
  &__owner-container {
9
- position: sticky;
10
- z-index: 2;
11
- top: 0;
12
-
6
+ padding-bottom: 25px;
7
+ }
8
+ &__result {
13
9
  padding-bottom: 16px;
10
+ }
14
11
 
15
- background-color: var(--g-color-base-background);
12
+ &__owner {
13
+ font-weight: 600;
14
+ }
15
+ &__definition-content {
16
+ display: flex;
17
+ flex-direction: column;
18
+ }
19
+ &__group-label {
20
+ @include subheader-2-typography();
16
21
  }
17
22
  }
@@ -2,13 +2,13 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import React from 'react';
3
3
  import { InfoViewer } from '../../../../../components/InfoViewer';
4
4
  import { cn } from '../../../../../utils/cn';
5
- import { getEntityName } from '../../../utils';
5
+ import { EntityTitle } from '../../../EntityTitle/EntityTitle';
6
6
  import i18n from './i18n';
7
7
  import { prepareTableInfo } from './prepareTableInfo';
8
8
  import './TableInfo.scss';
9
9
  const b = cn('ydb-diagnostics-table-info');
10
10
  export const TableInfo = ({ data, type, olapStats }) => {
11
- const entityName = getEntityName(data === null || data === void 0 ? void 0 : data.PathDescription);
11
+ const title = _jsx(EntityTitle, { data: data === null || data === void 0 ? void 0 : data.PathDescription });
12
12
  const { generalInfo = [], tableStatsInfo = [], tabletMetricsInfo = [], partitionConfigInfo = [], } = React.useMemo(() => prepareTableInfo(data, type, olapStats), [data, type, olapStats]);
13
- return (_jsxs("div", { className: b(), children: [_jsx(InfoViewer, { info: generalInfo, title: entityName, className: b('info-block'), renderEmptyState: () => _jsx("div", { className: b('title'), children: entityName }) }), _jsxs("div", { className: b('row'), children: [_jsx("div", { className: b('col'), children: tableStatsInfo.map((info, index) => (_jsx(InfoViewer, { info: info, title: index === 0 ? i18n('tableStats') : undefined, className: b('info-block'), renderEmptyState: () => null }, index))) }), tabletMetricsInfo.length > 0 || partitionConfigInfo.length > 0 ? (_jsxs("div", { className: b('col'), children: [_jsx(InfoViewer, { info: tabletMetricsInfo, title: i18n('tabletMetrics'), className: b('info-block'), renderEmptyState: () => null }), _jsx(InfoViewer, { info: partitionConfigInfo, title: i18n('partitionConfig'), className: b('info-block'), renderEmptyState: () => null })] })) : null] })] }));
13
+ return (_jsxs("div", { className: b(), children: [_jsx(InfoViewer, { info: generalInfo, title: title, className: b('info-block'), renderEmptyState: () => _jsx("div", { className: b('title'), children: title }) }), _jsxs("div", { className: b('row'), children: [_jsx("div", { className: b('col'), children: tableStatsInfo.map((info, index) => (_jsx(InfoViewer, { info: info, title: index === 0 ? i18n('tableStats') : undefined, className: b('info-block'), renderEmptyState: () => null }, index))) }), tabletMetricsInfo.length > 0 || partitionConfigInfo.length > 0 ? (_jsxs("div", { className: b('col'), children: [_jsx(InfoViewer, { info: tabletMetricsInfo, title: i18n('tabletMetrics'), className: b('info-block'), renderEmptyState: () => null }), _jsx(InfoViewer, { info: partitionConfigInfo, title: i18n('partitionConfig'), className: b('info-block'), renderEmptyState: () => null })] })) : null] })] }));
14
14
  };
@@ -1,2 +1,2 @@
1
- declare const _default: (key: "nodes" | "queries" | "groups" | "top" | "shards" | "tables" | "no-data" | "no-pools-data" | "top-nodes.empty-data" | "top-groups.empty-data" | "by-pools-usage" | "by-cpu-time" | "by-cpu-usage" | "by-load" | "by-memory" | "by-usage" | "by-size" | "cards.cpu-label" | "cards.storage-label" | "cards.memory-label" | "charts.queries-per-second" | "charts.transaction-latency" | "charts.cpu-usage" | "charts.storage-usage" | "charts.memory-usage" | "storage.tablet-storage-title" | "storage.tablet-storage-description" | "storage.db-storage-title" | "storage.db-storage-description", params?: import("@gravity-ui/i18n").Params | undefined) => string;
1
+ declare const _default: (key: "nodes" | "queries" | "groups" | "no-data" | "top" | "shards" | "tables" | "no-pools-data" | "top-nodes.empty-data" | "top-groups.empty-data" | "by-pools-usage" | "by-cpu-time" | "by-cpu-usage" | "by-load" | "by-memory" | "by-usage" | "by-size" | "cards.cpu-label" | "cards.storage-label" | "cards.memory-label" | "charts.queries-per-second" | "charts.transaction-latency" | "charts.cpu-usage" | "charts.storage-usage" | "charts.memory-usage" | "storage.tablet-storage-title" | "storage.tablet-storage-description" | "storage.db-storage-title" | "storage.db-storage-description", params?: import("@gravity-ui/i18n").Params | undefined) => string;
2
2
  export default _default;
@@ -0,0 +1,6 @@
1
+ import type { TPathDescription } from '../../../types/api/schema';
2
+ interface EntityTitleProps {
3
+ data?: TPathDescription;
4
+ }
5
+ export declare function EntityTitle({ data }: EntityTitleProps): string | import("react/jsx-runtime").JSX.Element | undefined;
6
+ export {};
@@ -0,0 +1,11 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Flex, Label } from '@gravity-ui/uikit';
3
+ import i18n from '../i18n';
4
+ import { getEntityName, isReadOnlyTable } from '../utils';
5
+ export function EntityTitle({ data }) {
6
+ const entityName = getEntityName(data);
7
+ if (isReadOnlyTable(data)) {
8
+ return (_jsxs(Flex, { gap: 1, wrap: 'nowrap', children: [entityName, " ", _jsx(Label, { children: i18n('label.read-only') })] }));
9
+ }
10
+ return entityName;
11
+ }
@@ -13,7 +13,6 @@ import InfoViewer from '../../../components/InfoViewer/InfoViewer';
13
13
  import { LinkWithIcon } from '../../../components/LinkWithIcon/LinkWithIcon';
14
14
  import { Loader } from '../../../components/Loader';
15
15
  import SplitPane from '../../../components/SplitPane';
16
- import { getEntityName } from '../../../containers/Tenant/utils';
17
16
  import routes, { createExternalUILink, createHref } from '../../../routes';
18
17
  import { schemaApi, setShowPreview } from '../../../store/reducers/schema/schema';
19
18
  import { TENANT_PAGES_IDS, TENANT_QUERY_TABS_ID, TENANT_SUMMARY_TABS_IDS, } from '../../../store/reducers/tenant/constants';
@@ -24,6 +23,7 @@ import { DEFAULT_IS_TENANT_COMMON_INFO_COLLAPSED, DEFAULT_SIZE_TENANT_SUMMARY_KE
24
23
  import { formatDateTime, formatSecondsToHours } from '../../../utils/dataFormatters/dataFormatters';
25
24
  import { useTypedDispatch, useTypedSelector } from '../../../utils/hooks';
26
25
  import { Acl } from '../Acl/Acl';
26
+ import { EntityTitle } from '../EntityTitle/EntityTitle';
27
27
  import { SchemaTree } from '../Schema/SchemaTree/SchemaTree';
28
28
  import { SchemaViewer } from '../Schema/SchemaViewer/SchemaViewer';
29
29
  import { TENANT_INFO_TABS, TENANT_SCHEMA_TAB, TenantTabsGroups } from '../TenantPages';
@@ -86,7 +86,7 @@ export function ObjectSummary({ type, subType, tenantName, path, onCollapseSumma
86
86
  value: formatDateTime(CreateStep, ''),
87
87
  });
88
88
  const { PathDescription } = currentObjectData;
89
- const title = getEntityName(PathDescription);
89
+ const title = _jsx(EntityTitle, { data: PathDescription });
90
90
  const getPathTypeOverview = {
91
91
  [EPathType.EPathTypeInvalid]: undefined,
92
92
  [EPathType.EPathTypeDir]: undefined,
@@ -15,5 +15,5 @@ export const TenantNavigation = () => {
15
15
  nextItem === null || nextItem === void 0 ? void 0 : nextItem.onForward();
16
16
  };
17
17
  const getCurrentItem = () => navigationItems.find((item) => item.current) || navigationItems[0];
18
- return (_jsx("div", { className: b(), children: _jsx(RadioButton, { width: "auto", onUpdate: handleUpdate, size: "l", className: b('body'), defaultValue: getCurrentItem().id, options: navigationItems.map(transformItemToOption) }) }));
18
+ return (_jsx("div", { className: b(), children: _jsx(RadioButton, { width: "auto", onUpdate: handleUpdate, size: "l", className: b('body'), value: getCurrentItem().id, options: navigationItems.map(transformItemToOption) }) }));
19
19
  };
@@ -21,6 +21,7 @@
21
21
  "summary.mode": "Mode",
22
22
  "summary.format": "Format",
23
23
  "summary.retention": "Retention",
24
+ "label.read-only": "ReadOnly",
24
25
  "actions.copied": "The path is copied to the clipboard",
25
26
  "actions.notCopied": "Couldn’t copy the path",
26
27
  "actions.copyPath": "Copy path",
@@ -29,6 +30,7 @@
29
30
  "actions.createExternalTable": "Create external table...",
30
31
  "actions.createTopic": "Create topic...",
31
32
  "actions.createColumnTable": "Create column table...",
33
+ "actions.createAsyncReplication": "Create async replication...",
32
34
  "actions.createView": "Create view...",
33
35
  "actions.dropTable": "Drop table...",
34
36
  "actions.dropTopic": "Drop topic...",
@@ -36,5 +38,7 @@
36
38
  "actions.alterTable": "Alter table...",
37
39
  "actions.alterTopic": "Alter topic...",
38
40
  "actions.selectQuery": "Select query...",
39
- "actions.upsertQuery": "Upsert query..."
41
+ "actions.upsertQuery": "Upsert query...",
42
+ "actions.alterReplication": "Alter async replicaton...",
43
+ "actions.dropReplication": "Drop async replicaton..."
40
44
  }
@@ -1,2 +1,2 @@
1
- declare const _default: (key: "page.title" | "pages.query" | "pages.diagnostics" | "acl.owner" | "acl.empty" | "summary.navigation" | "summary.showPreview" | "summary.source-type" | "summary.data-source" | "summary.copySchemaPath" | "summary.type" | "summary.subtype" | "summary.id" | "summary.version" | "summary.created" | "summary.partitions" | "summary.paths" | "summary.shards" | "summary.state" | "summary.mode" | "summary.format" | "summary.retention" | "actions.copied" | "actions.notCopied" | "actions.copyPath" | "actions.openPreview" | "actions.createTable" | "actions.createExternalTable" | "actions.createTopic" | "actions.createColumnTable" | "actions.createView" | "actions.dropTable" | "actions.dropTopic" | "actions.dropView" | "actions.alterTable" | "actions.alterTopic" | "actions.selectQuery" | "actions.upsertQuery", params?: import("@gravity-ui/i18n").Params | undefined) => string;
1
+ declare const _default: (key: "page.title" | "pages.query" | "pages.diagnostics" | "acl.owner" | "acl.empty" | "summary.navigation" | "summary.showPreview" | "summary.source-type" | "summary.data-source" | "summary.copySchemaPath" | "summary.type" | "summary.subtype" | "summary.id" | "summary.version" | "summary.created" | "summary.partitions" | "summary.paths" | "summary.shards" | "summary.state" | "summary.mode" | "summary.format" | "summary.retention" | "label.read-only" | "actions.copied" | "actions.notCopied" | "actions.copyPath" | "actions.openPreview" | "actions.createTable" | "actions.createExternalTable" | "actions.createTopic" | "actions.createColumnTable" | "actions.createAsyncReplication" | "actions.createView" | "actions.dropTable" | "actions.dropTopic" | "actions.dropView" | "actions.alterTable" | "actions.alterTopic" | "actions.selectQuery" | "actions.upsertQuery" | "actions.alterReplication" | "actions.dropReplication", params?: import("@gravity-ui/i18n").Params | undefined) => string;
2
2
  export default _default;
@@ -1,2 +1,3 @@
1
1
  import type { TPathDescription } from '../../../types/api/schema';
2
2
  export declare const getEntityName: (pathDescription?: TPathDescription) => string | undefined;
3
+ export declare const isReadOnlyTable: (pathDescription?: TPathDescription) => boolean | undefined;
@@ -3,3 +3,9 @@ export const getEntityName = (pathDescription) => {
3
3
  const { PathType, PathSubType } = (pathDescription === null || pathDescription === void 0 ? void 0 : pathDescription.Self) || {};
4
4
  return mapPathTypeToEntityName(PathType, PathSubType);
5
5
  };
6
+ export const isReadOnlyTable = (pathDescription) => {
7
+ var _a;
8
+ return (_a = pathDescription === null || pathDescription === void 0 ? void 0 : pathDescription.UserAttributes) === null || _a === void 0 ? void 0 : _a.some(({ Key, Value }) => {
9
+ return Key === '__async_replica' && Value === 'true';
10
+ });
11
+ };
@@ -1,5 +1,6 @@
1
1
  export declare const createTableTemplate: (path: string) => string;
2
2
  export declare const createColumnTableTemplate: (path: string) => string;
3
+ export declare const createAsyncReplicationTemplate: () => string;
3
4
  export declare const alterTableTemplate: (path: string) => string;
4
5
  export declare const selectQueryTemplate: (path: string) => string;
5
6
  export declare const upsertQueryTemplate: (path: string) => string;
@@ -10,3 +11,5 @@ export declare const alterTopicTemplate: (path: string) => string;
10
11
  export declare const dropTopicTemplate: (path: string) => string;
11
12
  export declare const createViewTemplate: (path: string) => string;
12
13
  export declare const dropViewTemplate: (path: string) => string;
14
+ export declare const dropAsyncReplicationTemplate: (path: string) => string;
15
+ export declare const alterAsyncReplicationTemplate: (path: string) => string;
@@ -42,6 +42,20 @@ CREATE TABLE \`${path}/ydb_column_table\` (
42
42
  PARTITION BY HASH(id)
43
43
  WITH (STORE = COLUMN)`;
44
44
  };
45
+ export const createAsyncReplicationTemplate = () => {
46
+ return `CREATE OBJECT secret_name (TYPE SECRET) WITH value="secret_value";
47
+
48
+ CREATE ASYNC REPLICATION my_replication
49
+ FOR \`/remote_database/table_name\` AS \`local_table_name\` --[, \`/remote_database/another_table_name\` AS \`another_local_table_name\` ...]
50
+ WITH (
51
+ CONNECTION_STRING="grpcs://mydb.ydb.tech:2135/?database=/remote_database",
52
+ TOKEN_SECRET_NAME = "secret_name"
53
+ -- ENDPOINT="mydb.ydb.tech:2135",
54
+ -- DATABASE=\`/remote_database\`,
55
+ -- USER="user",
56
+ -- PASSWORD_SECRET_NAME="your_password"
57
+ );`;
58
+ };
45
59
  export const alterTableTemplate = (path) => {
46
60
  return `ALTER TABLE \`${path}\`
47
61
  ADD COLUMN is_deleted Bool;`;
@@ -123,3 +137,9 @@ export const createViewTemplate = (path) => {
123
137
  export const dropViewTemplate = (path) => {
124
138
  return `DROP VIEW \`${path}\`;`;
125
139
  };
140
+ export const dropAsyncReplicationTemplate = (path) => {
141
+ return `DROP ASYNC REPLICATION \`${path}\`;`;
142
+ };
143
+ export const alterAsyncReplicationTemplate = (path) => {
144
+ return `ALTER ASYNC REPLICATION \`${path}\` SET (STATE = "DONE", FAILOVER_MODE = "FORCE");`;
145
+ };
@@ -4,7 +4,7 @@ import { TENANT_PAGES_IDS, TENANT_QUERY_TABS_ID } from '../../../store/reducers/
4
4
  import { setQueryTab, setTenantPage } from '../../../store/reducers/tenant/tenant';
5
5
  import createToast from '../../../utils/createToast';
6
6
  import i18n from '../i18n';
7
- import { alterTableTemplate, alterTopicTemplate, createColumnTableTemplate, createExternalTableTemplate, createTableTemplate, createTopicTemplate, createViewTemplate, dropExternalTableTemplate, dropTopicTemplate, dropViewTemplate, selectQueryTemplate, upsertQueryTemplate, } from './queryTemplates';
7
+ import { alterAsyncReplicationTemplate, alterTableTemplate, alterTopicTemplate, createAsyncReplicationTemplate, createColumnTableTemplate, createExternalTableTemplate, createTableTemplate, createTopicTemplate, createViewTemplate, dropAsyncReplicationTemplate, dropExternalTableTemplate, dropTopicTemplate, dropViewTemplate, selectQueryTemplate, upsertQueryTemplate, } from './queryTemplates';
8
8
  const bindActions = (path, dispatch, additionalEffects) => {
9
9
  const { setActivePath, setQueryMode } = additionalEffects;
10
10
  const inputQuery = (tmpl, mode) => () => {
@@ -19,6 +19,9 @@ const bindActions = (path, dispatch, additionalEffects) => {
19
19
  return {
20
20
  createTable: inputQuery(createTableTemplate, 'script'),
21
21
  createColumnTable: inputQuery(createColumnTableTemplate, 'script'),
22
+ createAsyncReplication: inputQuery(createAsyncReplicationTemplate, 'script'),
23
+ alterAsyncReplication: inputQuery(alterAsyncReplicationTemplate, 'script'),
24
+ dropAsyncReplication: inputQuery(dropAsyncReplicationTemplate, 'script'),
22
25
  alterTable: inputQuery(alterTableTemplate, 'script'),
23
26
  selectQuery: inputQuery(selectQueryTemplate),
24
27
  upsertQuery: inputQuery(upsertQueryTemplate),
@@ -57,6 +60,10 @@ export const getActions = (dispatch, additionalEffects) => (path, type) => {
57
60
  [
58
61
  { text: i18n('actions.createTable'), action: actions.createTable },
59
62
  { text: i18n('actions.createColumnTable'), action: actions.createColumnTable },
63
+ {
64
+ text: i18n('actions.createAsyncReplication'),
65
+ action: actions.createAsyncReplication,
66
+ },
60
67
  { text: i18n('actions.createTopic'), action: actions.createTopic },
61
68
  { text: i18n('actions.createView'), action: actions.createView },
62
69
  ],
@@ -95,11 +102,18 @@ export const getActions = (dispatch, additionalEffects) => (path, type) => {
95
102
  [{ text: i18n('actions.selectQuery'), action: actions.selectQuery }],
96
103
  [{ text: i18n('actions.dropView'), action: actions.dropView }],
97
104
  ];
105
+ const ASYNC_REPLICATION_SET = [
106
+ [copyItem],
107
+ [
108
+ { text: i18n('actions.alterReplication'), action: actions.alterAsyncReplication },
109
+ { text: i18n('actions.dropReplication'), action: actions.dropAsyncReplication },
110
+ ],
111
+ ];
98
112
  const JUST_COPY = [copyItem];
99
113
  // verbose mapping to guarantee a correct actions set for new node types
100
114
  // TS will error when a new type is added in the lib but is not mapped here
101
115
  const nodeTypeToActions = {
102
- async_replication: JUST_COPY,
116
+ async_replication: ASYNC_REPLICATION_SET,
103
117
  database: DIR_SET,
104
118
  directory: DIR_SET,
105
119
  table: TABLE_SET,
@@ -1,11 +1,16 @@
1
1
  /// <reference types="react" />
2
+ export interface SettingsInfoFieldProps {
3
+ type: 'info';
4
+ title: string;
5
+ description?: React.ReactNode;
6
+ content: React.ReactNode;
7
+ }
2
8
  export type SettingsElementType = 'switch' | 'radio';
3
9
  export interface SettingProps {
4
10
  type?: SettingsElementType;
5
11
  title: string;
6
12
  description?: React.ReactNode;
7
13
  settingKey: string;
8
- helpPopoverContent?: React.ReactNode;
9
14
  options?: {
10
15
  value: string;
11
16
  content: string;
@@ -13,11 +18,4 @@ export interface SettingProps {
13
18
  defaultValue?: unknown;
14
19
  onValueUpdate?: VoidFunction;
15
20
  }
16
- export declare const Setting: ({ type, settingKey, title, description, helpPopoverContent, options, defaultValue, onValueUpdate, }: SettingProps) => import("react/jsx-runtime").JSX.Element;
17
- export interface SettingsInfoFieldProps {
18
- type: 'info';
19
- title: string;
20
- description?: React.ReactNode;
21
- content: React.ReactNode;
22
- }
23
- export declare const SettingsInfoField: ({ title, description, content }: SettingsInfoFieldProps) => import("react/jsx-runtime").JSX.Element;
21
+ export declare const Setting: ({ type, settingKey, options, defaultValue, onValueUpdate, }: SettingProps) => import("react/jsx-runtime").JSX.Element | null;
@@ -1,40 +1,25 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import { Settings } from '@gravity-ui/navigation';
3
2
  import { RadioButton, Switch } from '@gravity-ui/uikit';
4
- import { LabelWithPopover } from '../../components/LabelWithPopover/LabelWithPopover';
5
3
  import { useSetting } from '../../utils/hooks';
6
- import { b } from './UserSettings';
7
- export const Setting = ({ type = 'switch', settingKey, title, description, helpPopoverContent, options, defaultValue, onValueUpdate, }) => {
4
+ export const Setting = ({ type = 'switch', settingKey, options, defaultValue, onValueUpdate, }) => {
8
5
  const [settingValue, setValue] = useSetting(settingKey, defaultValue);
9
6
  const onUpdate = (value) => {
10
7
  setValue(value);
11
8
  onValueUpdate === null || onValueUpdate === void 0 ? void 0 : onValueUpdate();
12
9
  };
13
- const renderTitleComponent = (value) => {
14
- if (helpPopoverContent) {
15
- return (_jsx(LabelWithPopover, { className: b('item-with-popup'), contentClassName: b('popup'), text: value, popoverContent: helpPopoverContent }));
10
+ switch (type) {
11
+ case 'switch': {
12
+ return _jsx(Switch, { checked: Boolean(settingValue), onUpdate: onUpdate });
16
13
  }
17
- return value;
18
- };
19
- const getSettingsElement = (elementType) => {
20
- switch (elementType) {
21
- case 'switch': {
22
- return _jsx(Switch, { checked: Boolean(settingValue), onUpdate: onUpdate });
23
- }
24
- case 'radio': {
25
- if (!options) {
26
- return null;
27
- }
28
- return (_jsx(RadioButton, { value: String(settingValue), onUpdate: onUpdate, children: options.map(({ value, content }) => {
29
- return (_jsx(RadioButton.Option, { value: value, children: content }, value));
30
- }) }));
31
- }
32
- default:
14
+ case 'radio': {
15
+ if (!options) {
33
16
  return null;
17
+ }
18
+ return (_jsx(RadioButton, { value: String(settingValue), onUpdate: onUpdate, children: options.map(({ value, content }) => {
19
+ return (_jsx(RadioButton.Option, { value: value, children: content }, value));
20
+ }) }));
34
21
  }
35
- };
36
- return (_jsx(Settings.Item, { title: title, highlightedTitle: title, description: description, renderTitleComponent: renderTitleComponent, children: getSettingsElement(type) }));
37
- };
38
- export const SettingsInfoField = ({ title, description, content }) => {
39
- return (_jsx(Settings.Item, { title: title, highlightedTitle: title, description: description, children: content }));
22
+ default:
23
+ return null;
24
+ }
40
25
  };
@@ -1,6 +1,4 @@
1
1
  import type { YDBEmbeddedUISettings } from './settings';
2
- import './UserSettings.scss';
3
- export declare const b: import("@bem-react/classname").ClassNameFormatter;
4
2
  interface UserSettingsProps {
5
3
  settings?: YDBEmbeddedUISettings;
6
4
  }
@@ -1,10 +1,7 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { Settings } from '@gravity-ui/navigation';
3
- import { cn } from '../../utils/cn';
4
- import { Setting, SettingsInfoField } from './Setting';
3
+ import { Setting } from './Setting';
5
4
  import { settings } from './settings';
6
- import './UserSettings.scss';
7
- export const b = cn('ydb-user-settings');
8
5
  export const UserSettings = ({ settings: userSettings = settings }) => {
9
6
  return (_jsx(Settings, { children: userSettings.map((page) => {
10
7
  const { id, title, icon, sections = [] } = page;
@@ -12,9 +9,9 @@ export const UserSettings = ({ settings: userSettings = settings }) => {
12
9
  const { title: sectionTitle, settings: sectionSettings = [] } = section;
13
10
  return (_jsx(Settings.Section, { title: sectionTitle, children: sectionSettings.map((setting) => {
14
11
  if (setting.type === 'info') {
15
- return (_jsx(SettingsInfoField, Object.assign({}, setting), setting.title));
12
+ return (_jsx(Settings.Item, Object.assign({}, setting, { children: setting.content }), setting.title));
16
13
  }
17
- return _jsx(Setting, Object.assign({}, setting), setting.settingKey);
14
+ return (_jsx(Settings.Item, Object.assign({}, setting, { children: _jsx(Setting, Object.assign({}, setting)) }), setting.title));
18
15
  }) }, id));
19
16
  }) }, id));
20
17
  }) }));
@@ -22,10 +22,10 @@
22
22
  "settings.binaryDataInPlainTextDisplay.description": "Available starting from version 24.1",
23
23
  "settings.invertedDisks.title": "Inverted disks space indicators",
24
24
  "settings.useNodesEndpoint.title": "Break the Nodes tab in Diagnostics",
25
- "settings.useNodesEndpoint.popover": "Use /viewer/json/nodes endpoint for Nodes Tab in diagnostics. It could return incorrect data on some versions",
25
+ "settings.useNodesEndpoint.popover": "Use /viewer/json/nodes endpoint for Nodes tab in diagnostics. It could return incorrect data on versions before 24-1",
26
26
  "settings.useVirtualTables.title": "Use table with data load on scroll for Nodes and Storage tabs",
27
27
  "settings.useVirtualTables.popover": "It will increase performance, but could work unstable",
28
28
  "settings.queryUseMultiSchema.title": "Allow queries with multiple result sets",
29
- "settings.queryUseMultiSchema.popover": "Use 'multi' schema for queries that enables queries with multiple result sets. Returns nothing on versions 23-3 and older",
29
+ "settings.queryUseMultiSchema.popover": "Use 'multi' schema for queries. It enables queries with multiple result sets. It returns nothing on versions 23-3 and older",
30
30
  "settings.about.interfaceVersionInfoField.title": "Interface version"
31
31
  }
@@ -57,17 +57,17 @@ export const invertedDisksSetting = {
57
57
  export const useNodesEndpointSetting = {
58
58
  settingKey: USE_NODES_ENDPOINT_IN_DIAGNOSTICS_KEY,
59
59
  title: i18n('settings.useNodesEndpoint.title'),
60
- helpPopoverContent: i18n('settings.useNodesEndpoint.popover'),
60
+ description: i18n('settings.useNodesEndpoint.popover'),
61
61
  };
62
62
  export const useVirtualTables = {
63
63
  settingKey: USE_BACKEND_PARAMS_FOR_TABLES_KEY,
64
64
  title: i18n('settings.useVirtualTables.title'),
65
- helpPopoverContent: i18n('settings.useVirtualTables.popover'),
65
+ description: i18n('settings.useVirtualTables.popover'),
66
66
  };
67
67
  export const queryUseMultiSchemaSetting = {
68
68
  settingKey: QUERY_USE_MULTI_SCHEMA_KEY,
69
69
  title: i18n('settings.queryUseMultiSchema.title'),
70
- helpPopoverContent: i18n('settings.queryUseMultiSchema.popover'),
70
+ description: i18n('settings.queryUseMultiSchema.popover'),
71
71
  };
72
72
  export const enableAutocompleteSetting = {
73
73
  settingKey: ENABLE_AUTOCOMPLETE,
@@ -128,6 +128,7 @@ export class YdbEmbeddedAPI extends AxiosWrapper {
128
128
  getSchemaAcl({ path }, { concurrentId, signal } = {}) {
129
129
  return this.get(this.getPath('/viewer/json/acl'), {
130
130
  path,
131
+ merge_rules: true,
131
132
  }, { concurrentId: concurrentId || `getSchemaAcl`, requestConfig: { signal } });
132
133
  }
133
134
  getHeatmapData({ path }, { concurrentId, signal } = {}) {
@@ -35,6 +35,11 @@
35
35
  line-height: var(--g-text-subheader-3-line-height);
36
36
  }
37
37
 
38
+ @mixin subheader-2-typography() {
39
+ font-size: var(--g-text-subheader-2-font-size);
40
+ line-height: var(--g-text-subheader-2-line-height);
41
+ }
42
+
38
43
  @mixin header-1-typography() {
39
44
  font-size: var(--g-text-header-1-font-size);
40
45
  line-height: var(--g-text-header-1-line-height);
@@ -7,7 +7,7 @@
7
7
 
8
8
  .g-root {
9
9
  --g-text-header-font-weight: 500;
10
- --g-text-subheader-font-weight: 500;
10
+ --g-text-subheader-font-weight: 600;
11
11
  --g-text-display-font-weight: 500;
12
12
  --g-text-accent-font-weight: 500;
13
13
 
@@ -17,7 +17,8 @@ export interface TMetaCommonInfo {
17
17
  export interface TACE {
18
18
  AccessType: string;
19
19
  AccessRights?: string[];
20
+ AccessRules?: string[];
20
21
  Subject: string;
21
22
  InheritanceType?: string[];
22
- AccessRule: string;
23
+ AccessRule?: string;
23
24
  }
@@ -56,6 +56,7 @@ export interface TPathDescription {
56
56
  /** info about the path itself */
57
57
  Self?: TDirEntry;
58
58
  DomainDescription?: TDomainDescription;
59
+ UserAttributes?: TUserAttribute[];
59
60
  Children?: TDirEntry[];
60
61
  Table?: TTableDescription;
61
62
  TableStats?: TTableStats;
@@ -250,4 +251,8 @@ interface TTablePartition {
250
251
  /** uint64 */
251
252
  DatashardId?: string;
252
253
  }
254
+ interface TUserAttribute {
255
+ Key?: string;
256
+ Value?: string;
257
+ }
253
258
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ydb-embedded-ui",
3
- "version": "6.7.0",
3
+ "version": "6.8.0",
4
4
  "files": [
5
5
  "dist"
6
6
  ],
@@ -12,18 +12,18 @@
12
12
  "dependencies": {
13
13
  "@bem-react/classname": "^1.6.0",
14
14
  "@gravity-ui/axios-wrapper": "^1.4.1",
15
- "@gravity-ui/chartkit": "^5.5.0",
16
- "@gravity-ui/components": "^3.6.2",
17
- "@gravity-ui/date-utils": "^2.4.0",
18
- "@gravity-ui/i18n": "^1.5.0",
19
- "@gravity-ui/icons": "^2.9.1",
20
- "@gravity-ui/navigation": "^2.10.0",
15
+ "@gravity-ui/chartkit": "^5.9.0",
16
+ "@gravity-ui/components": "^3.7.0",
17
+ "@gravity-ui/date-utils": "^2.5.3",
18
+ "@gravity-ui/i18n": "^1.5.1",
19
+ "@gravity-ui/icons": "^2.10.0",
20
+ "@gravity-ui/navigation": "^2.16.0",
21
21
  "@gravity-ui/paranoid": "^2.0.1",
22
22
  "@gravity-ui/react-data-table": "^2.1.1",
23
- "@gravity-ui/uikit": "^6.15.0",
23
+ "@gravity-ui/uikit": "^6.20.1",
24
24
  "@gravity-ui/websql-autocomplete": "^9.1.0",
25
25
  "@reduxjs/toolkit": "^2.2.3",
26
- "axios": "^1.6.8",
26
+ "axios": "^1.7.2",
27
27
  "axios-retry": "^4.4.0",
28
28
  "colord": "^2.9.3",
29
29
  "copy-to-clipboard": "^3.3.3",
@@ -35,17 +35,17 @@
35
35
  "path-to-regexp": "^3.0.0",
36
36
  "qs": "^6.12.0",
37
37
  "react-error-boundary": "^4.0.13",
38
- "react-helmet-async": "2.0.4",
38
+ "react-helmet-async": "^2.0.5",
39
39
  "react-json-inspector": "^7.1.1",
40
40
  "react-list": "^0.8.17",
41
41
  "react-monaco-editor": "^0.55.0",
42
- "react-redux": "^9.1.0",
42
+ "react-redux": "^9.1.2",
43
43
  "react-router": "^5.3.4",
44
44
  "react-router-dom": "^5.3.4",
45
45
  "react-split": "^2.0.14",
46
46
  "redux": "^5.0.1",
47
47
  "redux-location-state": "^2.8.2",
48
- "tslib": "^2.6.2",
48
+ "tslib": "^2.6.3",
49
49
  "url": "^0.11.3",
50
50
  "use-query-params": "^2.2.1",
51
51
  "web-vitals": "^1.1.2",
@@ -122,54 +122,54 @@
122
122
  ]
123
123
  },
124
124
  "devDependencies": {
125
- "@commitlint/cli": "^19.2.1",
126
- "@commitlint/config-conventional": "^19.1.0",
125
+ "@commitlint/cli": "^19.3.0",
126
+ "@commitlint/config-conventional": "^19.2.2",
127
127
  "@gravity-ui/eslint-config": "^3.2.0",
128
128
  "@gravity-ui/prettier-config": "^1.1.0",
129
129
  "@gravity-ui/stylelint-config": "^4.0.1",
130
130
  "@gravity-ui/tsconfig": "^1.0.0",
131
131
  "@playwright/test": "^1.42.1",
132
- "@testing-library/jest-dom": "^6.4.2",
132
+ "@testing-library/jest-dom": "^6.4.6",
133
133
  "@testing-library/react": "^14.2.2",
134
134
  "@testing-library/user-event": "^14.5.2",
135
135
  "@types/jest": "^29.5.12",
136
136
  "@types/lodash": "^4.17.0",
137
137
  "@types/numeral": "^2.0.5",
138
- "@types/qs": "^6.9.14",
139
- "@types/react": "^18.2.73",
140
- "@types/react-dom": "^18.2.23",
138
+ "@types/qs": "^6.9.15",
139
+ "@types/react": "^18.3.3",
140
+ "@types/react-dom": "^18.3.0",
141
141
  "@types/react-router": "^5.1.20",
142
142
  "@types/react-router-dom": "^5.3.3",
143
143
  "copyfiles": "^2.4.1",
144
144
  "http-proxy-middleware": "^2.0.6",
145
145
  "husky": "^9.0.11",
146
146
  "jest-transform-css": "^6.0.1",
147
- "lint-staged": "^15.2.2",
147
+ "lint-staged": "^15.2.7",
148
148
  "npm-run-all": "^4.1.5",
149
149
  "postcss": "^8.4.38",
150
150
  "prettier": "^3.2.5",
151
151
  "prop-types": "^15.8.1",
152
- "react": "^18.2.0",
152
+ "react": "^18.3.1",
153
153
  "react-app-rewired": "^2.2.1",
154
- "react-dom": "^18.2.0",
154
+ "react-dom": "^18.3.1",
155
155
  "react-scripts": "^5.0.1",
156
156
  "sass": "^1.72.0",
157
157
  "source-map-explorer": "^2.5.3",
158
- "stylelint": "^15.0.0",
159
- "ts-jest": "^29.1.2",
158
+ "stylelint": "^15.11.0",
159
+ "ts-jest": "^29.1.5",
160
160
  "typescript": "^5.4.3"
161
161
  },
162
162
  "peerDependencies": {
163
163
  "prop-types": "^15.8.1",
164
- "react": "^18.2.0",
165
- "react-dom": "^18.2.0"
164
+ "react": "^18.3.1",
165
+ "react-dom": "^18.3.1"
166
166
  },
167
167
  "overrides": {
168
168
  "fork-ts-checker-webpack-plugin": "^9.0.2",
169
- "react": "^18.2.0",
170
- "react-dom": "^18.2.0",
171
- "redux": "^5.0.1",
172
- "typescript": "^5.4.3",
173
- "monaco-editor": "^0.48.0"
169
+ "react": "$react",
170
+ "react-dom": "$react-dom",
171
+ "redux": "$redux",
172
+ "typescript": "$typescript",
173
+ "monaco-editor": "$monaco-editor"
174
174
  }
175
175
  }
@@ -1,4 +0,0 @@
1
- {
2
- "common.created": "Создано",
3
- "common.type": "Тип"
4
- }
@@ -1,9 +0,0 @@
1
- .ydb-user-settings {
2
- &__item-with-popup {
3
- max-width: 180px;
4
- }
5
-
6
- &__popup {
7
- max-width: 370px;
8
- }
9
- }