diff --git a/extension/src/setup/webview/contract.ts b/extension/src/setup/webview/contract.ts index 2bb21b79ce..20764a6277 100644 --- a/extension/src/setup/webview/contract.ts +++ b/extension/src/setup/webview/contract.ts @@ -25,6 +25,7 @@ export type SetupData = { } export enum SetupSection { + GET_STARTED = 'get-started', DVC = 'dvc', EXPERIMENTS = 'experiments', REMOTES = 'remotes', @@ -32,6 +33,7 @@ export enum SetupSection { } export const DEFAULT_SECTION_COLLAPSED = { + [SetupSection.GET_STARTED]: false, [SetupSection.DVC]: false, [SetupSection.EXPERIMENTS]: false, [SetupSection.REMOTES]: false, diff --git a/extension/src/setup/webview/messages.ts b/extension/src/setup/webview/messages.ts index 0a91f48b92..b5a0e3bf56 100644 --- a/extension/src/setup/webview/messages.ts +++ b/extension/src/setup/webview/messages.ts @@ -73,6 +73,8 @@ export class WebviewMessages { return commands.executeCommand(RegisteredCliCommands.INIT) case MessageFromWebviewType.INITIALIZE_GIT: return this.gitInit() + case MessageFromWebviewType.SHOW_WALKTHROUGH: + return commands.executeCommand(RegisteredCommands.EXTENSION_GET_STARTED) case MessageFromWebviewType.SHOW_SCM_PANEL: return this.showScmForCommit() case MessageFromWebviewType.SELECT_PYTHON_INTERPRETER: diff --git a/extension/src/test/suite/setup/index.test.ts b/extension/src/test/suite/setup/index.test.ts index e823b30192..c234851ae6 100644 --- a/extension/src/test/suite/setup/index.test.ts +++ b/extension/src/test/suite/setup/index.test.ts @@ -189,6 +189,24 @@ suite('Setup Test Suite', () => { expect(mockExecuteCommand).to.be.calledWithExactly(showScmPanelCommand) }).timeout(WEBVIEW_TEST_TIMEOUT) + it('should handle a show walkthrough message from the webview', async () => { + const { messageSpy, mockExecuteCommand, setup } = buildSetup(disposable) + + const webview = await setup.showWebview() + await webview.isReady() + + const mockMessageReceived = getMessageReceivedEmitter(webview) + + messageSpy.resetHistory() + mockMessageReceived.fire({ + type: MessageFromWebviewType.SHOW_WALKTHROUGH + }) + + expect(mockExecuteCommand).to.be.calledWithExactly( + RegisteredCommands.EXTENSION_GET_STARTED + ) + }).timeout(WEBVIEW_TEST_TIMEOUT) + it('should handle a setup the workspace message from the webview', async () => { const { messageSpy, mockExecuteCommand, setup } = buildSetup(disposable) diff --git a/extension/src/webview/contract.ts b/extension/src/webview/contract.ts index 1f98ea74cf..589b509bcd 100644 --- a/extension/src/webview/contract.ts +++ b/extension/src/webview/contract.ts @@ -38,6 +38,7 @@ export enum MessageFromWebviewType { RESIZE_PLOTS = 'resize-plots', SAVE_STUDIO_TOKEN = 'save-studio-token', SHOW_EXPERIMENT_LOGS = 'show-experiment-logs', + SHOW_WALKTHROUGH = 'show-walkthrough', STOP_EXPERIMENTS = 'stop-experiments', SORT_COLUMN = 'sort-column', TOGGLE_EXPERIMENT = 'toggle-experiment', @@ -215,6 +216,7 @@ export type MessageFromWebview = | { type: MessageFromWebviewType.CHECK_CLI_COMPATIBLE } | { type: MessageFromWebviewType.INITIALIZE_DVC } | { type: MessageFromWebviewType.INITIALIZE_GIT } + | { type: MessageFromWebviewType.SHOW_WALKTHROUGH } | { type: MessageFromWebviewType.SHOW_SCM_PANEL } | { type: MessageFromWebviewType.INSTALL_DVC } | { type: MessageFromWebviewType.UPGRADE_DVC } diff --git a/webview/src/setup/components/App.test.tsx b/webview/src/setup/components/App.test.tsx index 03beb10a26..502808456d 100644 --- a/webview/src/setup/components/App.test.tsx +++ b/webview/src/setup/components/App.test.tsx @@ -294,6 +294,7 @@ describe('App', () => { projectInitialized: false, sectionCollapsed: { [SetupSection.DVC]: false, + [SetupSection.GET_STARTED]: true, [SetupSection.EXPERIMENTS]: true, [SetupSection.REMOTES]: true, [SetupSection.STUDIO]: true @@ -452,6 +453,26 @@ describe('App', () => { }) }) + describe('Get Started', () => { + it('should show a button that takes the user to the "Get Started" walkthrough', () => { + renderApp() + + expect( + within(screen.getByTestId('get-started-section-details')).getAllByText( + 'Get Started' + ) + ).toHaveLength(2) + const walkthroughButton = screen.getByText('Show Walkthrough') + + expect(walkthroughButton).toBeInTheDocument() + + fireEvent.click(walkthroughButton) + expect(mockPostMessage).toHaveBeenCalledWith({ + type: MessageFromWebviewType.SHOW_WALKTHROUGH + }) + }) + }) + describe('Experiments', () => { it('should show a screen saying that dvc is not setup if the project is not initialized', () => { renderApp({ @@ -701,6 +722,7 @@ describe('App', () => { isStudioConnected: true, sectionCollapsed: { [SetupSection.DVC]: false, + [SetupSection.GET_STARTED]: true, [SetupSection.EXPERIMENTS]: true, [SetupSection.REMOTES]: true, [SetupSection.STUDIO]: true @@ -723,6 +745,7 @@ describe('App', () => { isStudioConnected: true, sectionCollapsed: { [SetupSection.DVC]: true, + [SetupSection.GET_STARTED]: true, [SetupSection.EXPERIMENTS]: false, [SetupSection.REMOTES]: true, [SetupSection.STUDIO]: true @@ -745,6 +768,7 @@ describe('App', () => { isStudioConnected: true, sectionCollapsed: { [SetupSection.DVC]: true, + [SetupSection.GET_STARTED]: true, [SetupSection.EXPERIMENTS]: true, [SetupSection.REMOTES]: true, [SetupSection.STUDIO]: false @@ -769,6 +793,7 @@ describe('App', () => { remoteList: undefined, sectionCollapsed: { [SetupSection.DVC]: true, + [SetupSection.GET_STARTED]: true, [SetupSection.EXPERIMENTS]: true, [SetupSection.REMOTES]: false, [SetupSection.STUDIO]: true @@ -786,6 +811,7 @@ describe('App', () => { remoteList: { demo: undefined, 'example-get-started': undefined }, sectionCollapsed: { [SetupSection.DVC]: true, + [SetupSection.GET_STARTED]: true, [SetupSection.EXPERIMENTS]: true, [SetupSection.REMOTES]: false, [SetupSection.STUDIO]: true @@ -803,6 +829,7 @@ describe('App', () => { remoteList: { demo: undefined, 'example-get-started': undefined }, sectionCollapsed: { [SetupSection.DVC]: true, + [SetupSection.GET_STARTED]: true, [SetupSection.EXPERIMENTS]: true, [SetupSection.REMOTES]: false, [SetupSection.STUDIO]: true @@ -827,6 +854,7 @@ describe('App', () => { }, sectionCollapsed: { [SetupSection.DVC]: true, + [SetupSection.GET_STARTED]: true, [SetupSection.EXPERIMENTS]: true, [SetupSection.REMOTES]: false, [SetupSection.STUDIO]: true @@ -854,6 +882,7 @@ describe('App', () => { }, sectionCollapsed: { [SetupSection.DVC]: true, + [SetupSection.GET_STARTED]: true, [SetupSection.EXPERIMENTS]: true, [SetupSection.REMOTES]: false, [SetupSection.STUDIO]: true diff --git a/webview/src/setup/components/App.tsx b/webview/src/setup/components/App.tsx index bcf4b123b0..980f004bdc 100644 --- a/webview/src/setup/components/App.tsx +++ b/webview/src/setup/components/App.tsx @@ -9,6 +9,7 @@ import { Dvc } from './dvc/Dvc' import { Experiments } from './experiments/Experiments' import { Studio } from './studio/Studio' import { SetupContainer } from './SetupContainer' +import { GetStarted } from './GetStarted' import { Remotes } from './remotes/Remotes' import { useVsCodeMessaging } from '../../shared/hooks/useVsCodeMessaging' import { sendMessage } from '../../shared/vscode' @@ -171,6 +172,13 @@ export const App: React.FC = () => { > + + + { + return ( + +

Get Started

+

+ New to the extension? Go through the walkthrough to familiarize yourself + with the different features. +

+