Skip to content

Commit

Permalink
Add a copy button for comparison table rows (#2216)
Browse files Browse the repository at this point in the history
* Add a copy button for comparision table rows

* Let the user select the text of the comparison row path

* Disable toggling while selecting comparison row path

* Add more tests

* Revert colspan move

* Revert change
  • Loading branch information
sroy3 authored Aug 19, 2022
1 parent 96663c1 commit 7b6d699
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ import {
} from './ComparisonTableRow'
import styles from '../styles.module.scss'
import { plotsReducers } from '../../store'
import {
clearSelection,
createWindowTextSelection
} from '../../../test/selection'

jest.mock('../../../shared/api')

Expand Down Expand Up @@ -67,27 +71,56 @@ describe('ComparisonTableRow', () => {
renderRow()

const rowToggler = screen.getByText(basicProps.path)
const [plot] = screen.getAllByAltText(
/(Plot of path\/to\/the-file\/image\.png)/
)
const [row] = screen.getAllByTestId('row-images')

/* eslint-disable testing-library/no-node-access */
expect(plot.parentElement).not.toHaveClass(styles.cellHidden)
expect(row).not.toHaveClass(styles.cellHidden)

fireEvent.click(rowToggler, {
bubbles: true,
cancelable: true
})

/* eslint-disable testing-library/no-node-access */
expect(plot.parentElement).toHaveClass(styles.cellHidden)
expect(row).toHaveClass(styles.cellHidden)

fireEvent.click(rowToggler, {
bubbles: true,
cancelable: true
})

/* eslint-disable testing-library/no-node-access */
expect(plot.parentElement).not.toHaveClass(styles.cellHidden)
expect(row).not.toHaveClass(styles.cellHidden)
})

it('should not toggle the row if the path was selected', () => {
renderRow()

const rowToggler = screen.getByText(basicProps.path)
const [row] = screen.getAllByTestId('row-images')

createWindowTextSelection(basicProps.path, 5)
fireEvent.click(rowToggler)

expect(row).not.toHaveClass(styles.cellHidden)

clearSelection()
fireEvent.click(rowToggler)

expect(row).toHaveClass(styles.cellHidden)

createWindowTextSelection(basicProps.path, 0)
fireEvent.click(rowToggler)

expect(row).not.toHaveClass(styles.cellHidden)
})

it('should toggle the row if some other path is selected', () => {
renderRow()

const rowToggler = screen.getByText(basicProps.path)
const [row] = screen.getAllByTestId('row-images')

createWindowTextSelection('other/path/img.gif', 5)
fireEvent.click(rowToggler)

expect(row).toHaveClass(styles.cellHidden)
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { RefreshButton } from '../../../shared/components/button/RefreshButton'
import { sendMessage } from '../../../shared/vscode'
import { ChevronDown, ChevronRight } from '../../../shared/components/icons'
import { PlotsState } from '../../store'
import { CopyButton } from '../../../shared/components/copyButton/CopyButton'

export interface ComparisonTableRowProps {
path: string
Expand All @@ -28,16 +29,28 @@ export const ComparisonTableRow: React.FC<ComparisonTableRowProps> = ({
)
const [isShown, setIsShown] = useState(true)

const toggleIsShownState = () => setIsShown(!isShown)
const toggleIsShownState = () => {
const selection = window.getSelection()
if (
selection?.focusNode?.nodeValue === path &&
selection.anchorOffset !== selection.focusOffset
) {
return
}
setIsShown(!isShown)
}

return (
<tbody>
<tr>
<td className={cx({ [styles.pinnedColumnCell]: pinnedColumn })}>
<button className={styles.rowToggler} onClick={toggleIsShownState}>
<Icon icon={isShown ? ChevronDown : ChevronRight} />
{path}
</button>
<div className={styles.rowPath}>
<button className={styles.rowToggler} onClick={toggleIsShownState}>
<Icon icon={isShown ? ChevronDown : ChevronRight} />
{path}
</button>
<CopyButton value={path} className={styles.copyButton} />
</div>
</td>
{nbColumns > 1 && <td colSpan={nbColumns - 1}></td>}
</tr>
Expand All @@ -56,6 +69,7 @@ export const ComparisonTableRow: React.FC<ComparisonTableRowProps> = ({
})}
>
<div
data-testid="row-images"
className={cx(styles.cell, { [styles.cellHidden]: !isShown })}
>
{missing ? (
Expand Down
17 changes: 16 additions & 1 deletion webview/src/plots/components/comparisonTable/styles.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -90,11 +90,11 @@ $gap: 4px;

.rowToggler {
border: none;
width: 100%;
background: none;
color: $fg-color;
text-align: left;
display: flex;
user-select: text;

svg {
fill: $fg-color;
Expand Down Expand Up @@ -173,3 +173,18 @@ $gap: 4px;
opacity: 1;
color: $bg-color;
}

.copyButton {
display: none;
}

.rowPath {
display: flex;
justify-content: flex-start;
align-items: center;

&:hover .copyButton {
display: inline;
font-size: 0.8125rem;
}
}
14 changes: 14 additions & 0 deletions webview/src/test/selection.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
export const createWindowTextSelection = (
nodeValue: string | null,
offset = 0
) => {
window.getSelection = () => {
return {
anchorOffset: 1,
focusNode: nodeValue ? ({ nodeValue } as Node) : null,
focusOffset: 1 + offset
} as Selection
}
}

export const clearSelection = () => createWindowTextSelection(null)

0 comments on commit 7b6d699

Please sign in to comment.