-
Notifications
You must be signed in to change notification settings - Fork 61
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add data tree output component implementation
The implementation is the first iteration. It introduces the component class which uses the tree implementation also used in the time-graph and XY components. The component is not enabled in this patch. The tree implementation need some UI/UX improvement, for example for styling or column resizing which will be done in a separated commit. Once some improvements are available, the data tree component will be shown as part of the available views list for a given trace. Signed-off-by: Bernd Hufmann <Bernd.Hufmann@ericsson.com>
- Loading branch information
Showing
2 changed files
with
128 additions
and
2 deletions.
There are no files selected for viewing
122 changes: 122 additions & 0 deletions
122
packages/react-components/src/components/datatree-output-component.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
/* eslint-disable @typescript-eslint/no-explicit-any */ | ||
import { AbstractOutputComponent, AbstractOutputProps, AbstractOutputState } from './abstract-output-component'; | ||
import * as React from 'react'; | ||
import { QueryHelper } from 'tsp-typescript-client/lib/models/query/query-helper'; | ||
import { Entry } from 'tsp-typescript-client/lib/models/entry'; | ||
import { ResponseStatus } from 'tsp-typescript-client/lib/models/response/responses'; | ||
import { EntryTree } from './utils/filtrer-tree/entry-tree'; | ||
import { getAllExpandedNodeIds } from './utils/filtrer-tree/utils'; | ||
import { TreeNode } from './utils/filtrer-tree/tree-node'; | ||
import ColumnHeader from './utils/filtrer-tree/column-header'; | ||
|
||
type DataTreeOutputProps = AbstractOutputProps & { | ||
}; | ||
|
||
type DataTreeOuputState = AbstractOutputState & { | ||
selectedSeriesId: number[]; | ||
xyTree: Entry[]; | ||
collapsedNodes: number[]; | ||
orderedNodes: number[]; | ||
columns: ColumnHeader[]; | ||
}; | ||
|
||
export class DataTreeOutputComponent extends AbstractOutputComponent<AbstractOutputProps, DataTreeOuputState> { | ||
treeRef: React.RefObject<HTMLDivElement> = React.createRef(); | ||
|
||
constructor(props: AbstractOutputProps) { | ||
super(props); | ||
this.state = { | ||
outputStatus: ResponseStatus.RUNNING, | ||
selectedSeriesId: [], | ||
xyTree: [], | ||
collapsedNodes: [], | ||
orderedNodes: [], | ||
columns: [{title: 'Name', sortable: true}], | ||
}; | ||
} | ||
|
||
componentDidMount(): void { | ||
this.waitAnalysisCompletion(); | ||
} | ||
|
||
async fetchTree(): Promise<ResponseStatus> { | ||
const parameters = QueryHelper.timeQuery([this.props.range.getStart(), this.props.range.getEnd()]); | ||
// TODO: use the data tree endpoint instead of the xy tree endpoint | ||
const tspClientResponse = await this.props.tspClient.fetchXYTree(this.props.traceId, this.props.outputDescriptor.id, parameters); | ||
const treeResponse = tspClientResponse.getModel(); | ||
if (tspClientResponse.isOk() && treeResponse) { | ||
if (treeResponse.model) { | ||
const headers = treeResponse.model.headers; | ||
const columns = []; | ||
if (headers && headers.length > 0) { | ||
headers.forEach(header => { | ||
columns.push({title: header.name, sortable: true, tooltip: header.tooltip}); | ||
}); | ||
} else { | ||
columns.push({title: 'Name', sortable: true}); | ||
} | ||
this.setState({ | ||
outputStatus: treeResponse.status, | ||
xyTree: treeResponse.model.entries, | ||
columns | ||
}); | ||
} | ||
return treeResponse.status; | ||
} | ||
return ResponseStatus.FAILED; | ||
} | ||
|
||
renderTree(): React.ReactNode | undefined { | ||
this.onToggleCollapse = this.onToggleCollapse.bind(this); | ||
this.onOrderChange = this.onOrderChange.bind(this); | ||
return this.state.xyTree.length | ||
? <EntryTree | ||
entries={this.state.xyTree} | ||
showCheckboxes={false} | ||
collapsedNodes={this.state.collapsedNodes} | ||
onToggleCollapse={this.onToggleCollapse} | ||
onOrderChange={this.onOrderChange} | ||
headers={this.state.columns} | ||
/> | ||
: undefined | ||
; | ||
} | ||
renderMainArea(): React.ReactNode { | ||
return <React.Fragment> | ||
<div ref={this.treeRef} className='output-component-tree' | ||
style={{ height: this.props.style.height, width: this.props.widthWPBugWorkaround }} | ||
> | ||
{this.renderTree()} | ||
</div> | ||
</React.Fragment>; | ||
} | ||
private onToggleCollapse(id: number, nodes: TreeNode[]) { | ||
let newList = [...this.state.collapsedNodes]; | ||
|
||
const exist = this.state.collapsedNodes.find(expandId => expandId === id); | ||
|
||
if (exist !== undefined) { | ||
newList = newList.filter(collapsed => id !== collapsed); | ||
} else { | ||
newList = newList.concat(id); | ||
} | ||
const orderedIds = getAllExpandedNodeIds(nodes, newList); | ||
this.setState({collapsedNodes: newList, orderedNodes: orderedIds}); | ||
} | ||
private onOrderChange(ids: number[]) { | ||
this.setState({orderedNodes: ids}); | ||
} | ||
|
||
protected async waitAnalysisCompletion(): Promise<void> { | ||
let outputStatus = this.state.outputStatus; | ||
const timeout = 500; | ||
while (this.state && outputStatus === ResponseStatus.RUNNING) { | ||
outputStatus = await this.fetchTree(); | ||
await new Promise(resolve => setTimeout(resolve, timeout)); | ||
} | ||
} | ||
componentWillUnmount(): void { | ||
// fix Warning: Can't perform a React state update on an unmounted component | ||
this.setState = (_state, _callback) => undefined; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters