chore(trace-viewer): preserve column widths after showing resource details
This commit is contained in:
parent
6e9c31f93b
commit
684159728f
|
|
@ -76,6 +76,10 @@ export const NetworkTab: React.FunctionComponent<{
|
||||||
return { renderedEntries };
|
return { renderedEntries };
|
||||||
}, [networkModel.resources, networkModel.contextIdMap, sorting, boundaries]);
|
}, [networkModel.resources, networkModel.contextIdMap, sorting, boundaries]);
|
||||||
|
|
||||||
|
const [widths, setWidths] = React.useState<Map<ColumnName, number>>(() => {
|
||||||
|
return new Map(allColumns().map(column => [column, columnWidth(column)]));
|
||||||
|
});
|
||||||
|
|
||||||
if (!networkModel.resources.length)
|
if (!networkModel.resources.length)
|
||||||
return <PlaceholderPanel text='No network calls' />;
|
return <PlaceholderPanel text='No network calls' />;
|
||||||
|
|
||||||
|
|
@ -87,7 +91,8 @@ export const NetworkTab: React.FunctionComponent<{
|
||||||
onHighlighted={item => onEntryHovered(item?.resource)}
|
onHighlighted={item => onEntryHovered(item?.resource)}
|
||||||
columns={visibleColumns(!!selectedEntry, renderedEntries)}
|
columns={visibleColumns(!!selectedEntry, renderedEntries)}
|
||||||
columnTitle={columnTitle}
|
columnTitle={columnTitle}
|
||||||
columnWidth={columnWidth}
|
columnWidths={widths}
|
||||||
|
setColumnWidths={setWidths}
|
||||||
isError={item => item.status.code >= 400}
|
isError={item => item.status.code >= 400}
|
||||||
isInfo={item => !!item.route}
|
isInfo={item => !!item.route}
|
||||||
render={(item, column) => renderCell(item, column)}
|
render={(item, column) => renderCell(item, column)}
|
||||||
|
|
@ -96,7 +101,7 @@ export const NetworkTab: React.FunctionComponent<{
|
||||||
/>;
|
/>;
|
||||||
return <>
|
return <>
|
||||||
{!selectedEntry && grid}
|
{!selectedEntry && grid}
|
||||||
{selectedEntry && <SplitView sidebarSize={200} sidebarIsFirst={true} orientation='horizontal'>
|
{selectedEntry && <SplitView sidebarSize={widths.get('name')!} sidebarIsFirst={true} orientation='horizontal' settingName='networkResourceDetails'>
|
||||||
<NetworkResourceDetails resource={selectedEntry.resource} onClose={() => setSelectedEntry(undefined)} />
|
<NetworkResourceDetails resource={selectedEntry.resource} onClose={() => setSelectedEntry(undefined)} />
|
||||||
{grid}
|
{grid}
|
||||||
</SplitView>}
|
</SplitView>}
|
||||||
|
|
@ -142,13 +147,16 @@ const columnWidth = (column: ColumnName) => {
|
||||||
function visibleColumns(entrySelected: boolean, renderedEntries: RenderedEntry[]): (keyof RenderedEntry)[] {
|
function visibleColumns(entrySelected: boolean, renderedEntries: RenderedEntry[]): (keyof RenderedEntry)[] {
|
||||||
if (entrySelected)
|
if (entrySelected)
|
||||||
return ['name'];
|
return ['name'];
|
||||||
const columns: (keyof RenderedEntry)[] = [];
|
let columns: (keyof RenderedEntry)[] = allColumns();
|
||||||
if (hasMultipleContexts(renderedEntries))
|
if (!hasMultipleContexts(renderedEntries))
|
||||||
columns.push('contextId');
|
columns = columns.filter(name => name !== 'contextId');
|
||||||
columns.push('name', 'method', 'status', 'contentType', 'duration', 'size', 'start', 'route');
|
|
||||||
return columns;
|
return columns;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function allColumns(): (keyof RenderedEntry)[] {
|
||||||
|
return ['contextId', 'name', 'method', 'status', 'contentType', 'duration', 'size', 'start', 'route'];
|
||||||
|
}
|
||||||
|
|
||||||
const renderCell = (entry: RenderedEntry, column: ColumnName): RenderedGridCell => {
|
const renderCell = (entry: RenderedEntry, column: ColumnName): RenderedGridCell => {
|
||||||
if (column === 'contextId') {
|
if (column === 'contextId') {
|
||||||
return {
|
return {
|
||||||
|
|
|
||||||
|
|
@ -30,19 +30,33 @@ export type RenderedGridCell = {
|
||||||
export type GridViewProps<T> = Omit<ListViewProps<T>, 'render'> & {
|
export type GridViewProps<T> = Omit<ListViewProps<T>, 'render'> & {
|
||||||
columns: (keyof T)[],
|
columns: (keyof T)[],
|
||||||
columnTitle: (column: keyof T) => string,
|
columnTitle: (column: keyof T) => string,
|
||||||
columnWidth: (column: keyof T) => number,
|
columnWidths: Map<keyof T, number>,
|
||||||
|
setColumnWidths: (widths: Map<keyof T, number>) => void,
|
||||||
render: (item: T, column: keyof T, index: number) => RenderedGridCell,
|
render: (item: T, column: keyof T, index: number) => RenderedGridCell,
|
||||||
sorting?: Sorting<T>,
|
sorting?: Sorting<T>,
|
||||||
setSorting?: (sorting: Sorting<T> | undefined) => void,
|
setSorting?: (sorting: Sorting<T> | undefined) => void,
|
||||||
};
|
};
|
||||||
|
|
||||||
export function GridView<T>(model: GridViewProps<T>) {
|
export function GridView<T>(model: GridViewProps<T>) {
|
||||||
const initialOffsets: number[] = [];
|
function offsets() {
|
||||||
for (let i = 0; i < model.columns.length - 1; ++i) {
|
const offsets: number[] = [];
|
||||||
const column = model.columns[i];
|
for (let i = 0; i < model.columns.length - 1; ++i) {
|
||||||
initialOffsets[i] = (initialOffsets[i - 1] || 0) + model.columnWidth(column);
|
const column = model.columns[i];
|
||||||
|
offsets[i] = (offsets[i - 1] || 0) + model.columnWidths.get(column)!;
|
||||||
|
}
|
||||||
|
console.log('offsets', offsets, model.columns);
|
||||||
|
return offsets;
|
||||||
|
}
|
||||||
|
function setOffsets(offsets: number[]) {
|
||||||
|
const widths = new Map<keyof T, number>(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);
|
||||||
|
}
|
||||||
|
console.log('setOffsets', offsets);
|
||||||
|
model.setColumnWidths(widths);
|
||||||
}
|
}
|
||||||
const [offsets, setOffsets] = React.useState<number[]>(initialOffsets);
|
|
||||||
|
|
||||||
const toggleSorting = React.useCallback((f: keyof T) => {
|
const toggleSorting = React.useCallback((f: keyof T) => {
|
||||||
model.setSorting?.({ by: f, negate: model.sorting?.by === f ? !model.sorting.negate : false });
|
model.setSorting?.({ by: f, negate: model.sorting?.by === f ? !model.sorting.negate : false });
|
||||||
|
|
@ -51,7 +65,7 @@ export function GridView<T>(model: GridViewProps<T>) {
|
||||||
return <div className={`grid-view ${model.name}-grid-view`}>
|
return <div className={`grid-view ${model.name}-grid-view`}>
|
||||||
<ResizeView
|
<ResizeView
|
||||||
orientation={'horizontal'}
|
orientation={'horizontal'}
|
||||||
offsets={offsets}
|
offsets={offsets()}
|
||||||
setOffsets={setOffsets}
|
setOffsets={setOffsets}
|
||||||
resizerColor='var(--vscode-panel-border)'
|
resizerColor='var(--vscode-panel-border)'
|
||||||
resizerWidth={1}
|
resizerWidth={1}
|
||||||
|
|
@ -63,7 +77,7 @@ export function GridView<T>(model: GridViewProps<T>) {
|
||||||
return <div
|
return <div
|
||||||
className={'grid-view-header-cell ' + sortingHeader(column, model.sorting)}
|
className={'grid-view-header-cell ' + sortingHeader(column, model.sorting)}
|
||||||
style={{
|
style={{
|
||||||
width: offsets[i] - (offsets[i - 1] || 0),
|
width: i < model.columns.length - 1 ? model.columnWidths.get(column) : undefined,
|
||||||
}}
|
}}
|
||||||
onClick={() => model.setSorting && toggleSorting(column)}
|
onClick={() => model.setSorting && toggleSorting(column)}
|
||||||
>
|
>
|
||||||
|
|
@ -84,7 +98,9 @@ export function GridView<T>(model: GridViewProps<T>) {
|
||||||
return <div
|
return <div
|
||||||
className={`grid-view-cell grid-view-column-${String(column)}`}
|
className={`grid-view-cell grid-view-column-${String(column)}`}
|
||||||
title={title}
|
title={title}
|
||||||
style={{ width: offsets[i] - (offsets[i - 1] || 0) }}>
|
style={{
|
||||||
|
width: i < model.columns.length - 1 ? model.columnWidths.get(column) : undefined,
|
||||||
|
}}>
|
||||||
{body}
|
{body}
|
||||||
</div>;
|
</div>;
|
||||||
})}
|
})}
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ import { kTargetClosedErrorMessage } from '../config/errors';
|
||||||
import { browserTest as it, expect } from '../config/browserTest';
|
import { browserTest as it, expect } from '../config/browserTest';
|
||||||
import { attachFrame, verifyViewport } from '../config/utils';
|
import { attachFrame, verifyViewport } from '../config/utils';
|
||||||
import type { Page } from '@playwright/test';
|
import type { Page } from '@playwright/test';
|
||||||
|
import { request } from '@playwright/test';
|
||||||
|
|
||||||
it('should create new context @smoke', async function({ browser }) {
|
it('should create new context @smoke', async function({ browser }) {
|
||||||
expect(browser.contexts().length).toBe(0);
|
expect(browser.contexts().length).toBe(0);
|
||||||
|
|
@ -31,6 +32,22 @@ it('should create new context @smoke', async function({ browser }) {
|
||||||
expect(browser).toBe(context.browser());
|
expect(browser).toBe(context.browser());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('log two contexts', async function({ browser }) {
|
||||||
|
const context1 = await browser.newContext();
|
||||||
|
const context2 = await browser.newContext();
|
||||||
|
const api1 = await request.newContext();
|
||||||
|
const api2 = await request.newContext();
|
||||||
|
const page1 = await context1.newPage();
|
||||||
|
const page2 = await context2.newPage();
|
||||||
|
await page1.evaluate(() => { window.open('about:blank'); });
|
||||||
|
const promises = [];
|
||||||
|
promises.push(page1.goto('https://playwright.dev/'));
|
||||||
|
promises.push(page2.goto('https://theverge.com/'));
|
||||||
|
promises.push(api1.get('https://playwright.dev/'));
|
||||||
|
promises.push(api2.get('https://theverge.com/'));
|
||||||
|
await Promise.all(promises);
|
||||||
|
});
|
||||||
|
|
||||||
it('should be able to click across browser contexts', async function({ browser }) {
|
it('should be able to click across browser contexts', async function({ browser }) {
|
||||||
it.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/29096' });
|
it.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/29096' });
|
||||||
expect(browser.contexts().length).toBe(0);
|
expect(browser.contexts().length).toBe(0);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue