@openshift-migration-advisor/shared-components 0.28.0-811d1036212f → 0.28.0-a68bc28c8af9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"MigrationDonutChart.d.ts","sourceRoot":"","sources":["../../src/charts/MigrationDonutChart.tsx"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,EAAE,EAAgB,MAAM,OAAO,CAAC;AAG9C,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1C,WAAW,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5C,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,MAAM,MAAM,gCAAgC,GAAG,MAAM,GAAG,OAAO,CAAC;AAEhE,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,wBAAwB,EAAE,CAAC;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qBAAqB,CAAC,EAAE,CAAC,IAAI,EAAE;QAC7B,KAAK,EAAE;YACL,CAAC,EAAE,MAAM,CAAC;YACV,CAAC,EAAE,MAAM,CAAC;YACV,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;YAC/B,cAAc,EAAE,MAAM,CAAC;SACxB,CAAC;QACF,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,EAAE,MAAM,CAAC;KACf,KAAK,MAAM,CAAC;IACb,iDAAiD;IACjD,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,wBAAwB,KAAK,IAAI,CAAC;IACvD,gDAAgD;IAChD,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,mFAAmF;IACnF,oBAAoB,CAAC,EAAE,CAAC,IAAI,EAAE;QAC5B,CAAC,EAAE,MAAM,CAAC;QACV,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;KAChC,KAAK,MAAM,CAAC;IACb;;;;OAIG;IACH,aAAa,CAAC,EAAE,gCAAgC,CAAC;IACjD,8CAA8C;IAC9C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,2CAA2C;IAC3C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,2CAA2C;IAC3C,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,0EAA0E;IAC1E,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAoFD,eAAO,MAAM,mBAAmB,EAAE,EAAE,CAAC,wBAAwB,CAoX5D,CAAC;AAEF,eAAe,mBAAmB,CAAC"}
1
+ {"version":3,"file":"MigrationDonutChart.d.ts","sourceRoot":"","sources":["../../src/charts/MigrationDonutChart.tsx"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,EAAE,EAAgB,MAAM,OAAO,CAAC;AAG9C,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1C,WAAW,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5C,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,MAAM,MAAM,gCAAgC,GAAG,MAAM,GAAG,OAAO,CAAC;AAEhE,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,wBAAwB,EAAE,CAAC;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qBAAqB,CAAC,EAAE,CAAC,IAAI,EAAE;QAC7B,KAAK,EAAE;YACL,CAAC,EAAE,MAAM,CAAC;YACV,CAAC,EAAE,MAAM,CAAC;YACV,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;YAC/B,cAAc,EAAE,MAAM,CAAC;SACxB,CAAC;QACF,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,EAAE,MAAM,CAAC;KACf,KAAK,MAAM,CAAC;IACb,iDAAiD;IACjD,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,wBAAwB,KAAK,IAAI,CAAC;IACvD,gDAAgD;IAChD,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,mFAAmF;IACnF,oBAAoB,CAAC,EAAE,CAAC,IAAI,EAAE;QAC5B,CAAC,EAAE,MAAM,CAAC;QACV,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;KAChC,KAAK,MAAM,CAAC;IACb;;;;OAIG;IACH,aAAa,CAAC,EAAE,gCAAgC,CAAC;IACjD,8CAA8C;IAC9C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,2CAA2C;IAC3C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,2CAA2C;IAC3C,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,0EAA0E;IAC1E,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAoFD,eAAO,MAAM,mBAAmB,EAAE,EAAE,CAAC,wBAAwB,CAgY5D,CAAC;AAEF,eAAe,mBAAmB,CAAC"}
@@ -111,9 +111,13 @@ export const MigrationDonutChart = ({ data, legend, customColors, height = 260,
111
111
  countDisplay: item.countDisplay ?? item.count,
112
112
  }));
113
113
  }, [data]);
114
- const colorScale = useMemo(() => {
115
- return chartData.map((item) => getColor(item.legendCategory));
116
- }, [chartData, getColor]);
114
+ // Victory renders zero-value slices as degenerate zero-angle wedges but still
115
+ // keeps a `padAngle` gap around each one.
116
+ const donutChartData = useMemo(() => chartData.filter((item) => Number(item.y) > 0), [chartData]);
117
+ const donutColorScale = useMemo(() => donutChartData.map((item) => getColor(item.legendCategory)), [donutChartData, getColor]);
118
+ // A lone slice has no neighbour to pad against; forcing padAngle to 0 keeps it
119
+ // from leaving a gap against itself.
120
+ const effectivePadAngle = donutChartData.length <= 1 ? 0 : padAngle;
117
121
  const legendData = useMemo(() => {
118
122
  return chartData.map((item) => ({
119
123
  name: `${item.x} (${item.countDisplay})`,
@@ -221,7 +225,7 @@ export const MigrationDonutChart = ({ data, legend, customColors, height = 260,
221
225
  fontFamily: chartTextFontFamily,
222
226
  },
223
227
  } }) }) }) }));
224
- return (_jsxs(Flex, { direction: { default: "column" }, alignItems: { default: "alignItemsCenter" }, className: `${onItemClick ? styles.cursorPointer : styles.cursorDefault} ${styles.chartContainer}`, children: [_jsxs("div", { className: styles.donutWrapper, children: [_jsx(ChartDonut, { ariaDesc: "Migration data donut chart", data: chartData, events: chartEvents, labelComponent: donutTooltip, labels: ({ datum, }) => formatLabel(datum), colorScale: colorScale, constrainToVisibleArea: true, innerRadius: innerRadius, padAngle: padAngle, title: title, subTitle: subTitle, height: height, width: width, padding: {
228
+ return (_jsxs(Flex, { direction: { default: "column" }, alignItems: { default: "alignItemsCenter" }, className: `${onItemClick ? styles.cursorPointer : styles.cursorDefault} ${styles.chartContainer}`, children: [_jsxs("div", { className: styles.donutWrapper, children: [_jsx(ChartDonut, { ariaDesc: "Migration data donut chart", data: donutChartData, events: chartEvents, labelComponent: donutTooltip, labels: ({ datum, }) => formatLabel(datum), colorScale: donutColorScale, constrainToVisibleArea: true, innerRadius: innerRadius, padAngle: effectivePadAngle, title: title, subTitle: subTitle, height: height, width: width, padding: {
225
229
  bottom: 5,
226
230
  left: 20,
227
231
  right: 20,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openshift-migration-advisor/shared-components",
3
- "version": "0.28.0-811d1036212f",
3
+ "version": "0.28.0-a68bc28c8af9",
4
4
  "description": "Shared React UI components for Migration Advisor apps (report charts, forms, OS support tiers)",
5
5
  "author": "Montse Ortega <mortegag@redhat.com>",
6
6
  "license": "Apache-2.0",
@@ -220,9 +220,21 @@ export const MigrationDonutChart: FC<MigrationDonutChartProps> = ({
220
220
  }));
221
221
  }, [data]);
222
222
 
223
- const colorScale = useMemo(() => {
224
- return chartData.map((item) => getColor(item.legendCategory));
225
- }, [chartData, getColor]);
223
+ // Victory renders zero-value slices as degenerate zero-angle wedges but still
224
+ // keeps a `padAngle` gap around each one.
225
+ const donutChartData = useMemo(
226
+ () => chartData.filter((item) => Number(item.y) > 0),
227
+ [chartData],
228
+ );
229
+
230
+ const donutColorScale = useMemo(
231
+ () => donutChartData.map((item) => getColor(item.legendCategory)),
232
+ [donutChartData, getColor],
233
+ );
234
+
235
+ // A lone slice has no neighbour to pad against; forcing padAngle to 0 keeps it
236
+ // from leaving a gap against itself.
237
+ const effectivePadAngle = donutChartData.length <= 1 ? 0 : padAngle;
226
238
 
227
239
  const legendData = useMemo(() => {
228
240
  return chartData.map((item) => ({
@@ -446,7 +458,7 @@ export const MigrationDonutChart: FC<MigrationDonutChartProps> = ({
446
458
  <div className={styles.donutWrapper}>
447
459
  <ChartDonut
448
460
  ariaDesc="Migration data donut chart"
449
- data={chartData}
461
+ data={donutChartData}
450
462
  events={chartEvents}
451
463
  labelComponent={donutTooltip}
452
464
  labels={({
@@ -459,10 +471,10 @@ export const MigrationDonutChart: FC<MigrationDonutChartProps> = ({
459
471
  countDisplay?: string | number;
460
472
  };
461
473
  }) => formatLabel(datum)}
462
- colorScale={colorScale}
474
+ colorScale={donutColorScale}
463
475
  constrainToVisibleArea
464
476
  innerRadius={innerRadius}
465
- padAngle={padAngle}
477
+ padAngle={effectivePadAngle}
466
478
  title={title}
467
479
  subTitle={subTitle}
468
480
  height={height}
@@ -0,0 +1,53 @@
1
+ import "@testing-library/jest-dom";
2
+ import { cleanup, render } from "@testing-library/react";
3
+ import { afterEach, describe, expect, it } from "vitest";
4
+ import {
5
+ MigrationDonutChart,
6
+ type MigrationDonutChartDatum,
7
+ } from "../MigrationDonutChart.js";
8
+
9
+ afterEach(() => cleanup());
10
+
11
+ /**
12
+ * Victory renders one `<path role="presentation">` per slice handed to ChartDonut.
13
+ * Only real pie slices carry an arc command (`A`) in their path data — legend
14
+ * symbols are squares — so filtering on it isolates the donut slices.
15
+ */
16
+ const sliceCount = (container: HTMLElement): number =>
17
+ Array.from(container.querySelectorAll("path[role='presentation']")).filter(
18
+ (path) => (path.getAttribute("d") ?? "").includes("A"),
19
+ ).length;
20
+
21
+ describe("MigrationDonutChart", () => {
22
+ it("does not render slices for zero-value categories", () => {
23
+ // Fixed-category chart (e.g. power states) where only one category is populated.
24
+ const data: MigrationDonutChartDatum[] = [
25
+ { name: "Powered on", count: 7, legendCategory: "Powered on" },
26
+ { name: "Powered off", count: 0, legendCategory: "Powered off" },
27
+ { name: "Standby", count: 0, legendCategory: "Standby" },
28
+ { name: "Not responding", count: 0, legendCategory: "Not responding" },
29
+ { name: "Maintenance", count: 0, legendCategory: "Maintenance" },
30
+ ];
31
+
32
+ const { container } = render(
33
+ <MigrationDonutChart data={data} legendVariant="chart" />,
34
+ );
35
+
36
+ // Only the single populated slice should be drawn, leaving no empty gap.
37
+ expect(sliceCount(container)).toBe(1);
38
+ });
39
+
40
+ it("renders one slice per populated category", () => {
41
+ const data: MigrationDonutChartDatum[] = [
42
+ { name: "Powered on", count: 5, legendCategory: "Powered on" },
43
+ { name: "Powered off", count: 3, legendCategory: "Powered off" },
44
+ { name: "Standby", count: 0, legendCategory: "Standby" },
45
+ ];
46
+
47
+ const { container } = render(
48
+ <MigrationDonutChart data={data} legendVariant="chart" />,
49
+ );
50
+
51
+ expect(sliceCount(container)).toBe(2);
52
+ });
53
+ });