Skip to content

Commit

Permalink
Autoclose DVC Section if completed (#3809)
Browse files Browse the repository at this point in the history
  • Loading branch information
julieg18 authored May 9, 2023
1 parent 52aafe7 commit 86e5418
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 53 deletions.
69 changes: 42 additions & 27 deletions webview/src/setup/components/App.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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(<App />)
Expand Down Expand Up @@ -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: {
Expand All @@ -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,
Expand All @@ -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', () => {
Expand Down Expand Up @@ -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
Expand Down
5 changes: 4 additions & 1 deletion webview/src/setup/components/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ export const App: React.FC = () => {
const [isStudioConnected, setIsStudioConnected] = useState<boolean>(false)
const [shareLiveToStudio, setShareLiveToStudioValue] =
useState<boolean>(false)
const [hasReceivedMessageFromVsCode, setHasReceivedMessageFromVsCode] =
useState(false)

useVsCodeMessaging(
useCallback(
Expand All @@ -64,6 +66,7 @@ export const App: React.FC = () => {
setSectionCollapsed(data.data.sectionCollapsed)
}
setShareLiveToStudioValue(data.data.shareLiveToStudio)
setHasReceivedMessageFromVsCode(true)
},
[
setCanGitInitialized,
Expand Down Expand Up @@ -109,8 +112,8 @@ export const App: React.FC = () => {
needsGitInitialized={needsGitInitialized}
projectInitialized={projectInitialized}
pythonBinPath={pythonBinPath}
isExperimentsAvailable={hasData}
setSectionCollapsed={setSectionCollapsed}
hasReceivedMessageFromVsCode={hasReceivedMessageFromVsCode}
/>
</SetupContainer>
<SetupContainer
Expand Down
65 changes: 41 additions & 24 deletions webview/src/setup/components/dvc/Dvc.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import React from 'react'
import { DvcCliDetails, SectionCollapsed } from 'dvc/src/setup/webview/contract'
import React, { useEffect, useState } from 'react'
import {
DvcCliDetails,
SetupSection,
SectionCollapsed
} from 'dvc/src/setup/webview/contract'
import { DvcEnvDetails } from './DvcEnvDetails'
import { CliIncompatible } from './CliIncompatible'
import { ProjectUninitialized } from './ProjectUninitialized'
Expand All @@ -9,12 +13,10 @@ import {
initializeDvc,
initializeGit,
installDvc,
setupWorkspace,
showExperiments
setupWorkspace
} from '../messages'
import { EmptyState } from '../../../shared/components/emptyState/EmptyState'
import { Beaker } from '../../../shared/components/icons'
import { IconButton } from '../../../shared/components/button/IconButton'
import { usePrevious } from '../../hooks/usePrevious'

type DvcProps = {
canGitInitialize: boolean | undefined
Expand All @@ -24,8 +26,8 @@ type DvcProps = {
needsGitInitialized: boolean | undefined
projectInitialized: boolean
pythonBinPath: string | undefined
isExperimentsAvailable: boolean | undefined
setSectionCollapsed: (sectionCollapsed: SectionCollapsed) => void
hasReceivedMessageFromVsCode: boolean
}

export const Dvc: React.FC<DvcProps> = ({
Expand All @@ -36,16 +38,46 @@ export const Dvc: React.FC<DvcProps> = ({
needsGitInitialized,
projectInitialized,
pythonBinPath,
setSectionCollapsed,
isExperimentsAvailable
hasReceivedMessageFromVsCode,
setSectionCollapsed
}) => {
const [isComplete, setIsComplete] = useState<boolean | null>(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 && (
<DvcEnvDetails
{...dvcCliDetails}
isPythonExtensionUsed={isPythonExtensionUsed}
/>
)

if (!hasReceivedMessageFromVsCode) {
return <EmptyState isFullScreen={false}>Loading...</EmptyState>
}

if (cliCompatible === false) {
return (
<CliIncompatible checkCompatibility={checkCompatibility}>
Expand Down Expand Up @@ -82,21 +114,6 @@ export const Dvc: React.FC<DvcProps> = ({
<EmptyState isFullScreen={false}>
<h1>Setup Complete</h1>
{children}
<IconButton
appearance="primary"
icon={Beaker}
onClick={
isExperimentsAvailable
? showExperiments
: () =>
setSectionCollapsed({
dvc: true,
experiments: false,
studio: true
})
}
text="Show Experiments"
/>
</EmptyState>
)
}
11 changes: 11 additions & 0 deletions webview/src/setup/hooks/usePrevious.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { useRef, useEffect } from 'react'

export const usePrevious = <T>(value: T): T | undefined => {
const ref = useRef<T>()

useEffect(() => {
ref.current = value
}, [value])

return ref.current
}
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,11 @@ export const SectionContainer: React.FC<
className={cx(styles.sectionContainerWrapper, className)}
data-testid="section-container"
>
<details open={open} className={styles.sectionContainer}>
<details
data-testid={`${sectionKey}-section-details`}
open={open}
className={styles.sectionContainer}
>
<summary onClick={toggleSection} style={{ top: stickyHeaderTop }}>
<div className={styles.summaryTitle}>
<Icon
Expand Down

0 comments on commit 86e5418

Please sign in to comment.