ui: remove resources cards from dashboard
This commit is contained in:
parent
c53604e216
commit
23c5eaebb7
27 changed files with 6 additions and 763 deletions
|
|
@ -1,54 +0,0 @@
|
|||
import React from 'react';
|
||||
import { NoContent, Icon } from 'UI';
|
||||
import { Styles } from '../../common';
|
||||
import {
|
||||
BarChart, Bar, CartesianGrid, Tooltip,
|
||||
Legend, ResponsiveContainer,
|
||||
XAxis, YAxis
|
||||
} from 'recharts';
|
||||
|
||||
interface Props {
|
||||
data: any
|
||||
metric?: any
|
||||
}
|
||||
function BreakdownOfLoadedResources(props: Props) {
|
||||
const { data, metric } = props;
|
||||
const gradientDef = Styles.gradientDef();
|
||||
|
||||
return (
|
||||
<NoContent
|
||||
size="small"
|
||||
title={
|
||||
<div className="flex items-center">
|
||||
<Icon name="info-circle" className="mr-2" size="14" />
|
||||
No data available for the selected period.
|
||||
</div>
|
||||
}
|
||||
show={ metric.data.chart && metric.data.chart.length === 0 }
|
||||
>
|
||||
<ResponsiveContainer height={ 240 } width="100%">
|
||||
<BarChart
|
||||
data={ metric.data.chart }
|
||||
margin={ Styles.chartMargins }
|
||||
>
|
||||
{gradientDef}
|
||||
<CartesianGrid strokeDasharray="3 3" vertical={ false } stroke="#EEEEEE" />
|
||||
<XAxis {...Styles.xaxis} dataKey="time" interval={metric.params.density/7} />
|
||||
<YAxis
|
||||
{...Styles.yaxis}
|
||||
allowDecimals={false}
|
||||
label={{ ...Styles.axisLabelLeft, value: "Number of Resources" }}
|
||||
tickFormatter={val => Styles.tickFormatter(val)}
|
||||
/>
|
||||
<Legend />
|
||||
<Tooltip {...Styles.tooltip} />
|
||||
<Bar minPointSize={1} name="CSS" dataKey="stylesheet" stackId="a" fill={Styles.compareColors[0]} />
|
||||
<Bar name="Images" dataKey="img" stackId="a" fill={Styles.compareColors[1]} />
|
||||
<Bar name="Scripts" dataKey="script" stackId="a" fill={Styles.compareColors[2]} />
|
||||
</BarChart>
|
||||
</ResponsiveContainer>
|
||||
</NoContent>
|
||||
);
|
||||
}
|
||||
|
||||
export default BreakdownOfLoadedResources;
|
||||
|
|
@ -1 +0,0 @@
|
|||
export { default } from './BreakdownOfLoadedResources'
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
import React from 'react';
|
||||
import { AreaChart, Area } from 'recharts';
|
||||
import { Styles } from '../../common';
|
||||
|
||||
const Chart = ({ data, compare }) => {
|
||||
const colors = compare ? Styles.compareColors : Styles.colors;
|
||||
|
||||
return (
|
||||
<AreaChart width={ 90 } height={ 30 } data={ data.chart } >
|
||||
<Area type="monotone" dataKey="count" stroke={colors[0]} fill={colors[3]} fillOpacity={ 0.5 } />
|
||||
</AreaChart>
|
||||
);
|
||||
}
|
||||
|
||||
Chart.displayName = 'Chart';
|
||||
|
||||
export default Chart;
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
import React from 'react'
|
||||
import copy from 'copy-to-clipboard'
|
||||
import { useState } from 'react'
|
||||
|
||||
const CopyPath = ({ data }) => {
|
||||
const [copied, setCopied] = useState(false)
|
||||
|
||||
const copyHandler = () => {
|
||||
copy(data.url);
|
||||
setCopied(true);
|
||||
setTimeout(function() {
|
||||
setCopied(false)
|
||||
}, 500);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="cursor-pointer color-teal" onClick={copyHandler}>
|
||||
{ copied ? 'Copied' : 'Copy Path'}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default CopyPath
|
||||
|
|
@ -1,75 +0,0 @@
|
|||
import React, { useEffect } from 'react';
|
||||
import { NoContent } from 'UI';
|
||||
import { Table } from '../../common';
|
||||
import { List } from 'immutable';
|
||||
|
||||
import Chart from './Chart';
|
||||
import ResourceInfo from './ResourceInfo';
|
||||
import CopyPath from './CopyPath';
|
||||
|
||||
const cols: Array<Object> = [
|
||||
{
|
||||
key: 'resource',
|
||||
title: 'Resource',
|
||||
Component: ResourceInfo,
|
||||
width: '40%',
|
||||
},
|
||||
{
|
||||
key: 'sessions',
|
||||
title: 'Sessions',
|
||||
toText: (count: number) =>
|
||||
`${count > 1000 ? Math.trunc(count / 1000) : count}${count > 1000 ? 'k' : ''}`,
|
||||
width: '20%',
|
||||
},
|
||||
{
|
||||
key: 'trend',
|
||||
title: 'Trend',
|
||||
Component: Chart,
|
||||
width: '20%',
|
||||
},
|
||||
];
|
||||
|
||||
const copyPathCol = {
|
||||
key: 'copy-path',
|
||||
title: '',
|
||||
Component: CopyPath,
|
||||
cellClass: 'invisible group-hover:visible text-right',
|
||||
width: '20%',
|
||||
};
|
||||
|
||||
interface Props {
|
||||
data: any;
|
||||
metric?: any;
|
||||
isTemplate?: boolean;
|
||||
}
|
||||
function MissingResources(props: Props) {
|
||||
const { data, metric, isTemplate } = props;
|
||||
|
||||
useEffect(() => {
|
||||
const lastCol: any = cols[cols.length - 1];
|
||||
if (!isTemplate && lastCol && lastCol.key !== 'copy-path') {
|
||||
cols.push(copyPathCol);
|
||||
}
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<NoContent
|
||||
title="No resources missing"
|
||||
size="small"
|
||||
show={metric.data.chart.length === 0}
|
||||
style={{ minHeight: 220 }}
|
||||
>
|
||||
<div style={{ height: '240px' }}>
|
||||
<Table
|
||||
small
|
||||
cols={cols}
|
||||
rows={List(metric.data.chart)}
|
||||
rowClass="group"
|
||||
isTemplate={isTemplate}
|
||||
/>
|
||||
</div>
|
||||
</NoContent>
|
||||
);
|
||||
}
|
||||
|
||||
export default MissingResources;
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
import React from 'react';
|
||||
import { diffFromNowString } from 'App/date';
|
||||
import { TextEllipsis } from 'UI';
|
||||
|
||||
import styles from './resourceInfo.module.css';
|
||||
|
||||
export default class ResourceInfo extends React.PureComponent {
|
||||
render() {
|
||||
const { data } = this.props;
|
||||
return (
|
||||
<div className="flex flex-col" >
|
||||
<TextEllipsis className={ styles.name } text={ data.url } hintText={ data.url } />
|
||||
<div className={ styles.timings }>
|
||||
{ data.endedAt && data.startedAt && `${ diffFromNowString(data.endedAt) } ago - ${ diffFromNowString(data.startedAt) } old` }
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
export { default } from './MissingResources'
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
.name {
|
||||
letter-spacing: -.04em;
|
||||
font-size: .9rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.timings {
|
||||
color: $gray-medium;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
|
@ -1,77 +0,0 @@
|
|||
import React from 'react';
|
||||
import { NoContent } from 'UI';
|
||||
import { Styles } from '../../common';
|
||||
import {
|
||||
ComposedChart, Bar, CartesianGrid, Line, Legend, ResponsiveContainer,
|
||||
XAxis, YAxis, Tooltip
|
||||
} from 'recharts';
|
||||
import { NO_METRIC_DATA } from 'App/constants/messages';
|
||||
import { InfoCircleOutlined } from '@ant-design/icons';
|
||||
|
||||
interface Props {
|
||||
data: any
|
||||
metric?: any
|
||||
}
|
||||
function ResourceLoadedVsResponseEnd(props: Props) {
|
||||
const { data, metric } = props;
|
||||
|
||||
return (
|
||||
<NoContent
|
||||
size="small"
|
||||
show={ metric.data.chart.length === 0 }
|
||||
title={
|
||||
<div className='flex items-center gap-2 text-base font-normal'>
|
||||
<InfoCircleOutlined size={12} /> { NO_METRIC_DATA }
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<ResponsiveContainer height={ 246 } width="100%">
|
||||
<ComposedChart
|
||||
data={metric.data.chart}
|
||||
margin={ Styles.chartMargins}
|
||||
>
|
||||
<CartesianGrid strokeDasharray="3 3" vertical={ false } stroke="#EEEEEE" />
|
||||
<XAxis
|
||||
{...Styles.xaxis}
|
||||
dataKey="time"
|
||||
// interval={3}
|
||||
interval={(metric.params.density / 7)}
|
||||
/>
|
||||
<YAxis
|
||||
{...Styles.yaxis}
|
||||
label={{ ...Styles.axisLabelLeft, value: "Number of Resources" }}
|
||||
yAxisId="left"
|
||||
tickFormatter={val => Styles.tickFormatter(val, 'ms')}
|
||||
/>
|
||||
<YAxis
|
||||
{...Styles.yaxis}
|
||||
label={{
|
||||
...Styles.axisLabelLeft,
|
||||
value: "Response End (ms)",
|
||||
position: "insideRight",
|
||||
offset: 0
|
||||
}}
|
||||
yAxisId="right"
|
||||
orientation="right"
|
||||
tickFormatter={val => Styles.tickFormatter(val, 'ms')}
|
||||
/>
|
||||
<Tooltip {...Styles.tooltip} />
|
||||
<Legend />
|
||||
<Bar minPointSize={1} yAxisId="left" name="XHR" dataKey="xhr" stackId="a" fill={Styles.colors[0]} />
|
||||
<Bar yAxisId="left" name="Other" dataKey="total" stackId="a" fill={Styles.colors[2]} />
|
||||
<Line
|
||||
yAxisId="right"
|
||||
strokeWidth={2}
|
||||
name="Response End"
|
||||
type="monotone"
|
||||
dataKey="avgResponseEnd"
|
||||
stroke={Styles.lineColor}
|
||||
dot={false}
|
||||
/>
|
||||
</ComposedChart>
|
||||
</ResponsiveContainer>
|
||||
</NoContent>
|
||||
);
|
||||
}
|
||||
|
||||
export default ResourceLoadedVsResponseEnd;
|
||||
|
|
@ -1 +0,0 @@
|
|||
export { default } from './ResourceLoadedVsResponseEnd'
|
||||
|
|
@ -1,79 +0,0 @@
|
|||
import React from 'react';
|
||||
import { NoContent } from 'UI';
|
||||
import { Styles } from '../../common';
|
||||
import {
|
||||
ComposedChart, Bar, CartesianGrid, Line, Legend, ResponsiveContainer,
|
||||
XAxis, YAxis, Tooltip
|
||||
} from 'recharts';
|
||||
import { NO_METRIC_DATA } from 'App/constants/messages';
|
||||
import { InfoCircleOutlined } from '@ant-design/icons';
|
||||
|
||||
interface Props {
|
||||
data: any
|
||||
metric?: any
|
||||
}
|
||||
function ResourceLoadedVsVisuallyComplete(props: Props) {
|
||||
const { metric } = props;
|
||||
|
||||
return (
|
||||
<NoContent
|
||||
size="small"
|
||||
show={ metric.data.chart.length === 0 }
|
||||
title={
|
||||
<div className='flex items-center gap-2 text-base font-normal'>
|
||||
<InfoCircleOutlined size={12} /> { NO_METRIC_DATA }
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<ResponsiveContainer height={ 240 } width="100%">
|
||||
<ComposedChart
|
||||
data={metric.data.chart}
|
||||
margin={ Styles.chartMargins}
|
||||
>
|
||||
<CartesianGrid strokeDasharray="3 3" vertical={ false } stroke="#EEEEEE" />
|
||||
<XAxis
|
||||
{...Styles.xaxis}
|
||||
dataKey="time"
|
||||
interval={(metric.params.density / 7)}
|
||||
/>
|
||||
<YAxis
|
||||
{...Styles.yaxis}
|
||||
label={{ ...Styles.axisLabelLeft, value: "Visually Complete (ms)" }}
|
||||
yAxisId="left"
|
||||
tickFormatter={val => Styles.tickFormatter(val, 'ms')}
|
||||
/>
|
||||
<YAxis
|
||||
{...Styles.yaxis}
|
||||
label={{
|
||||
...Styles.axisLabelLeft,
|
||||
value: "Number of Resources",
|
||||
position: "insideRight",
|
||||
offset: 0
|
||||
}}
|
||||
yAxisId="right"
|
||||
orientation="right"
|
||||
tickFormatter={val => Styles.tickFormatter(val)}
|
||||
/>
|
||||
<Tooltip {...Styles.tooltip} />
|
||||
<Legend />
|
||||
<Bar minPointSize={1} yAxisId="right" name="Images" type="monotone" dataKey="types.img" stackId="a" fill={Styles.compareColors[0]} />
|
||||
<Bar yAxisId="right" name="Scripts" type="monotone" dataKey="types.script" stackId="a" fill={Styles.compareColors[1]} />
|
||||
<Bar yAxisId="right" name="CSS" type="monotone" dataKey="types.stylesheet" stackId="a" fill={Styles.compareColors[2]} />
|
||||
<Line
|
||||
yAxisId="left"
|
||||
name="Visually Complete"
|
||||
type="monotone"
|
||||
dataKey="avgTimeToRender"
|
||||
stroke={Styles.strokeColor }
|
||||
|
||||
dot={false}
|
||||
unit=" ms"
|
||||
strokeWidth={2}
|
||||
/>
|
||||
</ComposedChart>
|
||||
</ResponsiveContainer>
|
||||
</NoContent>
|
||||
);
|
||||
}
|
||||
|
||||
export default ResourceLoadedVsVisuallyComplete;
|
||||
|
|
@ -1 +0,0 @@
|
|||
export { default } from './ResourceLoadedVsVisuallyComplete'
|
||||
|
|
@ -1,92 +0,0 @@
|
|||
import React from 'react';
|
||||
import { NoContent } from 'UI';
|
||||
import { Styles, AvgLabel } from '../../common';
|
||||
import { withRequest } from 'HOCs'
|
||||
import {
|
||||
AreaChart, Area,
|
||||
CartesianGrid, Tooltip,
|
||||
ResponsiveContainer,
|
||||
XAxis, YAxis
|
||||
} from 'recharts';
|
||||
import { toUnderscore } from 'App/utils';
|
||||
import { NO_METRIC_DATA } from 'App/constants/messages';
|
||||
import { InfoCircleOutlined } from '@ant-design/icons';
|
||||
|
||||
const WIDGET_KEY = 'resourcesLoadingTime';
|
||||
export const RESOURCE_OPTIONS = [
|
||||
{ text: 'All', value: 'all', },
|
||||
{ text: 'JS', value: "SCRIPT", },
|
||||
{ text: 'CSS', value: "STYLESHEET", },
|
||||
{ text: 'Fetch', value: "REQUEST", },
|
||||
{ text: 'Image', value: "IMG", },
|
||||
{ text: 'Media', value: "MEDIA", },
|
||||
{ text: 'Other', value: "OTHER", },
|
||||
];
|
||||
|
||||
interface Props {
|
||||
data: any
|
||||
optionsLoading: any
|
||||
fetchOptions: any
|
||||
options: any
|
||||
metric?: any
|
||||
}
|
||||
function ResourceLoadingTime(props: Props) {
|
||||
const { data, metric } = props;
|
||||
const gradientDef = Styles.gradientDef();
|
||||
|
||||
return (
|
||||
<NoContent
|
||||
size="small"
|
||||
show={ metric.data.chart.length === 0 }
|
||||
title={
|
||||
<div className='flex items-center gap-2 text-base font-normal'>
|
||||
<InfoCircleOutlined size={12} /> { NO_METRIC_DATA }
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<>
|
||||
<div className="flex items-center mb-3">
|
||||
<AvgLabel className="ml-auto" text="Avg" count={Math.round(data.avg)} unit="ms" />
|
||||
</div>
|
||||
<ResponsiveContainer height={ 207 } width="100%">
|
||||
<AreaChart
|
||||
data={ metric.data.chart }
|
||||
margin={ Styles.chartMargins }
|
||||
>
|
||||
{gradientDef}
|
||||
<CartesianGrid strokeDasharray="3 3" vertical={ false } stroke="#EEEEEE" />
|
||||
<XAxis {...Styles.xaxis} dataKey="time" interval={(metric.params.density/7)} />
|
||||
<YAxis
|
||||
{...Styles.yaxis}
|
||||
allowDecimals={false}
|
||||
tickFormatter={val => Styles.tickFormatter(val)}
|
||||
label={{ ...Styles.axisLabelLeft, value: "Resource Fetch Time (ms)" }}
|
||||
/>
|
||||
<Tooltip {...Styles.tooltip} />
|
||||
<Area
|
||||
name="Avg"
|
||||
unit=" ms"
|
||||
type="monotone"
|
||||
dataKey="avg"
|
||||
stroke={Styles.strokeColor}
|
||||
fillOpacity={ 1 }
|
||||
strokeWidth={ 2 }
|
||||
strokeOpacity={ 0.8 }
|
||||
fill={'url(#colorCount)'}
|
||||
/>
|
||||
</AreaChart>
|
||||
</ResponsiveContainer>
|
||||
</>
|
||||
</NoContent>
|
||||
);
|
||||
}
|
||||
|
||||
export default withRequest({
|
||||
dataName: "options",
|
||||
initialData: [],
|
||||
dataWrapper: data => data,
|
||||
loadingName: 'optionsLoading',
|
||||
requestName: "fetchOptions",
|
||||
endpoint: '/dashboard/' + toUnderscore(WIDGET_KEY) + '/search',
|
||||
method: 'GET'
|
||||
})(ResourceLoadingTime)
|
||||
|
|
@ -1 +0,0 @@
|
|||
export { default } from './ResourceLoadingTime'
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
import React from 'react';
|
||||
import { AreaChart, Area } from 'recharts';
|
||||
import { Styles } from '../../common';
|
||||
|
||||
const Chart = ({ data, compare }) => {
|
||||
const colors = compare ? Styles.compareColors : Styles.colors;
|
||||
return (
|
||||
<AreaChart width={ 90 } height={ 30 } data={ data.chart } >
|
||||
<Area type="monotone" dataKey="avg" stroke={colors[0]} fill={ colors[3] } fillOpacity={ 0.5 } />
|
||||
</AreaChart>
|
||||
);
|
||||
}
|
||||
|
||||
Chart.displayName = 'Chart';
|
||||
|
||||
export default Chart;
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
import React from 'react'
|
||||
import copy from 'copy-to-clipboard'
|
||||
import { useState } from 'react'
|
||||
|
||||
const CopyPath = ({ data }) => {
|
||||
const [copied, setCopied] = useState(false)
|
||||
|
||||
const copyHandler = () => {
|
||||
copy(data.url);
|
||||
setCopied(true);
|
||||
setTimeout(function() {
|
||||
setCopied(false)
|
||||
}, 500);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="cursor-pointer color-teal" onClick={copyHandler}>
|
||||
{ copied ? 'Copied' : 'Copy Path'}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default CopyPath
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
import React from 'react';
|
||||
import { Tooltip } from 'UI';
|
||||
import cn from 'classnames';
|
||||
import styles from './imageInfo.module.css';
|
||||
|
||||
const supportedTypes = ['png', 'jpg', 'jpeg', 'svg'];
|
||||
|
||||
const ImageInfo = ({ data }) => {
|
||||
const canPreview = supportedTypes.includes(data.type);
|
||||
return (
|
||||
<div className={styles.name}>
|
||||
<Tooltip
|
||||
className={styles.popup}
|
||||
disabled={!canPreview}
|
||||
title={
|
||||
<img
|
||||
src={`${data.url}`}
|
||||
className={styles.imagePreview}
|
||||
alt="One of the slowest images"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<div className={cn({ [styles.hasPreview]: canPreview })}>
|
||||
<div className={styles.label}>{data.name}</div>
|
||||
</div>
|
||||
</Tooltip>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
ImageInfo.displayName = 'ImageInfo';
|
||||
|
||||
export default ImageInfo;
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
import React from 'react'
|
||||
import cn from 'classnames'
|
||||
|
||||
const ResourceType = ({ data : { type = 'js' }, compare }) => {
|
||||
return (
|
||||
<div className={ cn("rounded-full p-2 color-white h-12 w-12 flex items-center justify-center", { 'bg-teal': compare, 'bg-tealx': !compare})}>
|
||||
<span className="overflow-hidden whitespace-no-wrap text-xs">{ type.toUpperCase() }</span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default ResourceType
|
||||
|
|
@ -1,98 +0,0 @@
|
|||
import React, { useEffect } from 'react';
|
||||
import { NoContent } from 'UI';
|
||||
import { Table } from '../../common';
|
||||
import { List } from 'immutable';
|
||||
import { numberWithCommas } from 'App/utils';
|
||||
|
||||
import Chart from './Chart';
|
||||
import ImageInfo from './ImageInfo';
|
||||
import ResourceType from './ResourceType';
|
||||
import CopyPath from './CopyPath';
|
||||
import { NO_METRIC_DATA } from 'App/constants/messages';
|
||||
import { InfoCircleOutlined } from '@ant-design/icons';
|
||||
|
||||
export const RESOURCE_OPTIONS = [
|
||||
{ text: 'All', value: 'ALL' },
|
||||
{ text: 'CSS', value: 'STYLESHEET' },
|
||||
{ text: 'JS', value: 'SCRIPT' },
|
||||
];
|
||||
|
||||
const cols: Array<Object> = [
|
||||
{
|
||||
key: 'type',
|
||||
title: 'Type',
|
||||
Component: ResourceType,
|
||||
className: 'text-center justify-center',
|
||||
cellClass: 'ml-2',
|
||||
width: '8%',
|
||||
},
|
||||
{
|
||||
key: 'name',
|
||||
title: 'File Name',
|
||||
Component: ImageInfo,
|
||||
cellClass: '-ml-2',
|
||||
width: '40%',
|
||||
},
|
||||
{
|
||||
key: 'avg',
|
||||
title: 'Load Time',
|
||||
toText: (avg) => `${avg ? numberWithCommas(Math.trunc(avg)) : 0} ms`,
|
||||
className: 'justify-center',
|
||||
width: '15%',
|
||||
},
|
||||
{
|
||||
key: 'trend',
|
||||
title: 'Trend',
|
||||
Component: Chart,
|
||||
width: '15%',
|
||||
},
|
||||
];
|
||||
|
||||
const copyPathCol = {
|
||||
key: 'copy-path',
|
||||
title: '',
|
||||
Component: CopyPath,
|
||||
cellClass: 'invisible group-hover:visible text-right',
|
||||
width: '15%',
|
||||
};
|
||||
|
||||
interface Props {
|
||||
data: any;
|
||||
metric?: any;
|
||||
isTemplate?: boolean;
|
||||
}
|
||||
function SlowestResources(props: Props) {
|
||||
const { data, metric, isTemplate } = props;
|
||||
|
||||
useEffect(() => {
|
||||
const lastCol: any = cols[cols.length - 1];
|
||||
if (!isTemplate && lastCol && lastCol.key !== 'copy-path') {
|
||||
cols.push(copyPathCol);
|
||||
}
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<NoContent
|
||||
title={
|
||||
<div className='flex items-center gap-2 text-base font-normal'>
|
||||
<InfoCircleOutlined size={12} /> { NO_METRIC_DATA }
|
||||
</div>
|
||||
}
|
||||
size="small"
|
||||
show={metric.data.chart.length === 0}
|
||||
style={{ minHeight: 220 }}
|
||||
>
|
||||
<div style={{ height: '240px', marginBottom: '10px' }}>
|
||||
<Table
|
||||
small
|
||||
cols={cols}
|
||||
rows={List(metric.data.chart)}
|
||||
rowClass="group"
|
||||
isTemplate={isTemplate}
|
||||
/>
|
||||
</div>
|
||||
</NoContent>
|
||||
);
|
||||
}
|
||||
|
||||
export default SlowestResources;
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
.name {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
& > span {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
max-width: 60%;
|
||||
}
|
||||
|
||||
& .label {
|
||||
max-width: 300px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
.hasPreview {
|
||||
/* text-decoration: underline; */
|
||||
border-bottom: 1px dotted;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.imagePreview {
|
||||
max-width: 200px;
|
||||
max-height: 200px;
|
||||
}
|
||||
|
||||
.imageWrapper {
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
align-items: center;
|
||||
width: 40px;
|
||||
text-align: center;
|
||||
margin-right: 10px;
|
||||
& > span {
|
||||
height: 16px;
|
||||
}
|
||||
& .label {
|
||||
font-size: 9px;
|
||||
color: $gray-light;
|
||||
}
|
||||
}
|
||||
|
||||
.popup {
|
||||
background-color: #f5f5f5 !important;
|
||||
&:before {
|
||||
background-color: #f5f5f5 !important;
|
||||
}
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
export { default } from './SlowestResources'
|
||||
|
|
@ -271,22 +271,6 @@ export const CARD_LIST: CardType[] = [
|
|||
example: BarChartCard
|
||||
},
|
||||
|
||||
{
|
||||
title: 'Resources vs Visually Completed',
|
||||
key: FilterKey.RESOURCES_VS_VISUALLY_COMPLETE,
|
||||
cardType: PERFORMANCE,
|
||||
metricOf: FilterKey.RESOURCES_VS_VISUALLY_COMPLETE,
|
||||
category: CARD_CATEGORIES[1].key,
|
||||
data: {
|
||||
chart: generateStackedBarChartData(['Images', 'Scripts', 'CSS']),
|
||||
label: 'Visually Completed (ms)',
|
||||
namesMap: [
|
||||
'Series 1'
|
||||
]
|
||||
},
|
||||
example: BarChartCard
|
||||
},
|
||||
|
||||
{
|
||||
title: 'Sessions by Browser & Version',
|
||||
key: FilterKey.SESSIONS_PER_BROWSER,
|
||||
|
|
|
|||
|
|
@ -14,16 +14,10 @@ import MemoryConsumption from 'App/components/Dashboard/Widgets/PredefinedWidget
|
|||
import ResponseTime from 'App/components/Dashboard/Widgets/PredefinedWidgets/ResponseTime';
|
||||
import TimeToRender from 'App/components/Dashboard/Widgets/PredefinedWidgets/TimeToRender';
|
||||
import SlowestDomains from 'App/components/Dashboard/Widgets/PredefinedWidgets/SlowestDomains';
|
||||
import ResourceLoadedVsVisuallyComplete from 'App/components/Dashboard/Widgets/PredefinedWidgets/ResourceLoadedVsVisuallyComplete';
|
||||
import SessionsImpactedBySlowRequests from 'App/components/Dashboard/Widgets/PredefinedWidgets/SessionsImpactedBySlowRequests';
|
||||
import ResourceLoadingTime from 'App/components/Dashboard/Widgets/PredefinedWidgets/ResourceLoadingTime';
|
||||
import BreakdownOfLoadedResources from 'App/components/Dashboard/Widgets/PredefinedWidgets/BreakdownOfLoadedResources';
|
||||
import MissingResources from 'App/components/Dashboard/Widgets/PredefinedWidgets/MissingResources';
|
||||
import ResourceLoadedVsResponseEnd from 'App/components/Dashboard/Widgets/PredefinedWidgets/ResourceLoadedVsResponseEnd';
|
||||
import SessionsPerBrowser from 'App/components/Dashboard/Widgets/PredefinedWidgets/SessionsPerBrowser';
|
||||
import CallWithErrors from '../../Widgets/PredefinedWidgets/CallWithErrors';
|
||||
import SpeedIndexByLocation from '../../Widgets/PredefinedWidgets/SpeedIndexByLocation';
|
||||
import SlowestResources from '../../Widgets/PredefinedWidgets/SlowestResources';
|
||||
import ResponseTimeDistribution from '../../Widgets/PredefinedWidgets/ResponseTimeDistribution';
|
||||
import { FilterKey } from 'Types/filter/filterType';
|
||||
|
||||
|
|
@ -73,8 +67,6 @@ function WidgetPredefinedChart(props: Props) {
|
|||
return <MemoryConsumption data={data} metric={metric} />
|
||||
case FilterKey.PAGES_RESPONSE_TIME:
|
||||
return <ResponseTime data={data} metric={metric} />
|
||||
case FilterKey.RESOURCES_VS_VISUALLY_COMPLETE:
|
||||
return <ResourceLoadedVsVisuallyComplete data={data} metric={metric} />
|
||||
case FilterKey.SESSIONS_PER_BROWSER:
|
||||
return <SessionsPerBrowser data={data} />
|
||||
case FilterKey.SLOWEST_DOMAINS:
|
||||
|
|
@ -82,18 +74,6 @@ function WidgetPredefinedChart(props: Props) {
|
|||
case FilterKey.TIME_TO_RENDER:
|
||||
return <TimeToRender data={data} metric={metric} />
|
||||
|
||||
// Resources
|
||||
case FilterKey.BREAKDOWN_OF_LOADED_RESOURCES:
|
||||
return <BreakdownOfLoadedResources data={data} metric={metric} />
|
||||
case FilterKey.MISSING_RESOURCES:
|
||||
return <MissingResources isTemplate={isTemplate} data={data} metric={metric} />
|
||||
case FilterKey.RESOURCE_TYPE_VS_RESPONSE_END:
|
||||
return <ResourceLoadedVsResponseEnd data={data} metric={metric} />
|
||||
case FilterKey.RESOURCES_LOADING_TIME:
|
||||
return <ResourceLoadingTime data={data} metric={metric} />
|
||||
case FilterKey.SLOWEST_RESOURCES:
|
||||
return <SlowestResources isTemplate={isTemplate} data={data} metric={metric} />
|
||||
|
||||
default:
|
||||
return <div className="h-40 color-red">Widget not supported</div>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -148,11 +148,12 @@ function WidgetView(props: Props) {
|
|||
<WidgetPreview name={widget.name} isEditing={expanded} />
|
||||
|
||||
{widget.metricOf !== FilterKey.SESSIONS && widget.metricOf !== FilterKey.ERRORS && (
|
||||
<>
|
||||
{(widget.metricType === TABLE || widget.metricType === TIMESERIES || widget.metricType === HEATMAP || widget.metricType === INSIGHTS) &&
|
||||
<WidgetSessions />}
|
||||
{widget.metricType === FUNNEL && <FunnelIssues />}
|
||||
</>
|
||||
(widget.metricType === TABLE
|
||||
|| widget.metricType === TIMESERIES
|
||||
|| widget.metricType === HEATMAP
|
||||
|| widget.metricType === INSIGHTS
|
||||
|| widget.metricType === FUNNEL) ?
|
||||
<WidgetSessions /> : null
|
||||
)}
|
||||
|
||||
{widget.metricType === USER_PATH && <CardIssues />}
|
||||
|
|
|
|||
|
|
@ -112,11 +112,6 @@ export const TYPES: CardType[] = [
|
|||
slug: FilterKey.PAGES_RESPONSE_TIME_DISTRIBUTION,
|
||||
description: '',
|
||||
},
|
||||
{
|
||||
title: 'Resources vs Visually Complete',
|
||||
slug: FilterKey.RESOURCES_VS_VISUALLY_COMPLETE,
|
||||
description: '',
|
||||
},
|
||||
{ title: 'Sessions per Browser', slug: FilterKey.SESSIONS_PER_BROWSER, description: '' },
|
||||
{ title: 'Slowest Domains', slug: FilterKey.SLOWEST_DOMAINS, description: '' },
|
||||
{ title: 'Speed Index by Location', slug: FilterKey.SPEED_LOCATION, description: '' },
|
||||
|
|
@ -128,27 +123,6 @@ export const TYPES: CardType[] = [
|
|||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Resource Monitoring',
|
||||
icon: 'files',
|
||||
description: 'Identify missing resources and those slowing down your app.',
|
||||
slug: RESOURCE_MONITORING,
|
||||
subTypes: [
|
||||
{
|
||||
title: 'Breakdown of Loaded Resources',
|
||||
slug: FilterKey.BREAKDOWN_OF_LOADED_RESOURCES,
|
||||
description: '',
|
||||
},
|
||||
{ title: 'Missing Resources', slug: FilterKey.MISSING_RESOURCES, description: '' },
|
||||
{
|
||||
title: 'Resource Type vs Response End',
|
||||
slug: FilterKey.RESOURCE_TYPE_VS_RESPONSE_END,
|
||||
description: '',
|
||||
},
|
||||
{ title: 'Resource Fetch Time', slug: FilterKey.RESOURCE_FETCH_TIME, description: '' },
|
||||
{ title: 'Slowest Resources', slug: FilterKey.SLOWEST_RESOURCES, description: '' },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Web Vitals',
|
||||
icon: 'activity',
|
||||
|
|
|
|||
|
|
@ -302,20 +302,12 @@ export enum FilterKey {
|
|||
MEMORY_CONSUMPTION = 'memoryConsumption',
|
||||
PAGES_RESPONSE_TIME = 'pagesResponseTime',
|
||||
PAGES_RESPONSE_TIME_DISTRIBUTION = 'pagesResponseTimeDistribution',
|
||||
RESOURCES_VS_VISUALLY_COMPLETE = 'resourcesVsVisuallyComplete',
|
||||
SESSIONS_PER_BROWSER = 'sessionsPerBrowser',
|
||||
SLOWEST_DOMAINS = 'slowestDomains',
|
||||
SPEED_LOCATION = 'speedLocation',
|
||||
TIME_TO_RENDER = 'timeToRender',
|
||||
IMPACTED_SESSIONS_BY_SLOW_PAGES = 'impactedSessionsBySlowPages',
|
||||
|
||||
// Resources
|
||||
BREAKDOWN_OF_LOADED_RESOURCES = 'resourcesCountByType',
|
||||
MISSING_RESOURCES = 'missingResources',
|
||||
RESOURCE_TYPE_VS_RESPONSE_END = 'resourceTypeVsResponseEnd',
|
||||
RESOURCE_FETCH_TIME = 'resourcesLoadingTime',
|
||||
SLOWEST_RESOURCES = 'slowestResources',
|
||||
|
||||
CLICKMAP_URL = 'clickMapUrl',
|
||||
FEATURE_FLAG = 'featureFlag',
|
||||
TAGGED_ELEMENT = 'tag',
|
||||
|
|
|
|||
|
|
@ -424,8 +424,6 @@ export default class Session {
|
|||
this.notesWithEvents = [...this.notesWithEvents, ...mixedEventsWithIssues].sort(sortEvents);
|
||||
this.errors = exceptions;
|
||||
this.issues = issuesList;
|
||||
// @ts-ignore legacy code? no idea
|
||||
this.resources = resources;
|
||||
this.stackEvents = stackEventsList;
|
||||
// @ts-ignore
|
||||
this.frustrations = frustrationList;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue