Merge branch '21128-toolbar-context-menu'
[arvados-workbench2.git] / src / components / details-attribute / details-attribute.tsx
index 4b8ee8378fa32c8fc3db839629780b2ebc133545..92d31b0b8e278b924bfc7fb2d25a61f5a497de1d 100644 (file)
@@ -2,19 +2,19 @@
 //
 // SPDX-License-Identifier: AGPL-3.0
 
-import * as React from 'react';
+import React from 'react';
 import { connect, DispatchProp } from 'react-redux';
 import Typography from '@material-ui/core/Typography';
 import { StyleRulesCallback, WithStyles, withStyles } from '@material-ui/core/styles';
 import { Tooltip } from '@material-ui/core';
-import { CopyIcon } from '~/components/icon/icon';
-import * as CopyToClipboard from 'react-copy-to-clipboard';
-import { ArvadosTheme } from '~/common/custom-theme';
-import * as classnames from "classnames";
+import { CopyIcon } from 'components/icon/icon';
+import CopyToClipboard from 'react-copy-to-clipboard';
+import { ArvadosTheme } from 'common/custom-theme';
+import classnames from "classnames";
 import { Link } from 'react-router-dom';
-import { RootState } from "~/store/store";
-import { FederationConfig, getNavUrl } from "~/routes/routes";
-import { snackbarActions, SnackbarKind } from '~/store/snackbar/snackbar-actions';
+import { RootState } from "store/store";
+import { FederationConfig, getNavUrl } from "routes/routes";
+import { snackbarActions, SnackbarKind } from 'store/snackbar/snackbar-actions';
 
 type CssRules = 'attribute' | 'label' | 'value' | 'lowercaseValue' | 'link' | 'copyIcon';
 
@@ -24,7 +24,7 @@ const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
     },
     label: {
         boxSizing: 'border-box',
-        color: theme.palette.grey["500"],
+        color: theme.palette.grey["600"],
         width: '100%'
     },
     value: {
@@ -42,7 +42,7 @@ const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
     },
     copyIcon: {
         marginLeft: theme.spacing.unit,
-        color: theme.palette.grey["500"],
+        color: theme.palette.grey["600"],
         cursor: 'pointer',
         display: 'inline',
         '& svg': {
@@ -61,6 +61,8 @@ interface DetailsAttributeDataProps {
     children?: React.ReactNode;
     onValueClick?: () => void;
     linkToUuid?: string;
+    copyValue?: string;
+    uuidEnhancer?: Function;
 }
 
 type DetailsAttributeProps = DetailsAttributeDataProps & WithStyles<CssRules> & FederationConfig & DispatchProp;
@@ -83,40 +85,51 @@ export const DetailsAttribute = connect(mapStateToProps)(withStyles(styles)(
         }
 
         render() {
-            const { label, link, value, children, classes, classLabel,
-                classValue, lowercaseValue, onValueClick, linkToUuid,
+            const { uuidEnhancer, link, value, classes, linkToUuid,
                 localCluster, remoteHostsConfig, sessions } = this.props;
             let valueNode: React.ReactNode;
 
             if (linkToUuid) {
+                const uuid = uuidEnhancer ? uuidEnhancer(linkToUuid) : linkToUuid;
                 const linkUrl = getNavUrl(linkToUuid || "", { localCluster, remoteHostsConfig, sessions });
                 if (linkUrl[0] === '/') {
-                    valueNode = <Link to={linkUrl} className={classes.link}>{linkToUuid}</Link>;
+                    valueNode = <Link to={linkUrl} className={classes.link}>{uuid}</Link>;
                 } else {
-                    valueNode = <a href={linkUrl} className={classes.link} target='_blank'>{linkToUuid}</a>;
+                    valueNode = <a href={linkUrl} className={classes.link} target='_blank' rel="noopener noreferrer">{uuid}</a>;
                 }
             } else if (link) {
-                valueNode = <a href={link} className={classes.link} target='_blank'>{value}</a>;
+                valueNode = <a href={link} className={classes.link} target='_blank' rel="noopener noreferrer">{value}</a>;
             } else {
                 valueNode = value;
             }
-            return <Typography component="div" className={classes.attribute}>
-                <Typography component="div" className={classnames([classes.label, classLabel])}>{label}</Typography>
-                <Typography
-                    onClick={onValueClick}
-                    component="div"
-                    className={classnames([classes.value, classValue, { [classes.lowercaseValue]: lowercaseValue }])}>
-                    {valueNode}
-                    {children}
-                    {linkToUuid && <Tooltip title="Copy">
-                        <span className={classes.copyIcon}>
-                            <CopyToClipboard text={linkToUuid || ""} onCopy={() => this.onCopy("Copied")}>
-                                <CopyIcon />
-                            </CopyToClipboard>
-                        </span>
-                    </Tooltip>}
-                </Typography>
-            </Typography>;
+
+            return <DetailsAttributeComponent {...this.props} value={valueNode} onCopy={this.onCopy} />;
         }
     }
 ));
+
+interface DetailsAttributeComponentProps {
+    value: React.ReactNode;
+    onCopy?: (msg: string) => void;
+}
+
+export const DetailsAttributeComponent = withStyles(styles)(
+    (props: DetailsAttributeDataProps & WithStyles<CssRules> & DetailsAttributeComponentProps) =>
+        <Typography component="div" className={props.classes.attribute}>
+            <Typography component="div" className={classnames([props.classes.label, props.classLabel])}>{props.label}</Typography>
+            <Typography
+                onClick={props.onValueClick}
+                component="div"
+                className={classnames([props.classes.value, props.classValue, { [props.classes.lowercaseValue]: props.lowercaseValue }])}>
+                {props.value}
+                {props.children}
+                {(props.linkToUuid || props.copyValue) && props.onCopy && <Tooltip title="Copy to clipboard">
+                    <span className={props.classes.copyIcon}>
+                        <CopyToClipboard text={props.linkToUuid || props.copyValue || ""} onCopy={() => props.onCopy!("Copied")}>
+                            <CopyIcon />
+                        </CopyToClipboard>
+                    </span>
+                </Tooltip>}
+            </Typography>
+        </Typography>);
+