diff --git a/extension/package.json b/extension/package.json
index 496995ae53..1831c18362 100644
--- a/extension/package.json
+++ b/extension/package.json
@@ -520,6 +520,11 @@
"category": "DVC",
"icon": "$(repo-push)"
},
+ {
+ "title": "%command.views.experiments.showLogs%",
+ "command": "dvc.views.experiments.showLogs",
+ "category": "DVC"
+ },
{
"title": "%command.views.experimentsTree.selectExperiments%",
"command": "dvc.views.experimentsTree.selectExperiments",
@@ -885,6 +890,10 @@
"command": "dvc.views.experiments.shareExperimentToStudio",
"when": "false"
},
+ {
+ "command": "dvc.views.experiments.showLogs",
+ "when": "false"
+ },
{
"command": "dvc.views.experimentsFilterByTree.removeAllFilters",
"when": "false"
@@ -1611,7 +1620,7 @@
"@types/node": "16.x",
"@types/react-vega": "7.0.0",
"@types/sinon-chai": "3.2.9",
- "@types/uuid": "9.0.0",
+ "@types/uuid": "9.0.1",
"@types/vscode": "1.64.0",
"@vscode/test-electron": "2.2.3",
"@vscode/vsce": "2.17.0",
diff --git a/extension/package.nls.json b/extension/package.nls.json
index 0b23181227..e9b1bc1381 100644
--- a/extension/package.nls.json
+++ b/extension/package.nls.json
@@ -76,6 +76,7 @@
"command.views.experiments.shareExperimentAsBranch": "Share as Branch",
"command.views.experiments.shareExperimentAsCommit": "Commit and Share",
"command.views.experiments.shareExperimentToStudio": "Share to Studio",
+ "command.views.experiments.showLogs": "Show Logs",
"command.views.experimentsTree.selectExperiments": "Select Experiments to Display in Plots",
"command.views.plotsPathsTree.selectPlots": "Select Plots to Display",
"command.views.plotsPathsTree.refreshPlots": "Refresh Plots for Selected Experiments",
diff --git a/extension/src/cli/dvc/viewer.ts b/extension/src/cli/dvc/viewer.ts
index b475241911..5781f468d6 100644
--- a/extension/src/cli/dvc/viewer.ts
+++ b/extension/src/cli/dvc/viewer.ts
@@ -53,7 +53,7 @@ export class DvcViewer extends Disposable implements ICli {
public queueLogs(cwd: string, expName: string) {
return this.run(
- expName,
+ `${expName} logs`,
cwd,
Command.QUEUE,
QueueSubCommand.LOGS,
diff --git a/extension/src/cli/viewable.ts b/extension/src/cli/viewable.ts
index fc3d47291c..9e7dcecb02 100644
--- a/extension/src/cli/viewable.ts
+++ b/extension/src/cli/viewable.ts
@@ -82,6 +82,7 @@ export class ViewableCliProcess extends DeferredDisposable {
},
processCompleted
)
+ this.pseudoTerminal.setBlocked(false)
processOutput.fire('\r\nPress any key to close\r\n\n')
})
}
diff --git a/extension/src/commands/external.ts b/extension/src/commands/external.ts
index df6134eae9..b3ec900ffd 100644
--- a/extension/src/commands/external.ts
+++ b/extension/src/commands/external.ts
@@ -19,6 +19,7 @@ export enum RegisteredCliCommands {
EXPERIMENT_VIEW_REMOVE = 'dvc.views.experiments.removeExperiment',
EXPERIMENT_VIEW_SHARE_AS_BRANCH = 'dvc.views.experiments.shareExperimentAsBranch',
EXPERIMENT_VIEW_SHARE_AS_COMMIT = 'dvc.views.experiments.shareExperimentAsCommit',
+ EXPERIMENT_VIEW_SHOW_LOGS = 'dvc.views.experiments.showLogs',
EXPERIMENT_VIEW_STOP = 'dvc.views.experiments.stopQueueExperiment',
EXPERIMENT_VIEW_QUEUE = 'dvc.views.experiments.queueExperiment',
diff --git a/extension/src/experiments/commands/register.ts b/extension/src/experiments/commands/register.ts
index cbd690b048..0973e87206 100644
--- a/extension/src/experiments/commands/register.ts
+++ b/extension/src/experiments/commands/register.ts
@@ -350,4 +350,10 @@ export const registerExperimentCommands = (
RegisteredCommands.EXPERIMENT_VIEW_SHARE_TO_STUDIO,
getShareExperimentToStudioCommand(internalCommands, connect)
)
+
+ internalCommands.registerExternalCliCommand(
+ RegisteredCliCommands.EXPERIMENT_VIEW_SHOW_LOGS,
+ ({ dvcRoot, id }: ExperimentDetails) =>
+ internalCommands.executeCommand(AvailableCommands.QUEUE_LOGS, dvcRoot, id)
+ )
}
diff --git a/extension/src/experiments/webview/messages.ts b/extension/src/experiments/webview/messages.ts
index cb87402439..e5de97c1af 100644
--- a/extension/src/experiments/webview/messages.ts
+++ b/extension/src/experiments/webview/messages.ts
@@ -190,6 +190,15 @@ export class WebviewMessages {
{ dvcRoot: this.dvcRoot, id: message.payload }
)
+ case MessageFromWebviewType.SHOW_EXPERIMENT_LOGS:
+ return commands.executeCommand(
+ RegisteredCliCommands.EXPERIMENT_VIEW_SHOW_LOGS,
+ {
+ dvcRoot: this.dvcRoot,
+ id: message.payload
+ }
+ )
+
default:
Logger.error(`Unexpected message: ${JSON.stringify(message)}`)
}
diff --git a/extension/src/telemetry/constants.ts b/extension/src/telemetry/constants.ts
index cf346e051f..e7c28a8f75 100644
--- a/extension/src/telemetry/constants.ts
+++ b/extension/src/telemetry/constants.ts
@@ -148,6 +148,7 @@ export interface IEventNamePropertyMapping {
[EventName.EXPERIMENT_VIEW_SHARE_AS_BRANCH]: undefined
[EventName.EXPERIMENT_VIEW_SHARE_AS_COMMIT]: undefined
[EventName.EXPERIMENT_VIEW_SHARE_TO_STUDIO]: undefined
+ [EventName.EXPERIMENT_VIEW_SHOW_LOGS]: undefined
[EventName.EXPERIMENT_VIEW_STOP]: undefined
[EventName.QUEUE_EXPERIMENT]: undefined
[EventName.QUEUE_KILL]: undefined
diff --git a/extension/src/test/suite/experiments/index.test.ts b/extension/src/test/suite/experiments/index.test.ts
index 878f5ce276..ece954f630 100644
--- a/extension/src/test/suite/experiments/index.test.ts
+++ b/extension/src/test/suite/experiments/index.test.ts
@@ -68,7 +68,10 @@ import { shortenForLabel } from '../../../util/string'
import { GitExecutor } from '../../../cli/git/executor'
import { WorkspacePlots } from '../../../plots/workspace'
import { PlotSizeNumber } from '../../../plots/webview/contract'
-import { RegisteredCommands } from '../../../commands/external'
+import {
+ RegisteredCliCommands,
+ RegisteredCommands
+} from '../../../commands/external'
import { ConfigKey } from '../../../vscode/config'
import { EXPERIMENT_WORKSPACE_ID } from '../../../cli/dvc/contract'
import * as Time from '../../../util/time'
@@ -78,6 +81,7 @@ import * as FileSystem from '../../../fileSystem'
import * as ProcessExecution from '../../../process/execution'
import { DvcReader } from '../../../cli/dvc/reader'
import { Connect } from '../../../connect'
+import { DvcViewer } from '../../../cli/dvc/viewer'
const { openFileInEditor } = FileSystem
@@ -549,6 +553,39 @@ suite('Experiments Test Suite', () => {
)
}).timeout(WEBVIEW_TEST_TIMEOUT)
+ it('should handle a message to show the logs of an experiment', async () => {
+ const { experiments } = buildExperiments(disposable)
+ await experiments.isReady()
+
+ const mockExpId = 'exp-e7a67'
+
+ const webview = await experiments.showWebview()
+ const mockMessageReceived = getMessageReceivedEmitter(webview)
+
+ const executeCommandSpy = spy(commands, 'executeCommand')
+
+ const mockShowLogs = stub(DvcViewer.prototype, 'queueLogs')
+
+ const logsShown = new Promise(resolve =>
+ mockShowLogs.callsFake(() => {
+ resolve(undefined)
+ return Promise.resolve(undefined)
+ })
+ )
+
+ mockMessageReceived.fire({
+ payload: mockExpId,
+ type: MessageFromWebviewType.SHOW_EXPERIMENT_LOGS
+ })
+
+ await logsShown
+
+ expect(executeCommandSpy).to.be.calledWithExactly(
+ RegisteredCliCommands.EXPERIMENT_VIEW_SHOW_LOGS,
+ { dvcRoot: dvcDemoPath, id: mockExpId }
+ )
+ }).timeout(WEBVIEW_TEST_TIMEOUT)
+
it('should handle a message to share an experiment to Studio', async () => {
const { experiments } = buildExperiments(disposable)
await experiments.isReady()
diff --git a/extension/src/test/suite/experiments/util.ts b/extension/src/test/suite/experiments/util.ts
index 183807845c..e7634392c0 100644
--- a/extension/src/test/suite/experiments/util.ts
+++ b/extension/src/test/suite/experiments/util.ts
@@ -51,6 +51,7 @@ export const buildExperiments = (
dvcExecutor,
dvcReader,
dvcRunner,
+ dvcViewer,
gitReader,
internalCommands,
messageSpy,
@@ -90,6 +91,7 @@ export const buildExperiments = (
dvcExecutor,
dvcReader,
dvcRunner,
+ dvcViewer,
experiments,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
experimentsModel: (experiments as any).experiments as ExperimentsModel,
diff --git a/extension/src/test/suite/util.ts b/extension/src/test/suite/util.ts
index f93ef57993..d20fbe15b5 100644
--- a/extension/src/test/suite/util.ts
+++ b/extension/src/test/suite/util.ts
@@ -34,6 +34,7 @@ import { TableData } from '../../experiments/webview/contract'
import { DvcExecutor } from '../../cli/dvc/executor'
import { GitReader } from '../../cli/git/reader'
import { SetupData } from '../../setup/webview/contract'
+import { DvcViewer } from '../../cli/dvc/viewer'
export const mockDisposable = {
dispose: stub()
@@ -141,6 +142,7 @@ export const buildInternalCommands = (disposer: Disposer) => {
const dvcReader = disposer.track(new DvcReader(config))
const dvcRunner = disposer.track(new DvcRunner(config))
const dvcExecutor = disposer.track(new DvcExecutor(config))
+ const dvcViewer = disposer.track(new DvcViewer(config))
const gitReader = disposer.track(new GitReader())
const outputChannel = disposer.track(
@@ -153,6 +155,7 @@ export const buildInternalCommands = (disposer: Disposer) => {
dvcExecutor,
dvcReader,
dvcRunner,
+ dvcViewer,
gitReader
)
)
@@ -162,6 +165,7 @@ export const buildInternalCommands = (disposer: Disposer) => {
dvcExecutor,
dvcReader,
dvcRunner,
+ dvcViewer,
gitReader,
internalCommands
}
@@ -189,6 +193,7 @@ export const buildDependencies = (
dvcExecutor,
dvcReader,
dvcRunner,
+ dvcViewer,
gitReader,
internalCommands
} = buildInternalCommands(disposer)
@@ -223,6 +228,7 @@ export const buildDependencies = (
dvcExecutor,
dvcReader,
dvcRunner,
+ dvcViewer,
gitReader,
internalCommands,
messageSpy,
diff --git a/extension/src/webview/contract.ts b/extension/src/webview/contract.ts
index ccb4f574f1..00d071112b 100644
--- a/extension/src/webview/contract.ts
+++ b/extension/src/webview/contract.ts
@@ -35,6 +35,7 @@ export enum MessageFromWebviewType {
RESIZE_PLOTS = 'resize-plots',
SAVE_STUDIO_TOKEN = 'save-studio-token',
SHARE_EXPERIMENT_TO_STUDIO = 'share-experiment-to-studio',
+ SHOW_EXPERIMENT_LOGS = 'show-experiment-logs',
STOP_EXPERIMENT = 'stop-experiment',
SORT_COLUMN = 'sort-column',
TOGGLE_EXPERIMENT = 'toggle-experiment',
@@ -136,6 +137,7 @@ export type MessageFromWebview =
type: MessageFromWebviewType.STOP_EXPERIMENT
payload: { id: string; executor?: string | null }[]
}
+ | { type: MessageFromWebviewType.SHOW_EXPERIMENT_LOGS; payload: string }
| {
type: MessageFromWebviewType.SHARE_EXPERIMENT_TO_STUDIO
payload: string
diff --git a/webview/src/experiments/components/App.test.tsx b/webview/src/experiments/components/App.test.tsx
index bbed320f13..edd4d4a208 100644
--- a/webview/src/experiments/components/App.test.tsx
+++ b/webview/src/experiments/components/App.test.tsx
@@ -864,6 +864,7 @@ describe('App', () => {
const menuitems = screen.getAllByRole('menuitem')
const itemLabels = menuitems.map(item => item.textContent)
expect(itemLabels).toStrictEqual([
+ 'Show Logs',
'Apply to Workspace',
'Create new Branch',
'Share to Studio',
@@ -888,7 +889,7 @@ describe('App', () => {
fireEvent.contextMenu(row, { bubbles: true })
advanceTimersByTime(100)
- expect(screen.getAllByRole('menuitem')).toHaveLength(11)
+ expect(screen.getAllByRole('menuitem')).toHaveLength(12)
fireEvent.click(window, { bubbles: true })
advanceTimersByTime(100)
@@ -902,7 +903,7 @@ describe('App', () => {
fireEvent.contextMenu(row, { bubbles: true })
advanceTimersByTime(100)
- expect(screen.getAllByRole('menuitem')).toHaveLength(11)
+ expect(screen.getAllByRole('menuitem')).toHaveLength(12)
const commit = getRow('main')
fireEvent.click(commit, { bubbles: true })
@@ -917,13 +918,13 @@ describe('App', () => {
fireEvent.contextMenu(row, { bubbles: true })
advanceTimersByTime(100)
- expect(screen.queryAllByRole('menuitem')).toHaveLength(11)
+ expect(screen.queryAllByRole('menuitem')).toHaveLength(12)
fireEvent.contextMenu(within(row).getByText('[exp-e7a67]'), {
bubbles: true
})
advanceTimersByTime(200)
- expect(screen.queryAllByRole('menuitem')).toHaveLength(11)
+ expect(screen.queryAllByRole('menuitem')).toHaveLength(12)
})
it('should present the Remove experiment option for the checkpoint tips', () => {
diff --git a/webview/src/experiments/components/table/RowContextMenu.tsx b/webview/src/experiments/components/table/RowContextMenu.tsx
index 105ba077b3..11c8513362 100644
--- a/webview/src/experiments/components/table/RowContextMenu.tsx
+++ b/webview/src/experiments/components/table/RowContextMenu.tsx
@@ -3,7 +3,8 @@ import { MessageFromWebviewType } from 'dvc/src/webview/contract'
import {
ExperimentStatus,
isQueued,
- isRunning
+ isRunning,
+ isRunningInQueue
} from 'dvc/src/experiments/webview/contract'
import { EXPERIMENT_WORKSPACE_ID } from 'dvc/src/cli/dvc/contract'
import { RowProp } from './interfaces'
@@ -190,6 +191,12 @@ const getSingleSelectMenuOptions = (
)
return [
+ experimentMenuOption(
+ id,
+ 'Show Logs',
+ MessageFromWebviewType.SHOW_EXPERIMENT_LOGS,
+ !isRunningInQueue({ executor, status })
+ ),
notRunningWithId(
'Apply to Workspace',
MessageFromWebviewType.APPLY_EXPERIMENT_TO_WORKSPACE,
diff --git a/webview/src/plots/components/PlotsContainer.tsx b/webview/src/plots/components/PlotsContainer.tsx
index 3f65989b92..c157d23d3f 100644
--- a/webview/src/plots/components/PlotsContainer.tsx
+++ b/webview/src/plots/components/PlotsContainer.tsx
@@ -23,11 +23,7 @@ import {
import { isSelecting } from '../../util/strings'
import { isTooltip } from '../../util/helpers'
-export interface CommonPlotsContainerProps {
- onResize: (size: number) => void
-}
-
-export interface PlotsContainerProps extends CommonPlotsContainerProps {
+export interface PlotsContainerProps {
sectionCollapsed: boolean
sectionKey: Section
title: string
diff --git a/webview/src/plots/components/checkpointPlots/CheckpointPlotsWrapper.tsx b/webview/src/plots/components/checkpointPlots/CheckpointPlotsWrapper.tsx
index 708e5194b3..a1a8b03ef3 100644
--- a/webview/src/plots/components/checkpointPlots/CheckpointPlotsWrapper.tsx
+++ b/webview/src/plots/components/checkpointPlots/CheckpointPlotsWrapper.tsx
@@ -1,15 +1,13 @@
import { Section } from 'dvc/src/plots/webview/contract'
import { MessageFromWebviewType } from 'dvc/src/webview/contract'
import React, { useEffect, useState } from 'react'
-import { useSelector, useDispatch } from 'react-redux'
+import { useSelector } from 'react-redux'
import { CheckpointPlots } from './CheckpointPlots'
-import { changeSize } from './checkpointPlotsSlice'
import { PlotsContainer } from '../PlotsContainer'
import { sendMessage } from '../../../shared/vscode'
import { PlotsState } from '../../store'
export const CheckpointPlotsWrapper: React.FC = () => {
- const dispatch = useDispatch()
const { plotsIds, size, selectedMetrics, isCollapsed, colors } = useSelector(
(state: PlotsState) => state.checkpoint
)
@@ -29,10 +27,6 @@ export const CheckpointPlotsWrapper: React.FC = () => {
})
}
- const handleResize = (size: number) => {
- dispatch(changeSize(size))
- }
-
const menu =
plotsIds.length > 0
? {
@@ -49,7 +43,6 @@ export const CheckpointPlotsWrapper: React.FC = () => {
menu={menu}
currentSize={size}
sectionCollapsed={isCollapsed}
- onResize={handleResize}
>
diff --git a/webview/src/plots/components/comparisonTable/ComparisonTableWrapper.tsx b/webview/src/plots/components/comparisonTable/ComparisonTableWrapper.tsx
index e7d07f960f..476c4cf9fb 100644
--- a/webview/src/plots/components/comparisonTable/ComparisonTableWrapper.tsx
+++ b/webview/src/plots/components/comparisonTable/ComparisonTableWrapper.tsx
@@ -1,19 +1,14 @@
import { Section } from 'dvc/src/plots/webview/contract'
import React from 'react'
-import { useSelector, useDispatch } from 'react-redux'
+import { useSelector } from 'react-redux'
import { ComparisonTable } from './ComparisonTable'
-import { changeSize } from './comparisonTableSlice'
import { PlotsContainer } from '../PlotsContainer'
import { PlotsState } from '../../store'
export const ComparisonTableWrapper: React.FC = () => {
- const dispatch = useDispatch()
const { size, isCollapsed } = useSelector(
(state: PlotsState) => state.comparison
)
- const handleResize = (size: number) => {
- dispatch(changeSize(size))
- }
return (
{
sectionKey={Section.COMPARISON_TABLE}
currentSize={size}
sectionCollapsed={isCollapsed}
- onResize={handleResize}
>
diff --git a/webview/src/plots/components/templatePlots/TemplatePlotsWrapper.tsx b/webview/src/plots/components/templatePlots/TemplatePlotsWrapper.tsx
index 2b45f58120..1f0ed0b4fc 100644
--- a/webview/src/plots/components/templatePlots/TemplatePlotsWrapper.tsx
+++ b/webview/src/plots/components/templatePlots/TemplatePlotsWrapper.tsx
@@ -1,28 +1,20 @@
import { Section } from 'dvc/src/plots/webview/contract'
import React from 'react'
-import { useSelector, useDispatch } from 'react-redux'
+import { useSelector } from 'react-redux'
import { TemplatePlots } from './TemplatePlots'
-import { changeSize } from './templatePlotsSlice'
import { PlotsContainer } from '../PlotsContainer'
import { PlotsState } from '../../store'
export const TemplatePlotsWrapper: React.FC = () => {
- const dispatch = useDispatch()
const { size, isCollapsed } = useSelector(
(state: PlotsState) => state.template
)
-
- const handleResize = (size: number) => {
- dispatch(changeSize(size))
- }
-
return (
diff --git a/webview/src/shared/components/emptyState/styles.module.scss b/webview/src/shared/components/emptyState/styles.module.scss
index 751e59cd36..0613e16a2b 100644
--- a/webview/src/shared/components/emptyState/styles.module.scss
+++ b/webview/src/shared/components/emptyState/styles.module.scss
@@ -6,7 +6,7 @@
}
.emptySection {
- width: 100vw;
+ width: 100%;
height: 33vh;
}
diff --git a/yarn.lock b/yarn.lock
index 1a9006a209..8f44cb560e 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -4442,10 +4442,10 @@
resolved "https://registry.yarnpkg.com/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz#b6725d5f4af24ace33b36fafd295136e75509f43"
integrity sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA==
-"@types/uuid@9.0.0":
- version "9.0.0"
- resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-9.0.0.tgz#53ef263e5239728b56096b0a869595135b7952d2"
- integrity sha512-kr90f+ERiQtKWMz5rP32ltJ/BtULDI5RVO0uavn1HQUOwjx0R1h0rnDYNL0CepF1zL5bSY6FISAfd9tOdDhU5Q==
+"@types/uuid@9.0.1":
+ version "9.0.1"
+ resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-9.0.1.tgz#98586dc36aee8dacc98cc396dbca8d0429647aa6"
+ integrity sha512-rFT3ak0/2trgvp4yYZo5iKFEPsET7vKydKF+VRCxlQ9bpheehyAJH89dAkaLEq/j/RZXJIqcgsmPJKUP1Z28HA==
"@types/vscode@1.64.0":
version "1.64.0"