Skip to content

Commit d9aa633

Browse files
authored
Do not render section if it is not open (#5025)
* Do not render section if not opened * Reset state when closing a plot section
1 parent dd1f16d commit d9aa633

File tree

12 files changed

+250
-72
lines changed

12 files changed

+250
-72
lines changed

extension/src/plots/webview/messages.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,11 +140,26 @@ export class WebviewMessages {
140140
{ isImage: !!message.payload },
141141
undefined
142142
)
143+
case MessageFromWebviewType.REFRESH_PLOTS:
144+
return this.sendDataForSection(message.payload)
143145
default:
144146
Logger.error(`Unexpected message: ${JSON.stringify(message)}`)
145147
}
146148
}
147149

150+
private sendDataForSection(section: PlotsSection) {
151+
switch (section) {
152+
case PlotsSection.COMPARISON_TABLE:
153+
return this.sendComparisonPlots()
154+
case PlotsSection.CUSTOM_PLOTS:
155+
return this.sendCustomPlots()
156+
case PlotsSection.TEMPLATE_PLOTS:
157+
return this.sendTemplatePlots()
158+
default:
159+
return this.sendWebviewMessage()
160+
}
161+
}
162+
148163
private async getWebviewData(): Promise<TPlotsData> {
149164
const selectedRevisions = this.plots.getSelectedRevisionDetails()
150165

extension/src/test/suite/plots/index.test.ts

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -533,6 +533,60 @@ suite('Plots Test Suite', () => {
533533
)
534534
}).timeout(WEBVIEW_TEST_TIMEOUT)
535535

536+
it('should handle refresh plots message from the webview for the template plots', async () => {
537+
const { mockMessageReceived, messageSpy } = await buildPlotsWebview({
538+
disposer: disposable,
539+
plotsDiff: plotsDiffFixture
540+
})
541+
542+
messageSpy.resetHistory()
543+
mockMessageReceived.fire({
544+
payload: PlotsSection.TEMPLATE_PLOTS,
545+
type: MessageFromWebviewType.REFRESH_PLOTS
546+
})
547+
548+
expect(messageSpy).to.be.calledOnce
549+
expect(messageSpy).to.be.calledWithExactly({
550+
template: templatePlotsFixture
551+
})
552+
}).timeout(WEBVIEW_TEST_TIMEOUT)
553+
554+
it('should handle refresh plots message from the webview for the custom plots', async () => {
555+
const { mockMessageReceived, messageSpy } = await buildPlotsWebview({
556+
disposer: disposable,
557+
plotsDiff: plotsDiffFixture
558+
})
559+
560+
messageSpy.resetHistory()
561+
mockMessageReceived.fire({
562+
payload: PlotsSection.CUSTOM_PLOTS,
563+
type: MessageFromWebviewType.REFRESH_PLOTS
564+
})
565+
566+
expect(messageSpy).to.be.calledOnce
567+
expect(messageSpy).to.be.calledWithExactly({
568+
custom: customPlotsFixture
569+
})
570+
}).timeout(WEBVIEW_TEST_TIMEOUT)
571+
572+
it('should handle refresh plots message from the webview for the comparison table', async () => {
573+
const { mockMessageReceived, messageSpy } = await buildPlotsWebview({
574+
disposer: disposable,
575+
plotsDiff: plotsDiffFixture
576+
})
577+
578+
messageSpy.resetHistory()
579+
mockMessageReceived.fire({
580+
payload: PlotsSection.COMPARISON_TABLE,
581+
type: MessageFromWebviewType.REFRESH_PLOTS
582+
})
583+
584+
expect(messageSpy).to.be.calledOnce
585+
expect(messageSpy).to.be.calledWithExactly({
586+
comparison: comparisonPlotsFixture
587+
})
588+
}).timeout(WEBVIEW_TEST_TIMEOUT)
589+
536590
it('should open an image when receiving a plot zoomed message from the webview with a payload', async () => {
537591
const { webview, mockMessageReceived } = await buildPlotsWebview({
538592
disposer: disposable,

extension/src/webview/contract.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,8 @@ export enum MessageFromWebviewType {
8888
SHOW_LESS_COMMITS = 'show-less-commits',
8989
SWITCH_BRANCHES_VIEW = 'show-all-branches',
9090
SWITCH_COMMITS_VIEW = 'show-commits',
91-
SELECT_BRANCHES = 'select-branches'
91+
SELECT_BRANCHES = 'select-branches',
92+
REFRESH_PLOTS = 'refresh-plots'
9293
}
9394

9495
export type ColumnResizePayload = {
@@ -299,6 +300,7 @@ export type MessageFromWebview =
299300
| { type: MessageFromWebviewType.SWITCH_BRANCHES_VIEW }
300301
| { type: MessageFromWebviewType.SWITCH_COMMITS_VIEW }
301302
| { type: MessageFromWebviewType.SELECT_BRANCHES }
303+
| { type: MessageFromWebviewType.REFRESH_PLOTS; payload: PlotsSection }
302304

303305
export type MessageToWebview<T extends WebviewData> = {
304306
type: MessageToWebviewType.SET_DATA

webview/src/plots/components/App.test.tsx

Lines changed: 98 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,15 @@ import {
4545
TemplatePlotsById
4646
} from './plotDataStore'
4747
import { setMaxNbPlotsPerRow } from './webviewSlice'
48-
import { toggleDragAndDropMode as toggleTemplatePlotsDragAndDropMode } from './templatePlots/templatePlotsSlice'
49-
import { toggleDragAndDropMode as toggleCustomPlotsDragAndDropMode } from './customPlots/customPlotsSlice'
48+
import {
49+
templatePlotsInitialState,
50+
toggleDragAndDropMode as toggleTemplatePlotsDragAndDropMode
51+
} from './templatePlots/templatePlotsSlice'
52+
import {
53+
customPlotsInitialState,
54+
toggleDragAndDropMode as toggleCustomPlotsDragAndDropMode
55+
} from './customPlots/customPlotsSlice'
56+
import { comparisonTableInitialState } from './comparisonTable/comparisonTableSlice'
5057
import { plotsReducers, plotsStore } from '../store'
5158
import { vsCodeApi } from '../../shared/api'
5259
import {
@@ -700,42 +707,6 @@ describe('App', () => {
700707
expect(screen.queryByText('Images')).not.toBeInTheDocument()
701708
})
702709

703-
it('should hide plots when their section is collapsed (setting to null can break some Vega plots)', async () => {
704-
renderAppWithOptionalData({
705-
custom: customPlotsFixture
706-
})
707-
708-
const summaryElement = await screen.findByText('Custom')
709-
const visiblePlots = await screen.findAllByLabelText('Vega visualization')
710-
for (const visiblePlot of visiblePlots) {
711-
expect(visiblePlot).toBeInTheDocument()
712-
expect(visiblePlot).toBeVisible()
713-
}
714-
715-
fireEvent.click(summaryElement, {
716-
bubbles: true,
717-
cancelable: true
718-
})
719-
720-
expect(mockPostMessage).toHaveBeenCalledWith({
721-
payload: { [PlotsSection.CUSTOM_PLOTS]: true },
722-
type: MessageFromWebviewType.TOGGLE_PLOTS_SECTION
723-
})
724-
725-
sendSetDataMessage({
726-
sectionCollapsed: {
727-
...DEFAULT_SECTION_COLLAPSED,
728-
[PlotsSection.CUSTOM_PLOTS]: true
729-
}
730-
})
731-
732-
const hiddenPlots = await screen.findAllByLabelText('Vega visualization')
733-
for (const hiddenPlot of hiddenPlots) {
734-
expect(hiddenPlot).toBeInTheDocument()
735-
expect(hiddenPlot).not.toBeVisible()
736-
}
737-
})
738-
739710
it('should not toggle the custom plots section when its header is clicked and its title is selected', async () => {
740711
renderAppWithOptionalData({
741712
custom: customPlotsFixture
@@ -851,6 +822,95 @@ describe('App', () => {
851822
})
852823
})
853824

825+
it('should clear the template plots state when closing the section', () => {
826+
const store = renderAppWithOptionalData({
827+
template: templatePlotsFixture
828+
})
829+
830+
const toggle = within(
831+
screen.getByTestId(`${PlotsSection.TEMPLATE_PLOTS}-section-details`)
832+
).getAllByRole('button')[0]
833+
fireEvent.click(toggle)
834+
835+
expect(store.getState().template).toMatchObject(templatePlotsInitialState)
836+
})
837+
838+
it('should clear the custom plots state when closing the section', () => {
839+
const store = renderAppWithOptionalData({
840+
custom: customPlotsFixture
841+
})
842+
843+
const toggle = within(
844+
screen.getByTestId(`${PlotsSection.CUSTOM_PLOTS}-section-details`)
845+
).getAllByRole('button')[0]
846+
fireEvent.click(toggle)
847+
848+
expect(store.getState().custom).toMatchObject(customPlotsInitialState)
849+
})
850+
851+
it('should clear the comparison table state when closing the section', () => {
852+
const store = renderAppWithOptionalData({
853+
comparison: comparisonTableFixture
854+
})
855+
856+
const toggle = within(
857+
screen.getByTestId(`${PlotsSection.COMPARISON_TABLE}-section-details`)
858+
).getAllByRole('button')[0]
859+
fireEvent.click(toggle)
860+
861+
expect(store.getState().comparison).toMatchObject(
862+
comparisonTableInitialState
863+
)
864+
})
865+
866+
it('should send a message to refresh the template plots when closing the section', () => {
867+
renderAppWithOptionalData({
868+
template: templatePlotsFixture
869+
})
870+
871+
const toggle = within(
872+
screen.getByTestId(`${PlotsSection.TEMPLATE_PLOTS}-section-details`)
873+
).getAllByRole('button')[0]
874+
fireEvent.click(toggle)
875+
876+
expect(mockPostMessage).toHaveBeenCalledWith({
877+
payload: PlotsSection.TEMPLATE_PLOTS,
878+
type: MessageFromWebviewType.REFRESH_PLOTS
879+
})
880+
})
881+
882+
it('should send a message to refresh the custom plots when closing the section', () => {
883+
renderAppWithOptionalData({
884+
custom: customPlotsFixture
885+
})
886+
887+
const toggle = within(
888+
screen.getByTestId(`${PlotsSection.CUSTOM_PLOTS}-section-details`)
889+
).getAllByRole('button')[0]
890+
fireEvent.click(toggle)
891+
892+
expect(mockPostMessage).toHaveBeenCalledWith({
893+
payload: PlotsSection.CUSTOM_PLOTS,
894+
type: MessageFromWebviewType.REFRESH_PLOTS
895+
})
896+
})
897+
898+
it('should send a message to refresh the comparison table when closing the section', () => {
899+
renderAppWithOptionalData({
900+
comparison: comparisonTableFixture
901+
})
902+
903+
const toggle = within(
904+
screen.getByTestId(`${PlotsSection.COMPARISON_TABLE}-section-details`)
905+
).getAllByRole('button')[0]
906+
fireEvent.click(toggle)
907+
908+
expect(mockPostMessage).toHaveBeenCalledWith({
909+
payload: PlotsSection.COMPARISON_TABLE,
910+
type: MessageFromWebviewType.REFRESH_PLOTS
911+
})
912+
})
913+
854914
it('should display a slider to pick the number of items per row if there are items and the action is available', () => {
855915
const store = renderAppWithOptionalData({
856916
custom: customPlotsFixture

webview/src/plots/components/PlotsContainer.tsx

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import cx from 'classnames'
22
import React, { useEffect, DetailedHTMLProps, HTMLAttributes } from 'react'
3-
import { useSelector } from 'react-redux'
3+
import { useDispatch, useSelector } from 'react-redux'
44
import { PlotHeight, PlotsSection } from 'dvc/src/plots/webview/contract'
55
import styles from './styles.module.scss'
66
import { SizeSliders } from './SizeSliders'
7-
import { isDragAndDropModeSelector } from './util'
7+
import { clearStateActions, isDragAndDropModeSelector } from './util'
88
import { PlotsState } from '../store'
9-
import { togglePlotsSection } from '../util/messages'
9+
import { refreshSection, togglePlotsSection } from '../util/messages'
1010
import { IconMenuItemProps } from '../../shared/components/iconMenu/IconMenuItem'
1111
import { Trash } from '../../shared/components/icons'
1212
import { SectionContainer } from '../../shared/components/sectionContainer/SectionContainer'
@@ -34,6 +34,7 @@ export const PlotsContainer: React.FC<PlotsContainerProps> = ({
3434
hasItems,
3535
noHeight
3636
}) => {
37+
const dispatch = useDispatch()
3738
const open = !sectionCollapsed
3839
const maxNbPlotsPerRow = useSelector(
3940
(state: PlotsState) => state.webview.maxNbPlotsPerRow
@@ -57,7 +58,14 @@ export const PlotsContainer: React.FC<PlotsContainerProps> = ({
5758
})
5859
}
5960

60-
const toggleSection = () => togglePlotsSection(sectionKey, sectionCollapsed)
61+
const toggleSection = (open: boolean) => {
62+
togglePlotsSection(sectionKey, sectionCollapsed)
63+
64+
if (!open) {
65+
dispatch(clearStateActions[sectionKey]())
66+
refreshSection(sectionKey)
67+
}
68+
}
6169

6270
return (
6371
<SectionContainer

webview/src/plots/components/comparisonTable/comparisonTableSlice.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ export const comparisonTableSlice = createSlice({
4747
) => {
4848
state.width = action.payload.nbItemsPerRowOrWidth
4949
},
50+
clearState: () => {
51+
return comparisonTableInitialState
52+
},
5053
setCollapsed: (state, action: PayloadAction<boolean>) => {
5154
state.isCollapsed = action.payload
5255
},
@@ -72,7 +75,8 @@ export const {
7275
changeSize,
7376
changeDisabledDragIds,
7477
changeRowHeight,
75-
toggleDragAndDropMode
78+
toggleDragAndDropMode,
79+
clearState
7680
} = comparisonTableSlice.actions
7781

7882
export default comparisonTableSlice.reducer

webview/src/plots/components/customPlots/customPlotsSlice.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@ export const customPlotsSlice = createSlice({
4646
state.nbItemsPerRow = action.payload.nbItemsPerRowOrWidth
4747
state.height = action.payload.height
4848
},
49+
clearState: () => {
50+
removePlots([], PlotsSection.TEMPLATE_PLOTS)
51+
return customPlotsInitialState
52+
},
4953
setCollapsed: (state, action: PayloadAction<boolean>) => {
5054
state.isCollapsed = action.payload
5155
},
@@ -75,7 +79,12 @@ export const customPlotsSlice = createSlice({
7579
}
7680
})
7781

78-
export const { update, setCollapsed, changeSize, toggleDragAndDropMode } =
79-
customPlotsSlice.actions
82+
export const {
83+
update,
84+
setCollapsed,
85+
changeSize,
86+
toggleDragAndDropMode,
87+
clearState
88+
} = customPlotsSlice.actions
8089

8190
export default customPlotsSlice.reducer

webview/src/plots/components/templatePlots/templatePlotsSlice.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@ export const templatePlotsSlice = createSlice({
4747
state.nbItemsPerRow = action.payload.nbItemsPerRowOrWidth
4848
state.height = action.payload.height
4949
},
50+
clearState: () => {
51+
removePlots([], PlotsSection.TEMPLATE_PLOTS)
52+
return templatePlotsInitialState
53+
},
5054
setCollapsed: (state, action: PayloadAction<boolean>) => {
5155
state.isCollapsed = action.payload
5256
},
@@ -98,7 +102,8 @@ export const {
98102
setCollapsed,
99103
changeSize,
100104
toggleDragAndDropMode,
101-
updateSections
105+
updateSections,
106+
clearState
102107
} = templatePlotsSlice.actions
103108

104109
export default templatePlotsSlice.reducer

0 commit comments

Comments
 (0)