From 9828c767c310f24aea087aaa9f33a2134f0b1809 Mon Sep 17 00:00:00 2001 From: Stephen Smith Date: Wed, 30 Mar 2022 20:51:27 -0400 Subject: [PATCH] 18559: Add copy to clipboard to rendered UUIDs Arvados-DCO-1.1-Signed-off-by: Stephen Smith --- .../copy-to-clipboard-snackbar.tsx | 58 +++++++++++++++++++ .../data-explorer/renderers.tsx | 15 ++--- .../user-profile-panel-root.tsx | 21 +------ 3 files changed, 69 insertions(+), 25 deletions(-) create mode 100644 src/components/copy-to-clipboard-snackbar/copy-to-clipboard-snackbar.tsx diff --git a/src/components/copy-to-clipboard-snackbar/copy-to-clipboard-snackbar.tsx b/src/components/copy-to-clipboard-snackbar/copy-to-clipboard-snackbar.tsx new file mode 100644 index 00000000..3b2ff68a --- /dev/null +++ b/src/components/copy-to-clipboard-snackbar/copy-to-clipboard-snackbar.tsx @@ -0,0 +1,58 @@ +// Copyright (C) The Arvados Authors. All rights reserved. +// +// SPDX-License-Identifier: AGPL-3.0 + +import React from "react"; +import { connect, DispatchProp } from "react-redux"; +import { StyleRulesCallback, Tooltip, WithStyles, withStyles } from "@material-ui/core"; +import { ArvadosTheme } from 'common/custom-theme'; +import CopyToClipboard from 'react-copy-to-clipboard'; +import { snackbarActions, SnackbarKind } from 'store/snackbar/snackbar-actions'; +import { CopyIcon } from 'components/icon/icon'; + +type CssRules = 'copyIcon'; + +const styles: StyleRulesCallback = (theme: ArvadosTheme) => ({ + copyIcon: { + marginLeft: theme.spacing.unit, + color: theme.palette.grey["500"], + cursor: 'pointer', + display: 'inline', + '& svg': { + fontSize: '1rem', + verticalAlign: 'middle', + } + } +}); + +interface CopyToClipboardDataProps { + children?: React.ReactNode; + value: string; +} + +type CopyToClipboardProps = CopyToClipboardDataProps & WithStyles & DispatchProp; + +export const CopyToClipboardSnackbar = connect()(withStyles(styles)( + class CopyToClipboardSnackbar extends React.Component { + onCopy = () => { + this.props.dispatch(snackbarActions.OPEN_SNACKBAR({ + message: 'Copied', + hideDuration: 2000, + kind: SnackbarKind.SUCCESS + })); + }; + + render() { + const { children, value, classes } = this.props; + return ( + + + + {children || } + + + + ); + } + } +)); diff --git a/src/views-components/data-explorer/renderers.tsx b/src/views-components/data-explorer/renderers.tsx index 51b7dcc8..d1fed3a9 100644 --- a/src/views-components/data-explorer/renderers.tsx +++ b/src/views-components/data-explorer/renderers.tsx @@ -50,6 +50,7 @@ import { PermissionLevel } from 'models/permission'; import { openPermissionEditContextMenu } from 'store/context-menu/context-menu-actions'; import { getUserUuid } from 'common/getuser'; import { VirtualMachinesResource } from 'models/virtual-machines'; +import { CopyToClipboardSnackbar } from 'components/copy-to-clipboard-snackbar/copy-to-clipboard-snackbar'; const renderName = (dispatch: Dispatch, item: GroupContentsResource) => { @@ -192,15 +193,15 @@ export const UserResourceFullName = connect( return {item: resource || { uuid: '', firstName: '', lastName: '' }, link: props.link}; })((props: {item: {uuid: string, firstName: string, lastName: string}, link?: boolean} & DispatchProp) => renderFullName(props.dispatch, props.item, props.link)); - const renderUuid = (item: { uuid: string }) => - {item.uuid}; + + {item.uuid} + + ; -export const ResourceUuid = connect( - (state: RootState, props: { uuid: string }) => { - const resource = getResource(props.uuid)(state.resources); - return resource || { uuid: '' }; - })(renderUuid); +export const ResourceUuid = connect((state: RootState, props: { uuid: string }) => ( + getResource(props.uuid)(state.resources) || { uuid: '' } + ))(renderUuid); const renderEmail = (item: { email: string }) => {item.email}; diff --git a/src/views/user-profile-panel/user-profile-panel-root.tsx b/src/views/user-profile-panel/user-profile-panel-root.tsx index f89ca5c5..6a3adb92 100644 --- a/src/views/user-profile-panel/user-profile-panel-root.tsx +++ b/src/views/user-profile-panel/user-profile-panel-root.tsx @@ -28,14 +28,13 @@ import { DataTableDefaultView } from 'components/data-table-default-view/data-ta import { PROFILE_EMAIL_VALIDATION } from "validators/validators"; import { USER_PROFILE_PANEL_ID } from 'store/user-profile/user-profile-actions'; import { noop } from 'lodash'; -import { CopyIcon, DetailsIcon, GroupsIcon, MoreOptionsIcon } from 'components/icon/icon'; +import { DetailsIcon, GroupsIcon, MoreOptionsIcon } from 'components/icon/icon'; import { DataColumns } from 'components/data-table/data-table'; import { ResourceLinkHeadUuid, ResourceLinkHeadPermissionLevel, ResourceLinkHead, ResourceLinkDelete, ResourceLinkTailIsVisible } from 'views-components/data-explorer/renderers'; import { createTree } from 'models/tree'; import { getResource, ResourcesState } from 'store/resources/resources'; -import { snackbarActions, SnackbarKind } from 'store/snackbar/snackbar-actions'; -import CopyToClipboard from 'react-copy-to-clipboard'; import { DefaultView } from 'components/default-view/default-view'; +import { CopyToClipboardSnackbar } from 'components/copy-to-clipboard-snackbar/copy-to-clipboard-snackbar'; type CssRules = 'root' | 'emptyRoot' | 'gridItem' | 'label' | 'readOnlyValue' | 'title' | 'description' | 'actions' | 'content' | 'copyIcon'; @@ -188,14 +187,6 @@ export const UserProfilePanelRoot = withStyles(styles)( this.setState({ value: TABS.PROFILE}); } - onCopy = (message: string) => { - this.props.dispatch(snackbarActions.OPEN_SNACKBAR({ - message, - hideDuration: 2000, - kind: SnackbarKind.SUCCESS - })); - } - render() { if (this.props.isInaccessible) { return ( @@ -217,13 +208,7 @@ export const UserProfilePanelRoot = withStyles(styles)( {this.props.userUuid} - - - this.onCopy!("Copied")}> - - - - + -- 2.30.2