ydb-embedded-ui 4.29.0 → 4.30.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## [4.30.0](https://github.com/ydb-platform/ydb-embedded-ui/compare/v4.29.0...v4.30.0) (2024-01-16)
4
+
5
+
6
+ ### Features
7
+
8
+ * add clipboard button to nodes tree titles ([#648](https://github.com/ydb-platform/ydb-embedded-ui/issues/648)) ([1411651](https://github.com/ydb-platform/ydb-embedded-ui/commit/141165173189be064e9e9314b42aa3eb7fce9c69))
9
+
3
10
  ## [4.29.0](https://github.com/ydb-platform/ydb-embedded-ui/compare/v4.28.0...v4.29.0) (2024-01-12)
4
11
 
5
12
 
package/README.md CHANGED
@@ -2,7 +2,8 @@
2
2
 
3
3
  Local viewer for YDB clusters
4
4
 
5
- [Docs for users](https://ydb.tech/en/docs/maintenance/embedded_monitoring/ydb_monitoring)
5
+ * [Docs for users](https://ydb.tech/en/docs/maintenance/embedded_monitoring/ydb_monitoring)
6
+ * [Project Roadmap](ROADMAP.md)
6
7
 
7
8
  ## Preview
8
9
 
@@ -0,0 +1,52 @@
1
+ import {
2
+ Button,
3
+ ButtonProps,
4
+ ClipboardIcon,
5
+ CopyToClipboard as CopyToClipboardUiKit,
6
+ CopyToClipboardStatus,
7
+ Tooltip,
8
+ } from '@gravity-ui/uikit';
9
+ import cn from 'bem-cn-lite';
10
+
11
+ const b = cn('clipboard-button');
12
+
13
+ interface ClipboardButtonProps extends Pick<ButtonProps, 'disabled' | 'size' | 'title' | 'view'> {
14
+ className?: string;
15
+ text: string;
16
+ }
17
+
18
+ /**
19
+ * An inner component required
20
+ * because `react-copy-to-clipboard` doesn't work with `Tooltip` otherwise.
21
+ */
22
+ function InnerButton({
23
+ className,
24
+ status,
25
+ title,
26
+ ...props
27
+ }: Omit<ClipboardButtonProps, 'text'> & {status: CopyToClipboardStatus}) {
28
+ return (
29
+ <Tooltip
30
+ content={status === CopyToClipboardStatus.Success ? 'Copied!' : title || 'Copy'}
31
+ /**
32
+ * Auto-placement has a bug with text changing.
33
+ * @link https://github.com/ydb-platform/ydb-embedded-ui/pull/648#discussion_r1453530092
34
+ */
35
+ placement="bottom-start"
36
+ >
37
+ <Button {...props} className={b(null, className)}>
38
+ <Button.Icon>
39
+ <ClipboardIcon status={status} size={16} />
40
+ </Button.Icon>
41
+ </Button>
42
+ </Tooltip>
43
+ );
44
+ }
45
+
46
+ export function ClipboardButton({text, ...props}: ClipboardButtonProps) {
47
+ return (
48
+ <CopyToClipboardUiKit text={text} timeout={1000}>
49
+ {(status) => <InnerButton {...props} status={status} />}
50
+ </CopyToClipboardUiKit>
51
+ );
52
+ }
@@ -0,0 +1 @@
1
+ export * from './ClipboardButton';
@@ -1,14 +1,13 @@
1
- import React from 'react';
2
- import PropTypes from 'prop-types';
1
+ import {Icon, Link as UIKitLink} from '@gravity-ui/uikit';
3
2
  import cn from 'bem-cn-lite';
3
+ import PropTypes from 'prop-types';
4
+ import React from 'react';
4
5
  import {Link} from 'react-router-dom';
5
- import {ClipboardButton, Link as UIKitLink, Button, Icon} from '@gravity-ui/uikit';
6
-
7
- import circleInfoIcon from '../../assets/icons/circle-info.svg';
8
6
  import circleExclamationIcon from '../../assets/icons/circle-exclamation.svg';
9
- import triangleExclamationIcon from '../../assets/icons/triangle-exclamation.svg';
7
+ import circleInfoIcon from '../../assets/icons/circle-info.svg';
10
8
  import circleTimesIcon from '../../assets/icons/circle-xmark.svg';
11
-
9
+ import triangleExclamationIcon from '../../assets/icons/triangle-exclamation.svg';
10
+ import {ClipboardButton} from '../ClipboardButton';
12
11
  import './EntityStatus.scss';
13
12
 
14
13
  const icons = {
@@ -121,15 +120,13 @@ class EntityStatus extends React.Component {
121
120
  {this.renderLink()}
122
121
  </span>
123
122
  {hasClipboardButton && (
124
- <Button
125
- component="span"
123
+ <ClipboardButton
124
+ text={name}
126
125
  size="s"
127
126
  className={b('clipboard-button', {
128
127
  visible: this.props.clipboardButtonAlwaysVisible,
129
128
  })}
130
- >
131
- <ClipboardButton text={name} size={16} />
132
- </Button>
129
+ />
133
130
  )}
134
131
  </div>
135
132
  );
@@ -10,25 +10,14 @@
10
10
  @include body-2-typography();
11
11
 
12
12
  &__clipboard-button {
13
- display: none;
14
- justify-content: center;
15
- align-items: center;
13
+ visibility: hidden;
16
14
 
17
15
  margin-left: 8px;
18
16
 
19
17
  color: var(--yc-color-text-secondary);
20
18
 
21
- .yc-button__text {
22
- margin: 0;
23
- }
24
-
25
- .yc-clipboard-button {
26
- width: 24px;
27
- height: 24px;
28
- }
29
-
30
19
  &_visible {
31
- display: inline-flex;
20
+ visibility: visible;
32
21
  }
33
22
  }
34
23
 
@@ -107,21 +107,21 @@ body,
107
107
  border-right: unset;
108
108
  border-left: unset;
109
109
  }
110
-
111
- .yc-clipboard-button {
112
- display: inline-flex;
113
- justify-content: center;
114
- align-items: center;
115
- }
116
110
  }
117
111
 
118
112
  .error {
119
113
  color: var(--g-color-text-danger);
120
114
  }
121
115
 
122
- .data-table__row:hover .entity-status__clipboard-button,
123
- .ydb-virtual-table__row:hover .entity-status__clipboard-button {
124
- display: flex;
116
+ .data-table__row,
117
+ .ydb-virtual-table__row,
118
+ .ydb-tree-view__item {
119
+ &:hover,
120
+ &:focus-within {
121
+ & .clipboard-button {
122
+ visibility: visible;
123
+ }
124
+ }
125
125
  }
126
126
 
127
127
  .g-root .data-table_highlight-rows .data-table__row:hover {
@@ -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
  );
@@ -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>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ydb-embedded-ui",
3
- "version": "4.29.0",
3
+ "version": "4.30.0",
4
4
  "files": [
5
5
  "dist"
6
6
  ],
@@ -46,7 +46,7 @@
46
46
  "sass": "1.32.8",
47
47
  "url": "^0.11.0",
48
48
  "web-vitals": "1.1.2",
49
- "ydb-ui-components": "^3.5.0"
49
+ "ydb-ui-components": "^3.6.0"
50
50
  },
51
51
  "scripts": {
52
52
  "start": "react-app-rewired start",
@@ -1,38 +0,0 @@
1
- import {Button, CopyToClipboard as CopyToClipboardUiKit} from '@gravity-ui/uikit';
2
- import createToast from '../../utils/createToast';
3
- import {Icon} from '../Icon';
4
-
5
- interface CopyToClipboardProps {
6
- text: string;
7
- title?: string;
8
- disabled?: boolean;
9
- toastText?: string;
10
- }
11
-
12
- function CopyToClipboard(props: CopyToClipboardProps) {
13
- return (
14
- <CopyToClipboardUiKit text={props.text} timeout={1000}>
15
- {(state) => {
16
- if (state === 'success') {
17
- createToast({
18
- name: 'Copied',
19
- title: props.toastText ?? 'Data was copied to clipboard successfully',
20
- type: state,
21
- });
22
- }
23
-
24
- return (
25
- <Button
26
- disabled={props.disabled}
27
- title={props.title ?? 'Copy'}
28
- view="flat-secondary"
29
- >
30
- <Icon name="copy" viewBox={'0 0 16 16'} width={16} height={16} />
31
- </Button>
32
- );
33
- }}
34
- </CopyToClipboardUiKit>
35
- );
36
- }
37
-
38
- export default CopyToClipboard;