diff --git a/packages/core/web-reporter-ui/index.tsx b/packages/core/web-reporter-ui/index.tsx index a8044410..d8398847 100644 --- a/packages/core/web-reporter-ui/index.tsx +++ b/packages/core/web-reporter-ui/index.tsx @@ -5,3 +5,4 @@ export { Button } from "./src/components/Button"; export { getThemeColorPalette, setThemeAtRandom } from "./src/theme/colors"; export { Chart } from "./src/components/Charts/Chart"; export { ChartRangeArea } from "./src/components/Charts/ChartRangeArea"; +export { ApexOptions } from "apexcharts"; diff --git a/packages/core/web-reporter-ui/src/components/Charts/Chart.tsx b/packages/core/web-reporter-ui/src/components/Charts/Chart.tsx index 1e54be4e..ef403092 100644 --- a/packages/core/web-reporter-ui/src/components/Charts/Chart.tsx +++ b/packages/core/web-reporter-ui/src/components/Charts/Chart.tsx @@ -1,59 +1,39 @@ -import React, { useMemo, useContext } from "react"; -import ReactApexChart from "react-apexcharts"; -import { VideoEnabledContext } from "../../../videoCurrentTimeContext"; +import React, { useMemo } from "react"; +import ReactApexChart, { Props as ApexChartProps } from "react-apexcharts"; import { ApexOptions } from "apexcharts"; -import { getColorPalette } from "../../theme/colors"; import { POLLING_INTERVAL } from "@perf-profiler/types"; -import { getLastX, useSetVideoTimeOnMouseHover } from "./useSetVideoTimeOnMouseHover"; -import { AnnotationInterval, LineSeriesType } from "./types"; -import { getAnnotations } from "./getAnnotations"; +import { merge } from "lodash"; export const Chart = ({ + type, title, series, + options = {}, height, - interval = POLLING_INTERVAL, - timeLimit, - maxValue, - showLegendForSingleSeries, - colors = getColorPalette(), - annotationIntervalList = undefined, + colors, }: { + type: Exclude; title: string; - series: LineSeriesType; + series: ApexAxisChartSeries; + options?: ApexOptions; height: number; - interval?: number; - timeLimit?: number | null; - maxValue?: number; - showLegendForSingleSeries?: boolean; colors?: string[]; - annotationIntervalList?: AnnotationInterval[]; }) => { - const setVideoCurrentTimeOnMouseHover = useSetVideoTimeOnMouseHover({ - lastX: getLastX(series), - }); - - const videoEnabled = useContext(VideoEnabledContext); - - const options: ApexOptions = useMemo( + const commonOptions: ApexOptions = useMemo( () => ({ chart: { id: title, - height: 350, - type: "line", animations: { enabled: true, easing: "linear", dynamicAnimation: { - speed: interval, + speed: POLLING_INTERVAL, }, }, - events: videoEnabled ? setVideoCurrentTimeOnMouseHover : {}, zoom: { enabled: false, }, }, - annotations: getAnnotations(annotationIntervalList) || {}, title: { text: title, align: "left", @@ -69,22 +49,17 @@ export const Chart = ({ }, stroke: { curve: "smooth", - width: 2, }, xaxis: { - type: "numeric", - min: 0, - max: timeLimit || undefined, - labels: { style: { colors: "#FFFFFF99" } }, + labels: { + style: { colors: "#FFFFFF99" }, + }, }, yaxis: { - min: 0, - max: maxValue, labels: { style: { colors: "#FFFFFF99" } }, }, colors, legend: { - showForSingleSeries: showLegendForSingleSeries, labels: { colors: "#FFFFFF99", }, @@ -94,18 +69,10 @@ export const Chart = ({ strokeDashArray: 3, }, }), - [ - title, - interval, - timeLimit, - maxValue, - showLegendForSingleSeries, - colors, - annotationIntervalList, - setVideoCurrentTimeOnMouseHover, - videoEnabled, - ] + [colors, title] ); - return ; + const chartOptions = useMemo(() => merge(commonOptions, options), [commonOptions, options]); + + return ; }; diff --git a/packages/core/web-reporter-ui/src/components/Charts/ChartRangeArea.tsx b/packages/core/web-reporter-ui/src/components/Charts/ChartRangeArea.tsx index d5c10900..6b5f819a 100644 --- a/packages/core/web-reporter-ui/src/components/Charts/ChartRangeArea.tsx +++ b/packages/core/web-reporter-ui/src/components/Charts/ChartRangeArea.tsx @@ -1,11 +1,7 @@ import { ApexOptions } from "apexcharts"; -import React, { useContext, useMemo } from "react"; -import ReactApexChart from "react-apexcharts"; -import { VideoEnabledContext } from "../../../videoCurrentTimeContext"; -import { getLastX, useSetVideoTimeOnMouseHover } from "./useSetVideoTimeOnMouseHover"; +import React, { useMemo } from "react"; import { RangeAreaSeriesType } from "./types"; - -const labels = { style: { colors: "#FFFFFF99" } }; +import { Chart } from "./Chart"; /** * @description @@ -17,65 +13,46 @@ export const ChartRangeArea = ({ series, height, colors, + formatter, }: { title: string; series: RangeAreaSeriesType; height: number; - showLegendForSingleSeries?: boolean; colors: string[]; + formatter?: (label: string) => string; }) => { - const setVideoCurrentTimeOnMouseHover = useSetVideoTimeOnMouseHover({ - lastX: getLastX(series), - }); - const videoEnabled = useContext(VideoEnabledContext); - const options: ApexOptions = useMemo( () => ({ chart: { - id: title, - type: "rangeArea", animations: { enabled: false, - }, - events: videoEnabled ? setVideoCurrentTimeOnMouseHover : {}, - zoom: { - enabled: false, - }, - }, - title: { - text: title, - align: "left", - style: { - color: "#FFFFFF", - fontSize: "24px", - fontFamily: "Inter, sans-serif", - fontWeight: 500, + easing: undefined, + dynamicAnimation: undefined, }, }, - dataLabels: { - enabled: false, - }, stroke: { - curve: "smooth", width: [...Array(series.length / 2).fill(2), ...Array(series.length / 2).fill(0)], }, xaxis: { - type: "numeric", + type: "category", min: 0, - labels, - }, - yaxis: { min: 0, labels }, - colors, - legend: { - labels: labels.style, - }, - grid: { - borderColor: "#FFFFFF33", - strokeDashArray: 3, + labels: { + formatter: (label = "") => formatter?.(label) ?? label, + }, }, + yaxis: { min: 0 }, }), - [title, series.length, colors, videoEnabled, setVideoCurrentTimeOnMouseHover] + [series.length, formatter] ); - return ; + return ( + + ); }; diff --git a/packages/core/web-reporter-ui/src/components/Charts/ReportChart.tsx b/packages/core/web-reporter-ui/src/components/Charts/ReportChart.tsx new file mode 100644 index 00000000..0a463151 --- /dev/null +++ b/packages/core/web-reporter-ui/src/components/Charts/ReportChart.tsx @@ -0,0 +1,80 @@ +import React, { useMemo, useContext } from "react"; +import { VideoEnabledContext } from "../../../videoCurrentTimeContext"; +import { ApexOptions } from "apexcharts"; +import { getColorPalette } from "../../theme/colors"; +import { getLastX, useSetVideoTimeOnMouseHover } from "./useSetVideoTimeOnMouseHover"; +import { AnnotationInterval, LineSeriesType } from "./types"; +import { getAnnotations } from "./getAnnotations"; +import { Chart } from "./Chart"; + +export const ReportChart = ({ + title, + series, + height, + timeLimit, + maxValue, + showLegendForSingleSeries, + colors = getColorPalette(), + annotationIntervalList = undefined, + formatter, + onPointClick, +}: { + title: string; + series: LineSeriesType; + height: number; + timeLimit?: number | null; + maxValue?: number; + showLegendForSingleSeries?: boolean; + colors?: string[]; + annotationIntervalList?: AnnotationInterval[]; + formatter?: (label: string) => string; + onPointClick?: (seriesIndex: number, dataPointIndex: number) => void; +}) => { + const setVideoCurrentTimeOnMouseHover = useSetVideoTimeOnMouseHover({ + lastX: getLastX(series), + }); + + const videoEnabled = useContext(VideoEnabledContext); + + const options: ApexOptions = useMemo( + () => ({ + chart: { + events: videoEnabled ? setVideoCurrentTimeOnMouseHover : {}, + }, + annotations: getAnnotations(annotationIntervalList) || {}, + stroke: { + width: 2, + }, + xaxis: { + type: "numeric", + max: timeLimit || undefined, + }, + yaxis: { + min: 0, + max: maxValue, + }, + legend: { + showForSingleSeries: showLegendForSingleSeries, + }, + }), + [ + videoEnabled, + setVideoCurrentTimeOnMouseHover, + annotationIntervalList, + timeLimit, + maxValue, + showLegendForSingleSeries, + ] + ); + + return ( + + ); +}; diff --git a/packages/core/web-reporter-ui/src/components/Charts/types.ts b/packages/core/web-reporter-ui/src/components/Charts/types.ts index 55ce6181..ec444d50 100644 --- a/packages/core/web-reporter-ui/src/components/Charts/types.ts +++ b/packages/core/web-reporter-ui/src/components/Charts/types.ts @@ -1,4 +1,8 @@ -export type LineSeriesType = { name: string; data: { x: number | string; y: number }[] }[]; +export type LineDataPointType = { x: number | string; y: number }; + +export type LinePlotType = { name: string; data: LineDataPointType[] }; + +export type LineSeriesType = LinePlotType[]; export type RangeAreaSeriesType = ( | { diff --git a/packages/core/web-reporter-ui/src/sections/CPUReport.tsx b/packages/core/web-reporter-ui/src/sections/CPUReport.tsx index 406d8408..e4e30f11 100644 --- a/packages/core/web-reporter-ui/src/sections/CPUReport.tsx +++ b/packages/core/web-reporter-ui/src/sections/CPUReport.tsx @@ -6,11 +6,11 @@ import { ThreadNames, ThreadNamesIOS, } from "@perf-profiler/types"; -import { Chart } from "../components/Charts/Chart"; import { ComparativeThreadTable, ThreadTable } from "../components/ThreadTable"; import { Collapsible } from "../components/Collapsible"; import { getColorPalette } from "../theme/colors"; import { getAverageCpuUsage, roundToDecimal } from "@perf-profiler/reporter"; +import { ReportChart } from "../components/Charts/ReportChart"; const buildSeriesData = (measures: Measure[], calculate: (measure: Measure) => number) => measures @@ -76,17 +76,15 @@ export const CPUReport = ({ results }: { results: AveragedTestCaseResult[] }) => return ( <> - - 1 ? getColorPalette().slice(0, results.length) : undefined} maxValue={100} diff --git a/packages/core/web-reporter-ui/src/sections/FPSReport.tsx b/packages/core/web-reporter-ui/src/sections/FPSReport.tsx index 590bff9c..243bedcc 100644 --- a/packages/core/web-reporter-ui/src/sections/FPSReport.tsx +++ b/packages/core/web-reporter-ui/src/sections/FPSReport.tsx @@ -1,7 +1,7 @@ import React from "react"; -import { AveragedTestCaseResult, POLLING_INTERVAL } from "@perf-profiler/types"; -import { Chart } from "../components/Charts/Chart"; +import { AveragedTestCaseResult } from "@perf-profiler/types"; import { buildValueGraph } from "./hideSectionForEmptyValue"; +import { ReportChart } from "../components/Charts/ReportChart"; const fpsAnnotationInterval = [{ y: 57, y2: 60, color: "#158000", label: "Safe Zone" }]; @@ -12,10 +12,9 @@ export const FPSReport = ({ results }: { results: AveragedTestCaseResult[] }) => }); return ( - diff --git a/packages/core/web-reporter-ui/src/sections/RAMReport.tsx b/packages/core/web-reporter-ui/src/sections/RAMReport.tsx index 11c01990..e2221124 100644 --- a/packages/core/web-reporter-ui/src/sections/RAMReport.tsx +++ b/packages/core/web-reporter-ui/src/sections/RAMReport.tsx @@ -1,7 +1,7 @@ import React from "react"; -import { AveragedTestCaseResult, POLLING_INTERVAL } from "@perf-profiler/types"; -import { Chart } from "../components/Charts/Chart"; +import { AveragedTestCaseResult } from "@perf-profiler/types"; import { buildValueGraph } from "./hideSectionForEmptyValue"; +import { ReportChart } from "../components/Charts/ReportChart"; export const RAMReport = ({ results }: { results: AveragedTestCaseResult[] }) => { const ram = buildValueGraph({ @@ -9,9 +9,5 @@ export const RAMReport = ({ results }: { results: AveragedTestCaseResult[] }) => stat: "ram", }); - return ( - <> - - - ); + return ; };