4f19f9172623faf2b50dc55a7c3180fce5d1779d
[arvados-workbench2.git] / src / views / process-panel / process-log-code-snippet.tsx
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 import React from 'react';
6 import { MuiThemeProvider, createMuiTheme, StyleRulesCallback, withStyles, WithStyles } from '@material-ui/core/styles';
7 import { CodeSnippet } from 'components/code-snippet/code-snippet';
8 import grey from '@material-ui/core/colors/grey';
9 import { ArvadosTheme } from 'common/custom-theme';
10 import { Link, Typography } from '@material-ui/core';
11 import { navigateTo } from 'store/navigation/navigation-action';
12 import { Dispatch } from 'redux';
13 import { connect, DispatchProp } from 'react-redux';
14
15 type CssRules = 'wordWrap' | 'codeSnippetContainer';
16
17 const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
18     wordWrap: {
19         whiteSpace: 'pre-wrap',
20     },
21     codeSnippetContainer: {
22         height: `calc(100% - ${theme.spacing.unit * 4}px)`, // so that horizontal scollbar is visible
23     },
24 });
25
26 const theme = createMuiTheme({
27     overrides: {
28         MuiTypography: {
29             body2: {
30                 color: grey["200"]
31             },
32             root: {
33                 backgroundColor: '#000'
34             }
35         }
36     },
37     typography: {
38         fontFamily: 'monospace',
39         useNextVariants: true,
40     }
41 });
42
43 interface ProcessLogCodeSnippetProps {
44     lines: string[];
45     fontSize: number;
46     wordWrap?: boolean;
47 }
48
49 const renderLinks = (fontSize: number, dispatch: Dispatch) => (text: string) => {
50     // Matches UUIDs & PDHs
51     const REGEX = /[a-z0-9]{5}-[a-z0-9]{5}-[a-z0-9]{15}|[0-9a-f]{32}\+\d+/g;
52     const links = text.match(REGEX);
53     if (!links) {
54         return <Typography style={{ fontSize: fontSize }}>{text}</Typography>;
55     }
56     return <Typography style={{ fontSize: fontSize }}>
57         {text.split(REGEX).map((part, index) =>
58         <React.Fragment key={index}>
59             {part}
60             {links[index] &&
61             <Link onClick={() => dispatch<any>(navigateTo(links[index]))}
62                 style={ {cursor: 'pointer'} }>
63                 {links[index]}
64             </Link>}
65         </React.Fragment>
66         )}
67     </Typography>;
68 };
69
70 export const ProcessLogCodeSnippet = withStyles(styles)(connect()(
71     (props: ProcessLogCodeSnippetProps & WithStyles<CssRules> & DispatchProp) =>
72         <MuiThemeProvider theme={theme}>
73             <CodeSnippet lines={props.lines} fontSize={props.fontSize}
74                 customRenderer={renderLinks(props.fontSize, props.dispatch)}
75                 className={props.wordWrap ? props.classes.wordWrap : undefined}
76                 containerClassName={props.classes.codeSnippetContainer} />
77         </MuiThemeProvider>));