diff --git a/packages/base/src/signals/signal-manager.ts b/packages/base/src/signals/signal-manager.ts index 7f5c24eef..2cd3da831 100644 --- a/packages/base/src/signals/signal-manager.ts +++ b/packages/base/src/signals/signal-manager.ts @@ -30,6 +30,7 @@ export declare interface SignalManager { fireTraceServerStartedSignal(): void; fireUndoSignal(): void; fireRedoSignal(): void; + fireOutputDataChanged(outputs: OutputDescriptor[]): void; fireOpenOverviewOutputSignal(traceId: string): void; // eslint-disable-next-line @typescript-eslint/no-explicit-any firePinView(output: OutputDescriptor, payload?: any): void; @@ -73,7 +74,8 @@ export const Signals = { SAVE_AS_CSV: 'save as csv', VIEW_RANGE_UPDATED: 'view range updated', SELECTION_RANGE_UPDATED: 'selection range updated', - REQUEST_SELECTION_RANGE_CHANGE: 'change selection range' + REQUEST_SELECTION_RANGE_CHANGE: 'change selection range', + OUTPUT_DATA_CHANGED: 'output data changed' }; export class SignalManager extends EventEmitter implements SignalManager { @@ -143,6 +145,9 @@ export class SignalManager extends EventEmitter implements SignalManager { fireRedoSignal(): void { this.emit(Signals.REDO); } + fireOutputDataChanged(outputs: OutputDescriptor[]): void { + this.emit(Signals.OUTPUT_DATA_CHANGED, outputs); + } // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types firePinView(output: OutputDescriptor, payload?: any): void { this.emit(Signals.PIN_VIEW, output, payload); diff --git a/packages/react-components/src/components/table-output-component.tsx b/packages/react-components/src/components/table-output-component.tsx index 737a45235..df41e4de6 100644 --- a/packages/react-components/src/components/table-output-component.tsx +++ b/packages/react-components/src/components/table-output-component.tsx @@ -15,18 +15,21 @@ import { } from 'ag-grid-community'; import { QueryHelper } from 'tsp-typescript-client/lib/models/query/query-helper'; import { cloneDeep } from 'lodash'; -import { signalManager } from 'traceviewer-base/lib/signals/signal-manager'; +import { Signals, signalManager } from 'traceviewer-base/lib/signals/signal-manager'; import { TimelineChart } from 'timeline-chart/lib/time-graph-model'; import { CellKeyDownEvent } from 'ag-grid-community/dist/lib/events'; import { TableModel } from 'tsp-typescript-client/lib/models/table'; import { SearchFilterRenderer, CellRenderer, LoadingRenderer } from './table-renderer-components'; -import { ResponseStatus } from 'tsp-typescript-client'; +import { OutputDescriptor, ResponseStatus } from 'tsp-typescript-client'; import { PaginationBarComponent } from './utils/pagination-bar-component'; import { OptionCheckBoxState, OptionState, OptionType } from './drop-down-component'; type TableOuputState = AbstractOutputState & { tableColumns: ColDef[]; showToggleColumns: boolean; + tableSize: number; + pagination: boolean; + paginationTotalPages: number; }; type TableOutputProps = AbstractOutputProps & { @@ -50,9 +53,7 @@ export class TableOutputComponent extends AbstractOutputComponent = []; private fetchColumns = true; private columnArray = new Array(); - private pagination = true; private paginationPageSize = 250000; - private paginationTotalPages = 0; private showIndexColumn = false; private frameworkComponents: any; private gridApi: GridApi | undefined = undefined; @@ -71,7 +72,7 @@ export class TableOutputComponent extends AbstractOutputComponent = new Map(); private dataSource: IDatasource; - private tableSize = 0; + private onOutputDataChanged = (outputs: OutputDescriptor[]) => this.doHandleOutputDataChangedSignal(outputs); static defaultProps: Partial = { cacheBlockSize: 200, @@ -87,7 +88,10 @@ export class TableOutputComponent extends AbstractOutputComponent= this.paginationPageSize, + paginationTotalPages: Math.floor(this.props.nbEvents / this.paginationPageSize) }; this.frameworkComponents = { @@ -108,11 +112,9 @@ export class TableOutputComponent extends AbstractOutputComponent= this.paginationPageSize; - this.paginationTotalPages = Math.floor(this.props.nbEvents / this.paginationPageSize); this.onEventClick = this.onEventClick.bind(this); this.onModelUpdated = this.onModelUpdated.bind(this); this.onKeyDown = this.onKeyDown.bind(this); @@ -189,11 +191,11 @@ export class TableOutputComponent extends AbstractOutputComponent - {this.pagination && ( + {this.state.pagination && ( )} @@ -209,6 +211,22 @@ export class TableOutputComponent extends AbstractOutputComponent { this.handleTimeSelectionChange(range); }); + signalManager().on(Signals.OUTPUT_DATA_CHANGED, this.onOutputDataChanged); + } + + componentWillUnmount(): void { + // TODO: replace with removing the handler from unit controller + // See timeline-chart issue #98 + // In the meantime, replace the handler with a noop on unmount + this.handleTimeSelectionChange = () => Promise.resolve(); + signalManager().off(Signals.OUTPUT_DATA_CHANGED, this.onOutputDataChanged); + } + + doHandleOutputDataChangedSignal(outputs: OutputDescriptor[]): void { + const desc = outputs.find(descriptor => descriptor.id === this.props.outputDescriptor.id); + if (desc !== undefined) { + this.gridApi?.setDatasource(this.dataSource); + } } private checkFocus(event: React.FocusEvent): void { @@ -225,22 +243,23 @@ export class TableOutputComponent extends AbstractOutputComponent Promise.resolve(); - } - async componentDidUpdate(prevProps: TableOutputProps, _prevState: TableOuputState): Promise { if (this.props.nbEvents !== prevProps.nbEvents) { this.gridApi?.setRowCount(this.props.nbEvents); const newPagination = this.props.nbEvents >= this.paginationPageSize; - if (newPagination !== this.pagination) { - this.pagination = newPagination; - } + this.setState({ + pagination: newPagination, + paginationTotalPages: Math.floor(this.props.nbEvents / this.paginationPageSize) + }); + } - this.paginationTotalPages = Math.floor(this.props.nbEvents / this.paginationPageSize); + if (this.state.tableSize !== _prevState.tableSize) { + this.gridApi?.setRowCount(this.state.tableSize); + const newPagination = this.state.tableSize >= this.paginationPageSize; + this.setState({ + pagination: newPagination, + paginationTotalPages: Math.floor(this.state.tableSize / this.paginationPageSize) + }); } } @@ -638,7 +657,7 @@ export class TableOutputComponent extends AbstractOutputComponent(); } - this.tableSize = lineResponse.model.size; + this.setState({ tableSize: lineResponse.model.size }); return this.modelToRow(lineResponse.model); } diff --git a/packages/react-components/src/components/timegraph-output-component.tsx b/packages/react-components/src/components/timegraph-output-component.tsx index 7521bc41f..21cf4cbf2 100644 --- a/packages/react-components/src/components/timegraph-output-component.tsx +++ b/packages/react-components/src/components/timegraph-output-component.tsx @@ -27,7 +27,7 @@ import { listToTree, getAllExpandedNodeIds, getIndexOfNode, validateNumArray } f import hash from 'traceviewer-base/lib/utils/value-hash'; import ColumnHeader from './utils/filter-tree/column-header'; import { TimeGraphAnnotationComponent } from 'timeline-chart/lib/components/time-graph-annotation'; -import { Entry } from 'tsp-typescript-client'; +import { Entry, OutputDescriptor } from 'tsp-typescript-client'; import { isEqual } from 'lodash'; import { convertColorStringToHexNumber } from 'traceviewer-base/lib/utils/convert-color-string-to-hex'; import { faSpinner } from '@fortawesome/free-solid-svg-icons'; @@ -73,6 +73,7 @@ export class TimegraphOutputComponent extends AbstractTreeOutputComponent; private timeGraphTreeRef: React.RefObject; private markerTreeRef: React.RefObject; + private containerRef: React.RefObject; private tspDataProvider: TspDataProvider; private styleProvider: StyleProvider; @@ -81,9 +82,13 @@ export class TimegraphOutputComponent extends AbstractTreeOutputComponent this.doHandleSelectionChangedSignal(payload); + private onOutputDataChanged = (outputs: OutputDescriptor[]) => this.doHandleOutputDataChangedSignal(outputs); private pendingSelection: TimeGraphEntry | undefined; private _debouncedUpdateSearch = debounce(() => this.updateSearchFilter(), 500); + private _debouncedUpdateChart = debounce(() => { + this.chartLayer.updateChart(); + }, 500); constructor(props: TimegraphOutputProps) { super(props); @@ -124,6 +129,7 @@ export class TimegraphOutputComponent extends AbstractTreeOutputComponent => { + const desc = outputs.find(descriptor => descriptor.id === this.props.outputDescriptor.id); + if (desc !== undefined) { + await this.fetchTree(); + this._debouncedUpdateChart(); + } + }; + public onThemeChange = (): void => { // Simulate a click on the selected row when theme changes. // This changes the color of the selected row to new theme. diff --git a/packages/react-components/src/components/utils/timegraph-container-component.tsx b/packages/react-components/src/components/utils/timegraph-container-component.tsx index 834dde280..ad2283593 100644 --- a/packages/react-components/src/components/utils/timegraph-container-component.tsx +++ b/packages/react-components/src/components/utils/timegraph-container-component.tsx @@ -33,14 +33,17 @@ export class ReactTimeGraphContainer extends React.Component