ydb-embedded-ui 5.1.0 → 5.2.1

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/components/ComponentsProvider/ComponentsProvider.d.ts +4 -0
  2. package/dist/components/ComponentsProvider/componentsRegistry.d.ts +3 -0
  3. package/dist/components/ComponentsProvider/componentsRegistry.js +3 -1
  4. package/dist/components/ErrorBoundary/ErrorBoundary.d.ts +11 -1
  5. package/dist/components/ErrorBoundary/ErrorBoundary.js +11 -3
  6. package/dist/components/FullNodeViewer/FullNodeViewer.js +1 -2
  7. package/dist/containers/Cluster/Cluster.scss +3 -0
  8. package/dist/containers/ClusterModeGuard/ClusterModeGuard.d.ts +6 -0
  9. package/dist/containers/ClusterModeGuard/ClusterModeGuard.js +6 -0
  10. package/dist/containers/ClusterModeGuard/index.d.ts +1 -0
  11. package/dist/containers/ClusterModeGuard/index.js +1 -0
  12. package/dist/containers/Tenant/Query/QueryEditor/QueryEditor.js +5 -4
  13. package/dist/containers/Tenant/Query/i18n/en.json +5 -1
  14. package/dist/containers/Tenant/Query/i18n/index.d.ts +1 -1
  15. package/dist/containers/Tenant/Query/i18n/index.js +2 -5
  16. package/dist/containers/UserSettings/Setting.d.ts +2 -1
  17. package/dist/containers/UserSettings/Setting.js +2 -2
  18. package/dist/containers/UserSettings/i18n/en.json +2 -0
  19. package/dist/containers/UserSettings/i18n/index.d.ts +1 -1
  20. package/dist/containers/UserSettings/i18n/index.js +2 -6
  21. package/dist/containers/UserSettings/settings.d.ts +1 -0
  22. package/dist/containers/UserSettings/settings.js +9 -2
  23. package/dist/lib.d.ts +2 -1
  24. package/dist/lib.js +2 -1
  25. package/dist/services/api.js +8 -1
  26. package/dist/services/settings.js +2 -1
  27. package/dist/store/reducers/node/types.d.ts +2 -4
  28. package/dist/store/reducers/node/utils.js +3 -2
  29. package/dist/store/reducers/nodes/utils.js +3 -2
  30. package/dist/store/reducers/storage/utils.js +4 -17
  31. package/dist/utils/constants.d.ts +1 -0
  32. package/dist/utils/constants.js +1 -0
  33. package/dist/utils/nodes.d.ts +6 -0
  34. package/dist/utils/nodes.js +11 -0
  35. package/package.json +1 -1
  36. package/dist/containers/Tenant/Query/i18n/ru.json +0 -21
  37. package/dist/containers/UserSettings/i18n/ru.json +0 -20
@@ -9,9 +9,13 @@ export declare function useComponent<T extends Parameters<ComponentsRegistry['ge
9
9
  StaffCard: typeof import("../User/StaffCard").StaffCard;
10
10
  } & {
11
11
  AsideNavigation: typeof import("../../containers/AsideNavigation/AsideNavigation").AsideNavigation;
12
+ } & {
13
+ ErrorBoundary: typeof import("../ErrorBoundary/ErrorBoundary").ErrorBoundaryInner;
12
14
  })[T] extends React.ComponentType<any> ? React.ComponentType<React.PropsWithoutRef<React.ComponentProps<({
13
15
  StaffCard: typeof import("../User/StaffCard").StaffCard;
14
16
  } & {
15
17
  AsideNavigation: typeof import("../../containers/AsideNavigation/AsideNavigation").AsideNavigation;
18
+ } & {
19
+ ErrorBoundary: typeof import("../ErrorBoundary/ErrorBoundary").ErrorBoundaryInner;
16
20
  })[T]>>> : never;
17
21
  export {};
@@ -1,10 +1,13 @@
1
1
  import { StaffCard } from '../User/StaffCard';
2
2
  import { AsideNavigation } from '../../containers/AsideNavigation/AsideNavigation';
3
3
  import { ComponentsRegistryTemplate, Registry } from './registry';
4
+ import { ErrorBoundaryInner } from '../ErrorBoundary/ErrorBoundary';
4
5
  declare const componentsRegistryInner: Registry<{
5
6
  StaffCard: typeof StaffCard;
6
7
  } & {
7
8
  AsideNavigation: typeof AsideNavigation;
9
+ } & {
10
+ ErrorBoundary: typeof ErrorBoundaryInner;
8
11
  }>;
9
12
  export declare type ComponentsRegistry = ComponentsRegistryTemplate<typeof componentsRegistryInner>;
10
13
  export declare const componentsRegistry: ComponentsRegistry;
@@ -1,7 +1,9 @@
1
1
  import { StaffCard } from '../User/StaffCard';
2
2
  import { AsideNavigation } from '../../containers/AsideNavigation/AsideNavigation';
3
3
  import { Registry } from './registry';
4
+ import { ErrorBoundaryInner } from '../ErrorBoundary/ErrorBoundary';
4
5
  const componentsRegistryInner = new Registry()
5
6
  .register('StaffCard', StaffCard)
6
- .register('AsideNavigation', AsideNavigation);
7
+ .register('AsideNavigation', AsideNavigation)
8
+ .register('ErrorBoundary', ErrorBoundaryInner);
7
9
  export const componentsRegistry = componentsRegistryInner;
@@ -1,9 +1,19 @@
1
1
  import type { ReactNode } from 'react';
2
2
  import './ErrorBoundary.scss';
3
+ export declare function ErrorBoundary({ children }: {
4
+ children?: ReactNode;
5
+ }): JSX.Element;
3
6
  interface ErrorBoundaryProps {
4
7
  children?: ReactNode;
5
8
  useRetry?: boolean;
6
9
  onReportProblem?: (error?: Error) => void;
7
10
  }
8
- export declare const ErrorBoundary: ({ children, useRetry, onReportProblem }: ErrorBoundaryProps) => JSX.Element;
11
+ export declare function ErrorBoundaryInner({ children, useRetry, onReportProblem, }: ErrorBoundaryProps): JSX.Element;
12
+ interface ErrorBoundaryFallbackProps {
13
+ error: Error;
14
+ useRetry?: boolean;
15
+ resetErrorBoundary: () => void;
16
+ onReportProblem?: (error?: Error) => void;
17
+ }
18
+ export declare function ErrorBoundaryFallback({ error, resetErrorBoundary, useRetry, onReportProblem, }: ErrorBoundaryFallbackProps): JSX.Element;
9
19
  export {};
@@ -4,13 +4,21 @@ import cn from 'bem-cn-lite';
4
4
  import { Button, Disclosure } from '@gravity-ui/uikit';
5
5
  import { registerError } from '../../utils/registerError';
6
6
  import { Illustration } from '../Illustration';
7
+ import { useComponent } from '../ComponentsProvider/ComponentsProvider';
7
8
  import i18n from './i18n';
8
9
  import './ErrorBoundary.scss';
9
10
  const b = cn('ydb-error-boundary');
10
- export const ErrorBoundary = ({ children, useRetry = true, onReportProblem }) => {
11
+ export function ErrorBoundary({ children }) {
12
+ const ErrorBoundaryComponent = useComponent('ErrorBoundary');
13
+ return _jsx(ErrorBoundaryComponent, { children: children });
14
+ }
15
+ export function ErrorBoundaryInner({ children, useRetry = true, onReportProblem, }) {
11
16
  return (_jsx(ErrorBoundaryBase, Object.assign({ onError: (error, info) => {
12
17
  registerError(error, info.componentStack, 'error-boundary');
13
18
  }, fallbackRender: ({ error, resetErrorBoundary }) => {
14
- return (_jsxs("div", Object.assign({ className: b(null) }, { children: [_jsx(Illustration, { name: "error", className: b('illustration') }), _jsxs("div", Object.assign({ className: b('content') }, { children: [_jsx("h2", Object.assign({ className: b('error-title') }, { children: i18n('error-title') })), _jsx("div", Object.assign({ className: b('error-description') }, { children: i18n('error-description') })), _jsx(Disclosure, Object.assign({ summary: i18n('show-details'), className: b('show-details'), size: "m" }, { children: _jsx("pre", Object.assign({ className: b('error-details') }, { children: error.stack })) })), _jsxs("div", Object.assign({ className: b('actions') }, { children: [useRetry && (_jsx(Button, Object.assign({ view: "outlined", onClick: resetErrorBoundary }, { children: i18n('button-reset') }))), onReportProblem && (_jsx(Button, Object.assign({ view: "outlined", onClick: () => onReportProblem(error) }, { children: i18n('report-problem') })))] }))] }))] })));
19
+ return (_jsx(ErrorBoundaryFallback, { error: error, useRetry: useRetry, resetErrorBoundary: resetErrorBoundary, onReportProblem: onReportProblem }));
15
20
  } }, { children: children })));
16
- };
21
+ }
22
+ export function ErrorBoundaryFallback({ error, resetErrorBoundary, useRetry, onReportProblem, }) {
23
+ return (_jsxs("div", Object.assign({ className: b() }, { children: [_jsx(Illustration, { name: "error", className: b('illustration') }), _jsxs("div", Object.assign({ className: b('content') }, { children: [_jsx("h2", Object.assign({ className: b('error-title') }, { children: i18n('error-title') })), _jsx("div", Object.assign({ className: b('error-description') }, { children: i18n('error-description') })), _jsx(Disclosure, Object.assign({ summary: i18n('show-details'), className: b('show-details'), size: "m" }, { children: _jsx("pre", Object.assign({ className: b('error-details') }, { children: error.stack })) })), _jsxs("div", Object.assign({ className: b('actions') }, { children: [useRetry && (_jsx(Button, Object.assign({ view: "outlined", onClick: resetErrorBoundary }, { children: i18n('button-reset') }))), onReportProblem && (_jsx(Button, Object.assign({ view: "outlined", onClick: () => onReportProblem(error) }, { children: i18n('report-problem') })))] }))] }))] })));
24
+ }
@@ -1,7 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import cn from 'bem-cn-lite';
3
3
  import { LOAD_AVERAGE_TIME_INTERVALS } from '../../utils/constants';
4
- import { calcUptime } from '../../utils/dataFormatters/dataFormatters';
5
4
  import InfoViewer from '../InfoViewer/InfoViewer';
6
5
  import { ProgressViewer } from '../ProgressViewer/ProgressViewer';
7
6
  import { PoolUsage } from '../PoolUsage/PoolUsage';
@@ -18,7 +17,7 @@ export const FullNodeViewer = ({ node, className }) => {
18
17
  if ((_b = node === null || node === void 0 ? void 0 : node.Tenants) === null || _b === void 0 ? void 0 : _b.length) {
19
18
  commonInfo.push({ label: 'Database', value: node.Tenants[0] });
20
19
  }
21
- commonInfo.push({ label: 'Version', value: node === null || node === void 0 ? void 0 : node.Version }, { label: 'Uptime', value: calcUptime(node === null || node === void 0 ? void 0 : node.StartTime) }, { label: 'DC', value: (node === null || node === void 0 ? void 0 : node.DataCenterDescription) || (node === null || node === void 0 ? void 0 : node.DC) }, { label: 'Rack', value: node === null || node === void 0 ? void 0 : node.Rack });
20
+ commonInfo.push({ label: 'Version', value: node === null || node === void 0 ? void 0 : node.Version }, { label: 'Uptime', value: node === null || node === void 0 ? void 0 : node.Uptime }, { label: 'DC', value: (node === null || node === void 0 ? void 0 : node.DataCenterDescription) || (node === null || node === void 0 ? void 0 : node.DC) }, { label: 'Rack', value: node === null || node === void 0 ? void 0 : node.Rack });
22
21
  const averageInfo = (_c = node === null || node === void 0 ? void 0 : node.LoadAverage) === null || _c === void 0 ? void 0 : _c.map((load, loadIndex) => ({
23
22
  label: LOAD_AVERAGE_TIME_INTERVALS[loadIndex],
24
23
  value: (_jsx(ProgressViewer, { value: load, percents: true, colorizeProgress: true, capacity: 100 })),
@@ -10,6 +10,9 @@
10
10
  @include flex-container();
11
11
 
12
12
  &__header {
13
+ position: sticky;
14
+ left: 0;
15
+
13
16
  padding: 20px 0;
14
17
  }
15
18
 
@@ -0,0 +1,6 @@
1
+ import { ReactNode } from 'react';
2
+ export interface ClusterModeGuardProps {
3
+ children: ReactNode;
4
+ mode: 'single' | 'multi';
5
+ }
6
+ export declare function ClusterModeGuard({ children, mode }: ClusterModeGuardProps): JSX.Element | null;
@@ -0,0 +1,6 @@
1
+ import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
2
+ import { useTypedSelector } from '../../lib';
3
+ export function ClusterModeGuard({ children, mode }) {
4
+ const shouldRender = useTypedSelector((state) => mode === 'single' ? state.singleClusterMode : !state.singleClusterMode);
5
+ return shouldRender ? _jsx(_Fragment, { children: children }) : null;
6
+ }
@@ -0,0 +1 @@
1
+ export * from './ClusterModeGuard';
@@ -0,0 +1 @@
1
+ export * from './ClusterModeGuard';
@@ -17,6 +17,7 @@ import { Preview } from '../Preview/Preview';
17
17
  import { ExecuteResult } from '../ExecuteResult/ExecuteResult';
18
18
  import { ExplainResult } from '../ExplainResult/ExplainResult';
19
19
  import { QueryEditorControls } from '../QueryEditorControls/QueryEditorControls';
20
+ import i18n from '../i18n';
20
21
  import './QueryEditor.scss';
21
22
  const EDITOR_OPTIONS = {
22
23
  automaticLayout: true,
@@ -196,7 +197,7 @@ function QueryEditor(props) {
196
197
  editor.focus();
197
198
  editor.addAction({
198
199
  id: 'sendQuery',
199
- label: 'Send query',
200
+ label: i18n('action.send-query'),
200
201
  keybindings: [
201
202
  // eslint-disable-next-line no-bitwise
202
203
  monaco.KeyMod.CtrlCmd | monaco.KeyCode.Enter,
@@ -220,7 +221,7 @@ function QueryEditor(props) {
220
221
  });
221
222
  editor.addAction({
222
223
  id: 'sendSelectedQuery',
223
- label: 'Send selected query',
224
+ label: i18n('action.send-selected-query'),
224
225
  keybindings: [
225
226
  // eslint-disable-next-line no-bitwise
226
227
  monaco.KeyMod.CtrlCmd | monaco.KeyMod.Shift | monaco.KeyCode.Enter,
@@ -232,7 +233,7 @@ function QueryEditor(props) {
232
233
  });
233
234
  editor.addAction({
234
235
  id: 'previous-query',
235
- label: 'Previous query',
236
+ label: i18n('action.previous-query'),
236
237
  keybindings: [
237
238
  // eslint-disable-next-line no-bitwise
238
239
  monaco.KeyMod.CtrlCmd | monaco.KeyCode.UpArrow,
@@ -245,7 +246,7 @@ function QueryEditor(props) {
245
246
  });
246
247
  editor.addAction({
247
248
  id: 'next-query',
248
- label: 'Next query',
249
+ label: i18n('action.next-query'),
249
250
  keybindings: [
250
251
  // eslint-disable-next-line no-bitwise
251
252
  monaco.KeyMod.CtrlCmd | monaco.KeyCode.DownArrow,
@@ -17,5 +17,9 @@
17
17
  "method-description.data": "DML queries for changing and fetching data in serialization mode.\nAPI call: table.executeDataQuery",
18
18
  "method-description.query": "Any query. An experimental API call supposed to replace all existing methods.\nAPI Call: query.ExecuteScript",
19
19
  "method-description.pg": "Queries in postgresql syntax.\nAPI call: query.ExecuteScript",
20
- "query-duration.description": "Duration of server-side query execution"
20
+ "query-duration.description": "Duration of server-side query execution",
21
+ "action.send-query": "Send query",
22
+ "action.send-selected-query": "Send selected query",
23
+ "action.previous-query": "Previous query in history",
24
+ "action.next-query": "Next query in history"
21
25
  }
@@ -1,2 +1,2 @@
1
- declare const _default: (key: string, params?: import("@gravity-ui/i18n").Params | undefined) => string;
1
+ declare const _default: (key: "controls.query-mode-selector_type" | "tabs.newQuery" | "tabs.history" | "tabs.saved" | "history.empty" | "saved.empty" | "delete-dialog.header" | "delete-dialog.question" | "delete-dialog.delete" | "delete-dialog.cancel" | "preview.title" | "preview.not-available" | "preview.close" | "method-description.script" | "method-description.scan" | "method-description.data" | "method-description.query" | "method-description.pg" | "query-duration.description" | "action.send-query" | "action.send-selected-query" | "action.previous-query" | "action.next-query", params?: import("@gravity-ui/i18n").Params | undefined) => string;
2
2
  export default _default;
@@ -1,7 +1,4 @@
1
- import { i18n, Lang } from '../../../../utils/i18n';
1
+ import { registerKeysets } from '../../../../utils/i18n';
2
2
  import en from './en.json';
3
- import ru from './ru.json';
4
3
  const COMPONENT = 'ydb-query-editor';
5
- i18n.registerKeyset(Lang.En, COMPONENT, en);
6
- i18n.registerKeyset(Lang.Ru, COMPONENT, ru);
7
- export default i18n.keyset(COMPONENT);
4
+ export default registerKeysets(COMPONENT, { en });
@@ -3,6 +3,7 @@ export declare type SettingsElementType = 'switch' | 'radio';
3
3
  export interface SettingProps {
4
4
  type?: SettingsElementType;
5
5
  title: string;
6
+ description?: ReactNode;
6
7
  settingKey: string;
7
8
  helpPopoverContent?: ReactNode;
8
9
  options?: {
@@ -12,4 +13,4 @@ export interface SettingProps {
12
13
  defaultValue?: unknown;
13
14
  onValueUpdate?: VoidFunction;
14
15
  }
15
- export declare const Setting: ({ type, settingKey, title, helpPopoverContent, options, defaultValue, onValueUpdate, }: SettingProps) => JSX.Element;
16
+ export declare const Setting: ({ type, settingKey, title, description, helpPopoverContent, options, defaultValue, onValueUpdate, }: SettingProps) => JSX.Element;
@@ -4,7 +4,7 @@ import { Settings } from '@gravity-ui/navigation';
4
4
  import { LabelWithPopover } from '../../components/LabelWithPopover/LabelWithPopover';
5
5
  import { useSetting } from '../../utils/hooks';
6
6
  import { b } from './UserSettings';
7
- export const Setting = ({ type = 'switch', settingKey, title, helpPopoverContent, options, defaultValue, onValueUpdate, }) => {
7
+ export const Setting = ({ type = 'switch', settingKey, title, description, helpPopoverContent, options, defaultValue, onValueUpdate, }) => {
8
8
  const [settingValue, setValue] = useSetting(settingKey, defaultValue);
9
9
  const onUpdate = (value) => {
10
10
  setValue(value);
@@ -33,5 +33,5 @@ export const Setting = ({ type = 'switch', settingKey, title, helpPopoverContent
33
33
  return null;
34
34
  }
35
35
  };
36
- return (_jsx(Settings.Item, Object.assign({ title: title, highlightedTitle: title, renderTitleComponent: renderTitleComponent }, { children: getSettingsElement(type) })));
36
+ return (_jsx(Settings.Item, Object.assign({ title: title, highlightedTitle: title, description: description, renderTitleComponent: renderTitleComponent }, { children: getSettingsElement(type) })));
37
37
  };
@@ -10,6 +10,8 @@
10
10
  "settings.language.title": "Interface language",
11
11
  "settings.language.option-russian": "Russian",
12
12
  "settings.language.option-english": "English",
13
+ "settings.binaryDataInPlainTextDisplay.title": "Display binary data in plain text",
14
+ "settings.binaryDataInPlainTextDisplay.description": "Available starting from version 24.1",
13
15
  "settings.invertedDisks.title": "Inverted disks space indicators",
14
16
  "settings.useNodesEndpoint.title": "Break the Nodes tab in Diagnostics",
15
17
  "settings.useNodesEndpoint.popover": "Use /viewer/json/nodes endpoint for Nodes Tab in diagnostics. It could return incorrect data on some versions",
@@ -1,2 +1,2 @@
1
- declare const _default: (key: string, params?: import("@gravity-ui/i18n").Params | undefined) => string;
1
+ declare const _default: (key: "page.general" | "section.appearance" | "page.experiments" | "section.experiments" | "settings.theme.title" | "settings.theme.option-dark" | "settings.theme.option-light" | "settings.theme.option-system" | "settings.language.title" | "settings.language.option-russian" | "settings.language.option-english" | "settings.binaryDataInPlainTextDisplay.title" | "settings.binaryDataInPlainTextDisplay.description" | "settings.invertedDisks.title" | "settings.useNodesEndpoint.title" | "settings.useNodesEndpoint.popover" | "settings.useVirtualTables.title" | "settings.useVirtualTables.popover" | "settings.queryUseMultiSchema.title" | "settings.queryUseMultiSchema.popover", params?: import("@gravity-ui/i18n").Params | undefined) => string;
2
2
  export default _default;
@@ -1,7 +1,3 @@
1
- import { i18n, Lang } from '../../../utils/i18n';
1
+ import { registerKeysets } from '../../../utils/i18n';
2
2
  import en from './en.json';
3
- import ru from './ru.json';
4
- const COMPONENT = 'ydb-user-settings';
5
- i18n.registerKeyset(Lang.En, COMPONENT, en);
6
- i18n.registerKeyset(Lang.Ru, COMPONENT, ru);
7
- export default i18n.keyset(COMPONENT);
3
+ export default registerKeysets('ydb-user-settings', { en });
@@ -14,6 +14,7 @@ export interface SettingsPage {
14
14
  export declare type YDBEmbeddedUISettings = SettingsPage[];
15
15
  export declare const themeSetting: SettingProps;
16
16
  export declare const languageSetting: SettingProps;
17
+ export declare const binaryDataInPlainTextDisplay: SettingProps;
17
18
  export declare const invertedDisksSetting: SettingProps;
18
19
  export declare const useNodesEndpointSetting: SettingProps;
19
20
  export declare const useVirtualTables: SettingProps;
@@ -1,8 +1,10 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
1
2
  import favoriteFilledIcon from '../../assets/icons/star.svg';
2
3
  import flaskIcon from '../../assets/icons/flask.svg';
3
- import { INVERTED_DISKS_KEY, LANGUAGE_KEY, THEME_KEY, USE_BACKEND_PARAMS_FOR_TABLES_KEY, USE_NODES_ENDPOINT_IN_DIAGNOSTICS_KEY, QUERY_USE_MULTI_SCHEMA_KEY, } from '../../utils/constants';
4
+ import { INVERTED_DISKS_KEY, LANGUAGE_KEY, THEME_KEY, USE_BACKEND_PARAMS_FOR_TABLES_KEY, USE_NODES_ENDPOINT_IN_DIAGNOSTICS_KEY, QUERY_USE_MULTI_SCHEMA_KEY, BINARY_DATA_IN_PLAIN_TEXT_DISPLAY, } from '../../utils/constants';
4
5
  import { Lang, defaultLang } from '../../utils/i18n';
5
6
  import i18n from './i18n';
7
+ import { ClusterModeGuard } from '../ClusterModeGuard';
6
8
  const themeOptions = [
7
9
  {
8
10
  value: 'system',
@@ -43,6 +45,11 @@ export const languageSetting = {
43
45
  window.location.reload();
44
46
  },
45
47
  };
48
+ export const binaryDataInPlainTextDisplay = {
49
+ settingKey: BINARY_DATA_IN_PLAIN_TEXT_DISPLAY,
50
+ title: i18n('settings.binaryDataInPlainTextDisplay.title'),
51
+ description: (_jsx(ClusterModeGuard, Object.assign({ mode: "multi" }, { children: i18n('settings.binaryDataInPlainTextDisplay.description') }))),
52
+ };
46
53
  export const invertedDisksSetting = {
47
54
  settingKey: INVERTED_DISKS_KEY,
48
55
  title: i18n('settings.invertedDisks.title'),
@@ -65,7 +72,7 @@ export const queryUseMultiSchemaSetting = {
65
72
  export const appearanceSection = {
66
73
  id: 'appearanceSection',
67
74
  title: i18n('section.appearance'),
68
- settings: [themeSetting, invertedDisksSetting],
75
+ settings: [themeSetting, invertedDisksSetting, binaryDataInPlainTextDisplay],
69
76
  };
70
77
  export const experimentsSection = {
71
78
  id: 'experimentsSection',
package/dist/lib.d.ts CHANGED
@@ -1,7 +1,8 @@
1
1
  export { App as SingleClusterApp, AppSlots } from './containers/App';
2
2
  export { AppWithClusters as MultiClusterApp } from './containers/AppWithClusters/AppWithClusters';
3
- export { ErrorBoundary } from './components/ErrorBoundary/ErrorBoundary';
3
+ export { ErrorBoundaryInner as ErrorBoundary, ErrorBoundaryFallback, } from './components/ErrorBoundary/ErrorBoundary';
4
4
  export { configureStore, rootReducer } from './store';
5
+ export { default as appRoutes } from './routes';
5
6
  export { createApi, YdbEmbeddedAPI, YdbWebVersionAPI } from './services/api';
6
7
  export { settingsManager } from './services/settings';
7
8
  export { settings as userSettings } from './containers/UserSettings/settings';
package/dist/lib.js CHANGED
@@ -1,7 +1,8 @@
1
1
  export { App as SingleClusterApp, AppSlots } from './containers/App';
2
2
  export { AppWithClusters as MultiClusterApp } from './containers/AppWithClusters/AppWithClusters';
3
- export { ErrorBoundary } from './components/ErrorBoundary/ErrorBoundary';
3
+ export { ErrorBoundaryInner as ErrorBoundary, ErrorBoundaryFallback, } from './components/ErrorBoundary/ErrorBoundary';
4
4
  export { configureStore, rootReducer } from './store';
5
+ export { default as appRoutes } from './routes';
5
6
  export { createApi, YdbEmbeddedAPI, YdbWebVersionAPI } from './services/api';
6
7
  export { settingsManager } from './services/settings';
7
8
  export { settings as userSettings } from './containers/UserSettings/settings';
@@ -12,8 +12,10 @@ var __rest = (this && this.__rest) || function (s, e) {
12
12
  import AxiosWrapper from '@gravity-ui/axios-wrapper';
13
13
  import { backend as BACKEND, metaBackend as META_BACKEND } from '../store';
14
14
  import { prepareSortValue } from '../utils/filters';
15
+ import { BINARY_DATA_IN_PLAIN_TEXT_DISPLAY } from '../utils/constants';
15
16
  import { parseMetaCluster } from './parsers/parseMetaCluster';
16
17
  import { parseMetaTenants } from './parsers/parseMetaTenants';
18
+ import { settingsManager } from './settings';
17
19
  export class YdbEmbeddedAPI extends AxiosWrapper {
18
20
  getPath(path) {
19
21
  return `${BACKEND !== null && BACKEND !== void 0 ? BACKEND : ''}${path}`;
@@ -179,7 +181,12 @@ export class YdbEmbeddedAPI extends AxiosWrapper {
179
181
  // Time difference to ensure that timeout from ui will be shown rather than backend error
180
182
  const uiTimeout = 9 * 60 * 1000;
181
183
  const backendTimeout = 10 * 60 * 1000;
182
- return this.post(this.getPath(`/viewer/json/query?timeout=${backendTimeout}${schema ? `&schema=${schema}` : ''}`), params, {}, {
184
+ /**
185
+ * Return strings using base64 encoding.
186
+ * @link https://github.com/ydb-platform/ydb/pull/647
187
+ */
188
+ const base64 = !settingsManager.readUserSettingsValue(BINARY_DATA_IN_PLAIN_TEXT_DISPLAY, true);
189
+ return this.post(this.getPath(`/viewer/json/query?timeout=${backendTimeout}&base64=${base64}${schema ? `&schema=${schema}` : ''}`), params, {}, {
183
190
  concurrentId,
184
191
  timeout: uiTimeout,
185
192
  });
@@ -1,5 +1,5 @@
1
1
  import { TENANT_PAGES_IDS } from '../store/reducers/tenant/constants';
2
- import { ASIDE_HEADER_COMPACT_KEY, INVERTED_DISKS_KEY, LANGUAGE_KEY, LAST_USED_QUERY_ACTION_KEY, PARTITIONS_HIDDEN_COLUMNS_KEY, QUERY_INITIAL_MODE_KEY, QUERY_USE_MULTI_SCHEMA_KEY, SAVED_QUERIES_KEY, TENANT_INITIAL_PAGE_KEY, THEME_KEY, USE_BACKEND_PARAMS_FOR_TABLES_KEY, USE_NODES_ENDPOINT_IN_DIAGNOSTICS_KEY, USE_CLUSTER_BALANCER_AS_BACKEND_KEY, } from '../utils/constants';
2
+ import { ASIDE_HEADER_COMPACT_KEY, INVERTED_DISKS_KEY, LANGUAGE_KEY, LAST_USED_QUERY_ACTION_KEY, PARTITIONS_HIDDEN_COLUMNS_KEY, QUERY_INITIAL_MODE_KEY, QUERY_USE_MULTI_SCHEMA_KEY, SAVED_QUERIES_KEY, TENANT_INITIAL_PAGE_KEY, THEME_KEY, USE_BACKEND_PARAMS_FOR_TABLES_KEY, USE_NODES_ENDPOINT_IN_DIAGNOSTICS_KEY, USE_CLUSTER_BALANCER_AS_BACKEND_KEY, BINARY_DATA_IN_PLAIN_TEXT_DISPLAY, } from '../utils/constants';
3
3
  import { QUERY_ACTIONS, QUERY_MODES } from '../utils/query';
4
4
  import { parseJson } from '../utils/utils';
5
5
  /** User settings keys and their default values */
@@ -9,6 +9,7 @@ export const DEFAULT_USER_SETTINGS = {
9
9
  [INVERTED_DISKS_KEY]: false,
10
10
  [USE_NODES_ENDPOINT_IN_DIAGNOSTICS_KEY]: false,
11
11
  [QUERY_USE_MULTI_SCHEMA_KEY]: false,
12
+ [BINARY_DATA_IN_PLAIN_TEXT_DISPLAY]: true,
12
13
  [SAVED_QUERIES_KEY]: [],
13
14
  [TENANT_INITIAL_PAGE_KEY]: TENANT_PAGES_IDS.query,
14
15
  [QUERY_INITIAL_MODE_KEY]: QUERY_MODES.script,
@@ -1,8 +1,8 @@
1
1
  import type { IResponseError } from '../../../types/api/error';
2
- import type { TSystemStateInfo } from '../../../types/api/nodes';
3
2
  import type { TPDiskStateInfo } from '../../../types/api/pdisk';
4
3
  import type { TStorageInfo } from '../../../types/api/storage';
5
4
  import type { TVDiskStateInfo } from '../../../types/api/vdisk';
5
+ import type { PreparedNodeSystemState } from '../../../utils/nodes';
6
6
  import type { ApiRequestAction } from '../../utils';
7
7
  import { FETCH_NODE, FETCH_NODE_STRUCTURE, resetNode } from './node';
8
8
  interface RawStructurePDisk extends TPDiskStateInfo {
@@ -17,9 +17,7 @@ export interface PreparedStructurePDisk extends TPDiskStateInfo {
17
17
  vDisks: PreparedStructureVDisk[];
18
18
  }
19
19
  export declare type PreparedNodeStructure = Record<string, PreparedStructurePDisk>;
20
- export interface PreparedNode extends TSystemStateInfo {
21
- DC?: string;
22
- Rack?: string;
20
+ export interface PreparedNode extends Partial<PreparedNodeSystemState> {
23
21
  }
24
22
  export interface NodeState {
25
23
  data: PreparedNode;
@@ -1,8 +1,9 @@
1
+ import { prepareNodeSystemState } from '../../../utils/nodes';
1
2
  export const prepareNodeData = (data) => {
2
- var _a, _b, _c;
3
+ var _a;
3
4
  if (!((_a = data.SystemStateInfo) === null || _a === void 0 ? void 0 : _a.length)) {
4
5
  return {};
5
6
  }
6
7
  const nodeData = data.SystemStateInfo[0];
7
- return Object.assign(Object.assign({}, nodeData), { DC: (_b = nodeData.Location) === null || _b === void 0 ? void 0 : _b.DataCenter, Rack: (_c = nodeData.Location) === null || _c === void 0 ? void 0 : _c.Rack });
8
+ return prepareNodeSystemState(nodeData);
8
9
  };
@@ -1,5 +1,6 @@
1
1
  import { calcUptime } from '../../../utils/dataFormatters/dataFormatters';
2
2
  import { generateEvaluator } from '../../../utils/generateEvaluator';
3
+ import { prepareNodeSystemState } from '../../../utils/nodes';
3
4
  const prepareComputeNode = (node, tenantName) => {
4
5
  var _a;
5
6
  return Object.assign(Object.assign({}, node), {
@@ -36,10 +37,10 @@ export const prepareComputeNodesData = (data) => {
36
37
  export const prepareNodesData = (data) => {
37
38
  const rawNodes = data.Nodes || [];
38
39
  const preparedNodes = rawNodes.map((node) => {
39
- var _a, _b, _c, _d, _e, _f, _g;
40
+ var _a, _b, _c, _d;
40
41
  // 0 limit means that limit is not set, so it should be undefined
41
42
  const sharedCacheLimit = Number((_a = node.SystemState.SharedCacheStats) === null || _a === void 0 ? void 0 : _a.LimitBytes) || undefined;
42
- return Object.assign(Object.assign({}, node.SystemState), { Tablets: node.Tablets, NodeId: node.NodeId, Uptime: calcUptime((_b = node.SystemState) === null || _b === void 0 ? void 0 : _b.StartTime), TenantName: (_d = (_c = node.SystemState) === null || _c === void 0 ? void 0 : _c.Tenants) === null || _d === void 0 ? void 0 : _d[0], DC: (_e = node.SystemState.Location) === null || _e === void 0 ? void 0 : _e.DataCenter, Rack: (_f = node.SystemState.Location) === null || _f === void 0 ? void 0 : _f.Rack, SharedCacheUsed: (_g = node.SystemState.SharedCacheStats) === null || _g === void 0 ? void 0 : _g.UsedBytes, SharedCacheLimit: sharedCacheLimit });
43
+ return Object.assign(Object.assign({}, prepareNodeSystemState(node.SystemState)), { Tablets: node.Tablets, NodeId: node.NodeId, TenantName: (_c = (_b = node.SystemState) === null || _b === void 0 ? void 0 : _b.Tenants) === null || _c === void 0 ? void 0 : _c[0], SharedCacheUsed: (_d = node.SystemState.SharedCacheStats) === null || _d === void 0 ? void 0 : _d.UsedBytes, SharedCacheLimit: sharedCacheLimit });
43
44
  });
44
45
  return {
45
46
  Nodes: preparedNodes,
@@ -3,7 +3,7 @@ import { TPDiskState } from '../../../types/api/pdisk';
3
3
  import { EFlag } from '../../../types/api/enums';
4
4
  import { getPDiskType } from '../../../utils/pdisk';
5
5
  import { getUsage } from '../../../utils/storage';
6
- import { calcUptime } from '../../../utils/dataFormatters/dataFormatters';
6
+ import { prepareNodeSystemState } from '../../../utils/nodes';
7
7
  // ==== Constants ====
8
8
  const FLAGS_POINTS = {
9
9
  [EFlag.Green]: 1,
@@ -85,24 +85,11 @@ export const prepareStorageGroups = (StorageGroups, StoragePools) => {
85
85
  };
86
86
  // ==== Prepare nodes ====
87
87
  const prepareStorageNodeData = (node) => {
88
- var _a, _b, _c, _d;
89
- const systemState = (_a = node.SystemState) !== null && _a !== void 0 ? _a : {};
90
- const missing = ((_b = node.PDisks) === null || _b === void 0 ? void 0 : _b.filter((pDisk) => {
88
+ var _a;
89
+ const missing = ((_a = node.PDisks) === null || _a === void 0 ? void 0 : _a.filter((pDisk) => {
91
90
  return pDisk.State !== TPDiskState.Normal;
92
91
  }).length) || 0;
93
- return {
94
- NodeId: node.NodeId,
95
- SystemState: systemState.SystemState,
96
- DC: (_c = systemState.Location) === null || _c === void 0 ? void 0 : _c.DataCenter,
97
- Rack: (_d = systemState.Location) === null || _d === void 0 ? void 0 : _d.Rack,
98
- Host: systemState.Host,
99
- Endpoints: systemState.Endpoints,
100
- Uptime: calcUptime(systemState.StartTime),
101
- StartTime: systemState.StartTime,
102
- PDisks: node.PDisks,
103
- VDisks: node.VDisks,
104
- Missing: missing,
105
- };
92
+ return Object.assign(Object.assign({}, prepareNodeSystemState(node.SystemState)), { NodeId: node.NodeId, PDisks: node.PDisks, VDisks: node.VDisks, Missing: missing });
106
93
  };
107
94
  // ==== Prepare responses ====
108
95
  export const prepareStorageNodesResponse = (data) => {
@@ -56,6 +56,7 @@ export declare const SAVED_QUERIES_KEY = "saved_queries";
56
56
  export declare const ASIDE_HEADER_COMPACT_KEY = "asideHeaderCompact";
57
57
  export declare const QUERIES_HISTORY_KEY = "queries_history";
58
58
  export declare const DATA_QA_TUNE_COLUMNS_POPUP = "tune-columns-popup";
59
+ export declare const BINARY_DATA_IN_PLAIN_TEXT_DISPLAY = "binaryDataInPlainTextDisplay";
59
60
  export declare const DEFAULT_SIZE_RESULT_PANE_KEY = "default-size-result-pane";
60
61
  export declare const DEFAULT_SIZE_TENANT_SUMMARY_KEY = "default-size-tenant-summary-pane";
61
62
  export declare const DEFAULT_SIZE_TENANT_KEY = "default-size-tenant-pane";
@@ -72,6 +72,7 @@ export const SAVED_QUERIES_KEY = 'saved_queries';
72
72
  export const ASIDE_HEADER_COMPACT_KEY = 'asideHeaderCompact';
73
73
  export const QUERIES_HISTORY_KEY = 'queries_history';
74
74
  export const DATA_QA_TUNE_COLUMNS_POPUP = 'tune-columns-popup';
75
+ export const BINARY_DATA_IN_PLAIN_TEXT_DISPLAY = 'binaryDataInPlainTextDisplay';
75
76
  export const DEFAULT_SIZE_RESULT_PANE_KEY = 'default-size-result-pane';
76
77
  export const DEFAULT_SIZE_TENANT_SUMMARY_KEY = 'default-size-tenant-summary-pane';
77
78
  export const DEFAULT_SIZE_TENANT_KEY = 'default-size-tenant-pane';
@@ -14,6 +14,12 @@ export declare const NodesUptimeFilterTitles: {
14
14
  };
15
15
  export declare const isUnavailableNode: (node: NodesPreparedEntity | TSystemStateInfo) => boolean;
16
16
  export declare const prepareNodesMap: (nodesList?: TNodeInfo[] | undefined) => NodesMap | undefined;
17
+ export interface PreparedNodeSystemState extends TSystemStateInfo {
18
+ Rack?: string;
19
+ DC?: string;
20
+ Uptime: string;
21
+ }
22
+ export declare const prepareNodeSystemState: (systemState?: TSystemStateInfo) => PreparedNodeSystemState;
17
23
  export declare const getProblemParamValue: (problemFilter: ProblemFilterValue | undefined) => boolean;
18
24
  export declare const getUptimeParamValue: (nodesUptimeFilter: NodesUptimeFilterValues | undefined) => number | undefined;
19
25
  /**
@@ -1,5 +1,6 @@
1
1
  import { ProblemFilterValues } from '../store/reducers/settings/settings';
2
2
  import { EFlag } from '../types/api/enums';
3
+ import { calcUptime } from './dataFormatters/dataFormatters';
3
4
  import { HOUR_IN_SECONDS } from './constants';
4
5
  export var NodesUptimeFilterValues;
5
6
  (function (NodesUptimeFilterValues) {
@@ -19,6 +20,16 @@ export const prepareNodesMap = (nodesList) => {
19
20
  return nodesMap;
20
21
  }, new Map());
21
22
  };
23
+ export const prepareNodeSystemState = (systemState = {}) => {
24
+ var _a, _b;
25
+ // There is no Rack in Location field for din nodes
26
+ const Rack = ((_a = systemState.Location) === null || _a === void 0 ? void 0 : _a.Rack) || systemState.Rack;
27
+ const DC = ((_b = systemState.Location) === null || _b === void 0 ? void 0 : _b.DataCenter) || systemState.DataCenter;
28
+ const Uptime = calcUptime(systemState.StartTime);
29
+ return Object.assign(Object.assign({}, systemState), { Rack,
30
+ DC,
31
+ Uptime });
32
+ };
22
33
  export const getProblemParamValue = (problemFilter) => {
23
34
  return problemFilter === ProblemFilterValues.PROBLEMS;
24
35
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ydb-embedded-ui",
3
- "version": "5.1.0",
3
+ "version": "5.2.1",
4
4
  "files": [
5
5
  "dist"
6
6
  ],
@@ -1,21 +0,0 @@
1
- {
2
- "controls.query-mode-selector_type": "Тип запроса:",
3
- "tabs.newQuery": "Запрос",
4
- "tabs.history": "История",
5
- "tabs.saved": "Сохраненные",
6
- "history.empty": "История пуста",
7
- "saved.empty": "Нет сохраненных запросов",
8
- "delete-dialog.header": "Удалить запрос",
9
- "delete-dialog.question": "Вы уверены что хотите удалить запрос",
10
- "delete-dialog.delete": "Удалить",
11
- "delete-dialog.cancel": "Отменить",
12
- "preview.title": "Предпросмотр",
13
- "preview.not-available": "Предпросмотр недоступен",
14
- "preview.close": "Закрыть предпросмотр",
15
- "method-description.script": "Для скриптов, совмещающих DDL и DML-конструкции.\nAPI call: schema.scripting",
16
- "method-description.scan": "Только читающие запросы, потенциально читающие много данных.\nAPI call: table.ExecuteScan",
17
- "method-description.data": "DML-запросы для изменения и выборки данных в режиме изоляции Serializable.\nAPI call: table.executeDataQuery",
18
- "method-description.query": "Любые запросы. Экспериментальный перспективный метод, который в будущем заменит все остальные.\nAPI call: query.ExecuteScript",
19
- "method-description.pg": "Запросы в синтаксисе postgresql.\nAPI call: query.ExecuteScript",
20
- "query-duration.description": "Время выполнения запроса на стороне сервера"
21
- }
@@ -1,20 +0,0 @@
1
- {
2
- "page.general": "Общие",
3
- "section.appearance": "Внешний вид",
4
- "page.experiments": "Эксперименты",
5
- "section.experiments": "Эксперименты",
6
- "settings.theme.title": "Тема",
7
- "settings.theme.option-dark": "Тёмная",
8
- "settings.theme.option-light": "Светлая",
9
- "settings.theme.option-system": "Системная",
10
- "settings.language.title": "Язык интерфейса",
11
- "settings.language.option-russian": "Русский",
12
- "settings.language.option-english": "English",
13
- "settings.invertedDisks.title": "Инвертированные индикаторы места на дисках",
14
- "settings.useNodesEndpoint.title": "Сломать вкладку Nodes в диагностике",
15
- "settings.useNodesEndpoint.popover": "Использовать эндпоинт /viewer/json/nodes для вкладки Nodes в диагностике. Может возвращать некорректные данные на некоторых версиях",
16
- "settings.useVirtualTables.title": "Использовать таблицу с загрузкой данных по скроллу для вкладок Nodes и Storage",
17
- "settings.useVirtualTables.popover": "Это улучшит производительность, но может работать нестабильно",
18
- "settings.queryUseMultiSchema.title": "Разрешить запросы с несколькими результатами",
19
- "settings.queryUseMultiSchema.popover": "Использовать для запросов схему 'multi', которая позволяет выполнять запросы с несколькими результатами. На версиях 23-3 и старше результат не возвращается вообще"
20
- }