Skip to content

Commit

Permalink
Create (shared) section container component (#3440)
Browse files Browse the repository at this point in the history
* create shared section container component

* pull out toggle section from shared component
  • Loading branch information
mattseddon authored Mar 12, 2023
1 parent 78fe80b commit e52033f
Show file tree
Hide file tree
Showing 5 changed files with 253 additions and 211 deletions.
6 changes: 3 additions & 3 deletions webview/src/plots/components/App.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ import { EXPERIMENT_WORKSPACE_ID } from 'dvc/src/cli/dvc/contract'
import { VisualizationSpec } from 'react-vega'
import { App } from './App'
import { NewSectionBlock } from './templatePlots/TemplatePlots'
import { SectionDescription } from './PlotsContainer'
import {
CheckpointPlotsById,
plotDataStore,
Expand All @@ -55,6 +54,7 @@ import {
dragEnter,
dragLeave
} from '../../test/dragDrop'
import { SectionDescription } from '../../shared/components/sectionContainer/SectionContainer'
import { DragEnterDirection } from '../../shared/components/dragDrop/util'
import { clearSelection, createWindowTextSelection } from '../../test/selection'
import * as EventCurrentTargetDistances from '../../shared/components/dragDrop/currentTarget'
Expand Down Expand Up @@ -163,7 +163,7 @@ describe('App', () => {

const getCheckpointMenuItem = (position: number) =>
within(
screen.getAllByTestId('plots-container')[
screen.getAllByTestId('section-container')[
sectionPosition[Section.CHECKPOINT_PLOTS]
]
).getAllByTestId('icon-menu-item')[position]
Expand Down Expand Up @@ -899,7 +899,7 @@ describe('App', () => {
})

const [pickerButton] = within(
screen.getAllByTestId('plots-container')[
screen.getAllByTestId('section-container')[
sectionPosition[Section.CHECKPOINT_PLOTS]
]
).queryAllByTestId('icon-menu-item')
Expand Down
191 changes: 47 additions & 144 deletions webview/src/plots/components/PlotsContainer.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import cx from 'classnames'
import React, {
MouseEvent,
useEffect,
DetailedHTMLProps,
HTMLAttributes,
Expand All @@ -12,23 +11,12 @@ import { Section } from 'dvc/src/plots/webview/contract'
import { MessageFromWebviewType } from 'dvc/src/webview/contract'
import { PlotsPicker, PlotsPickerProps } from './PlotsPicker'
import styles from './styles.module.scss'
import { Icon } from '../../shared/components/Icon'
import { IconMenu } from '../../shared/components/iconMenu/IconMenu'
import { IconMenuItemProps } from '../../shared/components/iconMenu/IconMenuItem'
import { sendMessage } from '../../shared/vscode'
import Tooltip from '../../shared/components/tooltip/Tooltip'
import {
ChevronDown,
ChevronRight,
Info,
Lines,
Add,
Trash
} from '../../shared/components/icons'
import { isSelecting } from '../../util/strings'
import { isTooltip } from '../../util/helpers'
import { Lines, Add, Trash } from '../../shared/components/icons'
import { MinMaxSlider } from '../../shared/components/slider/MinMaxSlider'
import { PlotsState } from '../store'
import { SectionContainer } from '../../shared/components/sectionContainer/SectionContainer'

export interface PlotsContainerProps {
sectionCollapsed: boolean
Expand All @@ -43,58 +31,6 @@ export interface PlotsContainerProps {
hasItems?: boolean
}

export const SectionDescription = {
// "Trends"
[Section.CHECKPOINT_PLOTS]: (
<span data-testid="tooltip-checkpoint-plots">
Automatically generated and updated linear plots that show metric value
per epoch if{' '}
<a href="https://dvc.org/doc/user-guide/experiment-management/checkpoints">
checkpoints
</a>{' '}
are enabled.
</span>
),
// "Custom"
[Section.CUSTOM_PLOTS]: (
<span data-testid="tooltip-custom-plots">
Generated custom linear plots comparing chosen metrics and params in all
experiments in the table.
</span>
),
// "Images"
[Section.COMPARISON_TABLE]: (
<span data-testid="tooltip-comparison-plots">
Images (e.g. any <code>.jpg</code>, <code>.svg</code>, or
<code>.png</code> file) rendered side by side across experiments. They
should be registered as{' '}
<a href="https://dvc.org/doc/user-guide/experiment-management/visualizing-plots">
plots
</a>
.
</span>
),
// "Data Series"
[Section.TEMPLATE_PLOTS]: (
<span data-testid="tooltip-template-plots">
Any <code>JSON</code>, <code>YAML</code>, <code>CSV</code>, or{' '}
<code>TSV</code> file(s) with data points, visualized using{' '}
<a href="https://dvc.org/doc/user-guide/experiment-management/visualizing-plots#plot-templates-data-series-only">
plot templates
</a>
. Either predefined (e.g. confusion matrix, linear) or{' '}
<a href="https://dvc.org/doc/command-reference/plots/templates#custom-templates">
custom Vega-lite templates
</a>
.
</span>
)
}

const InfoIcon = () => (
<Icon icon={Info} width={16} height={16} className={styles.infoIcon} />
)

export const PlotsContainer: React.FC<PlotsContainerProps> = ({
sectionCollapsed,
sectionKey,
Expand Down Expand Up @@ -143,28 +79,6 @@ export const PlotsContainer: React.FC<PlotsContainerProps> = ({
})
}

const tooltipContent = (
<div className={styles.infoTooltip}>
<InfoIcon />
{SectionDescription[sectionKey]}
</div>
)

const toggleSection = (e: MouseEvent) => {
e.preventDefault()
if (
!isSelecting([title, SectionDescription[sectionKey].props.children]) &&
!isTooltip(e.target as Element, ['SUMMARY', 'BODY'])
) {
sendMessage({
payload: {
[sectionKey]: !sectionCollapsed
},
type: MessageFromWebviewType.TOGGLE_PLOTS_SECTION
})
}
}

const handleResize = useCallback(
(nbItems: number) => {
if (changeNbItemsPerRow) {
Expand All @@ -183,66 +97,55 @@ export const PlotsContainer: React.FC<PlotsContainerProps> = ({
[dispatch, changeNbItemsPerRow, sectionKey]
)

const toggleSection = () =>
sendMessage({
payload: {
[sectionKey]: !sectionCollapsed
},
type: MessageFromWebviewType.TOGGLE_PLOTS_SECTION
})

return (
<div className={styles.plotsContainerWrapper} data-testid="plots-container">
<details open={open} className={styles.plotsContainer}>
<summary onClick={toggleSection}>
<Icon
icon={open ? ChevronDown : ChevronRight}
data-testid="plots-container-details-chevron"
width={20}
height={20}
className={styles.detailsIcon}
<SectionContainer
menuItems={menuItems}
sectionCollapsed={sectionCollapsed}
sectionKey={sectionKey}
title={title}
onToggleSection={toggleSection}
>
{changeNbItemsPerRow && hasItems && maxNbPlotsPerRow > 1 && (
<div
className={styles.nbItemsPerRowSlider}
data-testid="nb-items-per-row-slider"
>
<MinMaxSlider
maximum={-1}
minimum={-maxNbPlotsPerRow}
label="Plot Width"
onChange={handleResize}
defaultValue={-nbItemsPerRow}
/>
{title}
<Tooltip content={tooltipContent} placement="bottom-end" interactive>
<div
className={styles.infoTooltipToggle}
data-testid="info-tooltip-toggle"
</div>
)}
{open && (
<div
className={cx({
[styles.plotsWrapper]: sectionKey !== Section.COMPARISON_TABLE,
[styles.smallPlots]: nbItemsPerRow >= 4
})}
style={
{
'--nbPerRow': nbItemsPerRow
} as DetailedHTMLProps<
HTMLAttributes<HTMLDivElement>,
HTMLDivElement
>
<InfoIcon />
</div>
</Tooltip>
</summary>
{changeNbItemsPerRow && hasItems && maxNbPlotsPerRow > 1 && (
<div
className={styles.nbItemsPerRowSlider}
data-testid="nb-items-per-row-slider"
>
<MinMaxSlider
maximum={-1}
minimum={-maxNbPlotsPerRow}
label="Plot Width"
onChange={handleResize}
defaultValue={-nbItemsPerRow}
/>
</div>
)}
{open && (
<div
className={cx({
[styles.plotsWrapper]: sectionKey !== Section.COMPARISON_TABLE,
[styles.smallPlots]: nbItemsPerRow >= 4
})}
style={
{
'--nbPerRow': nbItemsPerRow
} as DetailedHTMLProps<
HTMLAttributes<HTMLDivElement>,
HTMLDivElement
>
}
data-testid="plots-wrapper"
>
{children}
</div>
)}
</details>
{menuItems.length > 0 && (
<div className={styles.iconMenu}>
<IconMenu items={menuItems} />
}
data-testid="plots-wrapper"
>
{children}
</div>
)}
</div>
</SectionContainer>
)
}
64 changes: 0 additions & 64 deletions webview/src/plots/components/styles.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -8,38 +8,6 @@ $gap: 20px;
height: 100%;
}

.plotsContainer {
width: 100%;

summary {
list-style-type: none;
font-family: var(--vscode-font-family);
margin: 14px 10px;
font-weight: bold;
font-size: 1.25rem;
display: flex;
align-items: center;
width: max-content;
cursor: pointer;
}
}

.plotsContainerWrapper {
position: relative;
}

.detailsIcon {
fill: $fg-color;
margin-bottom: -4px;
}

.iconMenu {
position: absolute;
right: $gap;
top: -15px;
z-index: 10;
}

.plotsWrapper {
width: 100%;
}
Expand Down Expand Up @@ -256,38 +224,6 @@ $gap: 20px;
}
}

.infoTooltipToggle {
display: flex;
align-items: center;
cursor: initial;
}

.infoIcon {
fill: $accent-color;
margin-left: 6px;
}

.infoTooltip {
max-width: 340px;
margin-left: 5px;
white-space: normal;
display: flex;
gap: 4px;
line-height: 16px;
font-size: 13px;
font-weight: 400;
cursor: auto;

svg {
min-width: 16px;
min-height: 16px;
}

a {
text-decoration: none;
}
}

.nbItemsPerRowSlider {
display: flex;
justify-content: end;
Expand Down
Loading

0 comments on commit e52033f

Please sign in to comment.