diff --git a/pkg/ui/workspaces/cluster-ui/src/barCharts/barCharts.tsx b/pkg/ui/workspaces/cluster-ui/src/barCharts/barCharts.tsx index 36800cb0638a..0b59ad42a1b4 100644 --- a/pkg/ui/workspaces/cluster-ui/src/barCharts/barCharts.tsx +++ b/pkg/ui/workspaces/cluster-ui/src/barCharts/barCharts.tsx @@ -10,7 +10,7 @@ import * as protos from "@cockroachlabs/crdb-protobuf-client"; import { stdDevLong, longToInt } from "src/util"; -import { Duration, Bytes, Percentage } from "src/util/format"; +import { Duration, Bytes, PercentageCustom } from "src/util/format"; import classNames from "classnames/bind"; import styles from "./barCharts.module.scss"; import { bar, approximify } from "./utils"; @@ -140,6 +140,6 @@ export function workloadPctBarChart( : 0, ), ], - v => Percentage(v, 1, 1), + v => PercentageCustom(v, 1, 1), )(statements, defaultBarChartOptions); } diff --git a/pkg/ui/workspaces/cluster-ui/src/util/format.spec.ts b/pkg/ui/workspaces/cluster-ui/src/util/format.spec.ts index e842ba892834..58620a22ab71 100644 --- a/pkg/ui/workspaces/cluster-ui/src/util/format.spec.ts +++ b/pkg/ui/workspaces/cluster-ui/src/util/format.spec.ts @@ -17,6 +17,7 @@ import { HexStringToInt64String, FixFingerprintHexValue, EncodeUriName, + PercentageCustom, } from "./format"; describe("Format utils", () => { @@ -89,4 +90,19 @@ describe("Format utils", () => { expect(EncodeUriName("12%abc")).toBe("12%252525abc"); }); }); + + describe("PercentageCustom", () => { + it("percentages bigger than 1", () => { + assert.equal(PercentageCustom(1, 1, 1), "100.0 %"); + assert.equal(PercentageCustom(0.1234, 1, 1), "12.3 %"); + assert.equal(PercentageCustom(0.23432, 1, 1), "23.4 %"); + assert.equal(PercentageCustom(0.23432, 1, 2), "23.43 %"); + }); + it("percentages between 0 and 1", () => { + assert.equal(PercentageCustom(0, 1, 1), "0.0 %"); + assert.equal(PercentageCustom(0.00023, 1, 1), "0.02 %"); + assert.equal(PercentageCustom(0.0000023, 1, 1), "0.0002 %"); + assert.equal(PercentageCustom(0.00000000000000004, 1, 1), "~0.0 %"); + }); + }); }); diff --git a/pkg/ui/workspaces/cluster-ui/src/util/format.ts b/pkg/ui/workspaces/cluster-ui/src/util/format.ts index c9c0857c536a..ea30e9b6bb41 100644 --- a/pkg/ui/workspaces/cluster-ui/src/util/format.ts +++ b/pkg/ui/workspaces/cluster-ui/src/util/format.ts @@ -132,6 +132,41 @@ export function Percentage( return Math.floor((numerator / denominator) * 100).toString() + " %"; } +/** + * PercentageCustom creates a string representation of a fraction as a percentage. + * Accepts a precision parameter as optional indicating how many digits + * after the decimal point are desired. (e.g. precision 2 returns 8.37 %) + * If the number is zero or grater than 1, it works the same way as the Percentage + * function above, if is between 0 and 1, it looks for the first non-zero + * decimal number, up to 10 decimal points, otherwise shows ~0.0% + */ +export function PercentageCustom( + numerator: number, + denominator: number, + precision?: number, +): string { + if (denominator === 0) { + return "--%"; + } + const pct = (numerator / denominator) * 100; + if (pct <= 0 || pct >= 1) { + return Percentage(numerator, denominator, precision); + } + const pctString = pct.toFixed(10); + let finalPct = "0."; + let found = false; + for (let index = 2; index < pctString.length && !found; index++) { + finalPct = `${finalPct}${pctString[index]}`; + if (pctString[index] != "0") { + found = true; + } + } + if (found) { + return finalPct + " %"; + } + return "~0.0 %"; +} + /** * ComputeDurationScale calculates an appropriate scale factor and unit to use * to display a given duration value, without actually converting the value.