import React from 'react'; import cn from 'classnames'; // import { connectPlayer } from 'Player'; import { QuestionMarkHint, Popup, Tabs, Input, NoContent, Icon, Button } from 'UI'; import { getRE } from 'App/utils'; import { TYPES } from 'Types/session/resource'; import { formatBytes } from 'App/utils'; import { formatMs } from 'App/date'; import TimeTable from '../TimeTable'; import BottomBlock from '../BottomBlock'; import InfoLine from '../BottomBlock/InfoLine'; import stl from './network.module.css'; import { Duration } from 'luxon'; import { jump } from 'Player'; const ALL = 'ALL'; const XHR = 'xhr'; const JS = 'js'; const CSS = 'css'; const IMG = 'img'; const MEDIA = 'media'; const OTHER = 'other'; const TAB_TO_TYPE_MAP = { [XHR]: TYPES.XHR, [JS]: TYPES.JS, [CSS]: TYPES.CSS, [IMG]: TYPES.IMG, [MEDIA]: TYPES.MEDIA, [OTHER]: TYPES.OTHER, }; const TABS = [ALL, XHR, JS, CSS, IMG, MEDIA, OTHER].map((tab) => ({ text: tab, key: tab, })); const DOM_LOADED_TIME_COLOR = 'teal'; const LOAD_TIME_COLOR = 'red'; export function renderType(r) { return ( {r.type}}>
{r.type}
); } export function renderName(r) { return ( {r.url}} >
{r.name}
); } export function renderStart(r) { return (
{Duration.fromMillis(r.time).toFormat('mm:ss.SSS')}
) } const renderXHRText = () => ( {XHR} Use our{' '} Fetch plugin {' to capture HTTP requests and responses, including status codes and bodies.'}
We also provide{' '} support for GraphQL {' for easy debugging of your queries.'} } className="ml-1" />
); function renderSize(r) { if (r.responseBodySize) return formatBytes(r.responseBodySize); let triggerText; let content; if (r.decodedBodySize == null) { triggerText = 'x'; content = 'Not captured'; } else { const headerSize = r.headerSize || 0; const encodedSize = r.encodedBodySize || 0; const transferred = headerSize + encodedSize; const showTransferred = r.headerSize != null; triggerText = formatBytes(r.decodedBodySize); content = ( ); } return (
{triggerText}
); } export function renderDuration(r) { if (!r.success) return 'x'; const text = `${Math.floor(r.duration)}ms`; if (!r.isRed() && !r.isYellow()) return text; let tooltipText; let className = 'w-full h-full flex items-center '; if (r.isYellow()) { tooltipText = 'Slower than average'; className += 'warn color-orange'; } else { tooltipText = 'Much slower than average'; className += 'error color-red'; } return (
{text}
); } export default class NetworkContent extends React.PureComponent { state = { filter: '', activeTab: ALL, }; onTabClick = (activeTab) => this.setState({ activeTab }); onFilterChange = ({ target: { value } }) => this.setState({ filter: value }); render() { const { location, resources, domContentLoadedTime, loadTime, domBuildingTime, fetchPresented, onRowClick, isResult = false, additionalHeight = 0, resourcesSize, transferredSize, time, currentIndex, } = this.props; const { filter, activeTab } = this.state; const filterRE = getRE(filter, 'i'); let filtered = resources.filter( ({ type, name }) => filterRE.test(name) && (activeTab === ALL || type === TAB_TO_TYPE_MAP[activeTab]) ); const lastIndex = currentIndex || filtered.filter((item) => item.time <= time).length - 1; const referenceLines = []; if (domContentLoadedTime != null) { referenceLines.push({ time: domContentLoadedTime.time, color: DOM_LOADED_TIME_COLOR, }); } if (loadTime != null) { referenceLines.push({ time: loadTime.time, color: LOAD_TIME_COLOR, }); } let tabs = TABS; if (!fetchPresented) { tabs = TABS.map((tab) => !isResult && tab.key === XHR ? { text: renderXHRText(), key: XHR, } : tab ); } return (
Network
0} /> 0} /> No Data } size="small" show={filtered.length === 0} > {[ { label: 'Start', width: 120, render: renderStart, }, { label: 'Status', dataKey: 'status', width: 70, }, { label: 'Type', dataKey: 'type', width: 90, render: renderType, }, { label: 'Name', width: 240, render: renderName, }, { label: 'Size', width: 60, render: renderSize, }, { label: 'Time', width: 80, render: renderDuration, }, ]}
); } }