Skip to content

Commit 8ea0dec

Browse files
committed
Column sorting
1 parent aad804f commit 8ea0dec

6 files changed

Lines changed: 341 additions & 37 deletions

File tree

src/components/calltree/CallTree.tsx

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@
44
import { PureComponent } from 'react';
55
import memoize from 'memoize-immutable';
66
import explicitConnect from 'firefox-profiler/utils/connect';
7-
import { TreeView } from 'firefox-profiler/components/shared/TreeView';
7+
import {
8+
TreeView,
9+
ColumnSortState,
10+
} from 'firefox-profiler/components/shared/TreeView';
811
import { CallTreeEmptyReasons } from './CallTreeEmptyReasons';
912
import {
1013
getInvertCallstack,
@@ -98,6 +101,7 @@ class CallTreeImpl extends PureComponent<Props> {
98101
_treeView: TreeView<CallNodeDisplayData> | null = null;
99102
_takeTreeViewRef = (treeView: TreeView<CallNodeDisplayData> | null) =>
100103
(this._treeView = treeView);
104+
_sortedColumns = new ColumnSortState([{ column: 'total', ascending: false }]);
101105

102106
/**
103107
* Call Trees can have different types of "weights" for the data. Choose the
@@ -204,6 +208,10 @@ class CallTreeImpl extends PureComponent<Props> {
204208
handleCallNodeTransformShortcut(event, threadsKey, callNodeInfo, nodeIndex);
205209
};
206210

211+
_onSort = (sortedColumns: ColumnSortState) => {
212+
this._sortedColumns = sortedColumns;
213+
};
214+
207215
_onEnterOrDoubleClick = (nodeId: IndexIntoCallNodeTable) => {
208216
const { tree, updateBottomBoxContentsAndMaybeOpen } = this.props;
209217
const bottomBoxInfo = tree.getBottomBoxInfoForCallNode(nodeId);
@@ -308,6 +316,8 @@ class CallTreeImpl extends PureComponent<Props> {
308316
onDoubleClick={this._onEnterOrDoubleClick}
309317
viewOptions={tableViewOptions}
310318
onViewOptionsChange={onTableViewOptionsChange}
319+
initialSortedColumns={this._sortedColumns}
320+
onColumnSortChange={this._onSort}
311321
/>
312322
);
313323
}

src/components/marker-table/index.tsx

Lines changed: 61 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { PureComponent } from 'react';
66
import memoize from 'memoize-immutable';
77

88
import explicitConnect from '../../utils/connect';
9-
import { TreeView } from '../shared/TreeView';
9+
import { TreeView, ColumnSortState } from '../shared/TreeView';
1010
import { MarkerTableEmptyReasons } from './MarkerTableEmptyReasons';
1111
import {
1212
getZeroAt,
@@ -73,6 +73,16 @@ class MarkerTree {
7373
this._getMarkerLabel = getMarkerLabel;
7474
}
7575

76+
static _sortableColumns = [
77+
{ name: 'start', prefersDescending: false },
78+
{ name: 'duration', prefersDescending: true },
79+
{ name: 'name', prefersDescending: false },
80+
];
81+
82+
getSortableColumns(): any[] {
83+
return MarkerTree._sortableColumns;
84+
}
85+
7686
copyTable = (
7787
format: 'plain' | 'markdown',
7888
onExceeedMaxCopyRows: (rows: number, maxRows: number) => void
@@ -167,12 +177,49 @@ class MarkerTree {
167177
copy(text);
168178
};
169179

170-
getRoots(): MarkerIndex[] {
180+
getRoots(sort: ColumnSortState | null = null): MarkerIndex[] {
181+
if (sort !== null) {
182+
return sort.sortItemsHelper(
183+
this._markerIndexes.slice(),
184+
(first: MarkerIndex, second: MarkerIndex, column: string) => {
185+
const firstValue = this._getSortValueForColumn(first, column);
186+
const secondValue = this._getSortValueForColumn(second, column);
187+
if (typeof firstValue === 'string') {
188+
return firstValue.localeCompare(secondValue as string);
189+
}
190+
return (secondValue as number) - (firstValue as number);
191+
}
192+
);
193+
}
171194
return this._markerIndexes;
172195
}
173196

174-
getChildren(markerIndex: MarkerIndex): MarkerIndex[] {
175-
return markerIndex === -1 ? this.getRoots() : [];
197+
_getSortValueForColumn(
198+
markerIndex: MarkerIndex,
199+
column: string
200+
): string | number {
201+
const marker = this._getMarker(markerIndex);
202+
switch (column) {
203+
case 'start':
204+
return marker.start;
205+
case 'duration': {
206+
if (marker.incomplete || marker.end === null) {
207+
return -Infinity;
208+
}
209+
return marker.end - marker.start;
210+
}
211+
case 'name':
212+
return marker.name;
213+
default:
214+
throw new Error('Invalid column ' + column);
215+
}
216+
}
217+
218+
getChildren(
219+
markerIndex: MarkerIndex,
220+
sort: ColumnSortState | null = null
221+
): MarkerIndex[] {
222+
return markerIndex === -1 ? this.getRoots(sort) : [];
176223
}
177224

178225
hasChildren(_markerIndex: MarkerIndex): boolean {
@@ -205,10 +252,11 @@ class MarkerTree {
205252
}
206253

207254
let duration = null;
255+
const markerEnd = marker.end;
208256
if (marker.incomplete) {
209257
duration = 'unknown';
210-
} else if (marker.end !== null) {
211-
duration = formatTimestamp(marker.end - marker.start);
258+
} else if (markerEnd !== null) {
259+
duration = formatTimestamp(markerEnd - marker.start);
212260
}
213261

214262
displayData = {
@@ -278,6 +326,7 @@ class MarkerTableImpl extends PureComponent<Props> {
278326
_treeView: TreeView<MarkerDisplayData> | null = null;
279327
_takeTreeViewRef = (treeView: TreeView<MarkerDisplayData> | null) =>
280328
(this._treeView = treeView);
329+
_sortedColumns = new ColumnSortState([{ column: 'start', ascending: true }]);
281330

282331
getMarkerTree = memoize(
283332
(
@@ -330,6 +379,10 @@ class MarkerTableImpl extends PureComponent<Props> {
330379
changeSelectedMarker(threadsKey, selectedMarker, context);
331380
};
332381

382+
_onColumnSortChange = (sortedColumns: ColumnSortState) => {
383+
this._sortedColumns = sortedColumns;
384+
};
385+
333386
_onRightClickSelection = (selectedMarker: MarkerIndex) => {
334387
const { threadsKey, changeRightClickedMarker } = this.props;
335388
changeRightClickedMarker(threadsKey, selectedMarker);
@@ -380,6 +433,8 @@ class MarkerTableImpl extends PureComponent<Props> {
380433
indentWidth={10}
381434
viewOptions={this.props.tableViewOptions}
382435
onViewOptionsChange={this.props.onTableViewOptionsChange}
436+
initialSortedColumns={this._sortedColumns}
437+
onColumnSortChange={this._onColumnSortChange}
383438
/>
384439
)}
385440
</div>

src/components/shared/TreeView.css

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,19 @@
123123
text-overflow: ellipsis;
124124
}
125125

126+
.treeViewHeaderColumn.sortInactive::after {
127+
content: ' ▲';
128+
opacity: 0;
129+
}
130+
131+
.treeViewHeaderColumn.sortDescending::after {
132+
content: ' ▲';
133+
}
134+
135+
.treeViewHeaderColumn.sortAscending::after {
136+
content: ' ▼ ';
137+
}
138+
126139
.treeViewColumnDivider {
127140
display: flex;
128141
width: 20px;

0 commit comments

Comments
 (0)