21651: Create CopyResultToClipboard to format cmd for clipboard using callback
authorStephen Smith <stephen@curii.com>
Fri, 5 Apr 2024 23:21:19 +0000 (19:21 -0400)
committerStephen Smith <stephen@curii.com>
Sat, 6 Apr 2024 03:07:57 +0000 (23:07 -0400)
Performs formatting on large text only when clicked

Arvados-DCO-1.1-Signed-off-by: Stephen Smith <stephen@curii.com>

services/workbench2/src/components/copy-to-clipboard/copy-result-to-clipboard.ts [new file with mode: 0644]
services/workbench2/src/views/process-panel/process-cmd-card.tsx

diff --git a/services/workbench2/src/components/copy-to-clipboard/copy-result-to-clipboard.ts b/services/workbench2/src/components/copy-to-clipboard/copy-result-to-clipboard.ts
new file mode 100644 (file)
index 0000000..129002b
--- /dev/null
@@ -0,0 +1,63 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import React from 'react';
+import { ReactElementLike } from 'prop-types';
+import copy from 'copy-to-clipboard';
+
+interface CopyToClipboardProps {
+  getText: (() => string);
+  children: ReactElementLike;
+  onCopy?(text: string, result: boolean): void;
+  options?: {
+    debug?: boolean;
+    message?: string;
+    format?: string; // MIME type
+  };
+}
+
+export default class CopyResultToClipboard extends React.PureComponent<CopyToClipboardProps> {
+  static defaultProps = {
+    onCopy: undefined,
+    options: undefined
+  };
+
+  onClick = event => {
+    const {
+      getText,
+      onCopy,
+      children,
+      options
+    } = this.props;
+
+    const elem = React.Children.only(children);
+
+    const text = getText();
+
+    const result = copy(text, options);
+
+    if (onCopy) {
+      onCopy(text, result);
+    }
+
+    // Bypass onClick if it was present
+    if (elem && elem.props && typeof elem.props.onClick === 'function') {
+      elem.props.onClick(event);
+    }
+  };
+
+
+  render() {
+    const {
+      getText: _getText,
+      onCopy: _onCopy,
+      options: _options,
+      children,
+      ...props
+    } = this.props;
+    const elem = React.Children.only(children);
+
+    return React.cloneElement(elem, {...props, onClick: this.onClick});
+  }
+}
index 488b8d7fb4a740db444478e0cb28ae45ec279ada..6cef09b4a898c73c5b2fa978de657d4dbc5213c3 100644 (file)
@@ -21,7 +21,7 @@ import { MPVPanelProps } from 'components/multi-panel-view/multi-panel-view';
 import { DefaultVirtualCodeSnippet } from 'components/default-code-snippet/default-virtual-code-snippet';
 import { Process } from 'store/processes/process';
 import shellescape from 'shell-escape';
-import CopyToClipboard from 'react-copy-to-clipboard';
+import CopyResultToClipboard from 'components/copy-to-clipboard/copy-result-to-clipboard';
 
 type CssRules = 'card' | 'content' | 'title' | 'header' | 'avatar' | 'iconHeader';
 
@@ -83,6 +83,12 @@ export const ProcessCmdCard = withStyles(styles)(
       return `${indent}${line}${lineBreak}`;
     };
 
+    const formatClipboardText = (command: string[]) => (): string => (
+      command.map((v) =>
+        shellescape([v]) // Escape each arg separately
+      ).join(' ')
+    );
+
     return (
       <Card className={classes.card}>
         <CardHeader
@@ -102,12 +108,12 @@ export const ProcessCmdCard = withStyles(styles)(
               <Grid item>
                 <Tooltip title="Copy link to clipboard" disableFocusListener>
                   <IconButton>
-                    <CopyToClipboard
-                      text={" "}
+                    <CopyResultToClipboard
+                      getText={formatClipboardText(process.containerRequest.command)}
                       onCopy={() => onCopy("Command copied to clipboard")}
                     >
                       <CopyIcon />
-                    </CopyToClipboard>
+                    </CopyResultToClipboard>
                   </IconButton>
                 </Tooltip>
               </Grid>