X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/a9a011ed1f1daec47a9bc306f13ff91a63954e42..8dde19120c7940fda1eb2698b3bcb72f37ca6e66:/services/workbench2/src/components/code-snippet/virtual-code-snippet.tsx?ds=sidebyside 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..e45289f02c 100644 --- a/services/workbench2/src/components/code-snippet/virtual-code-snippet.tsx +++ b/services/workbench2/src/components/code-snippet/virtual-code-snippet.tsx @@ -3,20 +3,25 @@ // SPDX-License-Identifier: AGPL-3.0 import React from 'react'; -import { StyleRulesCallback, WithStyles, Typography, withStyles } from '@material-ui/core'; +import { StyleRulesCallback, WithStyles, Typography, withStyles, Tooltip, IconButton } from '@material-ui/core'; import { ArvadosTheme } from 'common/custom-theme'; import classNames from 'classnames'; -import { connect, DispatchProp } from 'react-redux'; +import { connect } 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"; +import CopyResultToClipboard from 'components/copy-to-clipboard/copy-result-to-clipboard'; +import { CopyIcon } from 'components/icon/icon'; +import { SnackbarKind, snackbarActions } from 'store/snackbar/snackbar-actions'; +import { Dispatch } from "redux"; -type CssRules = 'root' | 'space' | 'content' ; +type CssRules = 'root' | 'space' | 'content' | 'copyButton' ; const styles: StyleRulesCallback = (theme: ArvadosTheme) => ({ root: { + position: 'relative', boxSizing: 'border-box', height: '100%', padding: theme.spacing.unit, @@ -28,35 +33,79 @@ const styles: StyleRulesCallback = (theme: ArvadosTheme) => ({ maxHeight: '100%', height: '100vh', }, + copyButton: { + position: 'absolute', + top: '8px', + right: '8px', + zIndex: 100, + }, }); export interface CodeSnippetDataProps { lines: string[]; - lineTransformer?: (line: string) => string; + lineFormatter?: (lines: string[], index: number) => string; className?: string; apiResponse?: boolean; linked?: boolean; + copyButton?: boolean; +} + +export interface CodeSnippetActionProps { + renderLinks: (auth: FederationConfig) => (text: string) => JSX.Element; + onCopyToClipboard: () => void; } interface CodeSnippetAuthProps { auth: FederationConfig; } -type CodeSnippetProps = CodeSnippetDataProps & WithStyles; +type CodeSnippetProps = CodeSnippetDataProps & CodeSnippetActionProps & WithStyles; 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}) => ( - {linked ? renderLinks(auth, dispatch)(lines[index]) : lines[index]} +const mapDispatchToProps = (dispatch: Dispatch): CodeSnippetActionProps => ({ + renderLinks: (auth: FederationConfig) => renderLinks(auth, dispatch), + onCopyToClipboard: () => { + dispatch( + snackbarActions.OPEN_SNACKBAR({ + message: "Contents copied to clipboard", + hideDuration: 2000, + kind: SnackbarKind.SUCCESS, + }) ); + }, +}); + +export const VirtualCodeSnippet = withStyles(styles)(connect(mapStateToProps, mapDispatchToProps)( + ({ classes, lines, lineFormatter, linked, copyButton, renderLinks, onCopyToClipboard, className, apiResponse, auth }: CodeSnippetProps & CodeSnippetAuthProps) => { + const RenderRow = ({index, style}) => { + const lineContents = lineFormatter ? lineFormatter(lines, index) : lines[index]; + return {linked ? renderLinks(auth)(lineContents) : lineContents} + }; + + const formatClipboardText = (lines: string[]) => () => { + return lines.join('\n'); + }; + + return + {copyButton && + + + + + + + + } {({ height, width }) =>