[arvados] created: 2.7.0-6359-g0a39d337a1
git repository hosting
git at public.arvados.org
Sat Apr 6 03:08:18 UTC 2024
at 0a39d337a1c58d7cbdd51b2f852b84eebc1c68ef (commit)
commit 0a39d337a1c58d7cbdd51b2f852b84eebc1c68ef
Author: Stephen Smith <stephen at curii.com>
Date: Fri Apr 5 23:05:57 2024 -0400
21651: Update io card unit tests for virtual list
Arvados-DCO-1.1-Signed-off-by: Stephen Smith <stephen at curii.com>
diff --git a/services/workbench2/src/views/process-panel/process-io-card.test.tsx b/services/workbench2/src/views/process-panel/process-io-card.test.tsx
index ff1ec24de1..c0feead398 100644
--- a/services/workbench2/src/views/process-panel/process-io-card.test.tsx
+++ b/services/workbench2/src/views/process-panel/process-io-card.test.tsx
@@ -11,7 +11,7 @@ import Adapter from "enzyme-adapter-react-16";
import { Provider } from 'react-redux';
import { ProcessIOCard, ProcessIOCardType } from './process-io-card';
import { DefaultView } from "components/default-view/default-view";
-import { DefaultCodeSnippet } from "components/default-code-snippet/default-code-snippet";
+import { DefaultVirtualCodeSnippet } from "components/default-code-snippet/default-virtual-code-snippet";
import { ProcessOutputCollectionFiles } from './process-output-collection-files';
import { MemoryRouter } from 'react-router-dom';
@@ -111,7 +111,7 @@ describe('renderers', () => {
// then
expect(panel.find(CircularProgress).exists()).toBeFalsy();
expect(panel.find(Tab).length).toBe(1);
- expect(panel.find(DefaultCodeSnippet).text()).toContain(JSON.stringify(raw, null, 2));
+ expect(panel.find(DefaultVirtualCodeSnippet).text()).toContain(JSON.stringify(raw, null, 2).replace(/\n/g, ''));
});
it('shows main process with params', () => {
commit 015668c71b0d0a88fefab6783d3199472df95eb2
Author: Stephen Smith <stephen at curii.com>
Date: Fri Apr 5 19:57:31 2024 -0400
21651: Change io panel json tab to virtual list, fix layout issues
Arvados-DCO-1.1-Signed-off-by: Stephen Smith <stephen at curii.com>
diff --git a/services/workbench2/src/views/process-panel/process-io-card.tsx b/services/workbench2/src/views/process-panel/process-io-card.tsx
index 25bcb19e78..d9e7b87c92 100644
--- a/services/workbench2/src/views/process-panel/process-io-card.tsx
+++ b/services/workbench2/src/views/process-panel/process-io-card.tsx
@@ -65,7 +65,7 @@ import { ProcessOutputCollectionFiles } from "./process-output-collection-files"
import { Process } from "store/processes/process";
import { navigateTo } from "store/navigation/navigation-action";
import classNames from "classnames";
-import { DefaultCodeSnippet } from "components/default-code-snippet/default-code-snippet";
+import { DefaultVirtualCodeSnippet } from "components/default-code-snippet/default-virtual-code-snippet";
import { KEEP_URL_REGEX } from "models/resource";
import { FixedSizeList } from 'react-window';
import AutoSizer from "react-virtualized-auto-sizer";
@@ -82,6 +82,7 @@ type CssRules =
| "paramTableRoot"
| "paramTableCellText"
| "mountsTableRoot"
+ | "jsonWrapper"
| "keepLink"
| "collectionLink"
| "secondaryVal"
@@ -122,7 +123,7 @@ const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
color: theme.customs.colors.greyD,
fontSize: "1.875rem",
},
- // Applies to each tab's content
+ // Applies to table tab's content
tableWrapper: {
height: "auto",
maxHeight: `calc(100% - ${theme.spacing.unit * 6}px)`,
@@ -206,6 +207,10 @@ const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
paddingRight: "25px",
},
},
+ // JSON tab wrapper
+ jsonWrapper: {
+ height: `calc(100% - ${theme.spacing.unit * 6}px)`,
+ },
keepLink: {
color: theme.palette.primary.main,
textDecoration: "none",
@@ -418,7 +423,7 @@ export const ProcessIOCard = withStyles(styles)(
</div>
)}
{(mainProcTabState === 1 || !hasParams) && (
- <div className={classes.tableWrapper}>
+ <div className={classes.jsonWrapper}>
<ProcessIORaw data={raw} />
</div>
)}
@@ -505,7 +510,7 @@ export const ProcessIOCard = withStyles(styles)(
</>
)}
{isRawLoaded && (subProcTabState === 1 || (!hasInputMounts && !hasOutputCollecton)) && (
- <div className={classes.tableWrapper}>
+ <div className={classes.jsonWrapper}>
<ProcessIORaw data={raw} />
</div>
)}
@@ -650,9 +655,9 @@ interface ProcessIORawDataProps {
}
const ProcessIORaw = withStyles(styles)(({ data }: ProcessIORawDataProps) => (
- <Paper elevation={0} style={{minWidth: "100%"}}>
- <DefaultCodeSnippet
- lines={[JSON.stringify(data, null, 2)]}
+ <Paper elevation={0} style={{minWidth: "100%", height: "100%"}}>
+ <DefaultVirtualCodeSnippet
+ lines={JSON.stringify(data, null, 2).split('\n')}
linked
/>
</Paper>
commit ff1759078071c52b857afdbe64713ebf0833fae4
Author: Stephen Smith <stephen at curii.com>
Date: Fri Apr 5 19:21:19 2024 -0400
21651: Create CopyResultToClipboard to format cmd for clipboard using callback
Performs formatting on large text only when clicked
Arvados-DCO-1.1-Signed-off-by: Stephen Smith <stephen at curii.com>
diff --git a/services/workbench2/src/components/copy-to-clipboard/copy-result-to-clipboard.ts b/services/workbench2/src/components/copy-to-clipboard/copy-result-to-clipboard.ts
new file mode 100644
index 0000000000..129002b247
--- /dev/null
+++ b/services/workbench2/src/components/copy-to-clipboard/copy-result-to-clipboard.ts
@@ -0,0 +1,63 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import React from 'react';
+import { ReactElementLike } from 'prop-types';
+import copy from 'copy-to-clipboard';
+
+interface CopyToClipboardProps {
+ getText: (() => string);
+ children: ReactElementLike;
+ onCopy?(text: string, result: boolean): void;
+ options?: {
+ debug?: boolean;
+ message?: string;
+ format?: string; // MIME type
+ };
+}
+
+export default class CopyResultToClipboard extends React.PureComponent<CopyToClipboardProps> {
+ static defaultProps = {
+ onCopy: undefined,
+ options: undefined
+ };
+
+ onClick = event => {
+ const {
+ getText,
+ onCopy,
+ children,
+ options
+ } = this.props;
+
+ const elem = React.Children.only(children);
+
+ const text = getText();
+
+ const result = copy(text, options);
+
+ if (onCopy) {
+ onCopy(text, result);
+ }
+
+ // Bypass onClick if it was present
+ if (elem && elem.props && typeof elem.props.onClick === 'function') {
+ elem.props.onClick(event);
+ }
+ };
+
+
+ render() {
+ const {
+ getText: _getText,
+ onCopy: _onCopy,
+ options: _options,
+ children,
+ ...props
+ } = this.props;
+ const elem = React.Children.only(children);
+
+ return React.cloneElement(elem, {...props, onClick: this.onClick});
+ }
+}
diff --git a/services/workbench2/src/views/process-panel/process-cmd-card.tsx b/services/workbench2/src/views/process-panel/process-cmd-card.tsx
index 488b8d7fb4..6cef09b4a8 100644
--- a/services/workbench2/src/views/process-panel/process-cmd-card.tsx
+++ b/services/workbench2/src/views/process-panel/process-cmd-card.tsx
@@ -21,7 +21,7 @@ import { MPVPanelProps } from 'components/multi-panel-view/multi-panel-view';
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';
+import CopyResultToClipboard from 'components/copy-to-clipboard/copy-result-to-clipboard';
type CssRules = 'card' | 'content' | 'title' | 'header' | 'avatar' | 'iconHeader';
@@ -83,6 +83,12 @@ export const ProcessCmdCard = withStyles(styles)(
return `${indent}${line}${lineBreak}`;
};
+ const formatClipboardText = (command: string[]) => (): string => (
+ command.map((v) =>
+ shellescape([v]) // Escape each arg separately
+ ).join(' ')
+ );
+
return (
<Card className={classes.card}>
<CardHeader
@@ -102,12 +108,12 @@ export const ProcessCmdCard = withStyles(styles)(
<Grid item>
<Tooltip title="Copy link to clipboard" disableFocusListener>
<IconButton>
- <CopyToClipboard
- text={" "}
+ <CopyResultToClipboard
+ getText={formatClipboardText(process.containerRequest.command)}
onCopy={() => onCopy("Command copied to clipboard")}
>
<CopyIcon />
- </CopyToClipboard>
+ </CopyResultToClipboard>
</IconButton>
</Tooltip>
</Grid>
commit 2bbea832f0a7a16e70b85b2e2ad9ca4637a80118
Author: Stephen Smith <stephen at curii.com>
Date: Fri Apr 5 21:46:29 2024 -0400
21651: Add line formatter to VirtualCodeSnippet to do cmd card line processing
Arvados-DCO-1.1-Signed-off-by: Stephen Smith <stephen at curii.com>
diff --git a/services/workbench2/src/components/code-snippet/virtual-code-snippet.tsx b/services/workbench2/src/components/code-snippet/virtual-code-snippet.tsx
index bc43d5d9f2..09db2c0426 100644
--- a/services/workbench2/src/components/code-snippet/virtual-code-snippet.tsx
+++ b/services/workbench2/src/components/code-snippet/virtual-code-snippet.tsx
@@ -32,7 +32,7 @@ const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
export interface CodeSnippetDataProps {
lines: string[];
- lineTransformer?: (line: string) => string;
+ lineFormatter?: (lines: string[], index: number) => string;
className?: string;
apiResponse?: boolean;
linked?: boolean;
@@ -49,10 +49,11 @@ const mapStateToProps = (state: RootState): CodeSnippetAuthProps => ({
});
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>
- );
+ ({ classes, lines, lineFormatter, linked, className, apiResponse, dispatch, auth }: CodeSnippetProps & CodeSnippetAuthProps & DispatchProp) => {
+ const RenderRow = ({index, style}) => {
+ const lineContents = lineFormatter ? lineFormatter(lines, index) : lines[index];
+ return <span style={style}>{linked ? renderLinks(auth, dispatch)(lineContents) : lineContents}</span>
+ };
return <Typography
component="div"
diff --git a/services/workbench2/src/views/process-panel/process-cmd-card.tsx b/services/workbench2/src/views/process-panel/process-cmd-card.tsx
index d7b47653e6..488b8d7fb4 100644
--- a/services/workbench2/src/views/process-panel/process-cmd-card.tsx
+++ b/services/workbench2/src/views/process-panel/process-cmd-card.tsx
@@ -71,18 +71,17 @@ export const ProcessCmdCard = withStyles(styles)(
classes,
doHidePanel,
}: ProcessCmdCardProps) => {
- const command = process.containerRequest.command.map((v) =>
- shellescape([v]) // Escape each arg separately
- );
- let formattedCommand = [...command];
- formattedCommand.forEach((item, i, arr) => {
+ const formatLine = (lines: string[], index: number): string => {
+ // Escape each arg separately
+ let line = shellescape([lines[index]])
// Indent lines after the first
- const indent = i > 0 ? ' ' : '';
- // Escape newlines on every non-last arg when there are multiple lines
- const lineBreak = arr.length > 1 && i < arr.length - 1 ? ' \\' : '';
- arr[i] = `${indent}${item}${lineBreak}`;
- });
+ const indent = index > 0 ? ' ' : '';
+ // Add backslash "escaped linebreak"
+ const lineBreak = lines.length > 1 && index < lines.length - 1 ? ' \\' : '';
+
+ return `${indent}${line}${lineBreak}`;
+ };
return (
<Card className={classes.card}>
@@ -104,7 +103,7 @@ export const ProcessCmdCard = withStyles(styles)(
<Tooltip title="Copy link to clipboard" disableFocusListener>
<IconButton>
<CopyToClipboard
- text={command.join(" ")}
+ text={" "}
onCopy={() => onCopy("Command copied to clipboard")}
>
<CopyIcon />
@@ -128,7 +127,11 @@ export const ProcessCmdCard = withStyles(styles)(
}
/>
<CardContent className={classes.content}>
- <DefaultVirtualCodeSnippet lines={formattedCommand} linked />
+ <DefaultVirtualCodeSnippet
+ lines={process.containerRequest.command}
+ lineFormatter={formatLine}
+ linked
+ />
</CardContent>
</Card>
);
commit a9a011ed1f1daec47a9bc306f13ff91a63954e42
Author: Stephen Smith <stephen at curii.com>
Date: Fri Apr 5 17:43:16 2024 -0400
21651: Add virtual code snippet, implement in cmd card
Arvados-DCO-1.1-Signed-off-by: Stephen Smith <stephen at curii.com>
diff --git a/services/workbench2/src/components/code-snippet/code-snippet.tsx b/services/workbench2/src/components/code-snippet/code-snippet.tsx
index 47d8fe1bf0..3be1e4fc71 100644
--- a/services/workbench2/src/components/code-snippet/code-snippet.tsx
+++ b/services/workbench2/src/components/code-snippet/code-snippet.tsx
@@ -66,7 +66,7 @@ export const CodeSnippet = withStyles(styles)(connect(mapStateToProps)(
</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);
diff --git a/services/workbench2/src/components/code-snippet/virtual-code-snippet.tsx b/services/workbench2/src/components/code-snippet/virtual-code-snippet.tsx
new file mode 100644
index 0000000000..bc43d5d9f2
--- /dev/null
+++ b/services/workbench2/src/components/code-snippet/virtual-code-snippet.tsx
@@ -0,0 +1,75 @@
+// 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>;
+}));
diff --git a/services/workbench2/src/components/default-code-snippet/default-virtual-code-snippet.tsx b/services/workbench2/src/components/default-code-snippet/default-virtual-code-snippet.tsx
new file mode 100644
index 0000000000..581f0f4acc
--- /dev/null
+++ b/services/workbench2/src/components/default-code-snippet/default-virtual-code-snippet.tsx
@@ -0,0 +1,31 @@
+// 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>;
diff --git a/services/workbench2/src/views/process-panel/process-cmd-card.tsx b/services/workbench2/src/views/process-panel/process-cmd-card.tsx
index 478b0bc56f..d7b47653e6 100644
--- a/services/workbench2/src/views/process-panel/process-cmd-card.tsx
+++ b/services/workbench2/src/views/process-panel/process-cmd-card.tsx
@@ -18,7 +18,7 @@ import {
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';
@@ -31,7 +31,7 @@ const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
},
header: {
paddingTop: theme.spacing.unit,
- paddingBottom: theme.spacing.unit,
+ paddingBottom: 0,
},
iconHeader: {
fontSize: '1.875rem',
@@ -42,8 +42,9 @@ const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
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,
}
@@ -52,7 +53,7 @@ const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
overflow: 'hidden',
paddingTop: theme.spacing.unit * 0.5,
color: theme.customs.colors.greyD,
- fontSize: '1.875rem'
+ fontSize: '1.875rem'
},
});
@@ -127,7 +128,7 @@ export const ProcessCmdCard = withStyles(styles)(
}
/>
<CardContent className={classes.content}>
- <DefaultCodeSnippet lines={formattedCommand} linked />
+ <DefaultVirtualCodeSnippet lines={formattedCommand} linked />
</CardContent>
</Card>
);
diff --git a/services/workbench2/src/views/process-panel/process-panel-root.tsx b/services/workbench2/src/views/process-panel/process-panel-root.tsx
index 2a9b3882e8..21f38b0938 100644
--- a/services/workbench2/src/views/process-panel/process-panel-root.tsx
+++ b/services/workbench2/src/views/process-panel/process-panel-root.tsx
@@ -198,6 +198,7 @@ export const ProcessPanelRoot = withStyles(styles)(
<MPVPanelContent
forwardProps
xs="auto"
+ maxHeight={"50%"}
data-cy="process-cmd">
<ProcessCmdCard
onCopy={props.onCopyToClipboard}
-----------------------------------------------------------------------
hooks/post-receive
--
More information about the arvados-commits
mailing list