ydb-embedded-ui 4.29.0 → 4.31.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/README.md +2 -1
  2. package/dist/components/ClipboardButton/ClipboardButton.tsx +52 -0
  3. package/dist/components/ClipboardButton/index.ts +1 -0
  4. package/dist/components/EntityStatus/EntityStatus.js +9 -12
  5. package/dist/components/EntityStatus/EntityStatus.scss +2 -13
  6. package/dist/components/MetricChart/MetricChart.scss +34 -0
  7. package/dist/components/MetricChart/MetricChart.tsx +198 -0
  8. package/dist/components/MetricChart/convertReponse.ts +32 -0
  9. package/dist/components/MetricChart/getChartData.ts +20 -0
  10. package/dist/components/MetricChart/getDefaultDataFormatter.ts +36 -0
  11. package/dist/components/MetricChart/index.ts +2 -0
  12. package/dist/components/MetricChart/reducer.ts +86 -0
  13. package/dist/components/MetricChart/types.ts +32 -0
  14. package/dist/components/TimeFrameSelector/TimeFrameSelector.scss +5 -0
  15. package/dist/components/TimeFrameSelector/TimeFrameSelector.tsx +33 -0
  16. package/dist/containers/App/App.scss +9 -9
  17. package/dist/containers/App/Content.js +16 -12
  18. package/dist/containers/Tenant/Diagnostics/TenantOverview/DefaultDashboard.tsx +50 -0
  19. package/dist/containers/Tenant/Diagnostics/TenantOverview/MetricsCards/MetricsCards.tsx +13 -4
  20. package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantCpu/CpuDashboard.tsx +18 -0
  21. package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantCpu/TenantCpu.tsx +2 -0
  22. package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantDashboard/TenantDashboard.scss +14 -0
  23. package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantDashboard/TenantDashboard.tsx +71 -0
  24. package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantMemory/MemoryDashboard.tsx +21 -0
  25. package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantMemory/TenantMemory.tsx +7 -1
  26. package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.tsx +2 -1
  27. package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantStorage/StorageDashboard.tsx +21 -0
  28. package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantStorage/TenantStorage.tsx +2 -0
  29. package/dist/containers/Tenant/Diagnostics/TenantOverview/i18n/en.json +7 -1
  30. package/dist/containers/Tenant/Diagnostics/TenantOverview/i18n/ru.json +7 -1
  31. package/dist/containers/Tenant/ObjectSummary/ObjectSummary.tsx +24 -30
  32. package/dist/containers/Tenant/Query/ExecuteResult/ExecuteResult.tsx +10 -16
  33. package/dist/containers/UserSettings/i18n/en.json +4 -1
  34. package/dist/containers/UserSettings/i18n/ru.json +4 -1
  35. package/dist/containers/UserSettings/settings.ts +12 -1
  36. package/dist/containers/Versions/NodesTreeTitle/NodesTreeTitle.scss +15 -0
  37. package/dist/containers/Versions/NodesTreeTitle/NodesTreeTitle.tsx +9 -6
  38. package/dist/services/api.ts +18 -0
  39. package/dist/services/settings.ts +2 -0
  40. package/dist/store/reducers/tenant/tenant.ts +6 -1
  41. package/dist/types/api/render.ts +34 -0
  42. package/dist/utils/cn.ts +3 -0
  43. package/dist/utils/constants.ts +2 -0
  44. package/dist/utils/timeParsers/formatDuration.ts +10 -0
  45. package/dist/utils/timeframes.ts +10 -0
  46. package/dist/utils/versions/getVersionsColors.ts +1 -0
  47. package/package.json +4 -2
  48. package/CHANGELOG.md +0 -1552
  49. package/dist/components/CopyToClipboard/CopyToClipboard.tsx +0 -38
@@ -1,5 +1,7 @@
1
1
  import React from 'react';
2
2
  import {Switch, Route, Redirect, Router, useLocation} from 'react-router-dom';
3
+ import {QueryParamProvider} from 'use-query-params';
4
+ import {ReactRouter5Adapter} from 'use-query-params/adapters/react-router-5';
3
5
  import cn from 'bem-cn-lite';
4
6
  import {connect} from 'react-redux';
5
7
 
@@ -80,18 +82,20 @@ function ContentWrapper(props) {
80
82
  <HistoryContext.Consumer>
81
83
  {(history) => (
82
84
  <Router history={history}>
83
- <Switch>
84
- <Route path={routes.auth}>
85
- <Authentication closable />
86
- </Route>
87
- <Route>
88
- <ThemeProvider theme={theme}>
89
- <div className={b({embedded: singleClusterMode})}>
90
- {isAuthenticated ? props.children : <Authentication />}
91
- </div>
92
- </ThemeProvider>
93
- </Route>
94
- </Switch>
85
+ <QueryParamProvider adapter={ReactRouter5Adapter}>
86
+ <Switch>
87
+ <Route path={routes.auth}>
88
+ <Authentication closable />
89
+ </Route>
90
+ <Route>
91
+ <ThemeProvider theme={theme}>
92
+ <div className={b({embedded: singleClusterMode})}>
93
+ {isAuthenticated ? props.children : <Authentication />}
94
+ </div>
95
+ </ThemeProvider>
96
+ </Route>
97
+ </Switch>
98
+ </QueryParamProvider>
95
99
  </Router>
96
100
  )}
97
101
  </HistoryContext.Consumer>
@@ -0,0 +1,50 @@
1
+ import {type ChartConfig, TenantDashboard} from './TenantDashboard/TenantDashboard';
2
+ import i18n from './i18n';
3
+
4
+ const defaultDashboardConfig: ChartConfig[] = [
5
+ {
6
+ title: i18n('charts.queries-per-second'),
7
+ metrics: [
8
+ {
9
+ target: 'queries.requests',
10
+ title: i18n('charts.queries-per-second'),
11
+ },
12
+ ],
13
+ },
14
+ {
15
+ title: i18n('charts.transaction-latency', {percentile: ''}),
16
+ metrics: [
17
+ {
18
+ target: 'queries.latencies.p50',
19
+ title: i18n('charts.transaction-latency', {
20
+ percentile: 'p50',
21
+ }),
22
+ },
23
+ {
24
+ target: 'queries.latencies.p75',
25
+ title: i18n('charts.transaction-latency', {
26
+ percentile: 'p75',
27
+ }),
28
+ },
29
+ {
30
+ target: 'queries.latencies.p90',
31
+ title: i18n('charts.transaction-latency', {
32
+ percentile: 'p90',
33
+ }),
34
+ },
35
+ {
36
+ target: 'queries.latencies.p99',
37
+ title: i18n('charts.transaction-latency', {
38
+ percentile: 'p99',
39
+ }),
40
+ },
41
+ ],
42
+ options: {
43
+ dataType: 'ms',
44
+ },
45
+ },
46
+ ];
47
+
48
+ export const DefaultDashboard = () => {
49
+ return <TenantDashboard charts={defaultDashboardConfig} />;
50
+ };
@@ -72,22 +72,31 @@ export function MetricsCards({
72
72
 
73
73
  const queryParams = parseQuery(location);
74
74
 
75
+ // Allow tabs untoggle behaviour
76
+ const getTabIfNotActive = (tab: TenantMetricsTab) => {
77
+ if (tab === metricsTab) {
78
+ return '';
79
+ }
80
+
81
+ return tab;
82
+ };
83
+
75
84
  const tabLinks: Record<TenantMetricsTab, string> = {
76
85
  [TENANT_METRICS_TABS_IDS.cpu]: getTenantPath({
77
86
  ...queryParams,
78
- [TenantTabsGroups.metricsTab]: TENANT_METRICS_TABS_IDS.cpu,
87
+ [TenantTabsGroups.metricsTab]: getTabIfNotActive(TENANT_METRICS_TABS_IDS.cpu),
79
88
  }),
80
89
  [TENANT_METRICS_TABS_IDS.storage]: getTenantPath({
81
90
  ...queryParams,
82
- [TenantTabsGroups.metricsTab]: TENANT_METRICS_TABS_IDS.storage,
91
+ [TenantTabsGroups.metricsTab]: getTabIfNotActive(TENANT_METRICS_TABS_IDS.storage),
83
92
  }),
84
93
  [TENANT_METRICS_TABS_IDS.memory]: getTenantPath({
85
94
  ...queryParams,
86
- [TenantTabsGroups.metricsTab]: TENANT_METRICS_TABS_IDS.memory,
95
+ [TenantTabsGroups.metricsTab]: getTabIfNotActive(TENANT_METRICS_TABS_IDS.memory),
87
96
  }),
88
97
  [TENANT_METRICS_TABS_IDS.healthcheck]: getTenantPath({
89
98
  ...queryParams,
90
- [TenantTabsGroups.metricsTab]: TENANT_METRICS_TABS_IDS.healthcheck,
99
+ [TenantTabsGroups.metricsTab]: getTabIfNotActive(TENANT_METRICS_TABS_IDS.healthcheck),
91
100
  }),
92
101
  };
93
102
 
@@ -0,0 +1,18 @@
1
+ import {type ChartConfig, TenantDashboard} from '../TenantDashboard/TenantDashboard';
2
+ import i18n from '../i18n';
3
+
4
+ const cpuDashboardConfig: ChartConfig[] = [
5
+ {
6
+ title: i18n('charts.cpu-usage'),
7
+ metrics: [
8
+ {
9
+ target: 'resources.cpu.usage',
10
+ title: i18n('charts.cpu-usage'),
11
+ },
12
+ ],
13
+ },
14
+ ];
15
+
16
+ export const CpuDashboard = () => {
17
+ return <TenantDashboard charts={cpuDashboardConfig} />;
18
+ };
@@ -1,4 +1,5 @@
1
1
  import type {AdditionalNodesProps} from '../../../../../types/additionalProps';
2
+ import {CpuDashboard} from './CpuDashboard';
2
3
  import {TopNodesByLoad} from './TopNodesByLoad';
3
4
  import {TopNodesByCpu} from './TopNodesByCpu';
4
5
  import {TopShards} from './TopShards';
@@ -12,6 +13,7 @@ interface TenantCpuProps {
12
13
  export function TenantCpu({path, additionalNodesProps}: TenantCpuProps) {
13
14
  return (
14
15
  <>
16
+ <CpuDashboard />
15
17
  <TopNodesByLoad path={path} additionalNodesProps={additionalNodesProps} />
16
18
  <TopNodesByCpu path={path} additionalNodesProps={additionalNodesProps} />
17
19
  <TopShards path={path} />
@@ -0,0 +1,14 @@
1
+ .ydb-tenant-dashboard {
2
+ width: var(--diagnostics-section-table-width);
3
+ margin-bottom: var(--diagnostics-section-margin);
4
+
5
+ &__controls {
6
+ margin-bottom: 10px;
7
+ }
8
+
9
+ &__charts {
10
+ display: flex;
11
+ flex-flow: row wrap;
12
+ gap: 16px;
13
+ }
14
+ }
@@ -0,0 +1,71 @@
1
+ import {StringParam, useQueryParam} from 'use-query-params';
2
+
3
+ import {cn} from '../../../../../utils/cn';
4
+ import type {TimeFrame} from '../../../../../utils/timeframes';
5
+ import {useSetting, useTypedSelector} from '../../../../../utils/hooks';
6
+ import {DISPLAY_CHARTS_IN_DB_DIAGNOSTICS_KEY} from '../../../../../utils/constants';
7
+ import {TimeFrameSelector} from '../../../../../components/TimeFrameSelector/TimeFrameSelector';
8
+ import {
9
+ type ChartOptions,
10
+ MetricChart,
11
+ type MetricDescription,
12
+ } from '../../../../../components/MetricChart';
13
+
14
+ import './TenantDashboard.scss';
15
+
16
+ const CHART_WIDTH = 428;
17
+ const CHART_WIDTH_FULL = 872;
18
+
19
+ const b = cn('ydb-tenant-dashboard');
20
+
21
+ export interface ChartConfig {
22
+ metrics: MetricDescription[];
23
+ title: string;
24
+ options?: ChartOptions;
25
+ }
26
+
27
+ interface TenantDashboardProps {
28
+ charts: ChartConfig[];
29
+ }
30
+
31
+ export const TenantDashboard = ({charts}: TenantDashboardProps) => {
32
+ const [timeFrame = '1h', setTimeframe] = useQueryParam('timeframe', StringParam);
33
+
34
+ const {autorefresh} = useTypedSelector((state) => state.schema);
35
+
36
+ const [chartsEnabled] = useSetting(DISPLAY_CHARTS_IN_DB_DIAGNOSTICS_KEY);
37
+
38
+ if (!chartsEnabled) {
39
+ return null;
40
+ }
41
+
42
+ // If there is only one chart, display it with full width
43
+ const chartWidth = charts.length === 1 ? CHART_WIDTH_FULL : CHART_WIDTH;
44
+ const chartHeight = CHART_WIDTH / 1.5;
45
+
46
+ const renderContent = () => {
47
+ return charts.map((chartConfig) => {
48
+ return (
49
+ <MetricChart
50
+ key={chartConfig.metrics.map(({target}) => target).join('&')}
51
+ title={chartConfig.title}
52
+ metrics={chartConfig.metrics}
53
+ timeFrame={timeFrame as TimeFrame}
54
+ chartOptions={chartConfig.options}
55
+ autorefresh={autorefresh}
56
+ width={chartWidth}
57
+ height={chartHeight}
58
+ />
59
+ );
60
+ });
61
+ };
62
+
63
+ return (
64
+ <div className={b(null)}>
65
+ <div className={b('controls')}>
66
+ <TimeFrameSelector value={timeFrame as TimeFrame} onChange={setTimeframe} />
67
+ </div>
68
+ <div className={b('charts')}>{renderContent()}</div>
69
+ </div>
70
+ );
71
+ };
@@ -0,0 +1,21 @@
1
+ import {type ChartConfig, TenantDashboard} from '../TenantDashboard/TenantDashboard';
2
+ import i18n from '../i18n';
3
+
4
+ const memoryDashboardConfig: ChartConfig[] = [
5
+ {
6
+ title: i18n('charts.memory-usage'),
7
+ metrics: [
8
+ {
9
+ target: 'resources.memory.used_bytes',
10
+ title: i18n('charts.memory-usage'),
11
+ },
12
+ ],
13
+ options: {
14
+ dataType: 'size',
15
+ },
16
+ },
17
+ ];
18
+
19
+ export const MemoryDashboard = () => {
20
+ return <TenantDashboard charts={memoryDashboardConfig} />;
21
+ };
@@ -1,3 +1,4 @@
1
+ import {MemoryDashboard} from './MemoryDashboard';
1
2
  import {TopNodesByMemory} from './TopNodesByMemory';
2
3
 
3
4
  interface TenantMemoryProps {
@@ -5,5 +6,10 @@ interface TenantMemoryProps {
5
6
  }
6
7
 
7
8
  export function TenantMemory({path}: TenantMemoryProps) {
8
- return <TopNodesByMemory path={path} />;
9
+ return (
10
+ <>
11
+ <MemoryDashboard />
12
+ <TopNodesByMemory path={path} />
13
+ </>
14
+ );
9
15
  }
@@ -17,6 +17,7 @@ import {HealthcheckDetails} from './Healthcheck/HealthcheckDetails';
17
17
  import {MetricsCards, type TenantMetrics} from './MetricsCards/MetricsCards';
18
18
  import {TenantStorage} from './TenantStorage/TenantStorage';
19
19
  import {TenantMemory} from './TenantMemory/TenantMemory';
20
+ import {DefaultDashboard} from './DefaultDashboard';
20
21
  import {useHealthcheck} from './useHealthcheck';
21
22
 
22
23
  import './TenantOverview.scss';
@@ -140,7 +141,7 @@ export function TenantOverview({
140
141
  );
141
142
  }
142
143
  default: {
143
- return undefined;
144
+ return <DefaultDashboard />;
144
145
  }
145
146
  }
146
147
  };
@@ -0,0 +1,21 @@
1
+ import {type ChartConfig, TenantDashboard} from '../TenantDashboard/TenantDashboard';
2
+ import i18n from '../i18n';
3
+
4
+ const storageDashboardConfig: ChartConfig[] = [
5
+ {
6
+ title: i18n('charts.storage-usage'),
7
+ metrics: [
8
+ {
9
+ target: 'resources.storage.used_bytes',
10
+ title: i18n('charts.storage-usage'),
11
+ },
12
+ ],
13
+ options: {
14
+ dataType: 'size',
15
+ },
16
+ },
17
+ ];
18
+
19
+ export const StorageDashboard = () => {
20
+ return <TenantDashboard charts={storageDashboardConfig} />;
21
+ };
@@ -7,6 +7,7 @@ import {getSizeWithSignificantDigits} from '../../../../../utils/bytesParsers';
7
7
 
8
8
  import '../TenantOverview.scss';
9
9
 
10
+ import {StorageDashboard} from './StorageDashboard';
10
11
  import {TopTables} from './TopTables';
11
12
  import {TopGroups} from './TopGroups';
12
13
 
@@ -62,6 +63,7 @@ export function TenantStorage({tenantName, metrics}: TenantStorageProps) {
62
63
  ];
63
64
  return (
64
65
  <>
66
+ <StorageDashboard />
65
67
  <InfoViewer className={b('storage-info')} title="Storage details" info={info} />
66
68
  <TopTables path={tenantName} />
67
69
  <TopGroups tenant={tenantName} />
@@ -23,5 +23,11 @@
23
23
  "by-load": "by load",
24
24
  "by-memory": "by memory",
25
25
  "by-usage": "by usage",
26
- "by-size": "by size"
26
+ "by-size": "by size",
27
+
28
+ "charts.queries-per-second": "Queries per second",
29
+ "charts.transaction-latency": "Transactions latencies {{percentile}}",
30
+ "charts.cpu-usage": "CPU usage",
31
+ "charts.storage-usage": "Storage usage",
32
+ "charts.memory-usage": "Memory usage"
27
33
  }
@@ -23,5 +23,11 @@
23
23
  "by-load": "по нагрузке",
24
24
  "by-memory": "по памяти",
25
25
  "by-usage": "по потреблению",
26
- "by-size": "по размеру"
26
+ "by-size": "по размеру",
27
+
28
+ "charts.queries-per-second": "Количество запросов в секунду",
29
+ "charts.transaction-latency": "Задержка транзакций {{percentile}}",
30
+ "charts.cpu-usage": "Использование CPU",
31
+ "charts.storage-usage": "Использование хранилища",
32
+ "charts.memory-usage": "Использование памяти"
27
33
  }
@@ -1,60 +1,53 @@
1
+ import {HelpPopover} from '@gravity-ui/components';
2
+ import {Button, Tabs} from '@gravity-ui/uikit';
3
+ import cn from 'bem-cn-lite';
4
+ import qs from 'qs';
1
5
  import React, {ReactNode, useEffect, useReducer} from 'react';
2
6
  import {useDispatch} from 'react-redux';
3
7
  import {useLocation} from 'react-router';
4
8
  import {Link} from 'react-router-dom';
5
- import qs from 'qs';
6
- import cn from 'bem-cn-lite';
7
-
8
- import {Button, Tabs} from '@gravity-ui/uikit';
9
- import {HelpPopover} from '@gravity-ui/components';
10
-
11
- import SplitPane from '../../../components/SplitPane';
12
- import CopyToClipboard from '../../../components/CopyToClipboard/CopyToClipboard';
9
+ import {ClipboardButton} from '../../../components/ClipboardButton';
10
+ import {Icon} from '../../../components/Icon';
13
11
  import InfoViewer from '../../../components/InfoViewer/InfoViewer';
14
12
  import {
15
13
  CDCStreamOverview,
16
14
  PersQueueGroupOverview,
17
15
  } from '../../../components/InfoViewer/schemaOverview';
18
- import {Icon} from '../../../components/Icon';
19
16
  import {Loader} from '../../../components/Loader';
20
-
17
+ import SplitPane from '../../../components/SplitPane';
18
+ import routes, {createHref} from '../../../routes';
19
+ import {setShowPreview} from '../../../store/reducers/schema/schema';
20
+ import {
21
+ TENANT_PAGES_IDS,
22
+ TENANT_QUERY_TABS_ID,
23
+ TENANT_SUMMARY_TABS_IDS,
24
+ } from '../../../store/reducers/tenant/constants';
25
+ import {setQueryTab, setSummaryTab, setTenantPage} from '../../../store/reducers/tenant/tenant';
21
26
  import {
22
27
  EPathSubType,
23
28
  EPathType,
24
29
  TColumnDescription,
25
30
  TColumnTableDescription,
26
31
  } from '../../../types/api/schema';
27
- import routes, {createHref} from '../../../routes';
28
- import {formatDateTime} from '../../../utils/dataFormatters/dataFormatters';
29
- import {useTypedSelector} from '../../../utils/hooks';
30
32
  import {
31
33
  DEFAULT_IS_TENANT_COMMON_INFO_COLLAPSED,
32
34
  DEFAULT_SIZE_TENANT_SUMMARY_KEY,
33
35
  } from '../../../utils/constants';
34
- import {setShowPreview} from '../../../store/reducers/schema/schema';
35
- import {setQueryTab, setSummaryTab, setTenantPage} from '../../../store/reducers/tenant/tenant';
36
- import {
37
- TENANT_PAGES_IDS,
38
- TENANT_QUERY_TABS_ID,
39
- TENANT_SUMMARY_TABS_IDS,
40
- } from '../../../store/reducers/tenant/constants';
41
-
42
- import {SchemaTree} from '../Schema/SchemaTree/SchemaTree';
43
- import {SchemaViewer} from '../Schema/SchemaViewer/SchemaViewer';
36
+ import {formatDateTime} from '../../../utils/dataFormatters/dataFormatters';
37
+ import {useTypedSelector} from '../../../utils/hooks';
44
38
  import {Acl} from '../Acl/Acl';
45
- import {ExternalTableSummary} from '../Info/ExternalTable/ExternalTable';
39
+ import i18n from '../i18n';
46
40
  import {ExternalDataSourceSummary} from '../Info/ExternalDataSource/ExternalDataSource';
47
-
41
+ import {ExternalTableSummary} from '../Info/ExternalTable/ExternalTable';
42
+ import {SchemaTree} from '../Schema/SchemaTree/SchemaTree';
43
+ import {SchemaViewer} from '../Schema/SchemaViewer/SchemaViewer';
48
44
  import {TenantTabsGroups, TENANT_INFO_TABS, TENANT_SCHEMA_TAB} from '../TenantPages';
49
45
  import {
50
46
  PaneVisibilityActionTypes,
51
- paneVisibilityToggleReducerCreator,
52
47
  PaneVisibilityToggleButtons,
48
+ paneVisibilityToggleReducerCreator,
53
49
  } from '../utils/paneVisibilityToggleHelpers';
54
50
  import {isColumnEntityType, isExternalTable, isIndexTable, isTableType} from '../utils/schema';
55
-
56
- import i18n from '../i18n';
57
-
58
51
  import './ObjectSummary.scss';
59
52
 
60
53
  const b = cn('object-summary');
@@ -306,8 +299,9 @@ export function ObjectSummary({
306
299
  </Button>
307
300
  )}
308
301
  {currentSchemaPath && (
309
- <CopyToClipboard
302
+ <ClipboardButton
310
303
  text={currentSchemaPath}
304
+ view="flat-secondary"
311
305
  title={i18n('summary.copySchemaPath')}
312
306
  />
313
307
  )}
@@ -1,31 +1,25 @@
1
- import React, {useEffect, useState} from 'react';
2
- import {useDispatch} from 'react-redux';
1
+ import {RadioButton, Tabs} from '@gravity-ui/uikit';
3
2
  import cn from 'bem-cn-lite';
3
+ import React, {useEffect, useState} from 'react';
4
4
  import JSONTree from 'react-json-inspector';
5
-
6
- import {RadioButton, Tabs} from '@gravity-ui/uikit';
7
-
8
- import CopyToClipboard from '../../../../components/CopyToClipboard/CopyToClipboard';
5
+ import {useDispatch} from 'react-redux';
6
+ import {ClipboardButton} from '../../../../components/ClipboardButton';
9
7
  import Divider from '../../../../components/Divider/Divider';
10
8
  import EnableFullscreenButton from '../../../../components/EnableFullscreenButton/EnableFullscreenButton';
11
9
  import Fullscreen from '../../../../components/Fullscreen/Fullscreen';
12
10
  import {QueryExecutionStatus} from '../../../../components/QueryExecutionStatus';
13
11
  import {QueryResultTable} from '../../../../components/QueryResultTable/QueryResultTable';
14
-
12
+ import {disableFullscreen} from '../../../../store/reducers/fullscreen';
13
+ import type {ColumnType, KeyValueRow} from '../../../../types/api/query';
15
14
  import type {ValueOf} from '../../../../types/common';
16
15
  import type {IQueryResult, QueryErrorResponse} from '../../../../types/store/query';
17
- import type {ColumnType, KeyValueRow} from '../../../../types/api/query';
18
- import {disableFullscreen} from '../../../../store/reducers/fullscreen';
19
- import {prepareQueryError} from '../../../../utils/query';
20
- import {useTypedSelector} from '../../../../utils/hooks';
21
16
  import {getArray} from '../../../../utils';
22
-
17
+ import {useTypedSelector} from '../../../../utils/hooks';
18
+ import {prepareQueryError} from '../../../../utils/query';
23
19
  import {PaneVisibilityToggleButtons} from '../../utils/paneVisibilityToggleHelpers';
24
-
25
20
  import {ResultIssues} from '../Issues/Issues';
26
21
  import {QueryDuration} from '../QueryDuration/QueryDuration';
27
22
  import {getPreparedResult} from '../utils/getPreparedResult';
28
-
29
23
  import './ExecuteResult.scss';
30
24
 
31
25
  const b = cn('ydb-query-execute-result');
@@ -115,10 +109,10 @@ export function ExecuteResult({
115
109
 
116
110
  const renderClipboardButton = () => {
117
111
  return (
118
- <CopyToClipboard
112
+ <ClipboardButton
119
113
  text={textResults}
114
+ view="flat-secondary"
120
115
  title="Copy results"
121
- toastText="Results were copied to clipboard successfully"
122
116
  disabled={copyDisabled}
123
117
  />
124
118
  );
@@ -23,5 +23,8 @@
23
23
  "settings.useVirtualTables.popover": "It will increase performance, but could work unstable",
24
24
 
25
25
  "settings.queryUseMultiSchema.title": "Allow queries with multiple result sets",
26
- "settings.queryUseMultiSchema.popover": "Use 'multi' schema for queries that enables queries with multiple result sets. Returns nothing on versions 23-3 and older"
26
+ "settings.queryUseMultiSchema.popover": "Use 'multi' schema for queries that enables queries with multiple result sets. Returns nothing on versions 23-3 and older",
27
+
28
+ "settings.displayChartsInDbDiagnostics.title": "Display charts in database diagnostics",
29
+ "settings.displayChartsInDbDiagnostics.popover": "Incorrect data may be displayed (shows data only for the database related to the current node), does not work well on static nodes"
27
30
  }
@@ -23,5 +23,8 @@
23
23
  "settings.useVirtualTables.popover": "Это улучшит производительность, но может работать нестабильно",
24
24
 
25
25
  "settings.queryUseMultiSchema.title": "Разрешить запросы с несколькими результатами",
26
- "settings.queryUseMultiSchema.popover": "Использовать для запросов схему 'multi', которая позволяет выполнять запросы с несколькими результатами. На версиях 23-3 и старше результат не возвращается вообще"
26
+ "settings.queryUseMultiSchema.popover": "Использовать для запросов схему 'multi', которая позволяет выполнять запросы с несколькими результатами. На версиях 23-3 и старше результат не возвращается вообще",
27
+
28
+ "settings.displayChartsInDbDiagnostics.title": "Показывать графики в диагностике базы данных",
29
+ "settings.displayChartsInDbDiagnostics.popover": "Могут отображаться неправильные данные (показывает данные только для базы, относящейся к текущей ноде), плохо работает на статических нодах"
27
30
  }
@@ -10,6 +10,7 @@ import {
10
10
  USE_BACKEND_PARAMS_FOR_TABLES_KEY,
11
11
  USE_NODES_ENDPOINT_IN_DIAGNOSTICS_KEY,
12
12
  QUERY_USE_MULTI_SCHEMA_KEY,
13
+ DISPLAY_CHARTS_IN_DB_DIAGNOSTICS_KEY,
13
14
  } from '../../utils/constants';
14
15
  import {Lang, defaultLang} from '../../utils/i18n';
15
16
 
@@ -94,6 +95,11 @@ export const queryUseMultiSchemaSetting: SettingProps = {
94
95
  title: i18n('settings.queryUseMultiSchema.title'),
95
96
  helpPopoverContent: i18n('settings.queryUseMultiSchema.popover'),
96
97
  };
98
+ export const displayChartsInDbDiagnosticsSetting: SettingProps = {
99
+ settingKey: DISPLAY_CHARTS_IN_DB_DIAGNOSTICS_KEY,
100
+ title: i18n('settings.displayChartsInDbDiagnostics.title'),
101
+ helpPopoverContent: i18n('settings.displayChartsInDbDiagnostics.popover'),
102
+ };
97
103
 
98
104
  export const appearanceSection: SettingsSection = {
99
105
  id: 'appearanceSection',
@@ -103,7 +109,12 @@ export const appearanceSection: SettingsSection = {
103
109
  export const experimentsSection: SettingsSection = {
104
110
  id: 'experimentsSection',
105
111
  title: i18n('section.experiments'),
106
- settings: [useNodesEndpointSetting, useVirtualTables, queryUseMultiSchemaSetting],
112
+ settings: [
113
+ useNodesEndpointSetting,
114
+ useVirtualTables,
115
+ queryUseMultiSchemaSetting,
116
+ displayChartsInDbDiagnosticsSetting,
117
+ ],
107
118
  };
108
119
 
109
120
  export const generalPage: SettingsPage = {
@@ -17,10 +17,12 @@
17
17
  margin-left: 30px;
18
18
  }
19
19
  }
20
+
20
21
  &__overview-container {
21
22
  display: flex;
22
23
  align-items: center;
23
24
  }
25
+
24
26
  &__info-label {
25
27
  font-weight: 200;
26
28
 
@@ -52,4 +54,17 @@
52
54
  width: 200px;
53
55
  }
54
56
  }
57
+
58
+ &__overview-title {
59
+ display: flex;
60
+ align-items: center;
61
+ }
62
+
63
+ &__clipboard-button {
64
+ visibility: hidden;
65
+
66
+ margin-left: 8px;
67
+
68
+ color: var(--yc-color-text-secondary);
69
+ }
55
70
  }
@@ -1,11 +1,9 @@
1
- import block from 'bem-cn-lite';
2
-
3
1
  import {Progress} from '@gravity-ui/uikit';
4
-
5
- import type {VersionValue} from '../../../types/versions';
2
+ import block from 'bem-cn-lite';
3
+ import {ClipboardButton} from '../../../components/ClipboardButton';
6
4
  import type {PreparedClusterNode} from '../../../store/reducers/clusterNodes/types';
5
+ import type {VersionValue} from '../../../types/versions';
7
6
  import type {GroupedNodesItem} from '../types';
8
-
9
7
  import './NodesTreeTitle.scss';
10
8
 
11
9
  const b = block('ydb-versions-nodes-tree-title');
@@ -43,7 +41,12 @@ export const NodesTreeTitle = ({
43
41
  {versionColor ? (
44
42
  <div className={b('version-color')} style={{background: versionColor}} />
45
43
  ) : null}
46
- <span className={b('overview-title')}>{title}</span>
44
+ {title ? (
45
+ <span className={b('overview-title')}>
46
+ {title}
47
+ <ClipboardButton text={title} size="s" className={b('clipboard-button')} />
48
+ </span>
49
+ ) : null}
47
50
  </div>
48
51
  <div className={b('overview-info')}>
49
52
  <div>