Skip to content

Commit

Permalink
Add prototype of React Component displaying configurations source types
Browse files Browse the repository at this point in the history
ADR-0011 introduces the API for managing global configurations. Thus, the
Trace Extension needs an interface to expose this API to users.

The purpose of this commit is to start creating this UI for the trace
extension as a React Component. It provides a skeleton for the component
so that it can be further extended in future commits:

[1] Added TraceConfigurationManager to handle calls to the TSPClient that
relates to trace configuration.

[2] Introduce a prototype of the UI as the
TraceConfigurationsDialogComponent. This is the main component of the UI
that handles the display logic for other sub-components, such as [3].

[3] Added TraceConfigurationListComponent to list the available
configuration source types and their instances from the server.

To test, open a trace and hover the mouse over the toolbar of the
Available Views widget. There should be an icon that appears. Click on the
icon to open the trace configuration dialog. In this prototype, the dialog
should only display the configuration source types.

Signed-off-by: Hoang Thuan Pham <hoang.pham@calian.ca>
  • Loading branch information
hoangphamEclipse committed Oct 11, 2023
1 parent 9b5a515 commit b903ecf
Show file tree
Hide file tree
Showing 11 changed files with 272 additions and 3 deletions.
7 changes: 6 additions & 1 deletion packages/base/src/signals/signal-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ export declare interface SignalManager {
fireSelectionRangeUpdated(payload: TimeRangeUpdatePayload): void;
fireViewRangeUpdated(payload: TimeRangeUpdatePayload): void;
fireRequestSelectionRangeChange(payload: TimeRangeUpdatePayload): void;
fireShowTraceConfigurations(): void;
}

export const Signals = {
Expand Down Expand Up @@ -75,7 +76,8 @@ export const Signals = {
VIEW_RANGE_UPDATED: 'view range updated',
SELECTION_RANGE_UPDATED: 'selection range updated',
REQUEST_SELECTION_RANGE_CHANGE: 'change selection range',
OUTPUT_DATA_CHANGED: 'output data changed'
OUTPUT_DATA_CHANGED: 'output data changed',
SHOW_TRACE_CONFIGURATIONS: 'open trace configurations'
};

export class SignalManager extends EventEmitter implements SignalManager {
Expand Down Expand Up @@ -174,6 +176,9 @@ export class SignalManager extends EventEmitter implements SignalManager {
fireRequestSelectionRangeChange(payload: TimeRangeUpdatePayload): void {
this.emit(Signals.REQUEST_SELECTION_RANGE_CHANGE, payload);
}
fireShowTraceConfigurations(): void {
this.emit(Signals.SHOW_TRACE_CONFIGURATIONS);
}
}

let instance: SignalManager = new SignalManager();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export abstract class AbstractDialogComponent<P extends DialogComponentProps, S>
className="dialog"
ariaHideApp={false}
onRequestClose={this.props.onCloseDialog}
onAfterOpen={() => this.onAfterOpen()}
shouldFocusAfterRender={false}
>
<div
Expand All @@ -42,4 +43,8 @@ export abstract class AbstractDialogComponent<P extends DialogComponentProps, S>

protected abstract renderDialogBody(): React.ReactElement;
protected abstract renderFooter(): React.ReactElement;

protected onAfterOpen(): void {
return;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import React from 'react';
import { ConfigurationSourceType } from 'tsp-typescript-client/lib/models/configuration-source';
import { ITspClient } from 'tsp-typescript-client';
import { TraceConfigurationListComponent } from './trace-configuration-list-component';
import { TraceConfigurationManager } from './trace-configuration-manager';
import { signalManager, Signals } from 'traceviewer-base/lib/signals/signal-manager';

const TRACE_CONFIGURATION_TITLE = 'Trace Configuration';

export interface TraceConfigurationVisibility {
list: boolean,
add: boolean
}

export interface TraceConfigurationsDialogComponentProps {
tspClient: ITspClient
}
export interface TraceConfigurationsDialogComponentState {
visibility: TraceConfigurationVisibility
configurationSourceTypes: ConfigurationSourceType[];
}

export class TraceConfigurationsDialogComponent extends React.Component<TraceConfigurationsDialogComponentProps, TraceConfigurationsDialogComponentState> {
private traceConfigurationManager: TraceConfigurationManager;

constructor(props: TraceConfigurationsDialogComponentProps) {
super(props);
this.traceConfigurationManager = new TraceConfigurationManager(this.props.tspClient);
this.state = {
visibility: {
list: false,
add: false
},
configurationSourceTypes: []
};

signalManager().on(Signals.SHOW_TRACE_CONFIGURATIONS, this.onOpenListView);
}

render(): React.ReactElement {
return (
<React.Fragment>
<TraceConfigurationListComponent
traceConfigurationManager={this.traceConfigurationManager}
title={TRACE_CONFIGURATION_TITLE}
onCloseDialog={this.onCloseListView}
isOpen={this.state.visibility.list}></TraceConfigurationListComponent>
</React.Fragment>
);
}

protected onCloseListView = (): void => {
this.updateVisibility({
list: false,
add: false,
});
};

protected onOpenListView = (): void => {
this.updateVisibility({
list: true,
add: false,
});
};

private updateVisibility(visibility: TraceConfigurationVisibility): void {
this.setState({
visibility: visibility
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@

import { ReactElement } from 'react';
import React from 'react';
import { ConfigurationSourceType } from 'tsp-typescript-client/lib/models/configuration-source';
import { AutoSizer, List, ListRowProps } from 'react-virtualized';
import { AbstractDialogComponent, DialogComponentProps } from '../abstract-dialog-component';
import { TraceConfigurationManager } from './trace-configuration-manager';

export interface TraceConfigurationListComponentProps extends DialogComponentProps {
traceConfigurationManager: TraceConfigurationManager
}

export interface TraceConfigurationListComponentState {
configurationSourceTypes: ConfigurationSourceType[];
}

export class TraceConfigurationListComponent extends AbstractDialogComponent<
TraceConfigurationListComponentProps,
TraceConfigurationListComponentState> {
private _forceUpdateKey = false;
private readonly TRACE_CONFIGURATIONS_ROW_HEIGHT = 20;

protected renderFooter(): ReactElement {
return (
<div>
</div>
);
}

constructor(props: TraceConfigurationListComponentProps) {
super(props);
this.state = {
configurationSourceTypes: []
};
}

protected onAfterOpen(): void {
this.props.traceConfigurationManager.getConfigurationSourceTypes().then(result => {
if (result !== undefined) {
this.setState({
configurationSourceTypes: result
});
}
});
}

protected renderDialogBody(): React.ReactElement {
this._forceUpdateKey = !this._forceUpdateKey;
const key = Number(this._forceUpdateKey);
let outputsRowCount = 0;
const outputs = this.state.configurationSourceTypes;
if (outputs) {
outputsRowCount = outputs.length;
}
const totalHeight = 400; // TODO: Change this value once styling is applied
return (
<div>
List of configurations
<AutoSizer>
{({ width }) => (
<List
key={key}
height={totalHeight}
width={width}
rowCount={outputsRowCount}
rowHeight={this.TRACE_CONFIGURATIONS_ROW_HEIGHT}
rowRenderer={this.renderRowOutputs}
/>
)}
</AutoSizer>
</div>
);
}

protected renderRowOutputs = (props: ListRowProps): React.ReactNode => this.doRenderRowOutputs(props);

private doRenderRowOutputs(props: ListRowProps): React.ReactNode {
let outputName = '';
let output: ConfigurationSourceType | undefined;
const configurationSourceTypes = this.state.configurationSourceTypes;
if (configurationSourceTypes && configurationSourceTypes.length && props.index < configurationSourceTypes.length) {
output = configurationSourceTypes[props.index];
outputName = output.name;
}

return (
<div>
<div style={{width: '100%'}}>
<h4 className="outputs-element-name">{outputName}</h4>
</div>
</div>
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { ITspClient } from 'tsp-typescript-client';
import { ConfigurationSourceType } from 'tsp-typescript-client/lib/models/configuration-source';

export class TraceConfigurationManager {
private tspClient: ITspClient;

constructor(tspClient: ITspClient) {
this.tspClient = tspClient;
}

/**
* Get an array of OutputDescriptor for a given experiment
* @param experimentUUID experiment UUID
*/
async getConfigurationSourceTypes(): Promise<ConfigurationSourceType[] | undefined> {
const outputsResponse = await this.tspClient.fetchConfigurationSourceTypes();
if (outputsResponse && outputsResponse.isOk()) {
return outputsResponse.getModel();
}
return undefined;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@

import { ReactElement } from 'react';
import React from 'react';
import { AbstractDialogComponent, DialogComponentProps } from '../abstract-dialog-component';

// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface TraceConfigurationsAddDialogComponentState {
}

export class TraceConfigurationsAddDialogComponent extends AbstractDialogComponent<DialogComponentProps, TraceConfigurationsAddDialogComponentState> {
protected renderFooter(): ReactElement {
return (
<div>
<button>Add</button>
</div>
);
}

constructor(props: DialogComponentProps) {
super(props);
}

protected renderDialogBody(): React.ReactElement {
return (
<div>
Add configurations
</div>
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { Experiment } from 'tsp-typescript-client/lib/models/experiment';
import { ITspClientProvider } from 'traceviewer-base/lib/tsp-client-provider';
import { ExperimentManager } from 'traceviewer-base/lib/experiment-manager';
import { AvailableViewsComponent } from '../components/utils/available-views-component';
import { TraceConfigurationsDialogComponent } from '../components/trace-configurations/trace-configuration-dialog-component';

export interface ReactAvailableViewsProps {
id: string;
Expand Down Expand Up @@ -44,6 +45,9 @@ export class ReactAvailableViewsWidget extends React.Component<ReactAvailableVie
render(): React.ReactNode {
return (
<div className="trace-explorer-views">
<TraceConfigurationsDialogComponent
tspClient={this.props.tspClientProvider.getTspClient()}
></TraceConfigurationsDialogComponent>
<AvailableViewsComponent
traceID={this._selectedExperiment?.UUID}
outputDescriptors={this.state.availableOutputDescriptors}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ export const OpenTraceWithRootPathCommand: Command = {
label: 'Open Trace With Root Path'
};

export const OpenTraceConfigurations: Command = {
id: 'open-trace-configurations',
label: 'Open Trace Configurations'
};

/**
* A command to open a trace in the trace viewer.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ import {
TraceViewerCommand,
KeyboardShortcutsCommand,
OpenTraceWithRootPathCommand,
OpenTraceWithPathCommand
OpenTraceWithPathCommand,
OpenTraceConfigurations
} from './trace-viewer-commands';
import { PortBusy, TraceServerConfigService } from '../../common/trace-server-config';
import { TracePreferences, TRACE_PATH, TRACE_ARGS } from '../trace-server-preference';
Expand Down Expand Up @@ -138,6 +139,10 @@ export class TraceViewerContribution
}
}

async openTraceConfigurations(): Promise<void> {
signalManager().fireShowTraceConfigurations();
}

async open(traceURI: URI, options?: TraceViewerWidgetOpenerOptions): Promise<TraceViewerWidget> {
let healthResponse;
try {
Expand Down Expand Up @@ -272,6 +277,9 @@ export class TraceViewerContribution
await new ChartShortcutsDialog({ title: 'Trace Viewer Keyboard and Mouse Shortcuts' }).open();
}
});
registry.registerCommand(OpenTraceConfigurations, {
execute: () => this.openTraceConfigurations()
});
}

canHandle(_uri: URI): number {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,12 @@ export namespace TraceViewerToolbarCommands {
label: 'Show trace overview',
iconClass: 'codicon codicon-graph-line'
};

export const OPEN_TRACE_CONFIGURATIONS: Command = {
id: 'trace.viewer.openTraceConfigurations',
label: 'Open trace configurations',
iconClass: 'codicon codicon-server-process'
};
}

export namespace TraceViewerToolbarMenus {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ 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 { OpenTraceCommand, OpenTraceConfigurations } from './trace-viewer-commands';
import { TraceExplorerViewsWidget } from '../trace-explorer/trace-explorer-sub-widgets/theia-trace-explorer-views-widget';

@injectable()
export class TraceViewerToolbarContribution implements TabBarToolbarContribution, CommandContribution {
Expand Down Expand Up @@ -140,6 +141,18 @@ export class TraceViewerToolbarContribution implements TabBarToolbarContribution
await new ChartShortcutsDialog({ title: 'Trace Viewer Keyboard and Mouse Shortcuts' }).open();
}
});

registry.registerCommand(TraceViewerToolbarCommands.OPEN_TRACE_CONFIGURATIONS, {
isVisible: (w: Widget) => {
if (w instanceof TraceExplorerViewsWidget) {
return true;
}
return false;
},
execute: async () => {
await registry.executeCommand(OpenTraceConfigurations.id);
}
});
}

registerToolbarItems(registry: TabBarToolbarRegistry): void {
Expand Down Expand Up @@ -348,5 +361,11 @@ export class TraceViewerToolbarContribution implements TabBarToolbarContribution
tooltip: TraceViewerToolbarCommands.CHARTS_CHEATSHEET.label,
priority: 10
});
registry.registerItem({
id: TraceViewerToolbarCommands.OPEN_TRACE_CONFIGURATIONS.id,
command: TraceViewerToolbarCommands.OPEN_TRACE_CONFIGURATIONS.id,
tooltip: TraceViewerToolbarCommands.OPEN_TRACE_CONFIGURATIONS.label,
priority: 11
});
}
}

0 comments on commit b903ecf

Please sign in to comment.