Skip to content

Commit

Permalink
Switch experiment table radio buttons to plot icons
Browse files Browse the repository at this point in the history
  • Loading branch information
mattseddon committed Jun 15, 2023
1 parent b90644c commit 45d893c
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 93 deletions.
8 changes: 4 additions & 4 deletions webview/src/experiments/components/App.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -668,10 +668,10 @@ describe('App', () => {

expect(screen.queryByRole('tooltip')).not.toBeInTheDocument()

const radioButton = within(getRow(EXPERIMENT_WORKSPACE_ID)).getByTestId(
const plotIcon = within(getRow(EXPERIMENT_WORKSPACE_ID)).getByTestId(
'row-action-plot'
)
fireEvent.mouseEnter(radioButton)
fireEvent.mouseEnter(plotIcon)

advanceTimersByTime(NORMAL_TOOLTIP_DELAY[0])
const tooltip = screen.queryByRole('tooltip')
Expand All @@ -692,8 +692,8 @@ describe('App', () => {

expect(screen.queryByRole('tooltip')).not.toBeInTheDocument()

const radioButton = within(getRow('main')).getByTestId('row-action-star')
fireEvent.mouseEnter(radioButton)
const starIcon = within(getRow('main')).getByTestId('row-action-star')
fireEvent.mouseEnter(starIcon)

advanceTimersByTime(NORMAL_TOOLTIP_DELAY[0])
const tooltip = screen.queryByRole('tooltip')
Expand Down
90 changes: 72 additions & 18 deletions webview/src/experiments/components/table/body/CellRowActions.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,37 @@
import React, { MouseEventHandler, ReactElement } from 'react'
import { VSCodeCheckbox } from '@vscode/webview-ui-toolkit/react'
import {
VSCodeCheckbox,
VSCodeProgressRing
} from '@vscode/webview-ui-toolkit/react'
import cx from 'classnames'
import {
ExperimentStatus,
isQueued
isQueued,
isRunning
} from 'dvc/src/experiments/webview/contract'
import { CellHintTooltip } from './CellHintTooltip'
import { Indicator } from '../Indicators'
import { addStarredFilter, openPlotsWebview } from '../../../util/messages'
import styles from '../styles.module.scss'
import { clickAndEnterProps } from '../../../../util/props'
import { Clock, StarFull, StarEmpty } from '../../../../shared/components/icons'
import {
Clock,
StarFull,
StarEmpty,
GraphScatter
} from '../../../../shared/components/icons'

export type CellRowActionsProps = {
bulletColor?: string
isRowSelected: boolean
plotColor?: string
showSubRowStates: boolean
starred?: boolean
status?: ExperimentStatus
subRowStates: {
plotSelections: number
running: number
selections: number
stars: number
plotSelections: number
}
toggleExperiment: () => void
toggleRowSelection: () => void
Expand All @@ -32,7 +43,7 @@ type CellRowActionProps = {
subRowsAffected: number
children: ReactElement
testId: string
tooltipContent: string | ReactElement
tooltipContent: string | ReactElement | null
onClick?: MouseEventHandler
}

Expand All @@ -46,20 +57,40 @@ const CellRowAction: React.FC<CellRowActionProps> = ({
}) => {
const count = (showSubRowStates && subRowsAffected) || 0

return (
<CellHintTooltip tooltipContent={tooltipContent}>
<div className={styles.rowActions} data-testid={testId}>
<Indicator onClick={onClick} count={count}>
{children}
</Indicator>
</div>
</CellHintTooltip>
const action = (
<div className={styles.rowActions} data-testid={testId}>
<Indicator onClick={onClick} count={count}>
{children}
</Indicator>
</div>
)

return tooltipContent ? (
<CellHintTooltip tooltipContent={tooltipContent}>{action}</CellHintTooltip>
) : (
action
)
}

const getTooltipContent = (determiner: boolean, action: string): string =>
'Click to ' + (determiner ? `un${action}` : action)

const getRunningTooltipContent = (
running: boolean,
showSubRowStates: boolean,
subRowsRunning: number
): string | null => {
if (running) {
return 'Experiment is currently running'
}

if (showSubRowStates && subRowsRunning) {
return `There are currently ${subRowsRunning} running under this commit.`
}

return null
}

type ClickableTooltipContentProps = {
clickableText: string
helperText: string
Expand All @@ -81,16 +112,18 @@ const ClickableTooltipContent: React.FC<ClickableTooltipContentProps> = ({
)

export const CellRowActions: React.FC<CellRowActionsProps> = ({
bulletColor,
plotColor,
status,
toggleExperiment,
isRowSelected,
showSubRowStates,
starred,
subRowStates: { selections, stars, plotSelections },
subRowStates: { plotSelections, running: subRowsRunning, selections, stars },
toggleRowSelection,
toggleStarred
}) => {
const running = isRunning(status)

return (
<>
<CellRowAction
Expand All @@ -104,6 +137,24 @@ export const CellRowActions: React.FC<CellRowActionsProps> = ({
checked={isRowSelected}
/>
</CellRowAction>
<CellRowAction
showSubRowStates={showSubRowStates}
subRowsAffected={subRowsRunning}
testId="row-action-running-indicator"
tooltipContent={getRunningTooltipContent(
running,
showSubRowStates,
subRowsRunning
)}
>
{running ? (
<VSCodeProgressRing
className={cx(styles.running, 'chromatic-ignore')}
/>
) : (
<div />
)}
</CellRowAction>
<CellRowAction
showSubRowStates={showSubRowStates}
subRowsAffected={stars}
Expand Down Expand Up @@ -141,13 +192,16 @@ export const CellRowActions: React.FC<CellRowActionsProps> = ({
tooltipContent={
<ClickableTooltipContent
clickableText="Open the plots view"
helperText={getTooltipContent(!!bulletColor, 'plot')}
helperText={getTooltipContent(!!plotColor, 'plot')}
onClick={openPlotsWebview}
/>
}
onClick={toggleExperiment}
>
<span className={styles.bullet} style={{ color: bulletColor }} />
<GraphScatter
style={{ fill: plotColor }}
className={styles.plotIcon}
/>
</CellRowAction>
)}
</>
Expand Down
26 changes: 8 additions & 18 deletions webview/src/experiments/components/table/body/Row.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import cx from 'classnames'
import React, { useCallback, useContext, useMemo } from 'react'
import { useSelector } from 'react-redux'
import { EXPERIMENT_WORKSPACE_ID } from 'dvc/src/cli/dvc/contract'
import { isQueued, isRunning } from 'dvc/src/experiments/webview/contract'
import { isRunning } from 'dvc/src/experiments/webview/contract'
import { FirstCell, CellWrapper } from './Cell'
import { RowContextMenu } from './RowContextMenu'
import styles from '../styles.module.scss'
Expand All @@ -24,9 +24,8 @@ export const RowContent: React.FC<
const changes = useSelector(
(state: ExperimentsState) => state.tableData.changes
)
const { getVisibleCells, original, index, getIsExpanded, subRows } = row
const { branch, displayColor, error, starred, id, status, selected } =
original
const { getVisibleCells, original, getIsExpanded, subRows } = row
const { branch, displayColor, error, starred, id } = original
const [firstCell, ...cells] = getVisibleCells()
const isWorkspace = id === EXPERIMENT_WORKSPACE_ID
const changesIfWorkspace = isWorkspace ? changes : undefined
Expand All @@ -53,6 +52,9 @@ export const RowContent: React.FC<
const plotSelections =
subRows?.filter(subRow => subRow.original.selected).length ?? 0

const running =
subRows?.filter(subRow => isRunning(subRow.original.status)).length ?? 0

const selections =
subRows?.filter(
subRow =>
Expand All @@ -63,16 +65,12 @@ export const RowContent: React.FC<

return {
plotSelections,
running,
selections,
stars
}
}, [subRows, selectedRows])

const running = isRunning(status)
const queued = isQueued(status)
const unselected = selected === false
const isOdd = index % 2 !== 0 && !isRowSelected

return (
<ContextMenu content={<RowContextMenu row={row} />}>
<tr
Expand All @@ -82,14 +80,6 @@ export const RowContent: React.FC<
styles.bodyRow,
styles.row,
{
[styles.runningExperiment]: running,
[styles.queuedExperiment]: queued,
[styles.unselectedExperiment]: !running && !queued && unselected,
[styles.normalExperiment]: !running && !queued && !unselected,
[styles.oddRow]: isOdd,
[styles.evenRow]: !isOdd,
[styles.workspaceRow]: isWorkspace,
[styles.normalRow]: !isWorkspace,
[styles.rowSelected]: isRowSelected
}
)}
Expand All @@ -100,7 +90,7 @@ export const RowContent: React.FC<
<FirstCell
cell={firstCell}
changesIfWorkspace={!!changesIfWorkspace?.length}
bulletColor={displayColor}
plotColor={displayColor}
starred={starred}
isRowSelected={isRowSelected}
showSubRowStates={!getIsExpanded() && !isWorkspace}
Expand Down
69 changes: 17 additions & 52 deletions webview/src/experiments/components/table/styles.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ $row-border: 1px solid $border-color;
$edge-padding: 0.8rem;
$cell-padding: 0.5rem;
$workspace-row-edge-margin: $edge-padding - $cell-padding;
$bullet-size: calc(var(--design-unit) * 4px);
$bullet-size: calc(var(--design-unit) * 8px);
$badge-size: 0.85rem;

// Extendable Silent Rules
Expand Down Expand Up @@ -451,6 +451,14 @@ $badge-size: 0.85rem;
visibility: hidden;
}

.running {
visibility: visible;
}

.plotIcon {
visibility: visible;
}

.timestampInnerCell {
height: 42px;
}
Expand Down Expand Up @@ -576,7 +584,7 @@ $badge-size: 0.85rem;
height: 100%;

&:first-child {
margin-right: 20px;
margin-right: 4px;
}

.nestedRow & {
Expand Down Expand Up @@ -626,57 +634,14 @@ $badge-size: 0.85rem;
font-size: 0.65rem;
}

.bullet {
visibility: visible;
align-items: center;
background: $checkbox-background;
border-radius: $bullet-size;
border: calc(var(--border-width) * 1px) solid $checkbox-border;
color: $icon-color;
cursor: pointer;
display: flex;
height: $bullet-size;
justify-content: center;
outline: none;
padding: 0;
position: relative;
width: $bullet-size;

&::before {
display: inline-block;
position: relative;
content: '';
border-radius: 99px;
width: 6px;
height: 6px;
z-index: 2;

.normalExperiment & {
line-height: 0;
background: currentcolor;
border-radius: 100%;
}

.unselectedExperiment & {
width: 4px;
height: 4px;
vertical-align: middle;
border: 1px solid $icon-color;
background-color: $checkbox-background;
}
.plotIcon {
margin-top: 4px;
}

.runningExperiment & {
width: 4px;
height: 4px;
vertical-align: middle;
border: 1.5px solid $checkbox-background;
border-radius: 100%;
border-right: 1.5px solid currentcolor;
border-top: 1.5px solid currentcolor;
animation: spin 1s cubic-bezier(0.53, 0.21, 0.29, 0.67) infinite;
background-color: $checkbox-background;
}
}
.running {
position: relative;
height: 16px;
width: 16px;
}

.queued {
Expand Down
5 changes: 4 additions & 1 deletion webview/src/plots/components/ribbon/RibbonBlock.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Revision } from 'dvc/src/plots/webview/contract'
import React from 'react'
import cx from 'classnames'
import { VSCodeProgressRing } from '@vscode/webview-ui-toolkit/react'
import styles from './styles.module.scss'
import { RibbonBlockTooltip } from './RibbonBlockTooltip'
Expand All @@ -19,7 +20,9 @@ const RevisionIcon: React.FC<{ fetched: boolean; errors?: string[] }> = ({
}) => (
<div className={styles.iconPlaceholder}>
{fetched && errors && '!'}
{!fetched && <VSCodeProgressRing className={styles.fetching} />}
{!fetched && (
<VSCodeProgressRing className={cx(styles.fetching, 'chromatic-ignore')} />
)}
</div>
)

Expand Down

0 comments on commit 45d893c

Please sign in to comment.