From 86e54180c6831fbcdd62ac4f346c3071f97d3427 Mon Sep 17 00:00:00 2001 From: Julie G <43496356+julieg18@users.noreply.github.com> Date: Tue, 9 May 2023 07:55:02 -0500 Subject: [PATCH] Autoclose DVC Section if completed (#3809) --- webview/src/setup/components/App.test.tsx | 69 +++++++++++-------- webview/src/setup/components/App.tsx | 5 +- webview/src/setup/components/dvc/Dvc.tsx | 65 ++++++++++------- webview/src/setup/hooks/usePrevious.ts | 11 +++ .../sectionContainer/SectionContainer.tsx | 6 +- 5 files changed, 103 insertions(+), 53 deletions(-) create mode 100644 webview/src/setup/hooks/usePrevious.ts diff --git a/webview/src/setup/components/App.test.tsx b/webview/src/setup/components/App.test.tsx index c057c3e938..5ecebf5ff2 100644 --- a/webview/src/setup/components/App.test.tsx +++ b/webview/src/setup/components/App.test.tsx @@ -56,6 +56,16 @@ const renderApp = ({ ) } +const sendSetDataMessage = (data: SetupData) => { + const message = new MessageEvent('message', { + data: { + data, + type: MessageToWebviewType.SET_DATA + } + }) + fireEvent(window, message) +} + describe('App', () => { it('should send the initialized message on first render', () => { render() @@ -422,8 +432,8 @@ describe('App', () => { }) }) - it('should open the experiments section when clicking the Open Experiments button when the project is initialized but has no data', () => { - renderApp({ + it('should autoclose and open other sections when user finishes setup', () => { + const dvcNotSetup = { canGitInitialize: false, cliCompatible: true, dvcCliDetails: { @@ -434,30 +444,25 @@ describe('App', () => { isPythonExtensionUsed: false, isStudioConnected: false, needsGitCommit: false, - needsGitInitialized: undefined, - projectInitialized: true, + needsGitInitialized: true, + projectInitialized: false, pythonBinPath: undefined, - sectionCollapsed: undefined, + sectionCollapsed: { + [SetupSection.DVC]: false, + [SetupSection.STUDIO]: true, + [SetupSection.EXPERIMENTS]: true + }, shareLiveToStudio: false - }) - - mockPostMessage.mockClear() - const button = screen.getAllByText('Show Experiments')[0] - fireEvent.click(button) - - expect(screen.getByText('Your project contains no data')).toBeVisible() - expect(screen.getByText('Setup Complete')).not.toBeVisible() - }) + } - it('should enable the user to open the experiments webview when they have completed onboarding', () => { - renderApp({ + const dvcSetup = { canGitInitialize: false, cliCompatible: true, dvcCliDetails: { command: 'python -m dvc', version: '1.0.0' }, - hasData: true, + hasData: false, isPythonExtensionUsed: true, isStudioConnected: true, needsGitCommit: false, @@ -466,14 +471,25 @@ describe('App', () => { pythonBinPath: 'python', sectionCollapsed: undefined, shareLiveToStudio: false - }) - mockPostMessage.mockClear() - const button = screen.getAllByText('Show Experiments')[0] - fireEvent.click(button) - expect(mockPostMessage).toHaveBeenCalledTimes(1) - expect(mockPostMessage).toHaveBeenCalledWith({ - type: MessageFromWebviewType.OPEN_EXPERIMENTS_WEBVIEW - }) + } + + renderApp(dvcNotSetup) + + const dvcDetails = screen.getByTestId('dvc-section-details') + const experimentsDetails = screen.getByTestId( + 'experiments-section-details' + ) + const studioDetails = screen.getByTestId('studio-section-details') + + expect(dvcDetails).toHaveAttribute('open') + expect(experimentsDetails).not.toHaveAttribute('open') + expect(studioDetails).not.toHaveAttribute('open') + + sendSetDataMessage(dvcSetup) + + expect(dvcDetails).not.toHaveAttribute('open') + expect(experimentsDetails).toHaveAttribute('open') + expect(studioDetails).toHaveAttribute('open') }) it('should show the user the version if dvc is installed', () => { @@ -869,8 +885,7 @@ describe('App', () => { shareLiveToStudio: false }) mockPostMessage.mockClear() - const button = screen.getAllByText('Show Experiments')[1] - fireEvent.click(button) + fireEvent.click(screen.getByText('Show Experiments')) expect(mockPostMessage).toHaveBeenCalledTimes(1) expect(mockPostMessage).toHaveBeenCalledWith({ type: MessageFromWebviewType.OPEN_EXPERIMENTS_WEBVIEW diff --git a/webview/src/setup/components/App.tsx b/webview/src/setup/components/App.tsx index d1026d9c3e..9ac4b25fd7 100644 --- a/webview/src/setup/components/App.tsx +++ b/webview/src/setup/components/App.tsx @@ -43,6 +43,8 @@ export const App: React.FC = () => { const [isStudioConnected, setIsStudioConnected] = useState(false) const [shareLiveToStudio, setShareLiveToStudioValue] = useState(false) + const [hasReceivedMessageFromVsCode, setHasReceivedMessageFromVsCode] = + useState(false) useVsCodeMessaging( useCallback( @@ -64,6 +66,7 @@ export const App: React.FC = () => { setSectionCollapsed(data.data.sectionCollapsed) } setShareLiveToStudioValue(data.data.shareLiveToStudio) + setHasReceivedMessageFromVsCode(true) }, [ setCanGitInitialized, @@ -109,8 +112,8 @@ export const App: React.FC = () => { needsGitInitialized={needsGitInitialized} projectInitialized={projectInitialized} pythonBinPath={pythonBinPath} - isExperimentsAvailable={hasData} setSectionCollapsed={setSectionCollapsed} + hasReceivedMessageFromVsCode={hasReceivedMessageFromVsCode} /> void + hasReceivedMessageFromVsCode: boolean } export const Dvc: React.FC = ({ @@ -36,9 +38,35 @@ export const Dvc: React.FC = ({ needsGitInitialized, projectInitialized, pythonBinPath, - setSectionCollapsed, - isExperimentsAvailable + hasReceivedMessageFromVsCode, + setSectionCollapsed }) => { + const [isComplete, setIsComplete] = useState(null) + const previousIsComplete = usePrevious(isComplete) + + useEffect(() => { + const isSetup = projectInitialized && !!cliCompatible + + if (hasReceivedMessageFromVsCode) { + setIsComplete(isSetup) + } + + if (previousIsComplete === false && isComplete) { + setSectionCollapsed({ + [SetupSection.DVC]: true, + [SetupSection.EXPERIMENTS]: false, + [SetupSection.STUDIO]: false + }) + } + }, [ + projectInitialized, + cliCompatible, + isComplete, + previousIsComplete, + setSectionCollapsed, + hasReceivedMessageFromVsCode + ]) + const children = dvcCliDetails && ( = ({ /> ) + if (!hasReceivedMessageFromVsCode) { + return Loading... + } + if (cliCompatible === false) { return ( @@ -82,21 +114,6 @@ export const Dvc: React.FC = ({

Setup Complete

{children} - - setSectionCollapsed({ - dvc: true, - experiments: false, - studio: true - }) - } - text="Show Experiments" - />
) } diff --git a/webview/src/setup/hooks/usePrevious.ts b/webview/src/setup/hooks/usePrevious.ts new file mode 100644 index 0000000000..175aae06b9 --- /dev/null +++ b/webview/src/setup/hooks/usePrevious.ts @@ -0,0 +1,11 @@ +import { useRef, useEffect } from 'react' + +export const usePrevious = (value: T): T | undefined => { + const ref = useRef() + + useEffect(() => { + ref.current = value + }, [value]) + + return ref.current +} diff --git a/webview/src/shared/components/sectionContainer/SectionContainer.tsx b/webview/src/shared/components/sectionContainer/SectionContainer.tsx index 9435594d14..5b82f7091b 100644 --- a/webview/src/shared/components/sectionContainer/SectionContainer.tsx +++ b/webview/src/shared/components/sectionContainer/SectionContainer.tsx @@ -117,7 +117,11 @@ export const SectionContainer: React.FC< className={cx(styles.sectionContainerWrapper, className)} data-testid="section-container" > -
+