Skip to content

Commit

Permalink
feat: add copy to clipboard buttons (#673)
Browse files Browse the repository at this point in the history
* feat: add copy icon

* feat: add button to copy filtered logs to clipboard

* feat: add button to copy single log lines to clipboard

* feat: add copy to clipboard button to highlight component

* fix: use anonymous function to copy log line to clipboard
  • Loading branch information
Panzer1119 authored Jan 11, 2024
1 parent ca405af commit babcc64
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 3 deletions.
8 changes: 8 additions & 0 deletions packages/ui/src/components/Highlight/Highlight.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.codeContainerWrapper {
display: flex;
align-items: flex-start;
}

.codeContainerWrapper pre {
margin-right: 1ch;
}
14 changes: 11 additions & 3 deletions packages/ui/src/components/Highlight/Highlight.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import cn from 'clsx';
import React from 'react';
import { asyncHighlight } from '../../utils/highlight/highlight';
import s from './Highlight.module.css';
import { Button } from '../Button/Button';
import { CopyIcon } from '../Icons/Copy';

interface HighlightProps {
language: 'json' | 'stacktrace';
Expand Down Expand Up @@ -32,9 +35,14 @@ export class Highlight extends React.Component<HighlightProps> {
public render() {
const { language } = this.props;
return (
<pre ref={this.codeRef}>
<code className={cn('hljs', language)} />
</pre>
<div className={s.codeContainerWrapper}>
<pre ref={this.codeRef}>
<code className={cn('hljs', language)} />
</pre>
<Button onClick={() => navigator.clipboard.writeText(this.props.children ?? '')}>
<CopyIcon />
</Button>
</div>
);
}

Expand Down
7 changes: 7 additions & 0 deletions packages/ui/src/components/Icons/Copy.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import React from 'react';

export const CopyIcon = () => (
<svg xmlns="http://www.w3.org/2000/svg" height="16" width="14" viewBox="0 0 448 512">
<path d="M208 0H332.1c12.7 0 24.9 5.1 33.9 14.1l67.9 67.9c9 9 14.1 21.2 14.1 33.9V336c0 26.5-21.5 48-48 48H208c-26.5 0-48-21.5-48-48V48c0-26.5 21.5-48 48-48zM48 128h80v64H64V448H256V416h64v48c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V176c0-26.5 21.5-48 48-48z" />
</svg>
);
Original file line number Diff line number Diff line change
Expand Up @@ -81,3 +81,13 @@
.toolbar .searchBar {
width: 100%;
}

.logLineCopyButton {
opacity: 0;
transition: opacity 150ms ease;
margin-inline-start: 1ch;
}

li:hover .logLineCopyButton {
opacity: 1;
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { InputField } from '../../../../Form/InputField/InputField';
import { FullscreenIcon } from '../../../../Icons/Fullscreen';
import { PauseIcon } from '../../../../Icons/Pause';
import { PlayIcon } from '../../../../Icons/Play';
import { CopyIcon } from '../../../../Icons/Copy';
import { Button } from '../../../../Button/Button';
import s from './JobLogs.module.css';

Expand All @@ -31,6 +32,10 @@ const onClickFullScreen = (el: HTMLElement | null) => async () => {
return document.exitFullscreen();
};

const copyLogToClipboard = (log: LogType) => async () => {
navigator.clipboard.writeText(log.message);
};

const shouldShow = (log: LogType, keyword = '') => {
return !keyword || new RegExp(`${keyword}`, 'i').test(log.message);
};
Expand Down Expand Up @@ -76,6 +81,11 @@ export const JobLogs = ({ actions, job }: JobLogsProps) => {
setLiveLogs(!liveLogs);
};

const copyLogsToShowToClipboard = () => {
const text: string = logsToShow.map((log) => log.message).join('\n');
navigator.clipboard.writeText(text);
};

const onSearch = (event: SyntheticEvent<HTMLInputElement>) => {
if (!event.currentTarget?.value) {
setKeyword('');
Expand Down Expand Up @@ -116,6 +126,11 @@ export const JobLogs = ({ actions, job }: JobLogsProps) => {
<FullscreenIcon />
</Button>
</li>
<li>
<Button onClick={copyLogsToShowToClipboard}>
<CopyIcon />
</Button>
</li>
</ul>
<div className={s.preWrapper}>
<pre>
Expand All @@ -127,6 +142,13 @@ export const JobLogs = ({ actions, job }: JobLogsProps) => {
data-line-number={`${log.lineNumber}.`}
>
{log.message}
<Button
onClick={() => copyLogToClipboard(log)}
className={s.logLineCopyButton}
tabIndex={-1}
>
<CopyIcon />
</Button>
</li>
))}
</ol>
Expand Down

0 comments on commit babcc64

Please sign in to comment.