15230: Link to other workbenches when double-clicking search results.
[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 } from 'react-redux';
7 import Typography from '@material-ui/core/Typography';
8 import { StyleRulesCallback, WithStyles, withStyles } from '@material-ui/core/styles';
9 import { ArvadosTheme } from '~/common/custom-theme';
10 import * as classnames from "classnames";
11 import { Link } from 'react-router-dom';
12 import { RootState } from "~/store/store";
13 import { FederationConfig, getNavUrl } from "~/routes/routes";
14
15 type CssRules = 'attribute' | 'label' | 'value' | 'lowercaseValue' | 'link';
16
17 const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
18     attribute: {
19         display: 'flex',
20         alignItems: 'flex-start',
21         marginBottom: theme.spacing.unit
22     },
23     label: {
24         boxSizing: 'border-box',
25         color: theme.palette.grey["500"],
26         width: '40%'
27     },
28     value: {
29         boxSizing: 'border-box',
30         width: '60%',
31         display: 'flex',
32         alignItems: 'flex-start'
33     },
34     lowercaseValue: {
35         textTransform: 'lowercase'
36     },
37     link: {
38         width: '60%',
39         color: theme.palette.primary.main,
40         textDecoration: 'none',
41         overflowWrap: 'break-word',
42         cursor: 'pointer'
43     }
44 });
45
46 interface DetailsAttributeDataProps {
47     label: string;
48     classLabel?: string;
49     value?: React.ReactNode;
50     classValue?: string;
51     lowercaseValue?: boolean;
52     link?: string;
53     children?: React.ReactNode;
54     onValueClick?: () => void;
55     linkToUuid?: string;
56 }
57
58 type DetailsAttributeProps = DetailsAttributeDataProps & WithStyles<CssRules> & FederationConfig;
59
60 const mapStateToProps = ({ auth }: RootState): FederationConfig => ({
61     localCluster: auth.localCluster,
62     remoteHostsConfig: auth.remoteHostsConfig,
63     sessions: auth.sessions
64 });
65
66 export const DetailsAttribute = connect(mapStateToProps)(withStyles(styles)(
67     ({ label, link, value, children, classes, classLabel,
68         classValue, lowercaseValue, onValueClick, linkToUuid,
69         localCluster, remoteHostsConfig, sessions }: DetailsAttributeProps) => {
70         let insertLink: React.ReactNode;
71         if (linkToUuid) {
72             const linkUrl = getNavUrl(linkToUuid || "", { localCluster, remoteHostsConfig, sessions });
73             if (linkUrl[0] === '/') {
74                 insertLink = <Link to={linkUrl} className={classes.link}>{value}</Link>;
75             } else {
76                 insertLink = <a href={linkUrl} className={classes.link} target='_blank'>{value}</a>;
77             }
78         } else if (link) {
79             insertLink = <a href={link} className={classes.link} target='_blank'>{value}</a>;
80         }
81         return <Typography component="div" className={classes.attribute}>
82             <Typography component="span" className={classnames([classes.label, classLabel])}>{label}</Typography>
83             {insertLink}
84             {!insertLink && <Typography
85                 onClick={onValueClick}
86                 component="span"
87                 className={classnames([classes.value, classValue, { [classes.lowercaseValue]: lowercaseValue }])}>
88                 {value}
89                 {children}
90             </Typography>
91             }
92         </Typography>;
93     }
94 ));