Skip to content

Commit f936a11

Browse files
hoangphamEclipseMatthewKhouzam
authored andcommitted
Refactor available views component
Currently, the trace-overview-selection-dialog-component and the trace-explorer-views-widget have some common code. This commit refactors the common code by creating the reusable available-view-component. The prior two components will then call the later component and thus use the same code. Signed-off-by: Hoang Thuan Pham <hoang.pham@calian.ca>
1 parent 84a090c commit f936a11

File tree

3 files changed

+51
-103
lines changed

3 files changed

+51
-103
lines changed

packages/react-components/src/components/trace-overview-selection-dialog-component.tsx

+1-3
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,10 @@ export class TraceOverviewSelectionDialogComponent extends AbstractDialogCompone
3232
Loading available outputs...
3333
</div>);
3434
}
35-
36-
const key = Number(true);
3735
return (
3836
<div id="trace-overview-selection-dialog-content-container">
3937
<AvailableViewsComponent
40-
availableViewListKey={key}
38+
traceID={this.props.traceID}
4139
onOutputClicked={e => {this.doHandleOutputClicked(e);}}
4240
outputDescriptors={this.state.outputDescriptors}
4341
listRowWidth='95%'

packages/react-components/src/components/utils/available-views-component.tsx

+35-19
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11
import { ListRowProps, AutoSizer, List } from 'react-virtualized';
22
import React from 'react';
33
import { OutputDescriptor } from 'tsp-typescript-client/lib/models/output-descriptor';
4+
import { Experiment } from 'tsp-typescript-client/lib/models/experiment';
5+
import { signalManager, Signals } from 'traceviewer-base/lib/signals/signal-manager';
46

57
export interface AvailableViewsComponentProps {
6-
availableViewListKey: number,
8+
traceID: string | undefined,
79
outputDescriptors: OutputDescriptor[],
810
onContextMenuEvent?: (event: React.MouseEvent<HTMLDivElement, MouseEvent>, output: OutputDescriptor | undefined) => void,
911
onOutputClicked: (selectedOutput: OutputDescriptor) => void,
10-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
1112
listRowWidth?: string,
12-
listRowPadding?: string
13+
listRowPadding?: string,
14+
highlightAfterSelection?: boolean
1315
}
1416

1517
export interface AvailableViewsComponentState {
@@ -21,36 +23,43 @@ export class AvailableViewsComponent extends React.Component<AvailableViewsComp
2123
static LINE_HEIGHT = 16;
2224
static ROW_HEIGHT = (2 * AvailableViewsComponent.LINE_HEIGHT) + AvailableViewsComponent.LIST_MARGIN;
2325

26+
private _forceUpdateKey = false;
2427
protected handleOutputClicked = (e: React.MouseEvent<HTMLDivElement>): void => this.doHandleOutputClicked(e);
28+
private _onExperimentSelected = (experiment: Experiment): void => this.doHandleExperimentSelectedSignal(experiment);
2529

2630
constructor(props: AvailableViewsComponentProps){
2731
super(props);
32+
signalManager().on(Signals.EXPERIMENT_SELECTED, this._onExperimentSelected);
2833
this.state = { lastSelectedOutputIndex: -1 };
2934
}
3035

36+
componentWillUnmount(): void {
37+
signalManager().off(Signals.EXPERIMENT_SELECTED, this._onExperimentSelected);
38+
}
39+
3140
render(): React.ReactNode {
41+
this._forceUpdateKey = !this._forceUpdateKey;
42+
const key = Number(this._forceUpdateKey);
3243
let outputsRowCount = 0;
3344
const outputs = this.props.outputDescriptors;
3445
if (outputs) {
3546
outputsRowCount = outputs.length;
3647
}
3748
const totalHeight = this.getTotalHeight();
3849
return (
39-
<div>
40-
<div className='trace-explorer-panel-content disable-select' style={{height: totalHeight}}>
41-
<AutoSizer>
42-
{({ width }) =>
43-
<List
44-
key={this.props.availableViewListKey}
45-
height={totalHeight}
46-
width={width}
47-
rowCount={outputsRowCount}
48-
rowHeight={AvailableViewsComponent.ROW_HEIGHT}
49-
rowRenderer={this.renderRowOutputs}
50-
/>
51-
}
52-
</AutoSizer>
53-
</div>
50+
<div className='trace-explorer-panel-content disable-select' style={{height: totalHeight}}>
51+
<AutoSizer>
52+
{({ width }) =>
53+
<List
54+
key={key}
55+
height={totalHeight}
56+
width={width}
57+
rowCount={outputsRowCount}
58+
rowHeight={AvailableViewsComponent.ROW_HEIGHT}
59+
rowRenderer={this.renderRowOutputs}
60+
/>
61+
}
62+
</AutoSizer>
5463
</div>
5564
);
5665
}
@@ -68,7 +77,7 @@ export class AvailableViewsComponent extends React.Component<AvailableViewsComp
6877
outputDescription = output.description;
6978
}
7079
let traceContainerClassName = 'outputs-list-container';
71-
if (props.index === this.state.lastSelectedOutputIndex) {
80+
if (this.props.highlightAfterSelection && props.index === this.state.lastSelectedOutputIndex) {
7281
traceContainerClassName = traceContainerClassName + ' theia-mod-selected';
7382
}
7483

@@ -106,8 +115,15 @@ export class AvailableViewsComponent extends React.Component<AvailableViewsComp
106115
{this.props.onContextMenuEvent(event, output);}
107116
}
108117

118+
protected doHandleExperimentSelectedSignal(experiment: Experiment | undefined): void {
119+
if ((this.props.traceID !== experiment?.UUID) || this.props.outputDescriptors.length === 0) {
120+
this.setState({ lastSelectedOutputIndex: -1 });
121+
}
122+
}
123+
109124
private doHandleOutputClicked(e: React.MouseEvent<HTMLDivElement>) {
110125
const index = Number(e.currentTarget.getAttribute('data-id'));
126+
this.setState({lastSelectedOutputIndex: index});
111127
const selectedOutput = this.props.outputDescriptors[index];
112128

113129
this.props.onOutputClicked(selectedOutput);

packages/react-components/src/trace-explorer/trace-explorer-views-widget.tsx

+15-81
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import * as React from 'react';
2-
import { List, ListRowProps, AutoSizer } from 'react-virtualized';
32
import { OutputAddedSignalPayload } from 'traceviewer-base/lib/signals/output-added-signal-payload';
43
import { signalManager, Signals } from 'traceviewer-base/lib/signals/signal-manager';
54
import { OutputDescriptor } from 'tsp-typescript-client/lib/models/output-descriptor';
65
import { Experiment } from 'tsp-typescript-client/lib/models/experiment';
76
import { ITspClientProvider } from 'traceviewer-base/lib/tsp-client-provider';
87
import { ExperimentManager } from 'traceviewer-base/lib/experiment-manager';
8+
import { AvailableViewsComponent } from '../components/utils/available-views-component';
99

1010
export interface ReactAvailableViewsProps {
1111
id: string,
@@ -15,16 +15,10 @@ export interface ReactAvailableViewsProps {
1515
}
1616

1717
export interface ReactAvailableViewsState {
18-
availableOutputDescriptors: OutputDescriptor[],
19-
lastSelectedOutputIndex: number;
18+
availableOutputDescriptors: OutputDescriptor[]
2019
}
2120

2221
export class ReactAvailableViewsWidget extends React.Component<ReactAvailableViewsProps, ReactAvailableViewsState> {
23-
static LIST_MARGIN = 2;
24-
static LINE_HEIGHT = 16;
25-
static ROW_HEIGHT = (2 * ReactAvailableViewsWidget.LINE_HEIGHT) + ReactAvailableViewsWidget.LIST_MARGIN;
26-
27-
private _forceUpdateKey = false;
2822
private _selectedExperiment: Experiment | undefined;
2923
private _experimentManager: ExperimentManager;
3024

@@ -39,7 +33,7 @@ export class ReactAvailableViewsWidget extends React.Component<ReactAvailableVie
3933
});
4034
signalManager().on(Signals.EXPERIMENT_SELECTED, this._onExperimentSelected);
4135
signalManager().on(Signals.EXPERIMENT_CLOSED, this._onExperimentClosed);
42-
this.state = { availableOutputDescriptors: [], lastSelectedOutputIndex: -1 };
36+
this.state = { availableOutputDescriptors: []};
4337
}
4438

4539
componentWillUnmount(): void {
@@ -48,85 +42,25 @@ export class ReactAvailableViewsWidget extends React.Component<ReactAvailableVie
4842
}
4943

5044
render(): React.ReactNode {
51-
this._forceUpdateKey = !this._forceUpdateKey;
52-
const key = Number(this._forceUpdateKey);
53-
let outputsRowCount = 0;
54-
const outputs = this.state.availableOutputDescriptors;
55-
if (outputs) {
56-
outputsRowCount = outputs.length;
57-
}
58-
const totalHeight = this.getTotalHeight();
5945
return (
6046
<div className='trace-explorer-views'>
61-
<div className='trace-explorer-panel-content disable-select'>
62-
<AutoSizer>
63-
{({ width }) =>
64-
<List
65-
key={key}
66-
height={totalHeight}
67-
width={width}
68-
rowCount={outputsRowCount}
69-
rowHeight={ReactAvailableViewsWidget.ROW_HEIGHT}
70-
rowRenderer={this.renderRowOutputs}
71-
/>
72-
}
73-
</AutoSizer>
74-
</div>
47+
<AvailableViewsComponent
48+
traceID={this._selectedExperiment?.UUID}
49+
outputDescriptors={this.state.availableOutputDescriptors}
50+
onContextMenuEvent={this.handleContextMenuEvent}
51+
onOutputClicked={this.handleOutputClicked}
52+
highlightAfterSelection={true}
53+
></AvailableViewsComponent>
7554
</div>
7655
);
7756
}
7857

79-
protected renderRowOutputs = (props: ListRowProps): React.ReactNode => this.doRenderRowOutputs(props);
80-
81-
private doRenderRowOutputs(props: ListRowProps): React.ReactNode {
82-
let outputName = '';
83-
let outputDescription = '';
84-
let output: OutputDescriptor | undefined;
85-
const outputDescriptors = this.state.availableOutputDescriptors;
86-
if (outputDescriptors && outputDescriptors.length && props.index < outputDescriptors.length) {
87-
output = outputDescriptors[props.index];
88-
outputName = output.name;
89-
outputDescription = output.description;
90-
}
91-
let traceContainerClassName = 'outputs-list-container';
92-
if (props.index === this.state.lastSelectedOutputIndex) {
93-
traceContainerClassName = traceContainerClassName + ' theia-mod-selected';
94-
}
95-
return <div className={traceContainerClassName}
96-
title={outputName + ':\n' + outputDescription}
97-
id={`${traceContainerClassName}-${props.index}`}
98-
key={props.key}
99-
style={props.style}
100-
onClick={this.handleOutputClicked}
101-
onContextMenu={event => { this.handleContextMenuEvent(event, output); }}
102-
data-id={`${props.index}`}
103-
>
104-
<h4 className='outputs-element-name'>
105-
{outputName}
106-
</h4>
107-
<div className='outputs-element-description child-element'>
108-
{outputDescription}
109-
</div>
110-
</div>;
111-
}
112-
113-
protected getTotalHeight(): number {
114-
let totalHeight = 0;
115-
const outputDescriptors = this.state.availableOutputDescriptors;
116-
outputDescriptors?.forEach(() => totalHeight += ReactAvailableViewsWidget.ROW_HEIGHT);
117-
return totalHeight;
118-
}
119-
120-
protected handleOutputClicked = (e: React.MouseEvent<HTMLDivElement>): void => this.doHandleOutputClicked(e);
58+
protected handleOutputClicked = (outputDescriptor: OutputDescriptor): void => this.doHandleOutputClicked(outputDescriptor);
12159
protected handleContextMenuEvent = (e: React.MouseEvent<HTMLDivElement>, output: OutputDescriptor | undefined): void => this.doHandleContextMenuEvent(e, output);
12260

123-
private doHandleOutputClicked(e: React.MouseEvent<HTMLDivElement>) {
124-
const index = Number(e.currentTarget.getAttribute('data-id'));
125-
this.setState({ lastSelectedOutputIndex: index });
126-
const outputs = this.state.availableOutputDescriptors;
127-
128-
if (outputs && this._selectedExperiment) {
129-
signalManager().fireOutputAddedSignal(new OutputAddedSignalPayload(outputs[index], this._selectedExperiment));
61+
private doHandleOutputClicked(selectedOutput: OutputDescriptor) {
62+
if (selectedOutput && this._selectedExperiment) {
63+
signalManager().fireOutputAddedSignal(new OutputAddedSignalPayload(selectedOutput, this._selectedExperiment));
13064
}
13165
}
13266

@@ -141,7 +75,7 @@ export class ReactAvailableViewsWidget extends React.Component<ReactAvailableVie
14175
protected doHandleExperimentSelectedSignal(experiment: Experiment | undefined): void {
14276
if ((this._selectedExperiment?.UUID !== experiment?.UUID) || this.state.availableOutputDescriptors.length === 0) {
14377
this._selectedExperiment = experiment;
144-
this.setState({ availableOutputDescriptors: [], lastSelectedOutputIndex: -1 });
78+
this.setState({ availableOutputDescriptors: []});
14579
this.updateAvailableViews();
14680
}
14781
}

0 commit comments

Comments
 (0)