</Typography>
));
-const renderLinks = (auth: FederationConfig, dispatch: Dispatch) => (text: string): JSX.Element => {
+export const renderLinks = (auth: FederationConfig, dispatch: Dispatch) => (text: string): JSX.Element => {
// 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);
--- /dev/null
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import React from 'react';
+import { StyleRulesCallback, WithStyles, Typography, withStyles } from '@material-ui/core';
+import { ArvadosTheme } from 'common/custom-theme';
+import classNames from 'classnames';
+import { connect, DispatchProp } from 'react-redux';
+import { RootState } from 'store/store';
+import { FederationConfig } from 'routes/routes';
+import { renderLinks } from './code-snippet';
+import { FixedSizeList } from 'react-window';
+import AutoSizer from "react-virtualized-auto-sizer";
+
+type CssRules = 'root' | 'space' | 'content' ;
+
+const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
+ root: {
+ boxSizing: 'border-box',
+ height: '100%',
+ padding: theme.spacing.unit,
+ },
+ space: {
+ marginLeft: '15px',
+ },
+ content: {
+ maxHeight: '100%',
+ height: '100vh',
+ },
+});
+
+export interface CodeSnippetDataProps {
+ lines: string[];
+ lineTransformer?: (line: string) => string;
+ className?: string;
+ apiResponse?: boolean;
+ linked?: boolean;
+}
+
+interface CodeSnippetAuthProps {
+ auth: FederationConfig;
+}
+
+type CodeSnippetProps = CodeSnippetDataProps & WithStyles<CssRules>;
+
+const mapStateToProps = (state: RootState): CodeSnippetAuthProps => ({
+ auth: state.auth,
+});
+
+export const VirtualCodeSnippet = withStyles(styles)(connect(mapStateToProps)(
+ ({ classes, lines, linked, className, apiResponse, dispatch, auth }: CodeSnippetProps & CodeSnippetAuthProps & DispatchProp) => {
+ const RenderRow = ({index, style}) => (
+ <span style={style}>{linked ? renderLinks(auth, dispatch)(lines[index]) : lines[index]}</span>
+ );
+
+ return <Typography
+ component="div"
+ className={classNames([classes.root, className])}>
+ <Typography className={classNames(classes.content, apiResponse ? classes.space : className)} component="pre">
+ <AutoSizer>
+ {({ height, width }) =>
+ <FixedSizeList
+ height={height}
+ width={width}
+ itemSize={21}
+ itemCount={lines.length}
+ >
+ {RenderRow}
+ </FixedSizeList>
+ }
+ </AutoSizer>
+ </Typography>
+ </Typography>;
+}));
--- /dev/null
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import React from 'react';
+import { MuiThemeProvider, createMuiTheme } from '@material-ui/core/styles';
+import { VirtualCodeSnippet, CodeSnippetDataProps } from 'components/code-snippet/virtual-code-snippet';
+import grey from '@material-ui/core/colors/grey';
+import { themeOptions } from 'common/custom-theme';
+
+const theme = createMuiTheme(Object.assign({}, themeOptions, {
+ overrides: {
+ MuiTypography: {
+ body1: {
+ color: grey["900"]
+ },
+ root: {
+ backgroundColor: grey["200"]
+ }
+ }
+ },
+ typography: {
+ fontFamily: 'monospace',
+ useNextVariants: true,
+ }
+}));
+
+export const DefaultVirtualCodeSnippet = (props: CodeSnippetDataProps) =>
+ <MuiThemeProvider theme={theme}>
+ <VirtualCodeSnippet {...props} />
+ </MuiThemeProvider>;
import { ArvadosTheme } from 'common/custom-theme';
import { CloseIcon, CommandIcon, CopyIcon } from 'components/icon/icon';
import { MPVPanelProps } from 'components/multi-panel-view/multi-panel-view';
-import { DefaultCodeSnippet } from 'components/default-code-snippet/default-code-snippet';
+import { DefaultVirtualCodeSnippet } from 'components/default-code-snippet/default-virtual-code-snippet';
import { Process } from 'store/processes/process';
import shellescape from 'shell-escape';
import CopyToClipboard from 'react-copy-to-clipboard';
},
header: {
paddingTop: theme.spacing.unit,
- paddingBottom: theme.spacing.unit,
+ paddingBottom: 0,
},
iconHeader: {
fontSize: '1.875rem',
paddingTop: theme.spacing.unit * 0.5
},
content: {
+ height: `calc(100% - ${theme.spacing.unit * 6}px)`,
padding: theme.spacing.unit * 1.0,
- paddingTop: theme.spacing.unit * 0.5,
+ paddingTop: 0,
'&:last-child': {
paddingBottom: theme.spacing.unit * 1,
}
overflow: 'hidden',
paddingTop: theme.spacing.unit * 0.5,
color: theme.customs.colors.greyD,
- fontSize: '1.875rem'
+ fontSize: '1.875rem'
},
});
}
/>
<CardContent className={classes.content}>
- <DefaultCodeSnippet lines={formattedCommand} linked />
+ <DefaultVirtualCodeSnippet lines={formattedCommand} linked />
</CardContent>
</Card>
);
<MPVPanelContent
forwardProps
xs="auto"
+ maxHeight={"50%"}
data-cy="process-cmd">
<ProcessCmdCard
onCopy={props.onCopyToClipboard}