From 4c020c986100a71ca96a33c558c59491efaae40f Mon Sep 17 00:00:00 2001 From: Yury Semikhatsky Date: Thu, 30 May 2024 12:21:32 -0700 Subject: [PATCH] chore(trace-viewer): preserve column widths after showing resource details (#31093) * Column widths are now stored on in the NetworkPanel context, this way they are not reset after selecting an empty range (and changing position of the NetworkGridView in the component tree). * Column widths values are now preserved if column set changes (e.g. selecting entries from a single context and then from multiple contexts). --- packages/trace-viewer/src/ui/networkTab.tsx | 20 ++++++++---- packages/web/src/components/gridView.tsx | 35 +++++++++++++++------ 2 files changed, 40 insertions(+), 15 deletions(-) diff --git a/packages/trace-viewer/src/ui/networkTab.tsx b/packages/trace-viewer/src/ui/networkTab.tsx index d007d58198..ecab8cacf0 100644 --- a/packages/trace-viewer/src/ui/networkTab.tsx +++ b/packages/trace-viewer/src/ui/networkTab.tsx @@ -76,6 +76,10 @@ export const NetworkTab: React.FunctionComponent<{ return { renderedEntries }; }, [networkModel.resources, networkModel.contextIdMap, sorting, boundaries]); + const [widths, setWidths] = React.useState>(() => { + return new Map(allColumns().map(column => [column, columnWidth(column)])); + }); + if (!networkModel.resources.length) return ; @@ -87,7 +91,8 @@ export const NetworkTab: React.FunctionComponent<{ onHighlighted={item => onEntryHovered(item?.resource)} columns={visibleColumns(!!selectedEntry, renderedEntries)} columnTitle={columnTitle} - columnWidth={columnWidth} + columnWidths={widths} + setColumnWidths={setWidths} isError={item => item.status.code >= 400} isInfo={item => !!item.route} render={(item, column) => renderCell(item, column)} @@ -96,7 +101,7 @@ export const NetworkTab: React.FunctionComponent<{ />; return <> {!selectedEntry && grid} - {selectedEntry && + {selectedEntry && setSelectedEntry(undefined)} /> {grid} } @@ -142,13 +147,16 @@ const columnWidth = (column: ColumnName) => { function visibleColumns(entrySelected: boolean, renderedEntries: RenderedEntry[]): (keyof RenderedEntry)[] { if (entrySelected) return ['name']; - const columns: (keyof RenderedEntry)[] = []; - if (hasMultipleContexts(renderedEntries)) - columns.push('contextId'); - columns.push('name', 'method', 'status', 'contentType', 'duration', 'size', 'start', 'route'); + let columns: (keyof RenderedEntry)[] = allColumns(); + if (!hasMultipleContexts(renderedEntries)) + columns = columns.filter(name => name !== 'contextId'); return columns; } +function allColumns(): (keyof RenderedEntry)[] { + return ['contextId', 'name', 'method', 'status', 'contentType', 'duration', 'size', 'start', 'route']; +} + const renderCell = (entry: RenderedEntry, column: ColumnName): RenderedGridCell => { if (column === 'contextId') { return { diff --git a/packages/web/src/components/gridView.tsx b/packages/web/src/components/gridView.tsx index 2a5257da2b..d5f0f905fb 100644 --- a/packages/web/src/components/gridView.tsx +++ b/packages/web/src/components/gridView.tsx @@ -30,19 +30,34 @@ export type RenderedGridCell = { export type GridViewProps = Omit, 'render'> & { columns: (keyof T)[], columnTitle: (column: keyof T) => string, - columnWidth: (column: keyof T) => number, + columnWidths: Map, + setColumnWidths: (widths: Map) => void, render: (item: T, column: keyof T, index: number) => RenderedGridCell, sorting?: Sorting, setSorting?: (sorting: Sorting | undefined) => void, }; export function GridView(model: GridViewProps) { - const initialOffsets: number[] = []; - for (let i = 0; i < model.columns.length - 1; ++i) { - const column = model.columns[i]; - initialOffsets[i] = (initialOffsets[i - 1] || 0) + model.columnWidth(column); + const [offsets, setOffsets] = React.useState([]); + + React.useEffect(() => { + const offsets: number[] = []; + for (let i = 0; i < model.columns.length - 1; ++i) { + const column = model.columns[i]; + offsets[i] = (offsets[i - 1] || 0) + model.columnWidths.get(column)!; + } + setOffsets(offsets); + }, [model.columns, model.columnWidths]); + + function updateWidths(offsets: number[]) { + const widths = new Map(model.columnWidths.entries()); + for (let i = 0; i < offsets.length; ++i) { + const width = offsets[i] - (offsets[i - 1] || 0); + const column = model.columns[i]; + widths.set(column, width); + } + model.setColumnWidths(widths); } - const [offsets, setOffsets] = React.useState(initialOffsets); const toggleSorting = React.useCallback((f: keyof T) => { model.setSorting?.({ by: f, negate: model.sorting?.by === f ? !model.sorting.negate : false }); @@ -52,7 +67,7 @@ export function GridView(model: GridViewProps) { @@ -63,7 +78,7 @@ export function GridView(model: GridViewProps) { return
model.setSorting && toggleSorting(column)} > @@ -84,7 +99,9 @@ export function GridView(model: GridViewProps) { return
+ style={{ + width: i < model.columns.length - 1 ? model.columnWidths.get(column) : undefined, + }}> {body}
; })}