1 // Copyright (C) The Arvados Authors. All rights reserved.
3 // SPDX-License-Identifier: AGPL-3.0
5 import React from 'react';
6 import { StyleRulesCallback, WithStyles, Typography, withStyles, Link } from '@material-ui/core';
7 import { ArvadosTheme } from 'common/custom-theme';
8 import classNames from 'classnames';
9 import { connect, DispatchProp } from 'react-redux';
10 import { RootState } from 'store/store';
11 import { FederationConfig, getNavUrl } from 'routes/routes';
12 import { Dispatch } from 'redux';
13 import { navigationNotAvailable } from 'store/navigation/navigation-action';
15 type CssRules = 'root' | 'inlineRoot' | 'space' | 'inline';
17 const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
19 boxSizing: 'border-box',
21 padding: theme.spacing.unit,
35 export interface CodeSnippetDataProps {
38 apiResponse?: boolean;
40 children?: JSX.Element;
44 interface CodeSnippetAuthProps {
45 auth: FederationConfig;
48 type CodeSnippetProps = CodeSnippetDataProps & WithStyles<CssRules>;
50 const mapStateToProps = (state: RootState): CodeSnippetAuthProps => ({
54 export const CodeSnippet = withStyles(styles)(connect(mapStateToProps)(
55 ({ classes, lines, linked, className, apiResponse, dispatch, auth, children, inline }: CodeSnippetProps & CodeSnippetAuthProps & DispatchProp) =>
58 className={classNames([classes.root, className, inline ? classes.inlineRoot : undefined])}>
59 <Typography className={apiResponse ? classes.space : classNames([className, inline ? classes.inline : undefined])} component="pre">
62 lines.map((line, index) => <React.Fragment key={index}>{renderLinks(auth, dispatch)(line)}{`\n`}</React.Fragment>) :
69 const renderLinks = (auth: FederationConfig, dispatch: Dispatch) => (text: string): JSX.Element => {
70 // Matches UUIDs & PDHs
71 const REGEX = /[a-z0-9]{5}-[a-z0-9]{5}-[a-z0-9]{15}|[0-9a-f]{32}\+\d+/g;
72 const links = text.match(REGEX);
77 {text.split(REGEX).map((part, index) =>
78 <React.Fragment key={index}>
81 <Link onClick={() => {
82 const url = getNavUrl(links[index], auth)
84 window.open(`${window.location.origin}${url}`, '_blank', "noopener");
86 dispatch(navigationNotAvailable(links[index]));
89 style={{ cursor: 'pointer' }}>