16672: Adds toggable word-wrapping to the log panel.
authorLucas Di Pentima <lucas.dipentima@curii.com>
Fri, 18 Mar 2022 20:51:17 +0000 (17:51 -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/icon/icon.tsx
src/views/process-panel/process-log-card.tsx
src/views/process-panel/process-log-code-snippet.tsx

index 54b7bee6cd827b044af7dd88197ae7c76e4a8d82..7fb74e81163cd3fc9b91eb7db117504ee69192fc 100644 (file)
@@ -65,6 +65,7 @@ import VpnKey from '@material-ui/icons/VpnKey';
 import LinkOutlined from '@material-ui/icons/LinkOutlined';
 import RemoveRedEye from '@material-ui/icons/RemoveRedEye';
 import Computer from '@material-ui/icons/Computer';
+import WrapText from '@material-ui/icons/WrapText';
 
 // Import FontAwesome icons
 import { library } from '@fortawesome/fontawesome-svg-core';
@@ -173,3 +174,4 @@ export const CanReadIcon: IconType = (props) => <RemoveRedEye {...props} />;
 export const CanWriteIcon: IconType = (props) => <Edit {...props} />;
 export const CanManageIcon: IconType = (props) => <Computer {...props} />;
 export const AddUserIcon: IconType = (props) => <PersonAdd {...props} />;
+export const WordWrapIcon: IconType = (props) => <WrapText {...props} />;
index bd700bcd4344b0295d35799933afc803b32b5122..bbb4ff9dc62e126ba04d83aebaa566f733b094fc 100644 (file)
@@ -2,7 +2,7 @@
 //
 // SPDX-License-Identifier: AGPL-3.0
 
-import React from 'react';
+import React, { useState } from 'react';
 import {
     StyleRulesCallback,
     WithStyles,
@@ -20,7 +20,8 @@ import {
     CloseIcon,
     CollectionIcon,
     LogIcon,
-    MaximizeIcon
+    MaximizeIcon,
+    WordWrapIcon
 } from 'components/icon/icon';
 import { Process } from 'store/processes/process';
 import { MPVPanelProps } from 'components/multi-panel-view/multi-panel-view';
@@ -84,8 +85,9 @@ type ProcessLogsCardProps = ProcessLogsCardDataProps
 
 export const ProcessLogsCard = withStyles(styles)(
     ({ classes, process, filters, selectedFilter, lines, onLogFilterChange, navigateToLog,
-        doHidePanel, doMaximizePanel, panelMaximized, panelName }: ProcessLogsCardProps) =>
-        <Grid item className={classes.root} xs={12}>
+        doHidePanel, doMaximizePanel, panelMaximized, panelName }: ProcessLogsCardProps) => {
+        const [wordWrapToggle, setWordWrapToggle] = useState<boolean>(true);
+        return <Grid item className={classes.root} xs={12}>
             <Card className={classes.card}>
                 <CardHeader className={classes.header}
                     avatar={<LogIcon className={classes.iconHeader} />}
@@ -94,6 +96,13 @@ export const ProcessLogsCard = withStyles(styles)(
                             <ProcessLogForm selectedFilter={selectedFilter}
                                 filters={filters} onChange={onLogFilterChange} />
                         </Grid>
+                        <Grid item>
+                            <Tooltip title="Toggle word wrapping" disableFocusListener>
+                                <IconButton onClick={() => setWordWrapToggle(!wordWrapToggle)}>
+                                    <WordWrapIcon />
+                                </IconButton>
+                            </Tooltip>
+                        </Grid>
                         <Grid item>
                             <Tooltip title="Go to Log collection" disableFocusListener>
                                 <IconButton onClick={() => navigateToLog(process.containerRequest.logUuid!)}>
@@ -124,7 +133,7 @@ export const ProcessLogsCard = withStyles(styles)(
                             spacing={24}
                             direction='column'>
                             <Grid className={classes.logViewer} item xs>
-                                <ProcessLogCodeSnippet lines={lines} />
+                                <ProcessLogCodeSnippet wordWrap={wordWrapToggle} lines={lines} />
                             </Grid>
                         </Grid>
                         : <DefaultView
@@ -134,5 +143,5 @@ export const ProcessLogsCard = withStyles(styles)(
                 </CardContent>
             </Card>
         </Grid >
-);
+});
 
index 01f5ca1cdb7f81330902f2373c8c49c274720008..eb3ede6f5f2ee75aa0c01f5e4a46dc340a598023 100644 (file)
@@ -8,10 +8,11 @@ import { CodeSnippet } from 'components/code-snippet/code-snippet';
 import grey from '@material-ui/core/colors/grey';
 import { ArvadosTheme } from 'common/custom-theme';
 
-type CssRules = 'codeSnippet' | 'codeSnippetContainer';
+type CssRules = 'wordWrap' | 'codeSnippetContainer';
 
 const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
-    codeSnippet: {
+    wordWrap: {
+        whiteSpace: 'pre-wrap',
     },
     codeSnippetContainer: {
         height: `calc(100% - ${theme.spacing.unit * 4}px)`, // so that horizontal scollbar is visible
@@ -37,11 +38,13 @@ const theme = createMuiTheme({
 
 interface ProcessLogCodeSnippetProps {
     lines: string[];
+    wordWrap?: boolean;
 }
 
 export const ProcessLogCodeSnippet = withStyles(styles)(
     (props: ProcessLogCodeSnippetProps & WithStyles<CssRules>) =>
         <MuiThemeProvider theme={theme}>
-            <CodeSnippet lines={props.lines} className={props.classes.codeSnippet}
+            <CodeSnippet lines={props.lines}
+                className={props.wordWrap ? props.classes.wordWrap : undefined}
                 containerClassName={props.classes.codeSnippetContainer} />
         </MuiThemeProvider>);
\ No newline at end of file