change(ui) - table sort

This commit is contained in:
Shekar Siri 2022-10-11 16:02:10 +02:00
parent 3684ab7be5
commit 3e3da8b660
2 changed files with 107 additions and 34 deletions

View file

@ -238,6 +238,14 @@ function NetworkPanel(props: Props) {
});
};
const handleSort = (sortKey: string) => {
if (sortKey === sortBy) {
setSortBy('time');
} else {
setSortBy(sortKey);
}
};
return (
<React.Fragment>
<BottomBlock style={{ height: 300 + additionalHeight + 'px' }} className="border">
@ -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,
},
]}
</TimeTable>

View file

@ -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<Line>;
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<Row>;
children: Array<Column>;
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<Row>, firstVisibleRowIndex: number, visibleCount: number): TimeLineInfo {
const visibleRows = rows.slice(firstVisibleRowIndex, firstVisibleRowIndex + visibleCount + _additionalHeight);
function computeTimeLine(
rows: Array<Row>,
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<Props, State> {
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<Props, State> {
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<Props, State> {
>
{columns.map(({ dataKey, render, width }) => (
<div className={stl.cell} style={{ width: `${width}px` }}>
{render ? render(row) : row[dataKey || ''] || <i className="color-gray-light">{'empty'}</i>}
{render
? render(row)
: row[dataKey || ''] || <i className="color-gray-light">{'empty'}</i>}
</div>
))}
<div className={cn('relative flex-1 flex', stl.timeBarWrapper)}>
<BarRow resource={row} timestart={timestart} timewidth={timewidth} popup={renderPopup} />
</div>
<div className="invisible group-hover:visible rounded-lg bg-active-blue text-xs flex items-center px-2 py-1 color-teal" onClick={(e) => this.onJump(e, index)}>
<div
className="invisible group-hover:visible rounded-lg bg-active-blue text-xs flex items-center px-2 py-1 color-teal"
onClick={(e) => this.onJump(e, index)}
>
<Icon name="caret-right-fill" size="12" color="teal" />
<span>JUMP</span>
</div>
@ -229,8 +259,25 @@ export default class TimeTable extends React.PureComponent<Props, State> {
}
};
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<Props, State> {
}
}
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<Props, State> {
)}
<div className={stl.headers}>
<div className={stl.infoHeaders}>
{columns.map(({ label, width }) => (
<div className={stl.headerCell} style={{ width: `${width}px` }}>
{label}
{columns.map(({ label, width, dataKey, onClick = null }) => (
<div
className={cn(stl.headerCell, 'flex items-center', { 'cursor-pointer': typeof onClick === 'function' })}
style={{ width: `${width}px` }}
onClick={() => this.onColumnClick(dataKey, onClick)}
>
<span>{label}</span>
{!!sortBy && sortBy === dataKey && (
<Icon name="caret-down-fill" className="ml-1" />
)}
</div>
))}
</div>
@ -327,4 +383,4 @@ export default class TimeTable extends React.PureComponent<Props, State> {
</div>
);
}
}
}