change(ui): speed index example, slowest domains example and card type change
This commit is contained in:
parent
f35456b3f8
commit
b3ee59c6e3
10 changed files with 307 additions and 219 deletions
65
frontend/app/components/Dashboard/Widgets/ListWithIcons.tsx
Normal file
65
frontend/app/components/Dashboard/Widgets/ListWithIcons.tsx
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
import React from 'react';
|
||||
import { List, Progress, Typography } from 'antd';
|
||||
import cn from 'classnames';
|
||||
|
||||
interface ListItem {
|
||||
icon?: any;
|
||||
title: string;
|
||||
progress: number;
|
||||
value?: number;
|
||||
}
|
||||
|
||||
interface Props {
|
||||
list: ListItem[];
|
||||
}
|
||||
|
||||
function ListWithIcons({ list = [] }: Props) {
|
||||
return (
|
||||
<List
|
||||
dataSource={list}
|
||||
split={false}
|
||||
renderItem={(row: any) => (
|
||||
<List.Item
|
||||
key={row.domain}
|
||||
// onClick={(e) => onClickHandler(e, row)} // Remove onClick handler to disable click interaction
|
||||
style={{
|
||||
borderBottom: '1px dotted rgba(0, 0, 0, 0.05)',
|
||||
padding: '4px 10px',
|
||||
lineHeight: '1px'
|
||||
}}
|
||||
className={cn('rounded')} // Remove hover:bg-active-blue and cursor-pointer
|
||||
>
|
||||
<List.Item.Meta
|
||||
className="m-0"
|
||||
avatar={row.icon ? row.icon : null}
|
||||
title={(
|
||||
<div className="m-0">
|
||||
<div className="flex justify-between m-0 p-0">
|
||||
<Typography.Text>{row.name}</Typography.Text>
|
||||
<Typography.Text type="secondary"> {row.value}</Typography.Text>
|
||||
</div>
|
||||
|
||||
<Progress
|
||||
percent={row.progress}
|
||||
showInfo={false}
|
||||
strokeColor={{
|
||||
'0%': '#394EFF',
|
||||
'100%': '#394EFF'
|
||||
}}
|
||||
size={['small', 2]}
|
||||
style={{
|
||||
padding: '0 0px',
|
||||
margin: '0 0px',
|
||||
height: 4
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
</List.Item>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export default ListWithIcons;
|
||||
|
|
@ -1,12 +1,7 @@
|
|||
import React from 'react';
|
||||
import { Icon, NoContent } from 'UI';
|
||||
import { Styles } from '../../common';
|
||||
import { numberWithCommas } from 'App/utils';
|
||||
import Bar from './Bar';
|
||||
import { NO_METRIC_DATA } from 'App/constants/messages';
|
||||
import CardSessionsByList from 'Components/Dashboard/Widgets/CardSessionsByList';
|
||||
import { List, Progress, Typography } from 'antd';
|
||||
import cn from 'classnames';
|
||||
import ListWithIcons from 'Components/Dashboard/Widgets/ListWithIcons';
|
||||
|
||||
interface Props {
|
||||
data: any;
|
||||
|
|
@ -15,7 +10,7 @@ interface Props {
|
|||
function SlowestDomains(props: Props) {
|
||||
const { data } = props;
|
||||
// TODO - move this to the store
|
||||
const highest = data.chart[0].value;
|
||||
const highest = data.chart[0]?.value;
|
||||
const list = data.chart.slice(0, 4).map((item: any) => ({
|
||||
name: item.domain,
|
||||
icon: <Icon name="link-45deg" size={24} />,
|
||||
|
|
@ -31,50 +26,7 @@ function SlowestDomains(props: Props) {
|
|||
title={NO_METRIC_DATA}
|
||||
>
|
||||
<div className="w-full" style={{ height: '240px' }}>
|
||||
<List
|
||||
dataSource={list}
|
||||
split={false}
|
||||
renderItem={(row: any) => (
|
||||
<List.Item
|
||||
key={row.domain}
|
||||
// onClick={(e) => onClickHandler(e, row)} // Remove onClick handler to disable click interaction
|
||||
style={{
|
||||
borderBottom: '1px dotted rgba(0, 0, 0, 0.05)',
|
||||
padding: '4px 10px',
|
||||
lineHeight: '1px'
|
||||
}}
|
||||
className={cn('rounded')} // Remove hover:bg-active-blue and cursor-pointer
|
||||
>
|
||||
<List.Item.Meta
|
||||
className="m-0"
|
||||
avatar={row.icon ? row.icon : null}
|
||||
title={(
|
||||
<div className="m-0">
|
||||
<div className="flex justify-between m-0 p-0">
|
||||
<Typography.Text>{row.name}</Typography.Text>
|
||||
<Typography.Text type="secondary"> {row.value}</Typography.Text>
|
||||
</div>
|
||||
|
||||
<Progress
|
||||
percent={row.progress}
|
||||
showInfo={false}
|
||||
strokeColor={{
|
||||
'0%': '#394EFF',
|
||||
'100%': '#394EFF'
|
||||
}}
|
||||
size={['small', 2]}
|
||||
style={{
|
||||
padding: '0 0px',
|
||||
margin: '0 0px',
|
||||
height: 4
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
</List.Item>
|
||||
)}
|
||||
/>
|
||||
<ListWithIcons list={list} />
|
||||
</div>
|
||||
</NoContent>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,25 +1,25 @@
|
|||
import React from 'react'
|
||||
import React from 'react';
|
||||
import { Styles } from '../../common';
|
||||
import cn from 'classnames';
|
||||
import stl from './scale.module.css';
|
||||
|
||||
function Scale({ colors }) {
|
||||
const lastIndex = (Styles.colorsTeal.length - 1)
|
||||
|
||||
const lastIndex = (Styles.compareColors.length - 1);
|
||||
|
||||
return (
|
||||
<div className={ cn(stl.bars, 'absolute bottom-0 mb-4')}>
|
||||
{Styles.colorsTeal.map((c, i) => (
|
||||
<div className={cn(stl.bars, 'absolute bottom-0 mb-4')}>
|
||||
{Styles.compareColors.map((c, i) => (
|
||||
<div
|
||||
key={i}
|
||||
style={{ backgroundColor: c, width: '6px', height: '15px', marginBottom: '1px' }}
|
||||
className="flex items-center justify-center"
|
||||
>
|
||||
{ i === 0 && <div className="text-xs pl-12">Slow</div>}
|
||||
{ i === lastIndex && <div className="text-xs pl-12">Fast</div>}
|
||||
{i === 0 && <div className="text-xs pl-12">Slow</div>}
|
||||
{i === lastIndex && <div className="text-xs pl-12">Fast</div>}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
export default Scale
|
||||
export default Scale;
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
&:focus,
|
||||
&:hover {
|
||||
fill: $teal !important;
|
||||
fill: #2E3ECC !important;
|
||||
outline: 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -25,23 +25,23 @@
|
|||
}
|
||||
|
||||
.heat_index5 {
|
||||
fill: #3EAAAF !important;
|
||||
fill: #B0B8FF !important;
|
||||
}
|
||||
|
||||
.heat_index4 {
|
||||
fill:#5FBABF !important;
|
||||
fill:#6171FF !important;
|
||||
}
|
||||
|
||||
.heat_index3 {
|
||||
fill: #7BCBCF !important;
|
||||
fill: #394EFF !important;
|
||||
}
|
||||
|
||||
.heat_index2 {
|
||||
fill: #96DCDF !important;
|
||||
fill: #2E3ECC !important;
|
||||
}
|
||||
|
||||
.heat_index1 {
|
||||
fill: #ADDCDF !important;
|
||||
fill: #222F99 !important;
|
||||
}
|
||||
|
||||
.tooltip {
|
||||
|
|
@ -52,4 +52,4 @@
|
|||
background-color: white;
|
||||
font-size: 12px;
|
||||
line-height: 1.2;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,99 +8,105 @@ import WorldMap from '@svg-maps/world';
|
|||
import { SVGMap } from 'react-svg-map';
|
||||
import stl from './SpeedIndexByLocation.module.css';
|
||||
import cn from 'classnames';
|
||||
import { NO_METRIC_DATA } from 'App/constants/messages'
|
||||
import { NO_METRIC_DATA } from 'App/constants/messages';
|
||||
|
||||
interface Props {
|
||||
metric?: any;
|
||||
data?: any;
|
||||
}
|
||||
|
||||
function SpeedIndexByLocation(props: Props) {
|
||||
const { metric } = props;
|
||||
const wrapper: any = React.useRef(null);
|
||||
let map: any = null;
|
||||
const [tooltipStyle, setTooltipStyle] = React.useState({ display: 'none' });
|
||||
const [pointedLocation, setPointedLocation] = React.useState<any>(null);
|
||||
const dataMap: any = React.useMemo(() => {
|
||||
const data: any = {};
|
||||
const max = metric.data.chart.reduce((acc: any, item: any) => Math.max(acc, item.value), 0);
|
||||
const min = metric.data.chart.reduce((acc: any, item: any) => Math.min(acc, item.value), 0);
|
||||
metric.data.chart.forEach((item: any) => {
|
||||
if (!item || !item.userCountry) { return }
|
||||
item.perNumber = positionOfTheNumber(min, max, item.value, 5);
|
||||
data[item.userCountry.toLowerCase()] = item;
|
||||
});
|
||||
return data;
|
||||
}, []);
|
||||
const { data } = props;
|
||||
console.log('data', data);
|
||||
const wrapper: any = React.useRef(null);
|
||||
let map: any = null;
|
||||
const [tooltipStyle, setTooltipStyle] = React.useState({ display: 'none' });
|
||||
const [pointedLocation, setPointedLocation] = React.useState<any>(null);
|
||||
|
||||
const getLocationClassName = (location: any) => {
|
||||
const i = dataMap[location.id] ? dataMap[location.id].perNumber : 0;
|
||||
const cls = stl['heat_index' + i];
|
||||
return cn(stl.location, cls);
|
||||
const dataMap: any = React.useMemo(() => {
|
||||
const _data: any = {};
|
||||
const max = data.chart?.reduce((acc: any, item: any) => Math.max(acc, item.value), 0);
|
||||
const min = data.chart?.reduce((acc: any, item: any) => Math.min(acc, item.value), 0);
|
||||
data.chart?.forEach((item: any) => {
|
||||
console.log('item', item);
|
||||
if (!item || !item.userCountry) {
|
||||
return;
|
||||
}
|
||||
item.perNumber = positionOfTheNumber(min, max, item.value, 5);
|
||||
_data[item.userCountry.toLowerCase()] = item;
|
||||
});
|
||||
return _data;
|
||||
}, [data.chart]);
|
||||
|
||||
const getLocationClassName = (location: any) => {
|
||||
const i = dataMap[location.id] ? dataMap[location.id].perNumber : 0;
|
||||
const cls = stl['heat_index' + i];
|
||||
return cn(stl.location, cls);
|
||||
};
|
||||
|
||||
const getLocationName = (event: any) => {
|
||||
if (!event) return null;
|
||||
const id = event.target.attributes.id.value;
|
||||
const name = event.target.attributes.name.value;
|
||||
const percentage = dataMap[id] ? dataMap[id].perNumber : 0;
|
||||
return { name, id, percentage };
|
||||
};
|
||||
|
||||
const handleLocationMouseOver = (event: any) => {
|
||||
const pointedLocation = getLocationName(event);
|
||||
setPointedLocation(pointedLocation);
|
||||
};
|
||||
|
||||
const handleLocationMouseOut = () => {
|
||||
setTooltipStyle({ display: 'none' });
|
||||
setPointedLocation(null);
|
||||
};
|
||||
|
||||
const handleLocationMouseMove = (event: any) => {
|
||||
const tooltipStyle = {
|
||||
display: 'block',
|
||||
top: event.clientY + 10,
|
||||
left: event.clientX - 100
|
||||
};
|
||||
setTooltipStyle(tooltipStyle);
|
||||
};
|
||||
|
||||
const getLocationName = (event: any) => {
|
||||
if (!event) return null;
|
||||
const id = event.target.attributes.id.value;
|
||||
const name = event.target.attributes.name.value;
|
||||
const percentage = dataMap[id] ? dataMap[id].perNumber : 0;
|
||||
return { name, id, percentage };
|
||||
};
|
||||
|
||||
const handleLocationMouseOver = (event: any) => {
|
||||
const pointedLocation = getLocationName(event);
|
||||
setPointedLocation(pointedLocation);
|
||||
};
|
||||
|
||||
const handleLocationMouseOut = () => {
|
||||
setTooltipStyle({ display: 'none' });
|
||||
setPointedLocation(null);
|
||||
};
|
||||
|
||||
const handleLocationMouseMove = (event: any) => {
|
||||
const tooltipStyle = {
|
||||
display: 'block',
|
||||
top: event.clientY + 10,
|
||||
left: event.clientX - 100,
|
||||
};
|
||||
setTooltipStyle(tooltipStyle);
|
||||
};
|
||||
|
||||
return (
|
||||
<NoContent size="small" show={false} style={{ height: '240px' }} title={NO_METRIC_DATA}>
|
||||
<div className="absolute right-0 mr-4 top=0 w-full flex justify-end">
|
||||
<AvgLabel text="Avg" count={Math.round(metric.data.value)} unit="ms" />
|
||||
return (
|
||||
<NoContent size="small" show={false} style={{ height: '240px' }} title={NO_METRIC_DATA}>
|
||||
<div className="absolute right-0 mr-4 top=0 w-full flex justify-end">
|
||||
<AvgLabel text="Avg" count={Math.round(data.value)} unit="ms" />
|
||||
</div>
|
||||
<Scale colors={Styles.compareColors} />
|
||||
<div className="map-target"></div>
|
||||
<div
|
||||
style={{
|
||||
height: '234px',
|
||||
width: '100%',
|
||||
margin: '0 auto',
|
||||
display: 'flex'
|
||||
}}
|
||||
ref={wrapper}
|
||||
>
|
||||
<SVGMap
|
||||
map={WorldMap}
|
||||
className={stl.maps}
|
||||
locationClassName={getLocationClassName}
|
||||
onLocationMouseOver={handleLocationMouseOver}
|
||||
onLocationMouseOut={handleLocationMouseOut}
|
||||
onLocationMouseMove={handleLocationMouseMove}
|
||||
/>
|
||||
</div>
|
||||
<div className={stl.tooltip} style={tooltipStyle}>
|
||||
{pointedLocation && (
|
||||
<>
|
||||
<div>{pointedLocation.name}</div>
|
||||
<div>
|
||||
Avg: <strong>{dataMap[pointedLocation.id] ? numberWithCommas(parseInt(dataMap[pointedLocation.id].value)) : 0}</strong>
|
||||
</div>
|
||||
<Scale colors={Styles.colors} />
|
||||
<div className="map-target"></div>
|
||||
<div
|
||||
style={{
|
||||
height: '234px',
|
||||
width: '100%',
|
||||
margin: '0 auto',
|
||||
display: 'flex',
|
||||
}}
|
||||
ref={wrapper}
|
||||
>
|
||||
<SVGMap
|
||||
map={WorldMap}
|
||||
className={stl.maps}
|
||||
locationClassName={getLocationClassName}
|
||||
onLocationMouseOver={handleLocationMouseOver}
|
||||
onLocationMouseOut={handleLocationMouseOut}
|
||||
onLocationMouseMove={handleLocationMouseMove}
|
||||
/>
|
||||
</div>
|
||||
<div className={stl.tooltip} style={tooltipStyle}>
|
||||
{pointedLocation && (
|
||||
<>
|
||||
<div>{pointedLocation.name}</div>
|
||||
<div>
|
||||
Avg: <strong>{dataMap[pointedLocation.id] ? numberWithCommas(parseInt(dataMap[pointedLocation.id].value)) : 0}</strong>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</NoContent>
|
||||
);
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</NoContent>
|
||||
);
|
||||
}
|
||||
|
||||
export default observer(SpeedIndexByLocation);
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@ import SessionsPerBrowserExample
|
|||
from 'Components/Dashboard/components/DashboardList/NewDashModal/Examples/SessionsPerBrowserExample';
|
||||
import SlowestDomains
|
||||
from 'Components/Dashboard/components/DashboardList/NewDashModal/Examples/SessionsBy/SlowestDomains';
|
||||
import SpeedIndexByLocationExample
|
||||
from 'Components/Dashboard/components/DashboardList/NewDashModal/Examples/SpeedIndexByLocationExample';
|
||||
|
||||
export const CARD_CATEGORY = {
|
||||
PRODUCT_ANALYTICS: 'product-analytics',
|
||||
|
|
@ -234,7 +236,8 @@ export const CARD_LIST: CardType[] = [
|
|||
category: CARD_CATEGORIES[1].key,
|
||||
data: {
|
||||
chart: generateAreaData(),
|
||||
label: "Number of Calls",
|
||||
label: "Page Response Time (ms)",
|
||||
unit: 'ms',
|
||||
namesMap: [
|
||||
"Series 1"
|
||||
]
|
||||
|
|
@ -289,7 +292,7 @@ export const CARD_LIST: CardType[] = [
|
|||
"Series 1"
|
||||
]
|
||||
},
|
||||
example: AreaChartCard,
|
||||
example: SpeedIndexByLocationExample,
|
||||
},
|
||||
|
||||
{
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ function AreaChartCard(props: Props) {
|
|||
{/*<div className="flex items-center justify-end mb-3">*/}
|
||||
{/* <AvgLabel text="Avg" className="ml-3" count={data?.value}/>*/}
|
||||
{/*</div>*/}
|
||||
<ResponsiveContainer height={207} width="100%">
|
||||
<ResponsiveContainer width="100%">
|
||||
<AreaChart
|
||||
data={data?.chart}
|
||||
margin={Styles.chartMargins}
|
||||
|
|
|
|||
|
|
@ -1,67 +1,35 @@
|
|||
import ExCard from '../ExCard'
|
||||
import React from 'react'
|
||||
import CardSessionsByList from "Components/Dashboard/Widgets/CardSessionsByList";
|
||||
import ExCard from '../ExCard';
|
||||
import React from 'react';
|
||||
import CardSessionsByList from 'Components/Dashboard/Widgets/CardSessionsByList';
|
||||
|
||||
function ByComponent({title, rows, lineWidth, onCard, type}: {
|
||||
title: string
|
||||
rows: {
|
||||
label: string
|
||||
progress: number
|
||||
value: string
|
||||
icon: React.ReactNode
|
||||
}[]
|
||||
onCard: (card: string) => void
|
||||
type: string
|
||||
lineWidth: number
|
||||
function ByComponent({ title, rows, lineWidth, onCard, type }: {
|
||||
title: string
|
||||
rows: {
|
||||
label: string
|
||||
progress: number
|
||||
value: string
|
||||
icon: React.ReactNode
|
||||
}[]
|
||||
onCard: (card: string) => void
|
||||
type: string
|
||||
lineWidth: number
|
||||
}) {
|
||||
const _rows = rows.map((r) => ({
|
||||
...r,
|
||||
name: r.label,
|
||||
sessionCount: r.value,
|
||||
})).slice(0, 4)
|
||||
return (
|
||||
<ExCard
|
||||
title={title}
|
||||
onCard={onCard}
|
||||
type={type}
|
||||
>
|
||||
<div className={'flex gap-1 flex-col'}>
|
||||
<CardSessionsByList list={_rows} selected={''} onClickHandler={() => null}/>
|
||||
|
||||
{/*{rows.map((r) => (*/}
|
||||
{/* <div*/}
|
||||
{/* className={*/}
|
||||
{/* 'flex items-center gap-2 border-b border-dotted py-2 last:border-0 first:pt-0 last:pb-0'*/}
|
||||
{/* }*/}
|
||||
{/* >*/}
|
||||
{/* <div>{r.icon}</div>*/}
|
||||
{/* <div>{r.label}</div>*/}
|
||||
{/* <div*/}
|
||||
{/* style={{marginLeft: 'auto', marginRight: 20, display: 'flex'}}*/}
|
||||
{/* >*/}
|
||||
{/* <div*/}
|
||||
{/* style={{*/}
|
||||
{/* height: 2,*/}
|
||||
{/* width: lineWidth * (0.01 * r.progress),*/}
|
||||
{/* background: '#394EFF',*/}
|
||||
{/* }}*/}
|
||||
{/* className={'rounded-l'}*/}
|
||||
{/* />*/}
|
||||
{/* <div*/}
|
||||
{/* style={{*/}
|
||||
{/* height: 2,*/}
|
||||
{/* width: lineWidth - lineWidth * (0.01 * r.progress),*/}
|
||||
{/* background: '#E2E4F6',*/}
|
||||
{/* }}*/}
|
||||
{/* className={'rounded-r'}*/}
|
||||
{/* />*/}
|
||||
{/* </div>*/}
|
||||
{/* <div className={'min-w-8'}>{r.value}</div>*/}
|
||||
{/* </div>*/}
|
||||
{/*))}*/}
|
||||
</div>
|
||||
</ExCard>
|
||||
)
|
||||
const _rows = rows.map((r) => ({
|
||||
...r,
|
||||
name: r.label,
|
||||
sessionCount: r.value
|
||||
})).slice(0, 4);
|
||||
return (
|
||||
<ExCard
|
||||
title={title}
|
||||
onCard={onCard}
|
||||
type={type}
|
||||
>
|
||||
<div className={'flex gap-1 flex-col'}>
|
||||
<CardSessionsByList list={_rows} selected={''} onClickHandler={() => null} />
|
||||
</div>
|
||||
</ExCard>
|
||||
);
|
||||
}
|
||||
|
||||
export default ByComponent
|
||||
export default ByComponent;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,94 @@
|
|||
import React from 'react';
|
||||
import ExCard from 'Components/Dashboard/components/DashboardList/NewDashModal/Examples/ExCard';
|
||||
import InsightsCard from 'Components/Dashboard/Widgets/CustomMetricsWidgets/InsightsCard';
|
||||
import { InsightIssue } from 'App/mstore/types/widget';
|
||||
import SessionsPerBrowser from 'Components/Dashboard/Widgets/PredefinedWidgets/SessionsPerBrowser';
|
||||
import SpeedIndexByLocation from 'Components/Dashboard/Widgets/PredefinedWidgets/SpeedIndexByLocation';
|
||||
|
||||
interface Props {
|
||||
title: string;
|
||||
type: string;
|
||||
onCard: (card: string) => void;
|
||||
}
|
||||
|
||||
function SpeedIndexByLocationExample(props: Props) {
|
||||
const data = {
|
||||
'value': 1480,
|
||||
'chart': [
|
||||
{
|
||||
'userCountry': 'AT',
|
||||
'value': 415
|
||||
},
|
||||
{
|
||||
'userCountry': 'PL',
|
||||
'value': 433.1666666666667
|
||||
},
|
||||
{
|
||||
'userCountry': 'FR',
|
||||
'value': 502
|
||||
},
|
||||
{
|
||||
'userCountry': 'IT',
|
||||
'value': 540.4117647058823
|
||||
},
|
||||
{
|
||||
'userCountry': 'TH',
|
||||
'value': 662.0
|
||||
},
|
||||
{
|
||||
'userCountry': 'ES',
|
||||
'value': 740.5454545454545
|
||||
},
|
||||
{
|
||||
'userCountry': 'SG',
|
||||
'value': 889.6666666666666
|
||||
},
|
||||
{
|
||||
'userCountry': 'TW',
|
||||
'value': 1008.0
|
||||
},
|
||||
{
|
||||
'userCountry': 'HU',
|
||||
'value': 1027.0
|
||||
},
|
||||
{
|
||||
'userCountry': 'DE',
|
||||
'value': 1054.4583333333333
|
||||
},
|
||||
{
|
||||
'userCountry': 'BE',
|
||||
'value': 1126.0
|
||||
},
|
||||
{
|
||||
'userCountry': 'TR',
|
||||
'value': 1174.0
|
||||
},
|
||||
{
|
||||
'userCountry': 'US',
|
||||
'value': 1273.3015873015872
|
||||
},
|
||||
{
|
||||
'userCountry': 'GB',
|
||||
'value': 1353.8095238095239
|
||||
},
|
||||
{
|
||||
'userCountry': 'VN',
|
||||
'value': 1473.8181818181818
|
||||
},
|
||||
{
|
||||
'userCountry': 'HK',
|
||||
'value': 1654.6666666666667
|
||||
},
|
||||
],
|
||||
'unit': 'ms'
|
||||
};
|
||||
return (
|
||||
<ExCard
|
||||
{...props}
|
||||
>
|
||||
<SpeedIndexByLocation data={data} />
|
||||
</ExCard>
|
||||
);
|
||||
}
|
||||
|
||||
export default SpeedIndexByLocationExample;
|
||||
|
|
@ -60,7 +60,7 @@ function WidgetPredefinedChart(props: Props) {
|
|||
case FilterKey.PAGES_RESPONSE_TIME_DISTRIBUTION:
|
||||
return <ResponseTimeDistribution data={data} metric={metric} />
|
||||
case FilterKey.SPEED_LOCATION:
|
||||
return <SpeedIndexByLocation metric={metric} />
|
||||
return <SpeedIndexByLocation data={data} />
|
||||
case FilterKey.CPU:
|
||||
return <CPULoad data={data} metric={metric} />
|
||||
case FilterKey.CRASHES:
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue