ui: drop deprecated TimeTable.tsx, point gql to correct one (#2567)
This commit is contained in:
parent
8e81bdea7e
commit
9030806146
12 changed files with 18 additions and 793 deletions
|
|
@ -145,7 +145,7 @@ function Player(props: IProps) {
|
|||
{bottomBlock === STORAGE && <Storage />}
|
||||
{bottomBlock === PROFILER && <ProfilerPanel panelHeight={panelHeight} />}
|
||||
{bottomBlock === PERFORMANCE && <ConnectedPerformance />}
|
||||
{bottomBlock === GRAPHQL && <GraphQL />}
|
||||
{bottomBlock === GRAPHQL && <GraphQL panelHeight={panelHeight} />}
|
||||
{bottomBlock === EXCEPTIONS && <Exceptions />}
|
||||
</div>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import React, { useEffect } from 'react';
|
|||
import { NoContent, Input, SlideModal, CloseButton, Button } from 'UI';
|
||||
import { getRE } from 'App/utils';
|
||||
import BottomBlock from '../BottomBlock';
|
||||
import TimeTable from '../TimeTable';
|
||||
import TimeTable from 'Components/shared/DevTools/TimeTable'
|
||||
import GQLDetails from './GQLDetails';
|
||||
import { PlayerContext } from 'App/components/Session/playerContext';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
|
|
@ -31,7 +31,9 @@ function renderDefaultStatus() {
|
|||
return '2xx-3xx';
|
||||
}
|
||||
|
||||
function GraphQL() {
|
||||
function GraphQL({
|
||||
panelHeight
|
||||
}: { panelHeight: number }) {
|
||||
const { player, store } = React.useContext(PlayerContext);
|
||||
const { time, livePlay, tabStates, currentTab } = store.get();
|
||||
const { graphqlList: list = [], graphqlListNow: listNow = [] } = tabStates[currentTab]
|
||||
|
|
@ -55,16 +57,6 @@ function GraphQL() {
|
|||
return (
|
||||
<div className="flex justify-between items-center grow-0 w-full">
|
||||
<div>{r.operationName}</div>
|
||||
<Button
|
||||
variant="text"
|
||||
className="right-0 text-xs uppercase p-2 color-gray-500 hover:color-teal"
|
||||
onClick={(e: React.MouseEvent<HTMLButtonElement>) => {
|
||||
e.stopPropagation();
|
||||
player.jump(r.time);
|
||||
}}
|
||||
>
|
||||
Jump
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -93,13 +85,16 @@ function GraphQL() {
|
|||
};
|
||||
|
||||
const setCurrent = (item: any, index: number) => {
|
||||
if (!livePlay) {
|
||||
player.pause();
|
||||
player.jump(item.time);
|
||||
}
|
||||
setState((prevState) => ({ ...prevState, current: item, currentIndex: index }));
|
||||
};
|
||||
|
||||
const onJump = (time: number) => {
|
||||
if (!livePlay) {
|
||||
player.pause();
|
||||
player.jump(time);
|
||||
}
|
||||
}
|
||||
|
||||
const closeModal = () =>
|
||||
setState((prevState) => ({ ...prevState, current: null, showFetchDetails: false }));
|
||||
|
||||
|
|
@ -155,8 +150,10 @@ function GraphQL() {
|
|||
<TimeTable
|
||||
rows={filteredList}
|
||||
onRowClick={setCurrent}
|
||||
tableHeight={panelHeight - 102}
|
||||
hoverable
|
||||
activeIndex={lastActiveItem}
|
||||
onJump={onJump}
|
||||
>
|
||||
{[
|
||||
{
|
||||
|
|
@ -164,19 +161,14 @@ function GraphQL() {
|
|||
width: 90,
|
||||
render: renderStart,
|
||||
},
|
||||
{
|
||||
label: 'Status',
|
||||
width: 70,
|
||||
render: renderDefaultStatus,
|
||||
},
|
||||
{
|
||||
label: 'Type',
|
||||
dataKey: 'operationKind',
|
||||
width: 60,
|
||||
width: 80,
|
||||
},
|
||||
{
|
||||
label: 'Name',
|
||||
width: 240,
|
||||
width: 300,
|
||||
render: renderName,
|
||||
},
|
||||
]}
|
||||
|
|
|
|||
|
|
@ -1,27 +0,0 @@
|
|||
import React from 'react';
|
||||
export default class ProfileInfo extends React.PureComponent {
|
||||
render() {
|
||||
const {
|
||||
profile: {
|
||||
name,
|
||||
args,
|
||||
result,
|
||||
}
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<div className="px-6" >
|
||||
<h5 className="py-3">{"Arguments"}</h5>
|
||||
<ul className="color-gray-medium">
|
||||
{ args.split(',').map(arg => (
|
||||
<li> { `${ arg }` } </li>
|
||||
))}
|
||||
</ul>
|
||||
<h5 className="py-3" >{"Result"}</h5>
|
||||
<div className="color-gray-medium" >
|
||||
{ `${ result }` }
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,82 +0,0 @@
|
|||
import React from 'react';
|
||||
import { connectPlayer } from 'Player';
|
||||
import { SlideModal, TextEllipsis, Input } from 'UI';
|
||||
import { getRE } from 'App/utils';
|
||||
|
||||
import ProfileInfo from './ProfileInfo';
|
||||
import TimeTable from '../TimeTable';
|
||||
import BottomBlock from '../BottomBlock';
|
||||
|
||||
const renderDuration = p => `${ p.duration }ms`;
|
||||
const renderName = p => <TextEllipsis text={ p.name } />;
|
||||
|
||||
@connectPlayer(state => ({
|
||||
profiles: state.profilesList,
|
||||
}))
|
||||
export default class Profiler extends React.PureComponent {
|
||||
state = {
|
||||
filter: '',
|
||||
modalProfile: null,
|
||||
}
|
||||
onFilterChange = ({ target: { value } }) => this.setState({ filter: value })
|
||||
|
||||
onProfileClick = resource => {
|
||||
this.setState({ modalProfile: resource });
|
||||
}
|
||||
closeModal = () => this.setState({ modalProfile: null })
|
||||
|
||||
render() {
|
||||
const { profiles } = this.props;
|
||||
const { filter, modalProfile } = this.state;
|
||||
const filterRE = getRE(filter, 'i');
|
||||
const filteredProfiles = profiles.filter(({ name }) => filterRE.test(name));
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<SlideModal
|
||||
title={ modalProfile && modalProfile.name }
|
||||
isDisplayed={ modalProfile !== null }
|
||||
content={ modalProfile && <ProfileInfo profile={ modalProfile } />}
|
||||
size="middle"
|
||||
onClose={ this.closeModal }
|
||||
/>
|
||||
<BottomBlock>
|
||||
<BottomBlock.Header>
|
||||
<div className="flex items-center">
|
||||
<span className="font-semibold color-gray-medium mr-4">Profiler</span>
|
||||
</div>
|
||||
<Input
|
||||
// className="input-small"
|
||||
placeholder="Filter by name"
|
||||
icon="search"
|
||||
name="filter"
|
||||
onChange={ this.onFilterChange }
|
||||
height={28}
|
||||
/>
|
||||
</BottomBlock.Header>
|
||||
<BottomBlock.Content>
|
||||
<TimeTable
|
||||
rows={ filteredProfiles }
|
||||
onRowClick={ this.onProfileClick }
|
||||
hoverable
|
||||
>
|
||||
{[
|
||||
{
|
||||
label: "Name",
|
||||
dataKey: 'name',
|
||||
width: 200,
|
||||
render: renderName,
|
||||
}, {
|
||||
label: "Time",
|
||||
key: 'duration',
|
||||
width: 80,
|
||||
render: renderDuration,
|
||||
}
|
||||
]}
|
||||
</TimeTable>
|
||||
</BottomBlock.Content>
|
||||
</BottomBlock>
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
export { default } from './Profiler';
|
||||
|
|
@ -1,108 +0,0 @@
|
|||
import { Tooltip } from 'UI';
|
||||
import { percentOf } from 'App/utils';
|
||||
import styles from './barRow.module.css';
|
||||
import tableStyles from './timeTable.module.css';
|
||||
import React from 'react';
|
||||
|
||||
const formatTime = (time) => (time < 1000 ? `${time.toFixed(2)}ms` : `${time / 1000}s`);
|
||||
|
||||
interface Props {
|
||||
resource: {
|
||||
time: number;
|
||||
ttfb?: number;
|
||||
duration?: number;
|
||||
key: string;
|
||||
};
|
||||
popup?: boolean;
|
||||
timestart: number;
|
||||
timewidth: number;
|
||||
}
|
||||
|
||||
// TODO: If request has no duration, set duration to 0.2s. Enforce existence of duration in the future.
|
||||
const BarRow = ({
|
||||
resource: { time, ttfb = 0, duration = 200, key },
|
||||
popup = false,
|
||||
timestart = 0,
|
||||
timewidth,
|
||||
}: Props) => {
|
||||
const timeOffset = time - timestart;
|
||||
ttfb = ttfb || 0;
|
||||
const trigger = (
|
||||
<div
|
||||
className={styles.barWrapper}
|
||||
style={{
|
||||
left: `${percentOf(timeOffset, timewidth)}%`,
|
||||
right: `${100 - percentOf(timeOffset + duration, timewidth)}%`,
|
||||
minWidth: '5px',
|
||||
}}
|
||||
>
|
||||
<div
|
||||
className={styles.ttfbBar}
|
||||
style={{
|
||||
width: `${percentOf(ttfb, duration)}%`,
|
||||
}}
|
||||
/>
|
||||
<div
|
||||
className={styles.downloadBar}
|
||||
style={{
|
||||
width: `${percentOf(duration - ttfb, duration)}%`,
|
||||
minWidth: '5px',
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
if (!popup)
|
||||
return (
|
||||
<div key={key} className={tableStyles.row}>
|
||||
{' '}
|
||||
{trigger}{' '}
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<div key={key} className={tableStyles.row}>
|
||||
<Tooltip
|
||||
title={
|
||||
<React.Fragment>
|
||||
{ttfb != null && (
|
||||
<div className={styles.popupRow}>
|
||||
<div className={styles.title}>{'Waiting (TTFB)'}</div>
|
||||
<div className={styles.popupBarWrapper}>
|
||||
<div
|
||||
className={styles.ttfbBar}
|
||||
style={{
|
||||
left: 0,
|
||||
width: `${percentOf(ttfb, duration)}%`,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.time}>{formatTime(ttfb)}</div>
|
||||
</div>
|
||||
)}
|
||||
<div className={styles.popupRow}>
|
||||
<div className={styles.title}>{'Content Download'}</div>
|
||||
<div className={styles.popupBarWrapper}>
|
||||
<div
|
||||
className={styles.downloadBar}
|
||||
style={{
|
||||
left: `${percentOf(ttfb, duration)}%`,
|
||||
width: `${percentOf(duration - ttfb, duration)}%`,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.time}>{formatTime(duration - ttfb)}</div>
|
||||
</div>
|
||||
</React.Fragment>
|
||||
}
|
||||
size="mini"
|
||||
position="top center"
|
||||
>
|
||||
{trigger}
|
||||
</Tooltip>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
BarRow.displayName = 'BarRow';
|
||||
|
||||
export default BarRow;
|
||||
|
|
@ -1,390 +0,0 @@
|
|||
import cn from 'classnames';
|
||||
import { Duration } from 'luxon';
|
||||
import React from 'react';
|
||||
import { VList, VListHandle } from 'virtua';
|
||||
|
||||
import { percentOf } from 'App/utils';
|
||||
import { Button, NoContent } from 'UI';
|
||||
|
||||
import autoscrollStl from '../autoscroll.module.css';
|
||||
import BarRow from './BarRow';
|
||||
import stl from './timeTable.module.css';
|
||||
|
||||
//aaa
|
||||
|
||||
type Timed = {
|
||||
time: number;
|
||||
};
|
||||
|
||||
type Durationed = {
|
||||
duration: number;
|
||||
};
|
||||
|
||||
type CanBeRed = {
|
||||
//+isRed: boolean,
|
||||
isRed: boolean;
|
||||
};
|
||||
|
||||
interface Row extends Timed, Durationed, CanBeRed {
|
||||
[key: string]: any;
|
||||
key: string;
|
||||
}
|
||||
|
||||
type Line = {
|
||||
color: string; // Maybe use typescript?
|
||||
hint?: string;
|
||||
onClick?: any;
|
||||
} & Timed;
|
||||
|
||||
type Column = {
|
||||
label: string;
|
||||
width: number;
|
||||
dataKey?: string;
|
||||
render?: (row: any) => void;
|
||||
referenceLines?: Array<Line>;
|
||||
style?: React.CSSProperties;
|
||||
} & RenderOrKey;
|
||||
|
||||
// type RenderOrKey = { // Disjoint?
|
||||
// render: Row => React.Node
|
||||
// } | {
|
||||
// dataKey: string,
|
||||
// }
|
||||
type RenderOrKey =
|
||||
| {
|
||||
render?: (row: Row) => React.ReactNode;
|
||||
key?: 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;
|
||||
};
|
||||
|
||||
type TimeLineInfo = {
|
||||
timestart: number;
|
||||
timewidth: number;
|
||||
};
|
||||
|
||||
type State = TimeLineInfo & typeof initialState;
|
||||
|
||||
//const TABLE_HEIGHT = 195;
|
||||
let _additionalHeight = 0;
|
||||
const ROW_HEIGHT = 32;
|
||||
//const VISIBLE_COUNT = Math.ceil(TABLE_HEIGHT/ROW_HEIGHT);
|
||||
|
||||
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');
|
||||
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
|
||||
);
|
||||
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;
|
||||
let timewidth = timeend - timestart;
|
||||
const offset = timewidth / 70;
|
||||
if (timestart >= offset) {
|
||||
timestart -= offset;
|
||||
}
|
||||
timewidth *= 1.5; // += offset;
|
||||
if (timewidth === 0) {
|
||||
timewidth = ZERO_TIMEWIDTH;
|
||||
}
|
||||
return {
|
||||
timestart,
|
||||
timewidth,
|
||||
};
|
||||
}
|
||||
|
||||
const initialState = {
|
||||
firstVisibleRowIndex: 0,
|
||||
};
|
||||
|
||||
export default class TimeTable extends React.PureComponent<Props, State> {
|
||||
state = {
|
||||
...computeTimeLine(
|
||||
this.props.rows,
|
||||
initialState.firstVisibleRowIndex,
|
||||
this.visibleCount
|
||||
),
|
||||
...initialState,
|
||||
};
|
||||
|
||||
get tableHeight() {
|
||||
return this.props.tableHeight || 195;
|
||||
}
|
||||
|
||||
get visibleCount() {
|
||||
return Math.ceil(this.tableHeight / ROW_HEIGHT);
|
||||
}
|
||||
|
||||
scroller = React.createRef<VListHandle>();
|
||||
autoScroll = true;
|
||||
|
||||
componentDidMount() {
|
||||
if (this.scroller.current) {
|
||||
this.scroller.current.scrollToIndex(this.props.activeIndex);
|
||||
}
|
||||
}
|
||||
|
||||
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.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
|
||||
) {
|
||||
this.scroller.current.scrollToIndex(this.props.activeIndex);
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
this.autoScroll =
|
||||
scrollHeight - clientHeight - scrollTop < ROW_HEIGHT / 2;
|
||||
this.setState({ firstVisibleRowIndex });
|
||||
}
|
||||
};
|
||||
|
||||
renderRow = (index: number) => {
|
||||
const { activeIndex } = this.props;
|
||||
const {
|
||||
children: columns,
|
||||
rows,
|
||||
renderPopup,
|
||||
hoverable,
|
||||
onRowClick,
|
||||
} = this.props;
|
||||
const { timestart, timewidth } = this.state;
|
||||
const row = rows[index];
|
||||
return (
|
||||
<div
|
||||
className={cn('border-b border-color-gray-light-shade', stl.row, {
|
||||
[stl.hoverable]: hoverable,
|
||||
'error color-red': !!row.isRed && row.isRed,
|
||||
'cursor-pointer': typeof onRowClick === 'function',
|
||||
[stl.activeRow]: activeIndex === index,
|
||||
// [stl.inactiveRow]: !activeIndex || index > activeIndex,
|
||||
})}
|
||||
onClick={
|
||||
typeof onRowClick === 'function'
|
||||
? () => onRowClick(row, index)
|
||||
: undefined
|
||||
}
|
||||
id="table-row"
|
||||
>
|
||||
{columns.map((column, key) => (
|
||||
<div
|
||||
key={column.label.replace(' ', '')}
|
||||
className={stl.cell}
|
||||
style={{ width: `${column.width}px` }}
|
||||
>
|
||||
{column.render
|
||||
? column.render(row)
|
||||
: row[column.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>
|
||||
);
|
||||
};
|
||||
|
||||
onPrevClick = () => {
|
||||
let prevRedIndex = -1;
|
||||
for (let i = this.state.firstVisibleRowIndex - 1; i >= 0; i--) {
|
||||
if (this.props.rows[i].isRed) {
|
||||
prevRedIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (this.scroller.current != null) {
|
||||
this.scroller.current.scrollToIndex(prevRedIndex);
|
||||
}
|
||||
};
|
||||
|
||||
onNextClick = () => {
|
||||
let prevRedIndex = -1;
|
||||
for (
|
||||
let i = this.state.firstVisibleRowIndex + 1;
|
||||
i < this.props.rows.length;
|
||||
i++
|
||||
) {
|
||||
if (this.props.rows[i].isRed) {
|
||||
prevRedIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (this.scroller.current != null) {
|
||||
this.scroller.current.scrollToIndex(prevRedIndex);
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
className,
|
||||
rows,
|
||||
children: columns,
|
||||
navigation = false,
|
||||
referenceLines = [],
|
||||
additionalHeight = 0,
|
||||
activeIndex,
|
||||
} = this.props;
|
||||
const { timewidth, timestart } = this.state;
|
||||
|
||||
_additionalHeight = additionalHeight;
|
||||
|
||||
const sectionDuration = Math.round(timewidth / TIME_SECTIONS_COUNT);
|
||||
const timeColumns: number[] = [];
|
||||
if (timewidth > 0) {
|
||||
for (let i = 0; i < TIME_SECTIONS_COUNT; i++) {
|
||||
timeColumns.push(timestart + i * sectionDuration);
|
||||
}
|
||||
}
|
||||
|
||||
const visibleRefLines = referenceLines.filter(
|
||||
({ time }) => time > timestart && time < timestart + timewidth
|
||||
);
|
||||
|
||||
const columnsSumWidth = columns.reduce((sum, { width }) => sum + width, 0);
|
||||
|
||||
return (
|
||||
<div className={cn(className, 'relative')}>
|
||||
{navigation && (
|
||||
<div className={cn(autoscrollStl.navButtons, 'flex items-center')}>
|
||||
<Button
|
||||
variant="text-primary"
|
||||
icon="chevron-up"
|
||||
tooltip={{
|
||||
title: 'Previous Error',
|
||||
delay: 0,
|
||||
}}
|
||||
onClick={this.onPrevClick}
|
||||
/>
|
||||
<Button
|
||||
variant="text-primary"
|
||||
icon="chevron-down"
|
||||
tooltip={{
|
||||
title: 'Next Error',
|
||||
delay: 0,
|
||||
}}
|
||||
onClick={this.onNextClick}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<div className={stl.headers}>
|
||||
<div className={stl.infoHeaders}>
|
||||
{columns.map(({ label, width }) => (
|
||||
<div
|
||||
key={label.replace(' ', '')}
|
||||
className={stl.headerCell}
|
||||
style={{ width: `${width}px` }}
|
||||
>
|
||||
{label}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<div className={stl.waterfallHeaders}>
|
||||
{timeColumns.map((time, i) => (
|
||||
<div className={stl.timeCell} key={`tc-${i}`}>
|
||||
{formatTime(time)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<NoContent size="small" show={rows.length === 0}>
|
||||
<div className="relative">
|
||||
<div
|
||||
className={stl.timePart}
|
||||
style={{ left: `${columnsSumWidth}px` }}
|
||||
>
|
||||
{timeColumns.map((_, index) => (
|
||||
<div key={`tc-${index}`} className={stl.timeCell} />
|
||||
))}
|
||||
{visibleRefLines.map((line, key) => (
|
||||
<div
|
||||
key={line.time + key}
|
||||
className={cn(stl.refLine, `bg-${line.color}`)}
|
||||
style={{
|
||||
left: `${percentOf(line.time - timestart, timewidth)}%`,
|
||||
cursor:
|
||||
typeof line.onClick === 'function' ? 'click' : 'auto',
|
||||
}}
|
||||
onClick={line.onClick}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
<VList
|
||||
ref={this.scroller}
|
||||
className={stl.list}
|
||||
count={rows.length}
|
||||
itemSize={ROW_HEIGHT}
|
||||
>
|
||||
{this.props.rows.map((_, i) => this.renderRow(i))}
|
||||
</VList>
|
||||
</div>
|
||||
</NoContent>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
|
||||
|
||||
|
||||
.barWrapper {
|
||||
display: flex;
|
||||
position: absolute;
|
||||
top: 35%;
|
||||
bottom: 35%;
|
||||
border-radius: 3px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.downloadBar, .ttfbBar {
|
||||
/* box-shadow: inset 0px 0px 0px 1px $teal; */
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
}
|
||||
.ttfbBar {
|
||||
background-color: rgba(175, 226, 221, 0.8);
|
||||
}
|
||||
.downloadBar {
|
||||
background-color: rgba(133, 200, 192, 0.8);
|
||||
}
|
||||
|
||||
.popupRow {
|
||||
color: $gray-medium;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 2px 0;
|
||||
font-size: 12px;
|
||||
}
|
||||
.title {
|
||||
width: 105px;
|
||||
}
|
||||
.time {
|
||||
width: 60px;
|
||||
padding-left: 10px;
|
||||
}
|
||||
.popupBarWrapper {
|
||||
width: 220px;
|
||||
height: 15px;
|
||||
border-radius: 3px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
export { default } from './TimeTable';
|
||||
|
|
@ -1,112 +0,0 @@
|
|||
|
||||
|
||||
$offset: 10px;
|
||||
|
||||
.timeCell {
|
||||
border-left: solid thin rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.headers {
|
||||
box-shadow: 0 1px 2px 0 $gray-light;
|
||||
background-color: $gray-lightest;
|
||||
color: $gray-darkest;
|
||||
font-size: 12px;
|
||||
overflow-x: hidden;
|
||||
white-space: nowrap;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
padding: 0 $offset;
|
||||
}
|
||||
.infoHeaders {
|
||||
text-transform: uppercase;
|
||||
display: flex;
|
||||
& .headerCell {
|
||||
padding: 4px 2px;
|
||||
}
|
||||
}
|
||||
.waterfallHeaders {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
& .timeCell {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
padding: 4px 0;
|
||||
}
|
||||
}
|
||||
|
||||
.list {
|
||||
/* TODO hide the scrollbar track */
|
||||
&::-webkit-scrollbar {
|
||||
width: 1px;
|
||||
}
|
||||
scrollbar-width: thin;
|
||||
font-size: 12px;
|
||||
font-family: 'Menlo', 'monaco', 'consolas', monospace;
|
||||
}
|
||||
|
||||
.row {
|
||||
display: flex;
|
||||
padding: 0 $offset;
|
||||
|
||||
&:hover {
|
||||
background-color: $active-blue;
|
||||
}
|
||||
/*align-items: center;
|
||||
cursor: pointer;
|
||||
*/
|
||||
/* &:nth-child(even) {
|
||||
background-color: $gray-lightest;
|
||||
} */
|
||||
/* & > div:first-child {
|
||||
padding-left: 5px;
|
||||
}*/
|
||||
}
|
||||
.cell {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
overflow: hidden;
|
||||
padding: 0 2px;
|
||||
}
|
||||
.hoverable {
|
||||
transition: all 0.3s;
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
background-color: $active-blue;
|
||||
transition: all 0.2s;
|
||||
color: $gray-dark;
|
||||
}
|
||||
}
|
||||
.timeBarWrapper{
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.timePart {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
/*left:0;*/
|
||||
right: 0;
|
||||
display: flex;
|
||||
margin: 0 $offset;
|
||||
& .timeCell {
|
||||
height: 100%;
|
||||
flex: 1;
|
||||
z-index: 1;
|
||||
pointer-events: none;
|
||||
}
|
||||
& .refLine {
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
width: 1px;
|
||||
z-index: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.activeRow {
|
||||
background-color: $teal-light;
|
||||
}
|
||||
|
||||
.inactiveRow {
|
||||
opacity: 0.4;
|
||||
}
|
||||
|
|
@ -71,7 +71,7 @@ type Props = {
|
|||
additionalHeight?: number;
|
||||
hoverable?: boolean;
|
||||
onRowClick?: (row: any, index: number) => void;
|
||||
onJump?: (time: any) => void;
|
||||
onJump?: (time: number) => void;
|
||||
};
|
||||
|
||||
type TimeLineInfo = {
|
||||
|
|
@ -221,7 +221,7 @@ export default class TimeTable extends React.PureComponent<Props, State> {
|
|||
: row[dataKey || ''] || <i className="color-gray-light">{'empty'}</i>}
|
||||
</div>
|
||||
))}
|
||||
<div className={cn('relative flex-1 flex', stl.timeBarWrapper)}>
|
||||
<div className={cn('relative flex-1 flex', stl.timeBarWrapper)} style={{ height: 15 }}>
|
||||
<BarRow resource={row} timestart={timestart} timewidth={timewidth} popup={renderPopup} />
|
||||
</div>
|
||||
<JumpButton onClick={() => this.onJump(index)} />
|
||||
|
|
|
|||
|
|
@ -38,7 +38,6 @@ export default class MessageLoader {
|
|||
private isClickmap: boolean,
|
||||
private uiErrorHandler?: { error: (msg: string) => void }
|
||||
) {}
|
||||
|
||||
setSession(session: SessionFilesInfo) {
|
||||
this.session = session
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue