From 3737a94edd8a084e4bb833ef30ab9a1045fede8b Mon Sep 17 00:00:00 2001 From: TzeYiing Date: Tue, 18 Oct 2022 22:40:44 +0800 Subject: [PATCH] fix: add number formatting to area chart as default number formatter --- .../ui/Charts/AreaChart.stories.tsx | 1 + studio/components/ui/Charts/AreaChart.tsx | 14 +++++-- studio/components/ui/Charts/Charts.types.tsx | 3 +- studio/components/ui/Charts/Charts.utils.ts | 38 +++++++++++++++++++ .../components/ui/Charts/Charts.utils.test.ts | 16 ++++++++ 5 files changed, 67 insertions(+), 5 deletions(-) create mode 100644 studio/components/ui/Charts/Charts.utils.ts create mode 100644 studio/tests/components/ui/Charts/Charts.utils.test.ts diff --git a/studio/components/ui/Charts/AreaChart.stories.tsx b/studio/components/ui/Charts/AreaChart.stories.tsx index 8a6da876ce0..599063c21ce 100644 --- a/studio/components/ui/Charts/AreaChart.stories.tsx +++ b/studio/components/ui/Charts/AreaChart.stories.tsx @@ -27,6 +27,7 @@ export const AreaChart = () => ( { title: 'Minimal Header', props: { minimalHeader: true } }, { title: 'Minimal Highlighted Value', props: { minimalHeader: true, highlightedValue: 123 } }, { title: 'Highlighted Value', props: { highlightedValue: 123, highlightedLabel: "some custom label" } }, + { title: 'Formatter - Auto 2 Precision for floats', props: { data: DATA.map(d=> ({...d, ram_usage: d.ram_usage + 0.1231233})) } }, { title: 'UTC Dates', props: { displayDateInUtc: true } }, { title: 'Custom date format', props: { customDateFormat: 'HH:mm' } }, { title: 'Value format', props: { format: 'c' } }, diff --git a/studio/components/ui/Charts/AreaChart.tsx b/studio/components/ui/Charts/AreaChart.tsx index 14ef0965cbc..90e783da40d 100644 --- a/studio/components/ui/Charts/AreaChart.tsx +++ b/studio/components/ui/Charts/AreaChart.tsx @@ -13,6 +13,7 @@ import ChartHeader from './ChartHeader' import { Datum, CommonChartProps } from './Charts.types' import utc from 'dayjs/plugin/utc' import ChartNoData from './NoDataPlaceholder' +import { numberFormatter } from './Charts.utils' dayjs.extend(utc) export interface AreaChartProps extends CommonChartProps { @@ -34,6 +35,7 @@ const AreaChart: React.FC = ({ highlightedLabel, displayDateInUtc, minimalHeader, + className = '', }) => { const [focusDataIndex, setFocusDataIndex] = useState(null) @@ -51,15 +53,19 @@ const AreaChart: React.FC = ({ highlightedLabel const resolvedHighlightedValue = - (focusDataIndex !== null ? data[focusDataIndex]?.[yAxisKey] : null) || highlightedValue + (focusDataIndex !== null ? data[focusDataIndex]?.[yAxisKey] : null) || highlightedValue return ( - <> +
@@ -113,7 +119,7 @@ const AreaChart: React.FC = ({ {dayjs(data[data?.length - 1]?.[xAxisKey]).format(customDateFormat)}
)} - + ) } export default AreaChart diff --git a/studio/components/ui/Charts/Charts.types.tsx b/studio/components/ui/Charts/Charts.types.tsx index c3baf5720cc..239d1f29368 100644 --- a/studio/components/ui/Charts/Charts.types.tsx +++ b/studio/components/ui/Charts/Charts.types.tsx @@ -9,7 +9,8 @@ export interface CommonChartProps | 'minimalHeader' | 'displayDateInUtc' > { - title?: string + title?: string; + className?: string } export type HeaderType = { diff --git a/studio/components/ui/Charts/Charts.utils.ts b/studio/components/ui/Charts/Charts.utils.ts new file mode 100644 index 00000000000..8683067c1b9 --- /dev/null +++ b/studio/components/ui/Charts/Charts.utils.ts @@ -0,0 +1,38 @@ + +/** + * Auto formats a number to a default precision if it is a float + * + * @example + * numberFormatter(123) // "123" + * numberFormatter(123.123) // "123.12" + * numberFormatter(123, 2) // "123.00" + */ +export const numberFormatter = (num: number, precision = 2) => isFloat(num) ? precisionFormatter(num, precision) : String(num); + + +/** + * Tests if a number is a float. + * + * @example + * isFloat(123) // false + * isFloat(123.123) // true + */ +export const isFloat = (num: number) => String(num).includes(".") + + +/** + * Formats a number to a particular precision. + * + * @example + * precisionFormatter(123, 2) // "123.00" + * precisionFormatter(123.123, 2) // "123.12" + */ +export const precisionFormatter = (num: number, precision: number): string => { + if (isFloat(num)) { + const [head, tail] = String(num).split(".") + return head + "." + tail.slice(0, precision) + } else { + // pad int with 0 + return String(num) + "." + ("0".repeat(precision)) + } +} \ No newline at end of file diff --git a/studio/tests/components/ui/Charts/Charts.utils.test.ts b/studio/tests/components/ui/Charts/Charts.utils.test.ts new file mode 100644 index 00000000000..071f19f02d9 --- /dev/null +++ b/studio/tests/components/ui/Charts/Charts.utils.test.ts @@ -0,0 +1,16 @@ +import { isFloat, numberFormatter, precisionFormatter } from "components/ui/Charts/Charts.utils" + + +test("isFloat", () => { + expect(isFloat(123)).toBe(false) + expect(isFloat(123.123)).toBe(true) +}) +test("numberFormatter", () => { + expect(numberFormatter(123)).toBe("123") + expect(numberFormatter(123.123)).toBe("123.12") +}) + +test("precisionFormatter", () => { + expect(precisionFormatter(123, 1)).toBe("123.0") + expect(precisionFormatter(123.12345, 4)).toBe("123.1234") +}) \ No newline at end of file