Skip to content

Commit

Permalink
Fix time graph filtering and collapsing
Browse files Browse the repository at this point in the history
Update the filtering of empty nodes to include visible nodes even if any
of their parent is filtered-out. Recursively replace filtered-out nodes
by their visible children, if any, but only if the filtered-out parent
node is not collapsed.

In TimeGraphOutputComponent update the arrows layer after empty nodes
have been determined, and filter out empty nodes from the rowIds passed
to the arrows layer.

Update getIndexOfNode() in utils to consider the list of empty nodes.

Fix names of selectedRow and multiSelectedRows in TableBodyProps.

Fixes #1132

Signed-off-by: Patrick Tasse <patrick.tasse@gmail.com>
  • Loading branch information
PatrickTasse committed Oct 29, 2024
1 parent 6cb44fc commit 73650f1
Show file tree
Hide file tree
Showing 7 changed files with 62 additions and 35 deletions.
2 changes: 1 addition & 1 deletion packages/react-components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
"react-virtualized": "^9.21.0",
"semantic-ui-css": "^2.4.1",
"semantic-ui-react": "^0.86.0",
"timeline-chart": "^0.4.0",
"timeline-chart": "^0.4.1",
"traceviewer-base": "0.3.0",
"tsp-typescript-client": "^0.4.3"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1056,9 +1056,6 @@ export class TimegraphOutputComponent extends AbstractTreeOutputComponent<Timegr
additionalProperties
);
this.updateMarkersData(timeGraphData.rangeEvents, newRange, nbTimes);
if (fetchArrows) {
this.arrowLayer.addArrows(timeGraphData.arrows, this.getTimegraphRowIds().rowIds);
}
this.rangeEventsLayer.addRangeEvents(timeGraphData.rangeEvents);

if (document.getElementById(this.props.traceId + this.props.outputDescriptor.id + 'handleSpinner')) {
Expand All @@ -1085,6 +1082,12 @@ export class TimegraphOutputComponent extends AbstractTreeOutputComponent<Timegr
emptyNodes = [];
}

if (fetchArrows) {
this.arrowLayer.addArrows(
timeGraphData.arrows,
this.getTimegraphRowIds().rowIds.filter(rowId => !emptyNodes.includes(rowId))
);
}
this.setState({ emptyNodes });

// Apply the pending selection here since the row provider had been called before this method.
Expand Down Expand Up @@ -1475,7 +1478,8 @@ export class TimegraphOutputComponent extends AbstractTreeOutputComponent<Timegr
const rowIndex = getIndexOfNode(
id,
listToTree(this.state.timegraphTree, this.state.columns),
this.state.collapsedNodes
this.state.collapsedNodes,
this.state.emptyNodes
);
this.chartLayer.selectAndReveal(rowIndex);
if (this.rowController.selectedRow?.id !== id) {
Expand All @@ -1489,13 +1493,18 @@ export class TimegraphOutputComponent extends AbstractTreeOutputComponent<Timegr

public onMultipleRowClick = (id: number, isShiftClicked?: boolean): void => {
const tree = listToTree(this.state.timegraphTree, this.state.columns);
const rowIndex = getIndexOfNode(id, tree, this.state.collapsedNodes);
const rowIndex = getIndexOfNode(id, tree, this.state.collapsedNodes, this.state.emptyNodes);

if (isShiftClicked) {
// Perform shift action based on selectedRow value
if (this.state.selectedRow !== undefined) {
const treeNodeIds = getAllExpandedNodeIds(tree, this.state.collapsedNodes);
const lastSelectedRowIndex = getIndexOfNode(this.state.selectedRow, tree, this.state.collapsedNodes);
const treeNodeIds = getAllExpandedNodeIds(tree, this.state.collapsedNodes, this.state.emptyNodes);
const lastSelectedRowIndex = getIndexOfNode(
this.state.selectedRow,
tree,
this.state.collapsedNodes,
this.state.emptyNodes
);
this.handleShiftClick(rowIndex, lastSelectedRowIndex, treeNodeIds);
} else {
// Do not have a previous selection therefore treat this as a normal row click
Expand All @@ -1514,7 +1523,12 @@ export class TimegraphOutputComponent extends AbstractTreeOutputComponent<Timegr
if (id === this.state.selectedRow) {
const prevRowId = rows.at(index - 1);
if (prevRowId && prevRowId !== id) {
const prevRowIndex = getIndexOfNode(prevRowId, tree, this.state.collapsedNodes);
const prevRowIndex = getIndexOfNode(
prevRowId,
tree,
this.state.collapsedNodes,
this.state.emptyNodes
);
this.chartLayer.selectAndReveal(prevRowIndex);
} else {
this.setState({ selectedRow: undefined });
Expand All @@ -1538,7 +1552,8 @@ export class TimegraphOutputComponent extends AbstractTreeOutputComponent<Timegr
const rowIndex = getIndexOfNode(
id,
listToTree(this.state.markerCategoryEntries, this.state.columns),
this.state.collapsedNodes
this.state.collapsedNodes,
this.state.emptyNodes
);
this.markersChartLayer.selectAndReveal(rowIndex);
};
Expand Down Expand Up @@ -1580,7 +1595,8 @@ export class TimegraphOutputComponent extends AbstractTreeOutputComponent<Timegr
const rowIndex = getIndexOfNode(
item.id,
listToTree(this.state.timegraphTree, this.state.columns),
this.state.collapsedNodes
this.state.collapsedNodes,
this.state.emptyNodes
);
this.chartLayer.selectAndReveal(rowIndex);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import { TableRow } from './table-row';

interface TableBodyProps {
nodes: TreeNode[];
selectedNode?: number;
multiSelectedNodes?: number[];
selectedRow?: number;
multiSelectedRows?: number[];
collapsedNodes: number[];
isCheckable: boolean;
isClosable: boolean;
Expand Down Expand Up @@ -34,7 +34,6 @@ export class TableBody extends React.Component<TableBodyProps> {
if (!this.props.nodes) {
return undefined;
}

return <tbody>{this.renderRows()}</tbody>;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ export class Table extends React.Component<TableProps> {
let nodes = sortNodes(this.props.nodes, this.props.sortConfig);

if (this.props.hideEmptyNodes) {
nodes = filterEmptyNodes(nodes, this.props.emptyNodes);
nodes = filterEmptyNodes(nodes, this.props.emptyNodes, this.props.collapsedNodes);
}

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { TreeNode } from './tree-node';
import { Message } from './message';
import { Filter } from './filter';
import { Table } from './table';
import { getAllExpandedNodeIds, filterEmptyNodes } from './utils';
import { getAllExpandedNodeIds } from './utils';
import { SortConfig, sortNodes } from './sort';
import ColumnHeader from './column-header';
import { isEqual } from 'lodash';
Expand Down Expand Up @@ -96,7 +96,7 @@ export class FilterTree extends React.Component<FilterTreeProps, FilterTreeState
};

handleOrderChange = (nodes: TreeNode[]): void => {
const ids = getAllExpandedNodeIds(nodes, this.props.collapsedNodes);
const ids = getAllExpandedNodeIds(nodes, this.props.collapsedNodes, this.props.emptyNodes);
this.props.onOrderChange(ids);
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,19 +47,26 @@ export const listToTree = (list: Entry[], headers: ColumnHeader[]): TreeNode[] =
return rootNodes;
};

export const getAllExpandedNodeIds = (nodes: TreeNode[], collapsedNodes: number[]): number[] => {
export const getAllExpandedNodeIds = (nodes: TreeNode[], collapsedNodes: number[], emptyNodes?: number[]): number[] => {
const visibleIds: number[] = [];
nodes.forEach((node: TreeNode) => {
visibleIds.push(node.id);
if (!emptyNodes?.includes(node.id)) {
visibleIds.push(node.id);
}
if (node.children.length && !collapsedNodes.includes(node.id)) {
visibleIds.push(...getAllExpandedNodeIds(node.children, collapsedNodes));
visibleIds.push(...getAllExpandedNodeIds(node.children, collapsedNodes, emptyNodes));
}
});
return visibleIds;
};

export const getIndexOfNode = (id: number, nodes: TreeNode[], collapsedNodes: number[]): number => {
const ids = getAllExpandedNodeIds(nodes, collapsedNodes);
export const getIndexOfNode = (
id: number,
nodes: TreeNode[],
collapsedNodes: number[],
emptyNodes: number[]
): number => {
const ids = getAllExpandedNodeIds(nodes, collapsedNodes, emptyNodes);
return ids.findIndex(eId => eId === id);
};

Expand All @@ -75,26 +82,31 @@ export const validateNumArray = (arr: any | undefined): boolean => {
* Removes specified nodes from the tree structure.
* @param nodes The array of root nodes of the tree.
* @param nodesToRemove An array of node IDs to be removed.
* @param collapsedNodes The array of collapsed node IDs.
* @returns A new array of root nodes with specified nodes removed.
*/
export function filterEmptyNodes(nodes: TreeNode[], nodesToRemove: number[]): TreeNode[] {
export function filterEmptyNodes(nodes: TreeNode[], nodesToRemove: number[], collapsedNodes: number[]): TreeNode[] {
// return nodes;
return nodes.reduce((acc: TreeNode[], node) => {
// If the current node is in the removal list, don't add it to the accumulator
if (nodesToRemove.includes(node.id)) {
return acc;
}

// Create a new node object with the same properties
const newNode: TreeNode = { ...node };

// Recursively remove nodes from children
if (newNode.children.length > 0) {
newNode.children = filterEmptyNodes(newNode.children, nodesToRemove);
newNode.children = filterEmptyNodes(newNode.children, nodesToRemove, collapsedNodes);
}

if (!nodesToRemove.includes(node.id)) {
// If the new node is not in the removal list, add it to the accumulator
acc.push(newNode);
} else if (!collapsedNodes.includes(node.id)) {
// If the new node is in the removal list and expanded, add its filtered children to the accumulator
newNode.children.forEach(child => {
child.parentId = newNode.parentId;
acc.push(child);
});
}

// Add the new node to the accumulator
acc.push(newNode);
return acc;
}, []);
}
8 changes: 4 additions & 4 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -13633,10 +13633,10 @@ through@2, "through@>=2.2.7 <3", through@^2.3.4, through@^2.3.6, through@^2.3.8:
resolved "https://registry.npmjs.org/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==

timeline-chart@^0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/timeline-chart/-/timeline-chart-0.4.0.tgz#c96301ce89b1306e4f69aa366b44e87bfcd4bffd"
integrity sha512-Pmsr+fLVBERWyKO3P9UJRIVWY3Sj+rqvzP4yg/RjCslqdQvl9qpQ+n8Tg7G9bxSvZ/NBKG+EpVpJGPDunPO84Q==
timeline-chart@^0.4.1:
version "0.4.1"
resolved "https://registry.yarnpkg.com/timeline-chart/-/timeline-chart-0.4.1.tgz#57cefac6cfa928cd84842cfb5031a157d8bb716e"
integrity sha512-f5lNTaY4438ml6x4bHdh29/FTXZgMOvunM5FDA1fWocxlq5PCBWvndwSh/HiqOHT0HLuom7jz9juxFtjyFCZmg==
dependencies:
"@types/lodash.throttle" "^4.1.4"
glob "^7.1.6"
Expand Down

0 comments on commit 73650f1

Please sign in to comment.