From 3e3da8b66000a99dc4509b4ac29c3cfb0ebfc593 Mon Sep 17 00:00:00 2001 From: Shekar Siri Date: Tue, 11 Oct 2022 16:02:10 +0200 Subject: [PATCH] change(ui) - table sort --- .../DevTools/NetworkPanel/NetworkPanel.tsx | 17 +++ .../shared/DevTools/TimeTable/TimeTable.tsx | 124 +++++++++++++----- 2 files changed, 107 insertions(+), 34 deletions(-) diff --git a/frontend/app/components/shared/DevTools/NetworkPanel/NetworkPanel.tsx b/frontend/app/components/shared/DevTools/NetworkPanel/NetworkPanel.tsx index af8b10aa1..241d449ff 100644 --- a/frontend/app/components/shared/DevTools/NetworkPanel/NetworkPanel.tsx +++ b/frontend/app/components/shared/DevTools/NetworkPanel/NetworkPanel.tsx @@ -238,6 +238,14 @@ function NetworkPanel(props: Props) { }); }; + const handleSort = (sortKey: string) => { + if (sortKey === sortBy) { + setSortBy('time'); + } else { + setSortBy(sortKey); + } + }; + return ( @@ -321,6 +329,7 @@ function NetworkPanel(props: Props) { onRowClick={onRowClick} additionalHeight={additionalHeight} onJump={jump} + sortBy={sortBy} // activeIndex={lastIndex} > {[ @@ -333,27 +342,35 @@ function NetworkPanel(props: Props) { label: 'Status', dataKey: 'status', width: 70, + onClick: handleSort, }, { label: 'Type', dataKey: 'type', width: 90, render: renderType, + onClick: handleSort, }, { label: 'Name', width: 240, + dataKey: 'name', render: renderName, + onClick: handleSort, }, { label: 'Size', width: 80, + dataKey: 'decodedBodySize', render: renderSize, + onClick: handleSort, }, { label: 'Time', width: 80, + dataKey: 'duration', render: renderDuration, + onClick: handleSort, }, ]} diff --git a/frontend/app/components/shared/DevTools/TimeTable/TimeTable.tsx b/frontend/app/components/shared/DevTools/TimeTable/TimeTable.tsx index be6a7c764..a0af1c906 100644 --- a/frontend/app/components/shared/DevTools/TimeTable/TimeTable.tsx +++ b/frontend/app/components/shared/DevTools/TimeTable/TimeTable.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { List, AutoSizer } from 'react-virtualized'; import cn from 'classnames'; -import { Duration } from "luxon"; +import { Duration } from 'luxon'; import { NoContent, Icon, Button } from 'UI'; import { percentOf } from 'App/utils'; @@ -24,7 +24,8 @@ type CanBeRed = { }; interface Row extends Timed, Durationed, CanBeRed { - [key: string]: any, key: string + [key: string]: any; + key: string; } type Line = { @@ -37,9 +38,10 @@ type Column = { label: string; width: number; dataKey?: string; - render?: (row: any) => void + render?: (row: any) => void; referenceLines?: Array; style?: React.CSSProperties; + onClick?: void; } & RenderOrKey; // type RenderOrKey = { // Disjoint? @@ -49,26 +51,27 @@ type Column = { // } type RenderOrKey = | { - render?: (row: Row) => React.ReactNode; - key?: string; - } + render?: (row: Row) => React.ReactNode; + key?: string; + } | { - dataKey: string; - }; + dataKey: string; + }; type Props = { className?: string; rows: Array; children: Array; - tableHeight?: number - activeIndex?: number - renderPopup?: boolean - navigation?: boolean - referenceLines?: any[] - additionalHeight?: number - hoverable?: boolean - onRowClick?: (row: any, index: number) => void - onJump?: (time: any) => void + tableHeight?: number; + activeIndex?: number; + renderPopup?: boolean; + navigation?: boolean; + referenceLines?: any[]; + additionalHeight?: number; + hoverable?: boolean; + onRowClick?: (row: any, index: number) => void; + onJump?: (time: any) => void; + sortBy?: string }; type TimeLineInfo = { @@ -87,15 +90,23 @@ const TIME_SECTIONS_COUNT = 8; const ZERO_TIMEWIDTH = 1000; function formatTime(ms: number) { if (ms < 0) return ''; - if (ms < 1000) return Duration.fromMillis(ms).toFormat('0.SSS') + if (ms < 1000) return Duration.fromMillis(ms).toFormat('0.SSS'); return Duration.fromMillis(ms).toFormat('mm:ss'); } -function computeTimeLine(rows: Array, firstVisibleRowIndex: number, visibleCount: number): TimeLineInfo { - const visibleRows = rows.slice(firstVisibleRowIndex, firstVisibleRowIndex + visibleCount + _additionalHeight); +function computeTimeLine( + rows: Array, + firstVisibleRowIndex: number, + visibleCount: number +): TimeLineInfo { + const visibleRows = rows.slice( + firstVisibleRowIndex, + firstVisibleRowIndex + visibleCount + _additionalHeight + ); let timestart = visibleRows.length > 0 ? Math.min(...visibleRows.map((r) => r.time)) : 0; // TODO: GraphQL requests do not have a duration, so their timeline is borked. Assume a duration of 0.2s for every GraphQL request - const timeend = visibleRows.length > 0 ? Math.max(...visibleRows.map((r) => r.time + (r.duration ?? 200))) : 0; + const timeend = + visibleRows.length > 0 ? Math.max(...visibleRows.map((r) => r.time + (r.duration ?? 200))) : 0; let timewidth = timeend - timestart; const offset = timewidth / 70; if (timestart >= offset) { @@ -141,18 +152,32 @@ export default class TimeTable extends React.PureComponent { componentDidUpdate(prevProps: any, prevState: any) { if ( prevState.firstVisibleRowIndex !== this.state.firstVisibleRowIndex || - (this.props.rows.length <= this.visibleCount + _additionalHeight && prevProps.rows.length !== this.props.rows.length) + (this.props.rows.length <= this.visibleCount + _additionalHeight && + prevProps.rows.length !== this.props.rows.length) ) { this.setState({ ...computeTimeLine(this.props.rows, this.state.firstVisibleRowIndex, this.visibleCount), }); } - if (this.props.activeIndex && this.props.activeIndex >= 0 && prevProps.activeIndex !== this.props.activeIndex && this.scroller.current) { + if ( + this.props.activeIndex && + this.props.activeIndex >= 0 && + prevProps.activeIndex !== this.props.activeIndex && + this.scroller.current + ) { this.scroller.current.scrollToRow(this.props.activeIndex); } } - onScroll = ({ scrollTop, scrollHeight, clientHeight }: { scrollTop: number; scrollHeight: number; clientHeight: number }): void => { + onScroll = ({ + scrollTop, + scrollHeight, + clientHeight, + }: { + scrollTop: number; + scrollHeight: number; + clientHeight: number; + }): void => { const firstVisibleRowIndex = Math.floor(scrollTop / ROW_HEIGHT + 0.33); if (this.state.firstVisibleRowIndex !== firstVisibleRowIndex) { @@ -164,9 +189,9 @@ export default class TimeTable extends React.PureComponent { onJump = (e: any, index: any) => { e.stopPropagation(); if (this.props.onJump) { - this.props.onJump(this.props.rows[index].time) + this.props.onJump(this.props.rows[index].time); } - } + }; renderRow = ({ index, key, style: rowStyle }: any) => { const { activeIndex } = this.props; @@ -189,13 +214,18 @@ export default class TimeTable extends React.PureComponent { > {columns.map(({ dataKey, render, width }) => (
- {render ? render(row) : row[dataKey || ''] || {'empty'}} + {render + ? render(row) + : row[dataKey || ''] || {'empty'}}
))}
-
this.onJump(e, index)}> +
this.onJump(e, index)} + > JUMP
@@ -229,8 +259,25 @@ export default class TimeTable extends React.PureComponent { } }; + onColumnClick = (dataKey: string, onClick: any) => { + if (typeof onClick === 'function') { + // this.scroller.current.scrollToRow(0); + onClick(dataKey) + this.scroller.current.forceUpdateGrid(); + } + } + render() { - const { className, rows, children: columns, navigation = false, referenceLines = [], additionalHeight = 0, activeIndex } = this.props; + const { + className, + rows, + children: columns, + navigation = false, + referenceLines = [], + additionalHeight = 0, + activeIndex, + sortBy = '', + } = this.props; const { timewidth, timestart } = this.state; _additionalHeight = additionalHeight; @@ -243,7 +290,9 @@ export default class TimeTable extends React.PureComponent { } } - const visibleRefLines = referenceLines.filter(({ time }) => time > timestart && time < timestart + timewidth); + const visibleRefLines = referenceLines.filter( + ({ time }) => time > timestart && time < timestart + timewidth + ); const columnsSumWidth = columns.reduce((sum, { width }) => sum + width, 0); @@ -273,9 +322,16 @@ export default class TimeTable extends React.PureComponent { )}
- {columns.map(({ label, width }) => ( -
- {label} + {columns.map(({ label, width, dataKey, onClick = null }) => ( +
this.onColumnClick(dataKey, onClick)} + > + {label} + {!!sortBy && sortBy === dataKey && ( + + )}
))}
@@ -327,4 +383,4 @@ export default class TimeTable extends React.PureComponent {
); } -} \ No newline at end of file +}