16672: Adds renderer for UUID & PDH links on the log viewer.
authorLucas Di Pentima <lucas.dipentima@curii.com>
Mon, 21 Mar 2022 19:37:33 +0000 (16:37 -0300)
committerLucas Di Pentima <lucas.dipentima@curii.com>
Fri, 25 Mar 2022 20:59:23 +0000 (17:59 -0300)
Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima <lucas.dipentima@curii.com>

src/components/code-snippet/code-snippet.tsx
src/components/multi-panel-view/multi-panel-view.tsx
src/views/process-panel/process-log-code-snippet.tsx
src/views/process-panel/process-panel-root.tsx

index 6dc124010d97407bf44091464dcc07f16795281c..fd44b5fc5e6f69ece2fe238b102c394a3749287f 100644 (file)
@@ -26,17 +26,22 @@ export interface CodeSnippetDataProps {
     apiResponse?: boolean;
     containerClassName?: string;
     fontSize?: number;
+    customRenderer?: (line: string) => React.ReactNode;
 }
 
 type CodeSnippetProps = CodeSnippetDataProps & WithStyles<CssRules>;
 
 export const CodeSnippet = withStyles(styles)(
-    ({ classes, lines, className, containerClassName, apiResponse, fontSize }: CodeSnippetProps) =>
-        <Typography
-            component="div"
+    ({ classes, lines, className, containerClassName,
+        apiResponse, fontSize, customRenderer }: CodeSnippetProps) =>
+        <Typography component="div"
             className={classNames(classes.root, containerClassName, className)}>
-                { lines.map((line: string, index: number) => {
-                    return <Typography key={index} style={{ fontSize: fontSize }} className={apiResponse ? classes.space : className} component="pre">{line}</Typography>;
-                }) }
+            { lines.map((line: string, index: number) => {
+            return <Typography key={index} style={{ fontSize: fontSize }}
+                className={apiResponse ? classes.space : className}
+                component="pre">
+                {customRenderer ? customRenderer(line) : line}
+            </Typography>;
+            }) }
         </Typography>
     );
\ No newline at end of file
index 48241c0b61e03063af90f92b23e0e699707cc43c..de8249909d3af4ba16c53b49490ec0144bc6b4d0 100644 (file)
@@ -88,12 +88,9 @@ export const MPVPanelContent = ({doHidePanel, doMaximizePanel, panelName,
         }
     }, [panelRef]);
 
-    // If maxHeight is set, only apply it when not maximized
-    const mh = maxHeight
-        ? panelMaximized
-            ? '100%'
-            : maxHeight
-        : undefined;
+    const mh = panelMaximized
+        ? '100%'
+        : maxHeight;
 
     return <Grid item style={{maxHeight: mh}} {...props}>
         <span ref={panelRef} /> {/* Element to scroll to when the panel is selected */}
index 1ea839122125c6ba8b270a7448776e9519120b9e..4f19f9172623faf2b50dc55a7c3180fce5d1779d 100644 (file)
@@ -7,6 +7,10 @@ import { MuiThemeProvider, createMuiTheme, StyleRulesCallback, withStyles, WithS
 import { CodeSnippet } from 'components/code-snippet/code-snippet';
 import grey from '@material-ui/core/colors/grey';
 import { ArvadosTheme } from 'common/custom-theme';
+import { Link, Typography } from '@material-ui/core';
+import { navigateTo } from 'store/navigation/navigation-action';
+import { Dispatch } from 'redux';
+import { connect, DispatchProp } from 'react-redux';
 
 type CssRules = 'wordWrap' | 'codeSnippetContainer';
 
@@ -42,10 +46,32 @@ interface ProcessLogCodeSnippetProps {
     wordWrap?: boolean;
 }
 
-export const ProcessLogCodeSnippet = withStyles(styles)(
-    (props: ProcessLogCodeSnippetProps & WithStyles<CssRules>) =>
+const renderLinks = (fontSize: number, dispatch: Dispatch) => (text: string) => {
+    // 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 <Typography style={{ fontSize: fontSize }}>{text}</Typography>;
+    }
+    return <Typography style={{ fontSize: fontSize }}>
+        {text.split(REGEX).map((part, index) =>
+        <React.Fragment key={index}>
+            {part}
+            {links[index] &&
+            <Link onClick={() => dispatch<any>(navigateTo(links[index]))}
+                style={ {cursor: 'pointer'} }>
+                {links[index]}
+            </Link>}
+        </React.Fragment>
+        )}
+    </Typography>;
+};
+
+export const ProcessLogCodeSnippet = withStyles(styles)(connect()(
+    (props: ProcessLogCodeSnippetProps & WithStyles<CssRules> & DispatchProp) =>
         <MuiThemeProvider theme={theme}>
             <CodeSnippet lines={props.lines} fontSize={props.fontSize}
+                customRenderer={renderLinks(props.fontSize, props.dispatch)}
                 className={props.wordWrap ? props.classes.wordWrap : undefined}
                 containerClassName={props.classes.codeSnippetContainer} />
-        </MuiThemeProvider>);
\ No newline at end of file
+        </MuiThemeProvider>));
\ No newline at end of file
index 78c79f8fec4c5cbe928648724b5c059484d0bbe2..862dbd68aba3b18b312b975b3a94806a57eccab1 100644 (file)
@@ -85,7 +85,7 @@ export const ProcessPanelRoot = withStyles(styles)(
                     navigateToLog={props.navigateToLog}
                 />
             </MPVPanelContent>
-            <MPVPanelContent forwardProps xs>
+            <MPVPanelContent forwardProps xs maxHeight='50%'>
                 <SubprocessPanel />
             </MPVPanelContent>
         </MPVContainer>