Skip to content

Commit 1411651

Browse files
authored
feat: add clipboard button to nodes tree titles (#648)
1 parent 0b72bf2 commit 1411651

File tree

12 files changed

+260
-254
lines changed

12 files changed

+260
-254
lines changed

package-lock.json

Lines changed: 128 additions & 129 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
"sass": "1.32.8",
4747
"url": "^0.11.0",
4848
"web-vitals": "1.1.2",
49-
"ydb-ui-components": "^3.5.0"
49+
"ydb-ui-components": "^3.6.0"
5050
},
5151
"scripts": {
5252
"start": "react-app-rewired start",
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './ClipboardButton';

src/components/CopyToClipboard/CopyToClipboard.tsx

Lines changed: 0 additions & 38 deletions
This file was deleted.

src/components/EntityStatus/EntityStatus.js

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -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';
32
import cn from 'bem-cn-lite';
3+
import PropTypes from 'prop-types';
4+
import React from 'react';
45
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';
86
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';
108
import circleTimesIcon from '../../assets/icons/circle-xmark.svg';
11-
9+
import triangleExclamationIcon from '../../assets/icons/triangle-exclamation.svg';
10+
import {ClipboardButton} from '../ClipboardButton';
1211
import './EntityStatus.scss';
1312

1413
const icons = {
@@ -121,15 +120,13 @@ class EntityStatus extends React.Component {
121120
{this.renderLink()}
122121
</span>
123122
{hasClipboardButton && (
124-
<Button
125-
component="span"
123+
<ClipboardButton
124+
text={name}
126125
size="s"
127126
className={b('clipboard-button', {
128127
visible: this.props.clipboardButtonAlwaysVisible,
129128
})}
130-
>
131-
<ClipboardButton text={name} size={16} />
132-
</Button>
129+
/>
133130
)}
134131
</div>
135132
);

src/components/EntityStatus/EntityStatus.scss

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,25 +10,14 @@
1010
@include body-2-typography();
1111

1212
&__clipboard-button {
13-
display: none;
14-
justify-content: center;
15-
align-items: center;
13+
visibility: hidden;
1614

1715
margin-left: 8px;
1816

1917
color: var(--yc-color-text-secondary);
2018

21-
.yc-button__text {
22-
margin: 0;
23-
}
24-
25-
.yc-clipboard-button {
26-
width: 24px;
27-
height: 24px;
28-
}
29-
3019
&_visible {
31-
display: inline-flex;
20+
visibility: visible;
3221
}
3322
}
3423

src/containers/App/App.scss

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -107,21 +107,21 @@ body,
107107
border-right: unset;
108108
border-left: unset;
109109
}
110-
111-
.yc-clipboard-button {
112-
display: inline-flex;
113-
justify-content: center;
114-
align-items: center;
115-
}
116110
}
117111

118112
.error {
119113
color: var(--g-color-text-danger);
120114
}
121115

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+
}
125125
}
126126

127127
.g-root .data-table_highlight-rows .data-table__row:hover {

src/containers/Tenant/ObjectSummary/ObjectSummary.tsx

Lines changed: 24 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -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';
15
import React, {ReactNode, useEffect, useReducer} from 'react';
26
import {useDispatch} from 'react-redux';
37
import {useLocation} from 'react-router';
48
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';
1311
import InfoViewer from '../../../components/InfoViewer/InfoViewer';
1412
import {
1513
CDCStreamOverview,
1614
PersQueueGroupOverview,
1715
} from '../../../components/InfoViewer/schemaOverview';
18-
import {Icon} from '../../../components/Icon';
1916
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';
2126
import {
2227
EPathSubType,
2328
EPathType,
2429
TColumnDescription,
2530
TColumnTableDescription,
2631
} from '../../../types/api/schema';
27-
import routes, {createHref} from '../../../routes';
28-
import {formatDateTime} from '../../../utils/dataFormatters/dataFormatters';
29-
import {useTypedSelector} from '../../../utils/hooks';
3032
import {
3133
DEFAULT_IS_TENANT_COMMON_INFO_COLLAPSED,
3234
DEFAULT_SIZE_TENANT_SUMMARY_KEY,
3335
} 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';
4438
import {Acl} from '../Acl/Acl';
45-
import {ExternalTableSummary} from '../Info/ExternalTable/ExternalTable';
39+
import i18n from '../i18n';
4640
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';
4844
import {TenantTabsGroups, TENANT_INFO_TABS, TENANT_SCHEMA_TAB} from '../TenantPages';
4945
import {
5046
PaneVisibilityActionTypes,
51-
paneVisibilityToggleReducerCreator,
5247
PaneVisibilityToggleButtons,
48+
paneVisibilityToggleReducerCreator,
5349
} from '../utils/paneVisibilityToggleHelpers';
5450
import {isColumnEntityType, isExternalTable, isIndexTable, isTableType} from '../utils/schema';
55-
56-
import i18n from '../i18n';
57-
5851
import './ObjectSummary.scss';
5952

6053
const b = cn('object-summary');
@@ -306,8 +299,9 @@ export function ObjectSummary({
306299
</Button>
307300
)}
308301
{currentSchemaPath && (
309-
<CopyToClipboard
302+
<ClipboardButton
310303
text={currentSchemaPath}
304+
view="flat-secondary"
311305
title={i18n('summary.copySchemaPath')}
312306
/>
313307
)}

src/containers/Tenant/Query/ExecuteResult/ExecuteResult.tsx

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -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';
32
import cn from 'bem-cn-lite';
3+
import React, {useEffect, useState} from 'react';
44
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';
97
import Divider from '../../../../components/Divider/Divider';
108
import EnableFullscreenButton from '../../../../components/EnableFullscreenButton/EnableFullscreenButton';
119
import Fullscreen from '../../../../components/Fullscreen/Fullscreen';
1210
import {QueryExecutionStatus} from '../../../../components/QueryExecutionStatus';
1311
import {QueryResultTable} from '../../../../components/QueryResultTable/QueryResultTable';
14-
12+
import {disableFullscreen} from '../../../../store/reducers/fullscreen';
13+
import type {ColumnType, KeyValueRow} from '../../../../types/api/query';
1514
import type {ValueOf} from '../../../../types/common';
1615
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';
2116
import {getArray} from '../../../../utils';
22-
17+
import {useTypedSelector} from '../../../../utils/hooks';
18+
import {prepareQueryError} from '../../../../utils/query';
2319
import {PaneVisibilityToggleButtons} from '../../utils/paneVisibilityToggleHelpers';
24-
2520
import {ResultIssues} from '../Issues/Issues';
2621
import {QueryDuration} from '../QueryDuration/QueryDuration';
2722
import {getPreparedResult} from '../utils/getPreparedResult';
28-
2923
import './ExecuteResult.scss';
3024

3125
const b = cn('ydb-query-execute-result');
@@ -115,10 +109,10 @@ export function ExecuteResult({
115109

116110
const renderClipboardButton = () => {
117111
return (
118-
<CopyToClipboard
112+
<ClipboardButton
119113
text={textResults}
114+
view="flat-secondary"
120115
title="Copy results"
121-
toastText="Results were copied to clipboard successfully"
122116
disabled={copyDisabled}
123117
/>
124118
);

0 commit comments

Comments
 (0)