Skip to content

Commit

Permalink
feat(Chart): separate chart components for report and evolution (#190)
Browse files Browse the repository at this point in the history
* feat(Chart): add formatter prop

* refacto(LineSeriesType): extract subtypes

* feat(Chart): add onPointClick prop

* fix(Chart): express x axis type as category

* feat(ChartRangeArea): add formatter

* fix(ChartRangeArea): specify x axis type as category

* refacto(Chart): remove unused interval prop

* refacto(Chart): extract common options

* refacto(Chart): remove redundant chart type

* refacto(Chart): extract base chart component

* refacto(Chart): simplify formatter

* refacto(BaseChart): introduce type prop

* refacto(ChartRangeArea): use BaseChart

* refacto(ChartRangeArea): remove report logic

* refacto(ChartRangeArea): remove unused prop

* refacto(Chart): rename components

* feat(index): export ApexOptions type

* refacto(DeprecatedChart): remove evolution components

* refacto(DeprecatedChart): rename to ReportChart

* refacto(ReportChart): move to own file
  • Loading branch information
hduprat authored Jan 18, 2024
1 parent 3a1d69c commit bd1f486
Show file tree
Hide file tree
Showing 8 changed files with 135 additions and 113 deletions.
1 change: 1 addition & 0 deletions packages/core/web-reporter-ui/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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";
69 changes: 18 additions & 51 deletions packages/core/web-reporter-ui/src/components/Charts/Chart.tsx
Original file line number Diff line number Diff line change
@@ -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<ApexChartProps["type"], undefined>;
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",
Expand All @@ -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",
},
Expand All @@ -94,18 +69,10 @@ export const Chart = ({
strokeDashArray: 3,
},
}),
[
title,
interval,
timeLimit,
maxValue,
showLegendForSingleSeries,
colors,
annotationIntervalList,
setVideoCurrentTimeOnMouseHover,
videoEnabled,
]
[colors, title]
);

return <ReactApexChart options={options} series={series} type={"line"} height={height} />;
const chartOptions = useMemo(() => merge(commonOptions, options), [commonOptions, options]);

return <ReactApexChart options={chartOptions} series={series} type={type} height={height} />;
};
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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 <ReactApexChart options={options} series={series} type={"rangeArea"} height={height} />;
return (
<Chart
type="rangeArea"
title={title}
series={series}
height={height}
colors={colors}
options={options}
/>
);
};
Original file line number Diff line number Diff line change
@@ -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 (
<Chart
type="line"
title={title}
series={series}
colors={colors}
height={height}
options={options}
/>
);
};
6 changes: 5 additions & 1 deletion packages/core/web-reporter-ui/src/components/Charts/types.ts
Original file line number Diff line number Diff line change
@@ -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 = (
| {
Expand Down
8 changes: 3 additions & 5 deletions packages/core/web-reporter-ui/src/sections/CPUReport.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -76,17 +76,15 @@ export const CPUReport = ({ results }: { results: AveragedTestCaseResult[] }) =>

return (
<>
<Chart
<ReportChart
title="Total CPU Usage (%)"
height={500}
interval={POLLING_INTERVAL}
series={totalCPUUsage}
annotationIntervalList={totalCpuAnnotationInterval}
/>
<Chart
<ReportChart
title="CPU Usage per thread (%)"
height={500}
interval={POLLING_INTERVAL}
series={threads}
colors={results.length > 1 ? getColorPalette().slice(0, results.length) : undefined}
maxValue={100}
Expand Down
7 changes: 3 additions & 4 deletions packages/core/web-reporter-ui/src/sections/FPSReport.tsx
Original file line number Diff line number Diff line change
@@ -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" }];

Expand All @@ -12,10 +12,9 @@ export const FPSReport = ({ results }: { results: AveragedTestCaseResult[] }) =>
});

return (
<Chart
<ReportChart
title="Frame rate (FPS)"
height={500}
interval={POLLING_INTERVAL}
series={fps}
annotationIntervalList={fpsAnnotationInterval}
/>
Expand Down
10 changes: 3 additions & 7 deletions packages/core/web-reporter-ui/src/sections/RAMReport.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,13 @@
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({
results,
stat: "ram",
});

return (
<>
<Chart title="RAM Usage (MB)" height={500} interval={POLLING_INTERVAL} series={ram} />
</>
);
return <ReportChart title="RAM Usage (MB)" height={500} series={ram} />;
};

0 comments on commit bd1f486

Please sign in to comment.