From 1ef8e2f7f2687f1654c1e5fec1a095ec556d2784 Mon Sep 17 00:00:00 2001 From: Neel Gondalia Date: Thu, 22 Feb 2024 17:11:54 -0500 Subject: [PATCH] Support opening trace files through a dialog This commit adds another button for opening trace files through a dialog. Futhermore, the theia-trace-explorer-placeholder-widget can be configured to render either one or both buttons (Open Trace folder, Open Trace File). Fixes #1053 Signed-off-by: Neel Gondalia --- .../trace-explorer-placeholder-widget.tsx | 39 ++++++++++++------- .../react-components/style/trace-explorer.css | 4 +- ...heia-trace-explorer-placeholder-widget.tsx | 17 +++++--- .../trace-viewer/trace-viewer-commands.ts | 11 ++++-- .../trace-viewer/trace-viewer-contribution.ts | 26 ++++++++----- .../trace-viewer-toolbar-commands.ts | 12 ++++-- .../trace-viewer-toolbar-contribution.tsx | 34 ++++++++++++---- 7 files changed, 100 insertions(+), 43 deletions(-) diff --git a/packages/react-components/src/trace-explorer/trace-explorer-placeholder-widget.tsx b/packages/react-components/src/trace-explorer/trace-explorer-placeholder-widget.tsx index 44bd1ffd0..bc65f95ad 100644 --- a/packages/react-components/src/trace-explorer/trace-explorer-placeholder-widget.tsx +++ b/packages/react-components/src/trace-explorer/trace-explorer-placeholder-widget.tsx @@ -2,9 +2,15 @@ import { faSpinner } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import * as React from 'react'; +export enum TraceResourceType { + FOLDER = 'Folder', + FILE = 'File' +} + export interface ReactPlaceholderWidgetProps { loading: boolean; - handleOpenTrace: () => void; + handleOpenTrace: (type?: TraceResourceType) => void; + renderOnly?: TraceResourceType; } export class ReactExplorerPlaceholderWidget extends React.Component { @@ -16,19 +22,26 @@ export class ReactExplorerPlaceholderWidget extends React.Component
{'You have not yet opened a trace.'}
-
- -
+ {this.renderButton(TraceResourceType.FOLDER, 'Open Trace Folder')} + {this.renderButton(TraceResourceType.FILE, 'Open Trace File')} ); } + + renderButton(type: TraceResourceType, title: string): React.ReactNode { + return this.props.renderOnly === undefined || this.props.renderOnly === type ? ( +
+ +
+ ) : undefined; + } } diff --git a/packages/react-components/style/trace-explorer.css b/packages/react-components/style/trace-explorer.css index fb9dd6bca..f6a5ca88f 100644 --- a/packages/react-components/style/trace-explorer.css +++ b/packages/react-components/style/trace-explorer.css @@ -374,10 +374,12 @@ .placeholder-open-workspace-button-container { margin: auto; - margin-top: 5px; + margin-top: 10px; + margin-bottom: 15px; display: flex; justify-content: center; align-self: center; + max-width: 300px; } .plcaeholder-open-workspace-button { diff --git a/theia-extensions/viewer-prototype/src/browser/trace-explorer/trace-explorer-sub-widgets/theia-trace-explorer-placeholder-widget.tsx b/theia-extensions/viewer-prototype/src/browser/trace-explorer/trace-explorer-sub-widgets/theia-trace-explorer-placeholder-widget.tsx index 9ef03f1bb..af6e5cb17 100644 --- a/theia-extensions/viewer-prototype/src/browser/trace-explorer/trace-explorer-sub-widgets/theia-trace-explorer-placeholder-widget.tsx +++ b/theia-extensions/viewer-prototype/src/browser/trace-explorer/trace-explorer-sub-widgets/theia-trace-explorer-placeholder-widget.tsx @@ -2,8 +2,11 @@ import { inject, injectable, postConstruct } from '@theia/core/shared/inversify' import { ReactWidget } from '@theia/core/lib/browser'; import * as React from 'react'; import { CommandService } from '@theia/core'; -import { OpenTraceCommand } from '../../trace-viewer/trace-viewer-commands'; -import { ReactExplorerPlaceholderWidget } from 'traceviewer-react-components/lib/trace-explorer/trace-explorer-placeholder-widget'; +import { OpenTraceFileCommand, OpenTraceFolderCommand } from '../../trace-viewer/trace-viewer-commands'; +import { + ReactExplorerPlaceholderWidget, + TraceResourceType +} from 'traceviewer-react-components/lib/trace-explorer/trace-explorer-placeholder-widget'; @injectable() export class TraceExplorerPlaceholderWidget extends ReactWidget { @@ -33,12 +36,16 @@ export class TraceExplorerPlaceholderWidget extends ReactWidget { ); } - protected handleOpenTrace = async (): Promise => this.doHandleOpenTrace(); + protected handleOpenTrace = async (type?: TraceResourceType): Promise => this.doHandleOpenTrace(type); - private async doHandleOpenTrace() { + private async doHandleOpenTrace(type?: TraceResourceType) { this.state.loading = true; this.update(); - await this.commandService.executeCommand(OpenTraceCommand.id); + if (type && type === TraceResourceType.FILE) { + await this.commandService.executeCommand(OpenTraceFileCommand.id); + } else { + await this.commandService.executeCommand(OpenTraceFolderCommand.id); + } this.state.loading = false; this.update(); } diff --git a/theia-extensions/viewer-prototype/src/browser/trace-viewer/trace-viewer-commands.ts b/theia-extensions/viewer-prototype/src/browser/trace-viewer/trace-viewer-commands.ts index 058d7c7b8..371f6bb48 100644 --- a/theia-extensions/viewer-prototype/src/browser/trace-viewer/trace-viewer-commands.ts +++ b/theia-extensions/viewer-prototype/src/browser/trace-viewer/trace-viewer-commands.ts @@ -1,8 +1,13 @@ import { Command } from '@theia/core'; -export const OpenTraceCommand: Command = { - id: 'open-trace', - label: 'Open Trace' +export const OpenTraceFolderCommand: Command = { + id: 'open-trace-folder', + label: 'Open Trace Folder' +}; + +export const OpenTraceFileCommand: Command = { + id: 'open-trace-file', + label: 'Open Trace File' }; export const TraceViewerCommand: Command = { diff --git a/theia-extensions/viewer-prototype/src/browser/trace-viewer/trace-viewer-contribution.ts b/theia-extensions/viewer-prototype/src/browser/trace-viewer/trace-viewer-contribution.ts index ccad55a82..5d9de8e91 100644 --- a/theia-extensions/viewer-prototype/src/browser/trace-viewer/trace-viewer-contribution.ts +++ b/theia-extensions/viewer-prototype/src/browser/trace-viewer/trace-viewer-contribution.ts @@ -11,13 +11,14 @@ import { TraceViewerWidget, TraceViewerWidgetOptions } from './trace-viewer'; import { FileDialogService, OpenFileDialogProps } from '@theia/filesystem/lib/browser'; import { WorkspaceService } from '@theia/workspace/lib/browser/workspace-service'; import { - OpenTraceCommand, + OpenTraceFolderCommand, StartServerCommand, StopServerCommand, TraceViewerCommand, KeyboardShortcutsCommand, OpenTraceWithRootPathCommand, - OpenTraceWithPathCommand + OpenTraceWithPathCommand, + OpenTraceFileCommand } from './trace-viewer-commands'; import { PortBusy, TraceServerConfigService } from '../../common/trace-server-config'; import { TracePreferences, TRACE_PATH, TRACE_ARGS } from '../trace-server-preference'; @@ -27,6 +28,7 @@ import { signalManager } from 'traceviewer-base/lib/signals/signal-manager'; import { TraceServerConnectionStatusClient } from '../../common/trace-server-connection-status'; import { FileStat } from '@theia/filesystem/lib/common/files'; import { ITspClient } from 'tsp-typescript-client'; +import { TraceResourceType } from 'traceviewer-react-components/lib/trace-explorer/trace-explorer-placeholder-widget'; interface TraceViewerWidgetOpenerOptions extends WidgetOpenerOptions { traceUUID: string; @@ -71,15 +73,16 @@ export class TraceViewerContribution }; } - protected async launchTraceServer(rootPath?: string): Promise { + protected async launchTraceServer(rootPath?: string, type?: TraceResourceType): Promise { let healthResponse; try { healthResponse = await this.tspClient.checkHealth(); } catch (err) { // continue to start trace server } + const selectFiles = type && type === TraceResourceType.FILE ? true : false; if (healthResponse && healthResponse.isOk() && healthResponse.getModel()?.status === 'UP') { - this.openDialog(rootPath); + this.openDialog(rootPath, selectFiles); } else { const progress = await this.messageService.showProgress({ text: '' }); progress.report({ message: 'Launching trace server... ', work: { done: 10, total: 100 } }); @@ -98,7 +101,7 @@ export class TraceViewerContribution progress.cancel(); this.serverStatusService.updateStatus(true); signalManager().fireTraceServerStartedSignal(); - this.openDialog(rootPath); + this.openDialog(rootPath, selectFiles); } } catch (err) { // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -120,12 +123,12 @@ export class TraceViewerContribution } } - async openDialog(rootPath?: string): Promise { + async openDialog(rootPath?: string, selectFiles = false): Promise { const props: OpenFileDialogProps = { title: 'Open Trace', // Only support selecting folders, both folders and file doesn't work in Electron (issue #227) - canSelectFolders: true, - canSelectFiles: false + canSelectFolders: !selectFiles, + canSelectFiles: selectFiles }; let fileURI = undefined; if (rootPath !== undefined) { @@ -201,8 +204,11 @@ export class TraceViewerContribution } registerCommands(registry: CommandRegistry): void { - registry.registerCommand(OpenTraceCommand, { - execute: () => this.launchTraceServer() + registry.registerCommand(OpenTraceFolderCommand, { + execute: () => this.launchTraceServer(undefined, TraceResourceType.FOLDER) + }); + registry.registerCommand(OpenTraceFileCommand, { + execute: () => this.launchTraceServer(undefined, TraceResourceType.FILE) }); registry.registerCommand(OpenTraceWithPathCommand, { isVisible: () => false, diff --git a/theia-extensions/viewer-prototype/src/browser/trace-viewer/trace-viewer-toolbar-commands.ts b/theia-extensions/viewer-prototype/src/browser/trace-viewer/trace-viewer-toolbar-commands.ts index 5c182617b..3c172b0a1 100644 --- a/theia-extensions/viewer-prototype/src/browser/trace-viewer/trace-viewer-toolbar-commands.ts +++ b/theia-extensions/viewer-prototype/src/browser/trace-viewer/trace-viewer-toolbar-commands.ts @@ -42,12 +42,18 @@ export namespace TraceViewerToolbarCommands { label: 'Markers', iconClass: 'fa fa-bars fa-lg' }; - export const OPEN_TRACE: Command = { - id: 'trace.viewer.openTrace', - label: 'Open Trace', + export const OPEN_TRACE_FOLDER: Command = { + id: 'trace.viewer.openTraceFolder', + label: 'Open Trace Folder', iconClass: 'codicon codicon-new-folder' }; + export const OPEN_TRACE_FILE: Command = { + id: 'trace.viewer.openTraceFile', + label: 'Open Trace File', + iconClass: 'codicon codicon-new-file' + }; + export const CHARTS_CHEATSHEET: Command = { id: 'trace.viewer.toolbar.cheatsheet', label: 'Keyboard Shortcuts (CTRL / command + F1)', diff --git a/theia-extensions/viewer-prototype/src/browser/trace-viewer/trace-viewer-toolbar-contribution.tsx b/theia-extensions/viewer-prototype/src/browser/trace-viewer/trace-viewer-toolbar-contribution.tsx index b0d313e70..be8aafc28 100644 --- a/theia-extensions/viewer-prototype/src/browser/trace-viewer/trace-viewer-toolbar-contribution.tsx +++ b/theia-extensions/viewer-prototype/src/browser/trace-viewer/trace-viewer-toolbar-contribution.tsx @@ -9,7 +9,7 @@ import { ChartShortcutsDialog } from '../trace-explorer/trace-explorer-sub-widge import { TspClientProvider } from '../tsp-client-provider-impl'; import { TraceViewerWidget } from './trace-viewer'; import { TraceViewerToolbarCommands, TraceViewerToolbarMenus } from './trace-viewer-toolbar-commands'; -import { OpenTraceCommand } from './trace-viewer-commands'; +import { OpenTraceFileCommand, OpenTraceFolderCommand } from './trace-viewer-commands'; @injectable() export class TraceViewerToolbarContribution implements TabBarToolbarContribution, CommandContribution { @@ -112,7 +112,7 @@ export class TraceViewerToolbarContribution implements TabBarToolbarContribution signalManager().fireResetZoomSignal(); } }); - registry.registerCommand(TraceViewerToolbarCommands.OPEN_TRACE, { + registry.registerCommand(TraceViewerToolbarCommands.OPEN_TRACE_FOLDER, { isVisible: (w: Widget) => { if (w instanceof TraceExplorerOpenedTracesWidget) { return true; @@ -120,7 +120,19 @@ export class TraceViewerToolbarContribution implements TabBarToolbarContribution return false; }, execute: async () => { - await registry.executeCommand(OpenTraceCommand.id); + await registry.executeCommand(OpenTraceFolderCommand.id); + } + }); + + registry.registerCommand(TraceViewerToolbarCommands.OPEN_TRACE_FILE, { + isVisible: (w: Widget) => { + if (w instanceof TraceExplorerOpenedTracesWidget) { + return true; + } + return false; + }, + execute: async () => { + await registry.executeCommand(OpenTraceFileCommand.id); } }); @@ -331,22 +343,28 @@ export class TraceViewerToolbarContribution implements TabBarToolbarContribution onDidChange: this.onMakerSetsChangedEvent }); registry.registerItem({ - id: TraceViewerToolbarCommands.OPEN_TRACE.id, - command: TraceViewerToolbarCommands.OPEN_TRACE.id, - tooltip: TraceViewerToolbarCommands.OPEN_TRACE.label, + id: TraceViewerToolbarCommands.OPEN_TRACE_FILE.id, + command: TraceViewerToolbarCommands.OPEN_TRACE_FILE.id, + tooltip: TraceViewerToolbarCommands.OPEN_TRACE_FILE.label, priority: 8 }); + registry.registerItem({ + id: TraceViewerToolbarCommands.OPEN_TRACE_FOLDER.id, + command: TraceViewerToolbarCommands.OPEN_TRACE_FOLDER.id, + tooltip: TraceViewerToolbarCommands.OPEN_TRACE_FOLDER.label, + priority: 9 + }); registry.registerItem({ id: TraceViewerToolbarCommands.OPEN_OVERVIEW_OUTPUT.id, command: TraceViewerToolbarCommands.OPEN_OVERVIEW_OUTPUT.id, tooltip: TraceViewerToolbarCommands.OPEN_OVERVIEW_OUTPUT.label, - priority: 9 + priority: 10 }); registry.registerItem({ id: TraceViewerToolbarCommands.CHARTS_CHEATSHEET.id, command: TraceViewerToolbarCommands.CHARTS_CHEATSHEET.id, tooltip: TraceViewerToolbarCommands.CHARTS_CHEATSHEET.label, - priority: 10 + priority: 11 }); } }