From: Stephen Smith Date: Mon, 25 Jul 2022 22:54:37 +0000 (-0400) Subject: 16070: Add optional linking to code snippet component. Base styles off of default... X-Git-Tag: 2.5.0~45^2~2 X-Git-Url: https://git.arvados.org/arvados-workbench2.git/commitdiff_plain/e2ac5434eb436b0e8ca8205dfe83d4ef1bcdd4c5 16070: Add optional linking to code snippet component. Base styles off of default theme for link color Arvados-DCO-1.1-Signed-off-by: Stephen Smith --- diff --git a/src/components/code-snippet/code-snippet.tsx b/src/components/code-snippet/code-snippet.tsx index f156e3e8..83c378b8 100644 --- a/src/components/code-snippet/code-snippet.tsx +++ b/src/components/code-snippet/code-snippet.tsx @@ -3,9 +3,14 @@ // SPDX-License-Identifier: AGPL-3.0 import React from 'react'; -import { StyleRulesCallback, WithStyles, Typography, withStyles } from '@material-ui/core'; +import { StyleRulesCallback, WithStyles, Typography, withStyles, Link } from '@material-ui/core'; import { ArvadosTheme } from 'common/custom-theme'; import classNames from 'classnames'; +import { connect, DispatchProp } from 'react-redux'; +import { RootState } from 'store/store'; +import { FederationConfig, getNavUrl } from 'routes/routes'; +import { Dispatch } from 'redux'; +import { navigationNotAvailable } from 'store/navigation/navigation-action'; type CssRules = 'root' | 'space'; @@ -24,17 +29,57 @@ export interface CodeSnippetDataProps { lines: string[]; className?: string; apiResponse?: boolean; + linked?: boolean; +} + +interface CodeSnippetAuthProps { + auth: FederationConfig; } type CodeSnippetProps = CodeSnippetDataProps & WithStyles; -export const CodeSnippet = withStyles(styles)( - ({ classes, lines, className, apiResponse }: CodeSnippetProps) => +const mapStateToProps = (state: RootState): CodeSnippetAuthProps => ({ + auth: state.auth, +}); + +export const CodeSnippet = withStyles(styles)(connect(mapStateToProps)( + ({ classes, lines, linked, className, apiResponse, dispatch, auth }: CodeSnippetProps & CodeSnippetAuthProps & DispatchProp) => - {lines.join('\n')} + {linked ? + lines.map((line, index) => {renderLinks(auth, dispatch)(line)}{`\n`}) : + lines.join('\n') + } - ); + )); + +const renderLinks = (auth: FederationConfig, dispatch: Dispatch) => (text: string): JSX.Element => { + // Matches UUIDs & PDHs + const REGEX = /[a-z0-9]{5}-[a-z0-9]{5}-[a-z0-9]{15}|[0-9a-f]{32}\+\d+/g; + const links = text.match(REGEX); + if (!links) { + return <>{text}; + } + return <> + {text.split(REGEX).map((part, index) => + + {part} + {links[index] && + { + const url = getNavUrl(links[index], auth) + if (url) { + window.open(`${window.location.origin}${url}`, '_blank'); + } else { + dispatch(navigationNotAvailable(links[index])); + } + }} + style={ {cursor: 'pointer'} }> + {links[index]} + } + + )} + ; + }; diff --git a/src/components/default-code-snippet/default-code-snippet.tsx b/src/components/default-code-snippet/default-code-snippet.tsx index 7ba97db4..bdcfc10f 100644 --- a/src/components/default-code-snippet/default-code-snippet.tsx +++ b/src/components/default-code-snippet/default-code-snippet.tsx @@ -6,8 +6,9 @@ import React from 'react'; import { MuiThemeProvider, createMuiTheme } from '@material-ui/core/styles'; import { CodeSnippet, CodeSnippetDataProps } from 'components/code-snippet/code-snippet'; import grey from '@material-ui/core/colors/grey'; +import { themeOptions } from 'common/custom-theme'; -const theme = createMuiTheme({ +const theme = createMuiTheme(Object.assign({}, themeOptions, { overrides: { MuiTypography: { body1: { @@ -22,9 +23,9 @@ const theme = createMuiTheme({ fontFamily: 'monospace', useNextVariants: true, } -}); +})); -export const DefaultCodeSnippet = (props: CodeSnippetDataProps) => +export const DefaultCodeSnippet = (props: CodeSnippetDataProps) => - ; \ No newline at end of file + ; diff --git a/src/views/process-panel/process-cmd-card.tsx b/src/views/process-panel/process-cmd-card.tsx index 36a0128b..4143501e 100644 --- a/src/views/process-panel/process-cmd-card.tsx +++ b/src/views/process-panel/process-cmd-card.tsx @@ -54,7 +54,7 @@ const styles: StyleRulesCallback = (theme: ArvadosTheme) => ({ }, }); -export interface ProcessCmdCardDataProps { +interface ProcessCmdCardDataProps { process: Process; onCopy: (text: string) => void; } @@ -125,7 +125,7 @@ export const ProcessCmdCard = withStyles(styles)( } /> - + );