Merge remote-tracking branch 'origin/main' into 19051-handle-quotes-in-search
[arvados-workbench2.git] / src / views / process-panel / process-log-card.tsx
index bbb4ff9dc62e126ba04d83aebaa566f733b094fc..936b31a5497612999aab5a340ab33cf8bd7b04f4 100644 (file)
@@ -19,9 +19,13 @@ import { ArvadosTheme } from 'common/custom-theme';
 import {
     CloseIcon,
     CollectionIcon,
+    CopyIcon,
     LogIcon,
     MaximizeIcon,
-    WordWrapIcon
+    TextDecreaseIcon,
+    TextIncreaseIcon,
+    WordWrapOffIcon,
+    WordWrapOnIcon,
 } from 'components/icon/icon';
 import { Process } from 'store/processes/process';
 import { MPVPanelProps } from 'components/multi-panel-view/multi-panel-view';
@@ -32,6 +36,7 @@ import {
 import { ProcessLogCodeSnippet } from 'views/process-panel/process-log-code-snippet';
 import { DefaultView } from 'components/default-view/default-view';
 import { CodeSnippetDataProps } from 'components/code-snippet/code-snippet';
+import CopyToClipboard from 'react-copy-to-clipboard';
 
 type CssRules = 'card' | 'content' | 'title' | 'iconHeader' | 'header' | 'root' | 'logViewer' | 'logViewerContainer';
 
@@ -75,6 +80,7 @@ export interface ProcessLogsCardDataProps {
 export interface ProcessLogsCardActionProps {
     onLogFilterChange: (filter: FilterOption) => void;
     navigateToLog: (uuid: string) => void;
+    onCopy: (text: string) => void;
 }
 
 type ProcessLogsCardProps = ProcessLogsCardDataProps
@@ -84,9 +90,14 @@ type ProcessLogsCardProps = ProcessLogsCardDataProps
     & MPVPanelProps;
 
 export const ProcessLogsCard = withStyles(styles)(
-    ({ classes, process, filters, selectedFilter, lines, onLogFilterChange, navigateToLog,
+    ({ classes, process, filters, selectedFilter, lines,
+        onLogFilterChange, navigateToLog, onCopy,
         doHidePanel, doMaximizePanel, panelMaximized, panelName }: ProcessLogsCardProps) => {
-        const [wordWrapToggle, setWordWrapToggle] = useState<boolean>(true);
+        const [wordWrap, setWordWrap] = useState<boolean>(true);
+        const [fontSize, setFontSize] = useState<number>(3);
+        const fontBaseSize = 10;
+        const fontStepSize = 1;
+
         return <Grid item className={classes.root} xs={12}>
             <Card className={classes.card}>
                 <CardHeader className={classes.header}
@@ -97,9 +108,32 @@ export const ProcessLogsCard = withStyles(styles)(
                                 filters={filters} onChange={onLogFilterChange} />
                         </Grid>
                         <Grid item>
-                            <Tooltip title="Toggle word wrapping" disableFocusListener>
-                                <IconButton onClick={() => setWordWrapToggle(!wordWrapToggle)}>
-                                    <WordWrapIcon />
+                            <Tooltip title="Decrease font size" disableFocusListener>
+                                <IconButton onClick={() => fontSize > 1 && setFontSize(fontSize-1)}>
+                                    <TextDecreaseIcon />
+                                </IconButton>
+                            </Tooltip>
+                        </Grid>
+                        <Grid item>
+                            <Tooltip title="Increase font size" disableFocusListener>
+                                <IconButton onClick={() => fontSize < 5 && setFontSize(fontSize+1)}>
+                                    <TextIncreaseIcon />
+                                </IconButton>
+                            </Tooltip>
+                        </Grid>
+                        <Grid item>
+                            <Tooltip title="Copy to clipboard" disableFocusListener>
+                                <IconButton>
+                                    <CopyToClipboard text={lines.join()} onCopy={() => onCopy("Log copied to clipboard")}>
+                                        <CopyIcon />
+                                    </CopyToClipboard>
+                                </IconButton>
+                            </Tooltip>
+                        </Grid>
+                        <Grid item>
+                            <Tooltip title={`${wordWrap ? 'Disable' : 'Enable'} word wrapping`} disableFocusListener>
+                                <IconButton onClick={() => setWordWrap(!wordWrap)}>
+                                    {wordWrap ? <WordWrapOffIcon /> : <WordWrapOnIcon />}
                                 </IconButton>
                             </Tooltip>
                         </Grid>
@@ -133,7 +167,7 @@ export const ProcessLogsCard = withStyles(styles)(
                             spacing={24}
                             direction='column'>
                             <Grid className={classes.logViewer} item xs>
-                                <ProcessLogCodeSnippet wordWrap={wordWrapToggle} lines={lines} />
+                                <ProcessLogCodeSnippet fontSize={fontBaseSize+(fontStepSize*fontSize)} wordWrap={wordWrap} lines={lines} />
                             </Grid>
                         </Grid>
                         : <DefaultView