19231: Add smaller page sizes (10 and 20 items) to load faster
[arvados-workbench2.git] / src / views / process-panel / process-log-card.tsx
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 import React, { useState } from 'react';
6 import {
7     StyleRulesCallback,
8     WithStyles,
9     withStyles,
10     Card,
11     CardHeader,
12     IconButton,
13     CardContent,
14     Tooltip,
15     Grid,
16     Typography,
17 } from '@material-ui/core';
18 import { ArvadosTheme } from 'common/custom-theme';
19 import {
20     CloseIcon,
21     CollectionIcon,
22     CopyIcon,
23     LogIcon,
24     MaximizeIcon,
25     TextDecreaseIcon,
26     TextIncreaseIcon,
27     WordWrapOffIcon,
28     WordWrapOnIcon,
29 } from 'components/icon/icon';
30 import { Process } from 'store/processes/process';
31 import { MPVPanelProps } from 'components/multi-panel-view/multi-panel-view';
32 import {
33     FilterOption,
34     ProcessLogForm
35 } from 'views/process-panel/process-log-form';
36 import { ProcessLogCodeSnippet } from 'views/process-panel/process-log-code-snippet';
37 import { DefaultView } from 'components/default-view/default-view';
38 import { CodeSnippetDataProps } from 'components/code-snippet/code-snippet';
39 import CopyToClipboard from 'react-copy-to-clipboard';
40
41 type CssRules = 'card' | 'content' | 'title' | 'iconHeader' | 'header' | 'root' | 'logViewer' | 'logViewerContainer';
42
43 const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
44     card: {
45         height: '100%'
46     },
47     header: {
48         paddingTop: theme.spacing.unit,
49         paddingBottom: theme.spacing.unit,
50     },
51     content: {
52         padding: theme.spacing.unit * 0,
53         height: '100%',
54     },
55     logViewer: {
56         height: '100%',
57     },
58     logViewerContainer: {
59         height: '100%',
60     },
61     title: {
62         overflow: 'hidden',
63         paddingTop: theme.spacing.unit * 0.5
64     },
65     iconHeader: {
66         fontSize: '1.875rem',
67         color: theme.customs.colors.green700
68     },
69     root: {
70         height: '100%',
71     },
72 });
73
74 export interface ProcessLogsCardDataProps {
75     process: Process;
76     selectedFilter: FilterOption;
77     filters: FilterOption[];
78 }
79
80 export interface ProcessLogsCardActionProps {
81     onLogFilterChange: (filter: FilterOption) => void;
82     navigateToLog: (uuid: string) => void;
83     onCopy: (text: string) => void;
84 }
85
86 type ProcessLogsCardProps = ProcessLogsCardDataProps
87     & ProcessLogsCardActionProps
88     & CodeSnippetDataProps
89     & WithStyles<CssRules>
90     & MPVPanelProps;
91
92 export const ProcessLogsCard = withStyles(styles)(
93     ({ classes, process, filters, selectedFilter, lines,
94         onLogFilterChange, navigateToLog, onCopy,
95         doHidePanel, doMaximizePanel, panelMaximized, panelName }: ProcessLogsCardProps) => {
96         const [wordWrap, setWordWrap] = useState<boolean>(true);
97         const [fontSize, setFontSize] = useState<number>(3);
98         const fontBaseSize = 10;
99         const fontStepSize = 1;
100
101         return <Grid item className={classes.root} xs={12}>
102             <Card className={classes.card}>
103                 <CardHeader className={classes.header}
104                     avatar={<LogIcon className={classes.iconHeader} />}
105                     action={<Grid container direction='row' alignItems='center'>
106                         <Grid item>
107                             <ProcessLogForm selectedFilter={selectedFilter}
108                                 filters={filters} onChange={onLogFilterChange} />
109                         </Grid>
110                         <Grid item>
111                             <Tooltip title="Decrease font size" disableFocusListener>
112                                 <IconButton onClick={() => fontSize > 1 && setFontSize(fontSize-1)}>
113                                     <TextDecreaseIcon />
114                                 </IconButton>
115                             </Tooltip>
116                         </Grid>
117                         <Grid item>
118                             <Tooltip title="Increase font size" disableFocusListener>
119                                 <IconButton onClick={() => fontSize < 5 && setFontSize(fontSize+1)}>
120                                     <TextIncreaseIcon />
121                                 </IconButton>
122                             </Tooltip>
123                         </Grid>
124                         <Grid item>
125                             <Tooltip title="Copy to clipboard" disableFocusListener>
126                                 <IconButton>
127                                     <CopyToClipboard text={lines.join()} onCopy={() => onCopy("Log copied to clipboard")}>
128                                         <CopyIcon />
129                                     </CopyToClipboard>
130                                 </IconButton>
131                             </Tooltip>
132                         </Grid>
133                         <Grid item>
134                             <Tooltip title={`${wordWrap ? 'Disable' : 'Enable'} word wrapping`} disableFocusListener>
135                                 <IconButton onClick={() => setWordWrap(!wordWrap)}>
136                                     {wordWrap ? <WordWrapOffIcon /> : <WordWrapOnIcon />}
137                                 </IconButton>
138                             </Tooltip>
139                         </Grid>
140                         <Grid item>
141                             <Tooltip title="Go to Log collection" disableFocusListener>
142                                 <IconButton onClick={() => navigateToLog(process.containerRequest.logUuid!)}>
143                                     <CollectionIcon />
144                                 </IconButton>
145                             </Tooltip>
146                         </Grid>
147                         { doMaximizePanel && !panelMaximized &&
148                         <Tooltip title={`Maximize ${panelName || 'panel'}`} disableFocusListener>
149                             <IconButton onClick={doMaximizePanel}><MaximizeIcon /></IconButton>
150                         </Tooltip> }
151                         { doHidePanel && <Grid item>
152                             <Tooltip title={`Close ${panelName || 'panel'}`} disableFocusListener>
153                                 <IconButton onClick={doHidePanel}><CloseIcon /></IconButton>
154                             </Tooltip>
155                         </Grid> }
156                     </Grid>}
157                     title={
158                         <Typography noWrap variant='h6' className={classes.title}>
159                             Logs
160                         </Typography>}
161                 />
162                 <CardContent className={classes.content}>
163                     {lines.length > 0
164                         ? < Grid
165                             className={classes.logViewerContainer}
166                             container
167                             spacing={24}
168                             direction='column'>
169                             <Grid className={classes.logViewer} item xs>
170                                 <ProcessLogCodeSnippet fontSize={fontBaseSize+(fontStepSize*fontSize)} wordWrap={wordWrap} lines={lines} />
171                             </Grid>
172                         </Grid>
173                         : <DefaultView
174                             icon={LogIcon}
175                             messages={['No logs yet']} />
176                     }
177                 </CardContent>
178             </Card>
179         </Grid >
180 });
181