17018: Fixes the bug adding checks for readonly context menu type.
[arvados-workbench2.git] / src / components / details-attribute / details-attribute.tsx
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 import * as React from 'react';
6 import { connect, DispatchProp } from 'react-redux';
7 import Typography from '@material-ui/core/Typography';
8 import { StyleRulesCallback, WithStyles, withStyles } from '@material-ui/core/styles';
9 import { Tooltip } from '@material-ui/core';
10 import { CopyIcon } from '~/components/icon/icon';
11 import * as CopyToClipboard from 'react-copy-to-clipboard';
12 import { ArvadosTheme } from '~/common/custom-theme';
13 import * as classnames from "classnames";
14 import { Link } from 'react-router-dom';
15 import { RootState } from "~/store/store";
16 import { FederationConfig, getNavUrl } from "~/routes/routes";
17 import { snackbarActions, SnackbarKind } from '~/store/snackbar/snackbar-actions';
18
19 type CssRules = 'attribute' | 'label' | 'value' | 'lowercaseValue' | 'link' | 'copyIcon';
20
21 const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
22     attribute: {
23         display: 'flex',
24         alignItems: 'flex-start',
25         marginBottom: theme.spacing.unit
26     },
27     label: {
28         boxSizing: 'border-box',
29         color: theme.palette.grey["500"],
30         width: '40%'
31     },
32     value: {
33         boxSizing: 'border-box',
34         width: '60%',
35         alignItems: 'flex-start'
36     },
37     lowercaseValue: {
38         textTransform: 'lowercase'
39     },
40     link: {
41         width: '60%',
42         color: theme.palette.primary.main,
43         textDecoration: 'none',
44         overflowWrap: 'break-word',
45         cursor: 'pointer'
46     },
47     copyIcon: {
48         marginLeft: theme.spacing.unit,
49         fontSize: '1.125rem',
50         color: theme.palette.grey["500"],
51         cursor: 'pointer'
52     }
53 });
54
55 interface DetailsAttributeDataProps {
56     label: string;
57     classLabel?: string;
58     value?: React.ReactNode;
59     classValue?: string;
60     lowercaseValue?: boolean;
61     link?: string;
62     children?: React.ReactNode;
63     onValueClick?: () => void;
64     linkToUuid?: string;
65 }
66
67 type DetailsAttributeProps = DetailsAttributeDataProps & WithStyles<CssRules> & FederationConfig & DispatchProp;
68
69 const mapStateToProps = ({ auth }: RootState): FederationConfig => ({
70     localCluster: auth.localCluster,
71     remoteHostsConfig: auth.remoteHostsConfig,
72     sessions: auth.sessions
73 });
74
75 export const DetailsAttribute = connect(mapStateToProps)(withStyles(styles)(
76     class extends React.Component<DetailsAttributeProps> {
77
78         onCopy = (message: string) => {
79             this.props.dispatch(snackbarActions.OPEN_SNACKBAR({
80                 message,
81                 hideDuration: 2000,
82                 kind: SnackbarKind.SUCCESS
83             }));
84         }
85
86         render() {
87             const { label, link, value, children, classes, classLabel,
88                 classValue, lowercaseValue, onValueClick, linkToUuid,
89                 localCluster, remoteHostsConfig, sessions } = this.props;
90             let valueNode: React.ReactNode;
91
92             if (linkToUuid) {
93                 const linkUrl = getNavUrl(linkToUuid || "", { localCluster, remoteHostsConfig, sessions });
94                 if (linkUrl[0] === '/') {
95                     valueNode = <Link to={linkUrl} className={classes.link}>{linkToUuid}</Link>;
96                 } else {
97                     valueNode = <a href={linkUrl} className={classes.link} target='_blank'>{linkToUuid}</a>;
98                 }
99             } else if (link) {
100                 valueNode = <a href={link} className={classes.link} target='_blank'>{value}</a>;
101             } else {
102                 valueNode = value;
103             }
104             return <Typography component="div" className={classes.attribute}>
105                 <Typography component="span" className={classnames([classes.label, classLabel])}>{label}</Typography>
106                 <Typography
107                     onClick={onValueClick}
108                     component="span"
109                     className={classnames([classes.value, classValue, { [classes.lowercaseValue]: lowercaseValue }])}>
110                     {valueNode}
111                     {children}
112                     {linkToUuid && <Tooltip title="Copy">
113                         <CopyToClipboard text={linkToUuid || ""} onCopy={() => this.onCopy("Copied")}>
114                             <CopyIcon className={classes.copyIcon} />
115                         </CopyToClipboard>
116                     </Tooltip>}
117                 </Typography>
118             </Typography>;
119         }
120     }
121 ));