From 87f0804f350e4985052df57a07a089b7ae67d441 Mon Sep 17 00:00:00 2001 From: julieg18 Date: Fri, 7 Apr 2023 14:25:49 -0500 Subject: [PATCH 1/9] Add Setup DVC Section --- extension/package.json | 2 +- extension/src/commands/external.ts | 1 + extension/src/setup/register.ts | 7 ++ extension/src/setup/webview/contract.ts | 6 +- extension/src/telemetry/constants.ts | 1 + webview/src/setup/components/App.test.tsx | 14 ++- webview/src/setup/components/App.tsx | 24 +++- webview/src/setup/components/Dvc.tsx | 95 ++++++++++++++++ webview/src/setup/components/Experiments.tsx | 103 ++++++------------ webview/src/setup/components/Studio.tsx | 2 +- .../sectionContainer/SectionContainer.tsx | 8 +- webview/src/stories/Setup.stories.tsx | 3 +- 12 files changed, 180 insertions(+), 86 deletions(-) create mode 100644 webview/src/setup/components/Dvc.tsx diff --git a/extension/package.json b/extension/package.json index d74fed1555..c409992269 100644 --- a/extension/package.json +++ b/extension/package.json @@ -1449,7 +1449,7 @@ }, { "view": "dvc.views.welcome", - "contents": "New to the extension?\n[Show Walkthrough](command:dvc.getStarted)\n\nThe extension is currently unable to initialize.\n[Show Setup](command:dvc.showExperimentsSetup)", + "contents": "New to the extension?\n[Show Walkthrough](command:dvc.getStarted)\n\nThe extension is currently unable to initialize.\n[Show Setup](command:dvc.showDvcSetup)", "when": "true" }, { diff --git a/extension/src/commands/external.ts b/extension/src/commands/external.ts index f92b6ddae0..2f2dbd4ed9 100644 --- a/extension/src/commands/external.ts +++ b/extension/src/commands/external.ts @@ -97,6 +97,7 @@ export enum RegisteredCommands { SETUP_SHOW = 'dvc.showSetup', SETUP_SHOW_EXPERIMENTS = 'dvc.showExperimentsSetup', + SETUP_SHOW_DVC = 'dvc.showDvcSetup', SELECT_FOCUSED_PROJECTS = 'dvc.selectFocusedProjects', ADD_STUDIO_ACCESS_TOKEN = 'dvc.addStudioAccessToken', diff --git a/extension/src/setup/register.ts b/extension/src/setup/register.ts index 7e65fbf393..f0e8468abc 100644 --- a/extension/src/setup/register.ts +++ b/extension/src/setup/register.ts @@ -44,6 +44,13 @@ const registerSetupShowCommands = ( } ) + internalCommands.registerExternalCommand( + RegisteredCommands.SETUP_SHOW_DVC, + async () => { + await setup.showSetup(SetupSection.DVC) + } + ) + internalCommands.registerExternalCommand( RegisteredCommands.SETUP_SHOW_STUDIO_CONNECT, async () => { diff --git a/extension/src/setup/webview/contract.ts b/extension/src/setup/webview/contract.ts index 6866baaff5..a3aa5df5ea 100644 --- a/extension/src/setup/webview/contract.ts +++ b/extension/src/setup/webview/contract.ts @@ -14,12 +14,14 @@ export type SetupData = { export enum SetupSection { EXPERIMENTS = 'experiments', - STUDIO = 'studio' + STUDIO = 'studio', + DVC = 'dvc' } export const DEFAULT_SECTION_COLLAPSED = { [SetupSection.EXPERIMENTS]: false, - [SetupSection.STUDIO]: false + [SetupSection.STUDIO]: false, + [SetupSection.DVC]: false } export type SectionCollapsed = typeof DEFAULT_SECTION_COLLAPSED diff --git a/extension/src/telemetry/constants.ts b/extension/src/telemetry/constants.ts index e365288daf..8b63d74e2d 100644 --- a/extension/src/telemetry/constants.ts +++ b/extension/src/telemetry/constants.ts @@ -275,6 +275,7 @@ export interface IEventNamePropertyMapping { [EventName.SETUP_SHOW]: undefined [EventName.SETUP_SHOW_EXPERIMENTS]: undefined + [EventName.SETUP_SHOW_DVC]: undefined [EventName.SELECT_FOCUSED_PROJECTS]: undefined [EventName.SETUP_SHOW_STUDIO_SETTINGS]: undefined [EventName.SETUP_SHOW_STUDIO_CONNECT]: undefined diff --git a/webview/src/setup/components/App.test.tsx b/webview/src/setup/components/App.test.tsx index 38ea22bbc1..51cf7a87d9 100644 --- a/webview/src/setup/components/App.test.tsx +++ b/webview/src/setup/components/App.test.tsx @@ -1,4 +1,4 @@ -import { fireEvent, render, screen } from '@testing-library/react' +import { fireEvent, render, screen, within } from '@testing-library/react' import { MessageFromWebviewType, MessageToWebviewType @@ -415,7 +415,7 @@ describe('App', () => { shareLiveToStudio: false }) mockPostMessage.mockClear() - const button = screen.getByText('Show Experiments') + const button = screen.getAllByText('Show Experiments')[0] fireEvent.click(button) expect(mockPostMessage).toHaveBeenCalledTimes(1) expect(mockPostMessage).toHaveBeenCalledWith({ @@ -439,7 +439,9 @@ describe('App', () => { sectionCollapsed: undefined, shareLiveToStudio: false }) - const buttons = await screen.findAllByRole('button') + const buttons = await within( + await screen.findByTestId('setup-studio-content') + ).findAllByRole('button') expect(buttons).toHaveLength(3) }) @@ -586,7 +588,8 @@ describe('App', () => { ...testData, sectionCollapsed: { [SetupSection.EXPERIMENTS]: false, - [SetupSection.STUDIO]: true + [SetupSection.STUDIO]: true, + [SetupSection.DVC]: false } }) mockPostMessage.mockClear() @@ -603,7 +606,8 @@ describe('App', () => { ...testData, sectionCollapsed: { [SetupSection.EXPERIMENTS]: true, - [SetupSection.STUDIO]: false + [SetupSection.STUDIO]: false, + [SetupSection.DVC]: false } }) mockPostMessage.mockClear() diff --git a/webview/src/setup/components/App.tsx b/webview/src/setup/components/App.tsx index 91d2020d44..b805f0285d 100644 --- a/webview/src/setup/components/App.tsx +++ b/webview/src/setup/components/App.tsx @@ -8,6 +8,7 @@ import { MessageToWebview } from 'dvc/src/webview/contract' import React, { useCallback, useState } from 'react' +import { Dvc } from './Dvc' import { Experiments } from './Experiments' import { Studio } from './Studio' import { SetupContainer } from './SetupContainer' @@ -84,20 +85,35 @@ export const App: React.FC = () => { return ( <> - + + + void +} + +export const Dvc: React.FC = ({ + canGitInitialize, + cliCompatible, + isPythonExtensionInstalled, + needsGitInitialized, + needsGitCommit, + projectInitialized, + pythonBinPath, + setSectionCollapsed, + hasData +}) => { + if (cliCompatible === false) { + return + } + + if (cliCompatible === undefined) { + return ( + + ) + } + + if (!projectInitialized) { + return ( + + ) + } + + if (needsGitCommit) { + return + } + + return ( + +

Setup Complete

+ + setSectionCollapsed({ + dvc: true, + experiments: false, + studio: true + }) + } + text="Show Experiments" + /> +
+ ) +} diff --git a/webview/src/setup/components/Experiments.tsx b/webview/src/setup/components/Experiments.tsx index ef186379f2..6c0d651022 100644 --- a/webview/src/setup/components/Experiments.tsx +++ b/webview/src/setup/components/Experiments.tsx @@ -1,26 +1,42 @@ import React from 'react' -import { CliIncompatible } from './CliIncompatible' -import { CliUnavailable } from './CliUnavailable' -import { ProjectUninitialized } from './ProjectUninitialized' -import { - checkCompatibility, - initializeDvc, - initializeGit, - installDvc, - selectPythonInterpreter, - setupWorkspace, - showExperiments, - showScmPanel -} from './messages' -import { NeedsGitCommit } from './NeedsGitCommit' +import { SectionCollapsed } from 'dvc/src/setup/webview/contract' +import { showExperiments } from './messages' import { NoData } from './NoData' import { EmptyState } from '../../shared/components/emptyState/EmptyState' import { IconButton } from '../../shared/components/button/IconButton' import { Beaker } from '../../shared/components/icons' +import { Button } from '../../shared/components/button/Button' -const ProjectSetup: React.FC<{ hasData: boolean | undefined }> = ({ - hasData +export type ExperimentsProps = { + isDvcSetup: boolean + hasData: boolean | undefined + setSectionCollapsed: (sectionCollapsed: SectionCollapsed) => void +} + +export const Experiments: React.FC = ({ + isDvcSetup, + hasData, + setSectionCollapsed }) => { + if (!isDvcSetup) { + return ( + +

DVC is not setup

+ {/* TBD review text */} +

DVC needs to be setup before you can access experiments.

+