ydb-embedded-ui 5.1.0 → 5.2.1

Sign up to get free protection for your applications and to get access to all the features.
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
- }