diff --git a/frontend/app/components/Dashboard/Widgets/ListWithIcons.tsx b/frontend/app/components/Dashboard/Widgets/ListWithIcons.tsx new file mode 100644 index 000000000..0b69fb4cc --- /dev/null +++ b/frontend/app/components/Dashboard/Widgets/ListWithIcons.tsx @@ -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 ( + ( + 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 + > + +
+ {row.name} + {row.value} +
+ + + + )} + /> +
+ )} + /> + ); +} + +export default ListWithIcons; diff --git a/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/SlowestDomains/SlowestDomains.tsx b/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/SlowestDomains/SlowestDomains.tsx index 661a5842f..7a2afeb9d 100644 --- a/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/SlowestDomains/SlowestDomains.tsx +++ b/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/SlowestDomains/SlowestDomains.tsx @@ -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: , @@ -31,50 +26,7 @@ function SlowestDomains(props: Props) { title={NO_METRIC_DATA} >
- ( - 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 - > - -
- {row.name} - {row.value} -
- - -
- )} - /> - - )} - /> + ); diff --git a/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/SpeedIndexByLocation/Scale.js b/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/SpeedIndexByLocation/Scale.js index 6b944518c..707f21eb9 100644 --- a/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/SpeedIndexByLocation/Scale.js +++ b/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/SpeedIndexByLocation/Scale.js @@ -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 ( -
- {Styles.colorsTeal.map((c, i) => ( +
+ {Styles.compareColors.map((c, i) => (
- { i === 0 &&
Slow
} - { i === lastIndex &&
Fast
} + {i === 0 &&
Slow
} + {i === lastIndex &&
Fast
}
))}
- ) + ); } -export default Scale +export default Scale; diff --git a/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/SpeedIndexByLocation/SpeedIndexByLocation.module.css b/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/SpeedIndexByLocation/SpeedIndexByLocation.module.css index a42f4af12..ec2c46f02 100644 --- a/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/SpeedIndexByLocation/SpeedIndexByLocation.module.css +++ b/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/SpeedIndexByLocation/SpeedIndexByLocation.module.css @@ -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; -} \ No newline at end of file +} diff --git a/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/SpeedIndexByLocation/SpeedIndexByLocation.tsx b/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/SpeedIndexByLocation/SpeedIndexByLocation.tsx index ca049a677..ef9565b2b 100644 --- a/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/SpeedIndexByLocation/SpeedIndexByLocation.tsx +++ b/frontend/app/components/Dashboard/Widgets/PredefinedWidgets/SpeedIndexByLocation/SpeedIndexByLocation.tsx @@ -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(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(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 ( - -
- + return ( + +
+ +
+ +
+
+ +
+
+ {pointedLocation && ( + <> +
{pointedLocation.name}
+
+ Avg: {dataMap[pointedLocation.id] ? numberWithCommas(parseInt(dataMap[pointedLocation.id].value)) : 0}
- -
-
- -
-
- {pointedLocation && ( - <> -
{pointedLocation.name}
-
- Avg: {dataMap[pointedLocation.id] ? numberWithCommas(parseInt(dataMap[pointedLocation.id].value)) : 0} -
- - )} -
- - ); + + )} +
+
+ ); } export default observer(SpeedIndexByLocation); diff --git a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/ExampleCards.tsx b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/ExampleCards.tsx index 499a560c7..d46d4d79b 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/ExampleCards.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/ExampleCards.tsx @@ -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, }, { diff --git a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/AreaChartCard.tsx b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/AreaChartCard.tsx index d50fcab52..871c4519d 100644 --- a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/AreaChartCard.tsx +++ b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/AreaChartCard.tsx @@ -46,7 +46,7 @@ function AreaChartCard(props: Props) { {/*
*/} {/* */} {/*
*/} - + 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 ( - -
- null}/> - - {/*{rows.map((r) => (*/} - {/* */} - {/*
{r.icon}
*/} - {/*
{r.label}
*/} - {/* */} - {/* */} - {/* */} - {/*
*/} - {/*
{r.value}
*/} - {/*
*/} - {/*))}*/} -
- - ) + const _rows = rows.map((r) => ({ + ...r, + name: r.label, + sessionCount: r.value + })).slice(0, 4); + return ( + +
+ null} /> +
+
+ ); } -export default ByComponent +export default ByComponent; diff --git a/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/SpeedIndexByLocationExample.tsx b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/SpeedIndexByLocationExample.tsx new file mode 100644 index 000000000..98a88eef7 --- /dev/null +++ b/frontend/app/components/Dashboard/components/DashboardList/NewDashModal/Examples/SpeedIndexByLocationExample.tsx @@ -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 ( + + + + ); +} + +export default SpeedIndexByLocationExample; diff --git a/frontend/app/components/Dashboard/components/WidgetPredefinedChart/WidgetPredefinedChart.tsx b/frontend/app/components/Dashboard/components/WidgetPredefinedChart/WidgetPredefinedChart.tsx index dc019b8f8..174bc93f1 100644 --- a/frontend/app/components/Dashboard/components/WidgetPredefinedChart/WidgetPredefinedChart.tsx +++ b/frontend/app/components/Dashboard/components/WidgetPredefinedChart/WidgetPredefinedChart.tsx @@ -60,7 +60,7 @@ function WidgetPredefinedChart(props: Props) { case FilterKey.PAGES_RESPONSE_TIME_DISTRIBUTION: return case FilterKey.SPEED_LOCATION: - return + return case FilterKey.CPU: return case FilterKey.CRASHES: