@openshift-migration-advisor/shared-components 0.22.0-dd51551836b7 → 0.23.0-54185b7f1be8

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.
Files changed (68) hide show
  1. package/README.md +6 -0
  2. package/dist/charts/MigrationDonutChart.d.ts +18 -1
  3. package/dist/charts/MigrationDonutChart.d.ts.map +1 -1
  4. package/dist/charts/MigrationDonutChart.js +103 -43
  5. package/dist/charts/index.d.ts +1 -1
  6. package/dist/charts/index.d.ts.map +1 -1
  7. package/dist/forms/RadioButtonFormGroup.d.ts.map +1 -1
  8. package/dist/forms/RadioButtonFormGroup.js +2 -2
  9. package/dist/report/FeatureStatusBadge.d.ts +7 -0
  10. package/dist/report/FeatureStatusBadge.d.ts.map +1 -0
  11. package/dist/report/FeatureStatusBadge.js +13 -0
  12. package/dist/report/HostPowerStates.d.ts +9 -0
  13. package/dist/report/HostPowerStates.d.ts.map +1 -0
  14. package/dist/report/HostPowerStates.js +11 -0
  15. package/dist/report/InfrastructureSummary.d.ts +7 -0
  16. package/dist/report/InfrastructureSummary.d.ts.map +1 -0
  17. package/dist/report/InfrastructureSummary.js +5 -0
  18. package/dist/report/OSDistribution.d.ts.map +1 -1
  19. package/dist/report/OSDistribution.js +5 -13
  20. package/dist/report/OsSupportTiersHelpPopover.d.ts.map +1 -1
  21. package/dist/report/OsSupportTiersHelpPopover.js +2 -31
  22. package/dist/report/OsUpgradeNotice.d.ts.map +1 -1
  23. package/dist/report/OsUpgradeNotice.js +1 -5
  24. package/dist/report/PowerStateCard.d.ts +17 -0
  25. package/dist/report/PowerStateCard.d.ts.map +1 -0
  26. package/dist/report/PowerStateCard.js +7 -0
  27. package/dist/report/SupportTierBadge.d.ts.map +1 -1
  28. package/dist/report/SupportTierBadge.js +4 -2
  29. package/dist/report/VCenterClusterDetails.d.ts +10 -0
  30. package/dist/report/VCenterClusterDetails.d.ts.map +1 -0
  31. package/dist/report/VCenterClusterDetails.js +26 -0
  32. package/dist/report/VmPowerStates.d.ts +9 -0
  33. package/dist/report/VmPowerStates.d.ts.map +1 -0
  34. package/dist/report/VmPowerStates.js +11 -0
  35. package/dist/report/constants.d.ts +2 -0
  36. package/dist/report/constants.d.ts.map +1 -1
  37. package/dist/report/constants.js +2 -0
  38. package/dist/report/index.d.ts +10 -0
  39. package/dist/report/index.d.ts.map +1 -1
  40. package/dist/report/index.js +8 -0
  41. package/dist/report/infrastructureSummary.d.ts +82 -0
  42. package/dist/report/infrastructureSummary.d.ts.map +1 -0
  43. package/dist/report/infrastructureSummary.js +139 -0
  44. package/dist/report/powerStates.d.ts +11 -0
  45. package/dist/report/powerStates.d.ts.map +1 -0
  46. package/dist/report/powerStates.js +113 -0
  47. package/package.json +1 -1
  48. package/src/charts/MigrationDonutChart.tsx +232 -111
  49. package/src/charts/index.ts +1 -0
  50. package/src/forms/RadioButtonFormGroup.tsx +10 -3
  51. package/src/report/FeatureStatusBadge.tsx +30 -0
  52. package/src/report/HostPowerStates.tsx +41 -0
  53. package/src/report/InfrastructureSummary.tsx +56 -0
  54. package/src/report/OSDistribution.tsx +60 -67
  55. package/src/report/OsSupportTiersHelpPopover.tsx +32 -61
  56. package/src/report/OsUpgradeNotice.tsx +1 -7
  57. package/src/report/PowerStateCard.tsx +73 -0
  58. package/src/report/SupportTierBadge.tsx +4 -2
  59. package/src/report/VCenterClusterDetails.tsx +211 -0
  60. package/src/report/VmPowerStates.tsx +41 -0
  61. package/src/report/__tests__/HostPowerStates.test.tsx +47 -0
  62. package/src/report/__tests__/InfrastructureSummary.test.tsx +148 -0
  63. package/src/report/__tests__/infrastructureSummary.test.ts +224 -0
  64. package/src/report/__tests__/powerStates.test.ts +70 -0
  65. package/src/report/constants.ts +2 -0
  66. package/src/report/index.ts +56 -0
  67. package/src/report/infrastructureSummary.ts +281 -0
  68. package/src/report/powerStates.ts +169 -0
package/README.md CHANGED
@@ -8,6 +8,7 @@ Includes:
8
8
  - Guest OS support-tier helpers and badges
9
9
  - Report chart primitives (`MigrationDonutChart`)
10
10
  - Operating Systems distribution card
11
+ - Infrastructure summary, vCenter cluster details, and host/VM power-state cards
11
12
 
12
13
  ## Installation
13
14
 
@@ -23,10 +24,15 @@ npm install @openshift-migration-advisor/shared-components
23
24
 
24
25
  ```tsx
25
26
  import {
27
+ buildInfrastructureSummary,
28
+ HostPowerStates,
29
+ InfrastructureSummary,
26
30
  MigrationDonutChart,
27
31
  OSDistribution,
28
32
  SupportTierBadge,
29
33
  TextInputFormGroup,
34
+ VCenterClusterDetails,
35
+ VmPowerStates,
30
36
  } from "@openshift-migration-advisor/shared-components";
31
37
  ```
32
38
 
@@ -15,6 +15,7 @@ export interface MigrationDonutChartDatum {
15
15
  clusterNames?: string[];
16
16
  networkNames?: string[];
17
17
  }
18
+ export type MigrationDonutChartLegendVariant = "html" | "chart";
18
19
  export interface MigrationDonutChartProps {
19
20
  data: MigrationDonutChartDatum[];
20
21
  legend?: Record<string, string>;
@@ -40,13 +41,29 @@ export interface MigrationDonutChartProps {
40
41
  percent: number;
41
42
  total: number;
42
43
  }) => string;
44
+ /** Agent-ui: slice / legend click drill-down. */
43
45
  onItemClick?: (item: MigrationDonutChartDatum) => void;
46
+ /** Agent-ui: clickable center title overlay. */
44
47
  onTitleClick?: () => void;
45
- /** When set, used for legend label instead of "name (countDisplay)". */
48
+ /** Agent-ui: custom HTML legend labels (ignored when legendVariant is "chart"). */
46
49
  legendLabelFormatter?: (item: {
47
50
  x: string;
48
51
  countDisplay?: string | number;
49
52
  }) => string;
53
+ /**
54
+ * Legend rendering mode.
55
+ * - `"html"` (default): custom clickable legend used by agent-ui
56
+ * - `"chart"`: PatternFly ChartLegend used by ui-app
57
+ */
58
+ legendVariant?: MigrationDonutChartLegendVariant;
59
+ /** ui-app ChartLegend: total legend width. */
60
+ legendWidth?: number;
61
+ /** ui-app ChartLegend: columns per row. */
62
+ itemsPerRow?: number;
63
+ /** ui-app ChartLegend: label font size. */
64
+ labelFontSize?: number;
65
+ /** Prefer themed Victory ChartTooltip (default true for chart legend). */
66
+ useThemedTooltip?: boolean;
50
67
  }
51
68
  export declare const MigrationDonutChart: FC<MigrationDonutChartProps>;
52
69
  export default MigrationDonutChart;
@@ -1 +1 @@
1
- {"version":3,"file":"MigrationDonutChart.d.ts","sourceRoot":"","sources":["../../src/charts/MigrationDonutChart.tsx"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAGhC,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,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,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,wBAAwB,KAAK,IAAI,CAAC;IACvD,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,wEAAwE;IACxE,oBAAoB,CAAC,EAAE,CAAC,IAAI,EAAE;QAC5B,CAAC,EAAE,MAAM,CAAC;QACV,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;KAChC,KAAK,MAAM,CAAC;CACd;AAkDD,eAAO,MAAM,mBAAmB,EAAE,EAAE,CAAC,wBAAwB,CAkS5D,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;AA8ED,eAAO,MAAM,mBAAmB,EAAE,EAAE,CAAC,wBAAwB,CAiX5D,CAAC;AAEF,eAAe,mBAAmB,CAAC"}
@@ -6,11 +6,35 @@ import { css } from "@emotion/css";
6
6
  // "@patternfly/react-charts/victory" subpath has no exports map entry and
7
7
  // resolves to a directory, which webpack refuses under fully-specified —
8
8
  // breaking the ui-app federated build.
9
- import { ChartDonut, ChartLabel, } from "@patternfly/react-charts/dist/esm/victory/index.js";
10
- import { EmptyState, EmptyStateVariant, Flex, FlexItem, } from "@patternfly/react-core";
11
- import { InboxIcon } from "@patternfly/react-icons";
9
+ import { ChartDonut, ChartLabel, ChartLegend, ChartTooltip, } from "@patternfly/react-charts/dist/esm/victory/index.js";
10
+ import { Flex, FlexItem } from "@patternfly/react-core";
12
11
  import { useCallback, useMemo } from "react";
13
- const legendColors = ["#0066cc", "#5e40be", "#b6a6e9", "#b98412"];
12
+ const legendColors = [
13
+ "#0066cc",
14
+ "#5e40be",
15
+ "#009596",
16
+ "#4cb140",
17
+ "#f0ab00",
18
+ "#b98412",
19
+ "#a30000",
20
+ "#b6a6e9",
21
+ ];
22
+ /** Victory chart tooltips that respect PatternFly light/dark themes. */
23
+ const themedChartTooltipStyle = {
24
+ fontSize: 9,
25
+ fill: "var(--pf-t--global--text--color--regular)",
26
+ };
27
+ const themedChartTooltipFlyoutStyle = {
28
+ stroke: "var(--pf-t--global--border--color--default)",
29
+ strokeWidth: 1,
30
+ fill: "var(--pf-t--global--background--color--floating--default)",
31
+ };
32
+ const themedChartTooltipFlyoutPadding = {
33
+ top: 6,
34
+ bottom: 6,
35
+ left: 10,
36
+ right: 10,
37
+ };
14
38
  const styles = {
15
39
  legendIcon: css `
16
40
  margin-right: 4px;
@@ -56,21 +80,25 @@ const styles = {
56
80
  padding: var(--pf-t--global--spacer--ml);
57
81
  `,
58
82
  };
59
- export const MigrationDonutChart = ({ data, legend, customColors, height = 260, width = 420, title, subTitle, titleColor = "#000000", subTitleColor = "#000000", marginLeft = "0%", titleFontSize = 28, subTitleFontSize = 14, donutThickness = 45, padAngle = 1, tooltipLabelFormatter, onItemClick, onTitleClick, legendLabelFormatter, }) => {
83
+ export const MigrationDonutChart = ({ data, legend, customColors, height = 260, width = 420, title, subTitle, titleColor = "var(--pf-t--global--text--color--regular)", subTitleColor = "var(--pf-t--global--text--color--subtle)", marginLeft = "0%", titleFontSize = 28, subTitleFontSize = 14, donutThickness = 45, padAngle = 1, tooltipLabelFormatter, onItemClick, onTitleClick, legendLabelFormatter, legendVariant = "html", legendWidth, itemsPerRow = 1, labelFontSize = 25, useThemedTooltip, }) => {
84
+ const showChartLegend = legendVariant === "chart";
85
+ const themedTooltipEnabled = useThemedTooltip ?? showChartLegend;
60
86
  const dynamicLegend = useMemo(() => {
61
- return data.reduce((acc, current) => {
62
- const key = `${current.legendCategory}`;
63
- if (!acc.seen.has(key)) {
64
- acc.seen.add(key);
65
- const color = customColors?.[key] ??
66
- legendColors[(acc.seen.size - 1) % legendColors.length];
67
- acc.result.push({ [key]: color });
87
+ const legendMap = {};
88
+ const seen = new Set();
89
+ for (const item of data) {
90
+ const key = item.legendCategory;
91
+ if (!seen.has(key)) {
92
+ seen.add(key);
93
+ legendMap[key] =
94
+ customColors?.[key] ??
95
+ legendColors[(seen.size - 1) % legendColors.length];
68
96
  }
69
- return acc;
70
- }, { seen: new Set(), result: [] }).result;
97
+ }
98
+ return legendMap;
71
99
  }, [data, customColors]);
72
- const chartLegend = legend ? legend : Object.assign({}, ...dynamicLegend);
73
- const getColor = useCallback((name) => chartLegend[name], [chartLegend]);
100
+ const chartLegend = legend ?? dynamicLegend;
101
+ const getColor = useCallback((name) => chartLegend[name] ?? legendColors[0], [chartLegend]);
74
102
  const chartData = useMemo(() => {
75
103
  return data.map((item) => ({
76
104
  x: item.name,
@@ -82,6 +110,29 @@ export const MigrationDonutChart = ({ data, legend, customColors, height = 260,
82
110
  const colorScale = useMemo(() => {
83
111
  return chartData.map((item) => getColor(item.legendCategory));
84
112
  }, [chartData, getColor]);
113
+ const legendData = useMemo(() => {
114
+ return chartData.map((item) => ({
115
+ name: `${item.x} (${item.countDisplay})`,
116
+ symbol: { fill: getColor(item.legendCategory) },
117
+ }));
118
+ }, [chartData, getColor]);
119
+ const legendWidthValue = legendWidth ?? 800;
120
+ const legendX = useMemo(() => {
121
+ const symbolAndGap = 34;
122
+ const charWidth = labelFontSize * 0.55;
123
+ const itemWidths = legendData.map((d) => symbolAndGap + d.name.length * charWidth);
124
+ const numCols = Math.min(legendData.length, itemsPerRow);
125
+ const gutter = 16;
126
+ let contentWidth = (numCols - 1) * gutter;
127
+ for (let c = 0; c < numCols; c++) {
128
+ let maxW = 0;
129
+ for (let i = c; i < itemWidths.length; i += itemsPerRow) {
130
+ maxW = Math.max(maxW, itemWidths[i] ?? 0);
131
+ }
132
+ contentWidth += maxW;
133
+ }
134
+ return Math.max(0, (legendWidthValue - contentWidth) / 2);
135
+ }, [legendData, itemsPerRow, legendWidthValue, labelFontSize]);
85
136
  const innerRadius = useMemo(() => {
86
137
  const outerApprox = Math.min(width, height) / 2;
87
138
  const computed = outerApprox - donutThickness;
@@ -130,24 +181,42 @@ export const MigrationDonutChart = ({ data, legend, customColors, height = 260,
130
181
  },
131
182
  ];
132
183
  }, [onItemClick, handleClick]);
184
+ const donutTooltip = useMemo(() => themedTooltipEnabled ? (_jsx(ChartTooltip, { style: themedChartTooltipStyle, flyoutStyle: themedChartTooltipFlyoutStyle, flyoutPadding: themedChartTooltipFlyoutPadding })) : undefined, [themedTooltipEnabled]);
185
+ const formatLabel = useCallback((datum) => {
186
+ const percent = totalY > 0 ? (Number(datum.y) / totalY) * 100 : 0;
187
+ return tooltipLabelFormatter
188
+ ? tooltipLabelFormatter({
189
+ datum: {
190
+ x: datum.x,
191
+ y: Number(datum.y),
192
+ countDisplay: datum.countDisplay,
193
+ legendCategory: datum.legendCategory,
194
+ },
195
+ percent,
196
+ total: totalY,
197
+ })
198
+ : `${datum.x}: ${datum.countDisplay ?? datum.y}`;
199
+ }, [tooltipLabelFormatter, totalY]);
133
200
  if (!data || data.length === 0) {
134
- return (_jsx(EmptyState, { headingLevel: "h3", titleText: "No data available", icon: InboxIcon, variant: EmptyStateVariant.xs }));
201
+ return null;
135
202
  }
136
- 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, labels: ({ datum, }) => {
137
- const percent = totalY > 0 ? (Number(datum.y) / totalY) * 100 : 0;
138
- return tooltipLabelFormatter
139
- ? tooltipLabelFormatter({
140
- datum: {
141
- x: datum.x,
142
- y: Number(datum.y),
143
- countDisplay: datum.countDisplay,
144
- legendCategory: datum.legendCategory,
145
- },
146
- percent,
147
- total: totalY,
148
- })
149
- : `${datum.x}: ${datum.countDisplay ?? datum.y}`;
150
- }, colorScale: colorScale, constrainToVisibleArea: true, innerRadius: innerRadius, padAngle: padAngle, title: title, subTitle: subTitle, height: height, width: width, padding: {
203
+ const htmlLegend = (_jsx(Flex, { className: `${styles.legendContainer} ${css `margin-left: ${marginLeft};`}`, justifyContent: { default: "justifyContentCenter" }, alignItems: { default: "alignItemsFlexStart" }, children: _jsx(Flex, { className: styles.legendInner, spaceItems: { default: "spaceItemsMd" }, justifyContent: { default: "justifyContentCenter" }, alignItems: { default: "alignItemsCenter" }, flexWrap: { default: "wrap" }, children: data.map((item) => {
204
+ const label = legendLabelFormatter
205
+ ? legendLabelFormatter({
206
+ x: item.name,
207
+ countDisplay: item.countDisplay,
208
+ })
209
+ : item.name;
210
+ const content = (_jsxs(_Fragment, { children: [_jsxs("svg", { width: "10", height: "10", "aria-hidden": "true", className: styles.legendIcon, children: [_jsx("title", { children: "Legend color indicator" }), _jsx("rect", { width: "10", height: "10", fill: getColor(item.legendCategory) })] }), _jsx("span", { children: label })] }));
211
+ return (_jsx(FlexItem, { children: onItemClick ? (_jsx("button", { type: "button", onClick: () => onItemClick(item), className: styles.legendButton, children: content })) : (_jsx("span", { className: styles.legendLabel, children: content })) }, `${item.legendCategory}-${item.name}`));
212
+ }) }) }));
213
+ const chartLegendElement = (_jsx(FlexItem, { flex: { default: "flex_1" }, children: _jsx(Flex, { justifyContent: { default: "justifyContentCenter" }, alignItems: { default: "alignItemsCenter" }, children: _jsx(FlexItem, { children: _jsx(ChartLegend, { data: legendData, orientation: "horizontal", height: 200, width: legendWidthValue, x: legendX, itemsPerRow: itemsPerRow, style: {
214
+ labels: {
215
+ fontSize: labelFontSize,
216
+ fill: "var(--pf-t--global--text--color--regular)",
217
+ },
218
+ } }) }) }) }));
219
+ 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: {
151
220
  bottom: 5,
152
221
  left: 20,
153
222
  right: 20,
@@ -158,7 +227,7 @@ export const MigrationDonutChart = ({ data, legend, customColors, height = 260,
158
227
  fontSize: titleFontSize,
159
228
  fontWeight: "bold",
160
229
  },
161
- ] })) : undefined, subTitleComponent: subTitle ? (_jsx(ChartLabel, { style: [
230
+ ] })) : undefined, subTitleComponent: subTitle ? (_jsx(ChartLabel, { dy: showChartLegend ? 7 : undefined, style: [
162
231
  {
163
232
  fill: subTitleColor,
164
233
  fontSize: subTitleFontSize,
@@ -178,15 +247,6 @@ export const MigrationDonutChart = ({ data, legend, customColors, height = 260,
178
247
  e.preventDefault();
179
248
  onTitleClick();
180
249
  }
181
- } }))] }), _jsx(Flex, { className: `${styles.legendContainer} ${css `margin-left: ${marginLeft};`}`, justifyContent: { default: "justifyContentCenter" }, alignItems: { default: "alignItemsFlexStart" }, children: _jsx(Flex, { className: styles.legendInner, spaceItems: { default: "spaceItemsMd" }, justifyContent: { default: "justifyContentCenter" }, alignItems: { default: "alignItemsCenter" }, flexWrap: { default: "wrap" }, children: data.map((item) => {
182
- const label = legendLabelFormatter
183
- ? legendLabelFormatter({
184
- x: item.name,
185
- countDisplay: item.countDisplay,
186
- })
187
- : item.name;
188
- const content = (_jsxs(_Fragment, { children: [_jsxs("svg", { width: "10", height: "10", "aria-hidden": "true", className: styles.legendIcon, children: [_jsx("title", { children: "Legend color indicator" }), _jsx("rect", { width: "10", height: "10", fill: getColor(item.legendCategory) })] }), _jsx("span", { children: label })] }));
189
- return (_jsx(FlexItem, { children: onItemClick ? (_jsx("button", { type: "button", onClick: () => onItemClick(item), className: styles.legendButton, children: content })) : (_jsx("span", { className: styles.legendLabel, children: content })) }, `${item.legendCategory}-${item.name}`));
190
- }) }) })] }));
250
+ } }))] }), showChartLegend ? chartLegendElement : htmlLegend] }));
191
251
  };
192
252
  export default MigrationDonutChart;
@@ -1,2 +1,2 @@
1
- export { MigrationDonutChart, type MigrationDonutChartDatum, type MigrationDonutChartProps, } from "./MigrationDonutChart.js";
1
+ export { MigrationDonutChart, type MigrationDonutChartDatum, type MigrationDonutChartLegendVariant, type MigrationDonutChartProps, } from "./MigrationDonutChart.js";
2
2
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/charts/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,KAAK,wBAAwB,EAC7B,KAAK,wBAAwB,GAC9B,MAAM,0BAA0B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/charts/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,KAAK,wBAAwB,EAC7B,KAAK,gCAAgC,EACrC,KAAK,wBAAwB,GAC9B,MAAM,0BAA0B,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"RadioButtonFormGroup.d.ts","sourceRoot":"","sources":["../../src/forms/RadioButtonFormGroup.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,UAAU,WAAW;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,UAAU,yBACR,SAAQ,IAAI,CAAC,cAAc,EAAE,aAAa,CAAC;IAC3C,OAAO,EAAE,WAAW,EAAE,CAAC;CACxB;AAED,MAAM,CAAC,OAAO,UAAU,oBAAoB,CAAC,EAC3C,EAAE,EACF,KAAK,EACL,IAAI,EACJ,UAAkB,EAClB,OAAO,EACP,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,yBAAyB,+BAoC3B"}
1
+ {"version":3,"file":"RadioButtonFormGroup.d.ts","sourceRoot":"","sources":["../../src/forms/RadioButtonFormGroup.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,UAAU,WAAW;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,UAAU,yBACR,SAAQ,IAAI,CAAC,cAAc,EAAE,aAAa,CAAC;IAC3C,OAAO,EAAE,WAAW,EAAE,CAAC;CACxB;AAED,MAAM,CAAC,OAAO,UAAU,oBAAoB,CAAC,EAC3C,EAAE,EACF,KAAK,EACL,IAAI,EACJ,UAAkB,EAClB,OAAO,EACP,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,yBAAyB,+BA2C3B"}
@@ -1,4 +1,4 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { FormGroup, Radio } from "@patternfly/react-core";
3
3
  import { Controller, useFormContext } from "react-hook-form";
4
4
  import FormFieldHelperText from "./FormFieldHelperText.js";
@@ -8,5 +8,5 @@ export default function RadioButtonFormGroup({ id, label, name, isRequired = fal
8
8
  const isTouched = methods.formState.touchedFields[name];
9
9
  const isSubmitted = methods.formState.isSubmitted;
10
10
  const showError = error && (isTouched || isSubmitted);
11
- return (_jsxs(FormGroup, { label: label, isRequired: isRequired, fieldId: id, ...props, children: [_jsx(Controller, { name: name, control: methods.control, render: ({ field }) => (_jsx("div", { style: { display: "flex", gap: "16px" }, role: "radiogroup", children: options.map((option) => (_jsx(Radio, { id: option.id, name: name, label: option.label, isChecked: field.value === option.value, onChange: () => field.onChange(option.value), onBlur: field.onBlur }, option.value))) })) }), _jsx(FormFieldHelperText, { helpText: helpText, errorMessage: showError ? error?.message : undefined })] }));
11
+ return (_jsxs(FormGroup, { label: label, isRequired: isRequired, fieldId: id, role: "radiogroup", isInline: true, ...props, children: [_jsx(Controller, { name: name, control: methods.control, render: ({ field }) => (_jsx(_Fragment, { children: options.map((option) => (_jsx(Radio, { id: option.id, name: name, label: option.label, isChecked: field.value === option.value, onChange: () => field.onChange(option.value), onBlur: field.onBlur }, option.value))) })) }), _jsx(FormFieldHelperText, { helpText: helpText, errorMessage: showError ? error?.message : undefined })] }));
12
12
  }
@@ -0,0 +1,7 @@
1
+ import type { FC } from "react";
2
+ import type { FeatureStatus } from "./infrastructureSummary.js";
3
+ export interface FeatureStatusBadgeProps {
4
+ status: FeatureStatus;
5
+ }
6
+ export declare const FeatureStatusBadge: FC<FeatureStatusBadgeProps>;
7
+ //# sourceMappingURL=FeatureStatusBadge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FeatureStatusBadge.d.ts","sourceRoot":"","sources":["../../src/report/FeatureStatusBadge.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAChC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAEhE,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,aAAa,CAAC;CACvB;AAED,eAAO,MAAM,kBAAkB,EAAE,EAAE,CAAC,uBAAuB,CAkB1D,CAAC"}
@@ -0,0 +1,13 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Label } from "@patternfly/react-core";
3
+ import { CheckCircleIcon, TimesCircleIcon } from "@patternfly/react-icons";
4
+ export const FeatureStatusBadge = ({ status }) => {
5
+ if (status === "unknown") {
6
+ return _jsx("span", { children: "\u2014" });
7
+ }
8
+ if (status === "enabled") {
9
+ return (_jsx(Label, { color: "green", isCompact: true, icon: _jsx(CheckCircleIcon, {}), children: "Enabled" }));
10
+ }
11
+ return (_jsx(Label, { color: "grey", isCompact: true, icon: _jsx(TimesCircleIcon, {}), children: "Disabled" }));
12
+ };
13
+ FeatureStatusBadge.displayName = "FeatureStatusBadge";
@@ -0,0 +1,9 @@
1
+ import type { FC } from "react";
2
+ import type { MigrationDonutChartLegendVariant } from "../charts/MigrationDonutChart.js";
3
+ export interface HostPowerStatesProps {
4
+ hostPowerStates?: Record<string, number>;
5
+ isExportMode?: boolean;
6
+ legendVariant?: MigrationDonutChartLegendVariant;
7
+ }
8
+ export declare const HostPowerStates: FC<HostPowerStatesProps>;
9
+ //# sourceMappingURL=HostPowerStates.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HostPowerStates.d.ts","sourceRoot":"","sources":["../../src/report/HostPowerStates.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAEhC,OAAO,KAAK,EAAE,gCAAgC,EAAE,MAAM,kCAAkC,CAAC;AAKzF,MAAM,WAAW,oBAAoB;IACnC,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,aAAa,CAAC,EAAE,gCAAgC,CAAC;CAClD;AAED,eAAO,MAAM,eAAe,EAAE,EAAE,CAAC,oBAAoB,CAwBpD,CAAC"}
@@ -0,0 +1,11 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { ServerIcon } from "@patternfly/react-icons";
3
+ import { useMemo } from "react";
4
+ import { REPORT_CARD_EMPTY_STATE_TITLES } from "./constants.js";
5
+ import { PowerStateCard } from "./PowerStateCard.js";
6
+ import { buildHostPowerStateChart } from "./powerStates.js";
7
+ export const HostPowerStates = ({ hostPowerStates, isExportMode = false, legendVariant, }) => {
8
+ const chart = useMemo(() => buildHostPowerStateChart(hostPowerStates), [hostPowerStates]);
9
+ return (_jsx(PowerStateCard, { id: "esxi-host-power-states", title: "ESXi host power states", icon: _jsx(ServerIcon, {}), emptyTitle: REPORT_CARD_EMPTY_STATE_TITLES.hostPowerStates, slices: chart.slices, legend: chart.legend, total: chart.total, subTitle: "Hosts", isExportMode: isExportMode, legendVariant: legendVariant }));
10
+ };
11
+ HostPowerStates.displayName = "HostPowerStates";
@@ -0,0 +1,7 @@
1
+ import type { FC } from "react";
2
+ import type { InfrastructureSummaryModel } from "./infrastructureSummary.js";
3
+ export interface InfrastructureSummaryProps {
4
+ summary: InfrastructureSummaryModel;
5
+ }
6
+ export declare const InfrastructureSummary: FC<InfrastructureSummaryProps>;
7
+ //# sourceMappingURL=InfrastructureSummary.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InfrastructureSummary.d.ts","sourceRoot":"","sources":["../../src/report/InfrastructureSummary.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAChC,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,4BAA4B,CAAC;AAE7E,MAAM,WAAW,0BAA0B;IACzC,OAAO,EAAE,0BAA0B,CAAC;CACrC;AAKD,eAAO,MAAM,qBAAqB,EAAE,EAAE,CAAC,0BAA0B,CAkChE,CAAC"}
@@ -0,0 +1,5 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Card, CardBody, CardTitle, DescriptionList, DescriptionListDescription, DescriptionListGroup, DescriptionListTerm, } from "@patternfly/react-core";
3
+ const formatCount = (value) => typeof value === "number" ? String(value) : "—";
4
+ export const InfrastructureSummary = ({ summary, }) => (_jsxs(Card, { isFullHeight: true, id: "infrastructure-summary", children: [_jsx(CardTitle, { children: "Infrastructure summary" }), _jsx(CardBody, { children: _jsxs(DescriptionList, { isAutoFit: true, displaySize: "lg", children: [_jsxs(DescriptionListGroup, { children: [_jsx(DescriptionListTerm, { children: "VMware version" }), _jsx(DescriptionListDescription, { children: summary.vmwareVersion })] }), _jsxs(DescriptionListGroup, { children: [_jsx(DescriptionListTerm, { children: "Datacenters" }), _jsx(DescriptionListDescription, { children: formatCount(summary.datacenters) })] }), _jsxs(DescriptionListGroup, { children: [_jsx(DescriptionListTerm, { children: "vCenters" }), _jsx(DescriptionListDescription, { children: formatCount(summary.vCenters) })] }), _jsxs(DescriptionListGroup, { children: [_jsx(DescriptionListTerm, { children: "ESXi hosts" }), _jsx(DescriptionListDescription, { children: formatCount(summary.esxiHosts) })] })] }) })] }));
5
+ InfrastructureSummary.displayName = "InfrastructureSummary";
@@ -1 +1 @@
1
- {"version":3,"file":"OSDistribution.d.ts","sourceRoot":"","sources":["../../src/report/OSDistribution.tsx"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,EAAE,EAAO,MAAM,OAAO,CAAC;AAQrC,OAAO,EAGL,KAAK,mBAAmB,EACzB,MAAM,oBAAoB,CAAC;AAyB5B,UAAU,mBAAmB;IAC3B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;IAC5C,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,eAAO,MAAM,cAAc,EAAE,EAAE,CAAC,mBAAmB,CAyBlD,CAAC;AAEF,UAAU,eAAe;IACvB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;IAC5C,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,eAAO,MAAM,UAAU,EAAE,EAAE,CAAC,eAAe,CAgH1C,CAAC"}
1
+ {"version":3,"file":"OSDistribution.d.ts","sourceRoot":"","sources":["../../src/report/OSDistribution.tsx"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,EAAE,EAAO,MAAM,OAAO,CAAC;AAQrC,OAAO,EAGL,KAAK,mBAAmB,EACzB,MAAM,oBAAoB,CAAC;AAY5B,UAAU,mBAAmB;IAC3B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;IAC5C,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,eAAO,MAAM,cAAc,EAAE,EAAE,CAAC,mBAAmB,CAyBlD,CAAC;AAEF,UAAU,eAAe;IACvB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;IAC5C,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,eAAO,MAAM,UAAU,EAAE,EAAE,CAAC,eAAe,CAoH1C,CAAC"}
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { css } from "@emotion/css";
3
- import { Card, CardBody, CardTitle, Flex, FlexItem, MenuToggle, SearchInput, Select, SelectList, SelectOption, Toolbar, ToolbarContent, ToolbarItem, } from "@patternfly/react-core";
3
+ import { Card, CardBody, CardTitle, Flex, FlexItem, MenuToggle, SearchInput, Select, SelectList, SelectOption, Stack, StackItem, Toolbar, ToolbarContent, ToolbarItem, } from "@patternfly/react-core";
4
4
  import { DesktopIcon } from "@patternfly/react-icons";
5
5
  import { Table, Tbody, Td, Th, Thead, Tr } from "@patternfly/react-table";
6
6
  import { CardEmptyState } from "./CardEmptyState.js";
@@ -13,19 +13,9 @@ import { OsNameCell } from "./OsUpgradeRecommendationPopover.js";
13
13
  import { getSupportTierLegendLabel, ORDERED_SUPPORT_TIERS, } from "./osSupportTier.js";
14
14
  import { SupportTierBadge } from "./SupportTierBadge.js";
15
15
  import { ALL_TIERS_FILTER, useOsBarChartViewModel, } from "./useOsBarChartViewModel.js";
16
- const filterToolbarStyle = css `
17
- padding-left: 0;
18
- padding-right: 0;
19
- `;
20
- const filterItemStyle = css `
21
- flex: 1 1 0;
22
- min-width: 0;
23
- `;
24
- const vmsColumnStyle = css `
25
- text-align: right;
26
- `;
27
16
  const tableScrollStyle = css `
28
17
  overflow: auto;
18
+ max-height: 350px;
29
19
  `;
30
20
  export const OSDistribution = ({ osData, isExportMode = false, }) => (_jsxs(Card, { className: isExportMode ? dashboardStyles.cardPrint : dashboardStyles.card, id: "os-distribution", children: [_jsx(CardTitle, { children: _jsxs(Flex, { alignItems: { default: "alignItemsCenter" }, spaceItems: { default: "spaceItemsSm" }, children: [_jsxs(FlexItem, { children: [_jsx(DesktopIcon, {}), " Operating Systems"] }), _jsx(FlexItem, { children: _jsx(OsSupportTiersHelpPopover, {}) })] }) }), _jsx(CardBody, { children: _jsx(OSBarChart, { osData: osData, isExportMode: isExportMode }) })] }));
31
21
  export const OSBarChart = ({ osData, isExportMode = false, }) => {
@@ -33,5 +23,7 @@ export const OSBarChart = ({ osData, isExportMode = false, }) => {
33
23
  if (vm.tableRows.length === 0) {
34
24
  return (_jsx(CardEmptyState, { title: REPORT_CARD_EMPTY_STATE_TITLES.operatingSystems }));
35
25
  }
36
- return (_jsxs(_Fragment, { children: [!isExportMode ? (_jsx(Toolbar, { className: filterToolbarStyle, children: _jsxs(ToolbarContent, { children: [_jsx(ToolbarItem, { className: filterItemStyle, children: _jsx(SearchInput, { placeholder: "Filter by OS", value: vm.osFilter, onChange: (_event, value) => vm.setOsFilter(value), onClear: vm.clearOsFilter, "aria-label": "Filter operating systems by name" }) }), _jsx(ToolbarItem, { className: filterItemStyle, children: _jsx(Select, { isOpen: vm.isTierSelectOpen, selected: vm.tierFilter, onSelect: vm.handleTierSelect, onOpenChange: vm.setIsTierSelectOpen, toggle: (toggleRef) => (_jsx(MenuToggle, { ref: toggleRef, isExpanded: vm.isTierSelectOpen, onClick: vm.toggleTierSelectOpen, style: { width: "100%" }, children: vm.tierFilterLabel })), "aria-label": "Filter operating systems by support tier", children: _jsxs(SelectList, { children: [_jsx(SelectOption, { value: ALL_TIERS_FILTER, children: "All tiers" }), ORDERED_SUPPORT_TIERS.map((tier) => (_jsx(SelectOption, { value: tier, children: getSupportTierLegendLabel(tier) }, tier)))] }) }) })] }) })) : null, vm.showUpgradeNotice ? _jsx(OsUpgradeNotice, {}) : null, _jsx("div", { className: isExportMode ? undefined : tableScrollStyle, style: isExportMode ? undefined : { maxHeight: "350px" }, children: _jsxs(Table, { "aria-label": "Operating systems", variant: "compact", className: tableFullWidthStyle, children: [_jsx(Thead, { children: _jsxs(Tr, { children: [_jsx(Th, { children: "OS" }), _jsx(Th, { children: "Tier" }), _jsx(Th, { className: vmsColumnStyle, children: "VMs" })] }) }), _jsx(Tbody, { children: vm.showNoResults ? (_jsx(Tr, { children: _jsx(Td, { colSpan: 3, children: _jsx(EmptySearchResults, { title: "No matching operating system found" }) }) })) : (vm.filteredRows.map((row) => (_jsxs(Tr, { children: [_jsx(Td, { dataLabel: "OS", children: _jsx(OsNameCell, { osName: row.osName, upgradeRecommendation: row.upgradeRecommendation, isExportMode: isExportMode }) }), _jsx(Td, { dataLabel: "Tier", children: _jsx(SupportTierBadge, { tier: row.tier, isExportMode: isExportMode }) }), _jsx(Td, { dataLabel: "VMs", className: vmsColumnStyle, children: row.count })] }, row.osName)))) })] }) })] }));
26
+ return (_jsxs(_Fragment, { children: [!isExportMode ? (_jsx(Toolbar, { hasNoPadding: true, children: _jsxs(ToolbarContent, { children: [_jsx(ToolbarItem, { children: _jsx(SearchInput, { placeholder: "Filter by OS", value: vm.osFilter, onChange: (_event, value) => vm.setOsFilter(value), onClear: vm.clearOsFilter, "aria-label": "Filter operating systems by name" }) }), _jsx(ToolbarItem, { children: _jsx(Select, { isOpen: vm.isTierSelectOpen, selected: vm.tierFilter, onSelect: vm.handleTierSelect, onOpenChange: vm.setIsTierSelectOpen, toggle: (toggleRef) => (_jsx(MenuToggle, { ref: toggleRef, isExpanded: vm.isTierSelectOpen, onClick: vm.toggleTierSelectOpen, isFullWidth: true, children: vm.tierFilterLabel })), "aria-label": "Filter operating systems by support tier", children: _jsxs(SelectList, { children: [_jsx(SelectOption, { value: ALL_TIERS_FILTER, children: "All tiers" }), ORDERED_SUPPORT_TIERS.map((tier) => (_jsx(SelectOption, { value: tier, children: getSupportTierLegendLabel(tier) }, tier)))] }) }) })] }) })) : null, _jsxs(Stack, { hasGutter: true, children: [vm.showUpgradeNotice ? (_jsx(StackItem, { children: _jsx(OsUpgradeNotice, {}) })) : null, _jsx(StackItem, { children: _jsx("div", { className: isExportMode
27
+ ? tableFullWidthStyle
28
+ : `${tableScrollStyle} ${tableFullWidthStyle}`, children: _jsxs(Table, { "aria-label": "Operating systems", variant: "compact", children: [_jsx(Thead, { children: _jsxs(Tr, { children: [_jsx(Th, { children: "OS" }), _jsx(Th, { children: "Tier" }), _jsx(Th, { children: "VMs" })] }) }), _jsx(Tbody, { children: vm.showNoResults ? (_jsx(Tr, { children: _jsx(Td, { colSpan: 3, children: _jsx(EmptySearchResults, { title: "No matching operating system found" }) }) })) : (vm.filteredRows.map((row) => (_jsxs(Tr, { children: [_jsx(Td, { dataLabel: "OS", children: _jsx(OsNameCell, { osName: row.osName, upgradeRecommendation: row.upgradeRecommendation, isExportMode: isExportMode }) }), _jsx(Td, { dataLabel: "Tier", children: _jsx(SupportTierBadge, { tier: row.tier, isExportMode: isExportMode }) }), _jsx(Td, { dataLabel: "VMs", children: row.count })] }, row.osName)))) })] }) }) })] })] }));
37
29
  };
@@ -1 +1 @@
1
- {"version":3,"file":"OsSupportTiersHelpPopover.d.ts","sourceRoot":"","sources":["../../src/report/OsSupportTiersHelpPopover.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAwEhC,eAAO,MAAM,yBAAyB,EAAE,EASvC,CAAC"}
1
+ {"version":3,"file":"OsSupportTiersHelpPopover.d.ts","sourceRoot":"","sources":["../../src/report/OsSupportTiersHelpPopover.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAsChC,eAAO,MAAM,yBAAyB,EAAE,EASvC,CAAC"}
@@ -1,37 +1,8 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { css } from "@emotion/css";
3
- import { Label } from "@patternfly/react-core";
2
+ import { Button, Content, Label, Stack, StackItem, } from "@patternfly/react-core";
4
3
  import { ExternalLinkAltIcon } from "@patternfly/react-icons";
5
4
  import { getSupportTierBadgeColor, getSupportTierDefinition, getSupportTierLegendLabel, ORDERED_SUPPORT_TIERS, SUPPORT_TIER_LEARN_MORE_URL, } from "./osSupportTier.js";
6
5
  import PopoverIcon from "./PopoverIcon.js";
7
- const tierListStyle = css `
8
- list-style: none;
9
- padding: 0;
10
- margin: 0;
11
- display: flex;
12
- flex-direction: column;
13
- gap: var(--pf-t--global--spacer--400);
14
- `;
15
- const tierItemStyle = css `
16
- display: flex;
17
- flex-direction: column;
18
- gap: var(--pf-t--global--spacer--100);
19
- `;
20
- const tierBadgeStyle = css `
21
- width: fit-content;
22
- max-width: 100%;
23
- align-self: flex-start;
24
- `;
25
- const tierDescriptionStyle = css `
26
- margin: 0;
27
- color: var(--pf-t--global--text--color--regular);
28
- `;
29
- const learnMoreLinkStyle = css `
30
- display: inline-flex;
31
- align-items: center;
32
- gap: var(--pf-t--global--spacer--xs);
33
- margin-top: var(--pf-t--global--spacer--400);
34
- `;
35
- const OsSupportTiersHelpBody = () => (_jsxs("div", { children: [_jsx("ul", { className: tierListStyle, children: ORDERED_SUPPORT_TIERS.map((tier) => (_jsxs("li", { className: tierItemStyle, children: [_jsx(Label, { className: tierBadgeStyle, color: getSupportTierBadgeColor(tier), isCompact: true, children: getSupportTierLegendLabel(tier) }), _jsx("p", { className: tierDescriptionStyle, children: getSupportTierDefinition(tier) })] }, tier))) }), _jsxs("a", { className: learnMoreLinkStyle, href: SUPPORT_TIER_LEARN_MORE_URL, target: "_blank", rel: "noopener noreferrer", children: ["Learn more ", _jsx(ExternalLinkAltIcon, {})] })] }));
6
+ const OsSupportTiersHelpBody = () => (_jsxs(Stack, { hasGutter: true, children: [ORDERED_SUPPORT_TIERS.map((tier) => (_jsxs(StackItem, { children: [_jsx(Label, { color: getSupportTierBadgeColor(tier), isCompact: true, children: getSupportTierLegendLabel(tier) }), _jsx(Content, { component: "p", children: getSupportTierDefinition(tier) })] }, tier))), _jsx(StackItem, { children: _jsx(Button, { variant: "link", isInline: true, component: "a", href: SUPPORT_TIER_LEARN_MORE_URL, target: "_blank", rel: "noopener noreferrer", icon: _jsx(ExternalLinkAltIcon, {}), iconPosition: "end", "aria-label": "Learn more about operating system support tiers", children: "Learn more" }) })] }));
36
7
  export const OsSupportTiersHelpPopover = () => (_jsx(PopoverIcon, { noVerticalAlign: true, maxWidth: "40rem", headerContent: "Guest OS support tiers", bodyContent: _jsx(OsSupportTiersHelpBody, {}), buttonOuiaId: "guest-os-support-tiers-help", "aria-label": "Guest OS support tiers help" }));
37
8
  OsSupportTiersHelpPopover.displayName = "OsSupportTiersHelpPopover";
@@ -1 +1 @@
1
- {"version":3,"file":"OsUpgradeNotice.d.ts","sourceRoot":"","sources":["../../src/report/OsUpgradeNotice.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAMhC,eAAO,MAAM,eAAe,EAAE,EAiB7B,CAAC"}
1
+ {"version":3,"file":"OsUpgradeNotice.d.ts","sourceRoot":"","sources":["../../src/report/OsUpgradeNotice.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAEhC,eAAO,MAAM,eAAe,EAAE,EAgB7B,CAAC"}
@@ -1,9 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { css } from "@emotion/css";
3
2
  import { Content, Flex, FlexItem, Icon } from "@patternfly/react-core";
4
3
  import { InfoCircleIcon } from "@patternfly/react-icons";
5
- const noticeStyle = css `
6
- margin-bottom: var(--pf-t--global--spacer--200);
7
- `;
8
- export const OsUpgradeNotice = () => (_jsxs(Flex, { alignItems: { default: "alignItemsCenter" }, spaceItems: { default: "spaceItemsSm" }, className: noticeStyle, children: [_jsx(FlexItem, { children: _jsx(Icon, { status: "info", children: _jsx(InfoCircleIcon, {}) }) }), _jsx(FlexItem, { children: _jsx(Content, { component: "p", style: { fontWeight: 500 }, children: "Some operating systems may need upgrades before migration" }) })] }));
4
+ export const OsUpgradeNotice = () => (_jsxs(Flex, { alignItems: { default: "alignItemsCenter" }, spaceItems: { default: "spaceItemsSm" }, children: [_jsx(FlexItem, { children: _jsx(Icon, { status: "info", children: _jsx(InfoCircleIcon, {}) }) }), _jsx(FlexItem, { children: _jsx(Content, { component: "p", children: "Some operating systems may need upgrades before migration" }) })] }));
9
5
  OsUpgradeNotice.displayName = "OsUpgradeNotice";
@@ -0,0 +1,17 @@
1
+ import type { FC, ReactNode } from "react";
2
+ import { type MigrationDonutChartDatum, type MigrationDonutChartLegendVariant } from "../charts/MigrationDonutChart.js";
3
+ export interface PowerStateCardProps {
4
+ id: string;
5
+ title: string;
6
+ icon: ReactNode;
7
+ emptyTitle: string;
8
+ slices: MigrationDonutChartDatum[];
9
+ legend: Record<string, string>;
10
+ total: number;
11
+ subTitle: string;
12
+ isExportMode?: boolean;
13
+ itemsPerRow?: number;
14
+ legendVariant?: MigrationDonutChartLegendVariant;
15
+ }
16
+ export declare const PowerStateCard: FC<PowerStateCardProps>;
17
+ //# sourceMappingURL=PowerStateCard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PowerStateCard.d.ts","sourceRoot":"","sources":["../../src/report/PowerStateCard.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAC3C,OAAO,EAEL,KAAK,wBAAwB,EAC7B,KAAK,gCAAgC,EACtC,MAAM,kCAAkC,CAAC;AAI1C,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,SAAS,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,wBAAwB,EAAE,CAAC;IACnC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,gCAAgC,CAAC;CAClD;AAED,eAAO,MAAM,cAAc,EAAE,EAAE,CAAC,mBAAmB,CA8ClD,CAAC"}
@@ -0,0 +1,7 @@
1
+ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
+ import { Card, CardBody, CardTitle } from "@patternfly/react-core";
3
+ import { MigrationDonutChart, } from "../charts/MigrationDonutChart.js";
4
+ import { CardEmptyState } from "./CardEmptyState.js";
5
+ import { dashboardStyles } from "./dashboardStyles.js";
6
+ export const PowerStateCard = ({ id, title, icon, emptyTitle, slices, legend, total, subTitle, isExportMode = false, itemsPerRow = 2, legendVariant = "html", }) => (_jsxs(Card, { className: isExportMode ? dashboardStyles.cardPrint : dashboardStyles.card, id: id, children: [_jsxs(CardTitle, { children: [icon, " ", title] }), _jsx(CardBody, { children: total === 0 ? (_jsx(CardEmptyState, { title: emptyTitle })) : (_jsx(MigrationDonutChart, { legendVariant: legendVariant, data: slices, legend: legend, height: 300, width: 420, donutThickness: 18, padAngle: 1, title: `${total}`, subTitle: subTitle, subTitleColor: "var(--pf-t--global--text--color--subtle)", titleFontSize: 34, labelFontSize: 16, itemsPerRow: itemsPerRow, marginLeft: "0%", tooltipLabelFormatter: ({ datum, percent }) => `${datum.countDisplay}\n${percent.toFixed(1)}%` })) })] }));
7
+ PowerStateCard.displayName = "PowerStateCard";
@@ -1 +1 @@
1
- {"version":3,"file":"SupportTierBadge.d.ts","sourceRoot":"","sources":["../../src/report/SupportTierBadge.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAChC,OAAO,EAKL,KAAK,WAAW,EACjB,MAAM,oBAAoB,CAAC;AAW5B,UAAU,qBAAqB;IAC7B,IAAI,EAAE,WAAW,CAAC;IAClB,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAYD,eAAO,MAAM,gBAAgB,EAAE,EAAE,CAAC,qBAAqB,CAiBtD,CAAC"}
1
+ {"version":3,"file":"SupportTierBadge.d.ts","sourceRoot":"","sources":["../../src/report/SupportTierBadge.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAChC,OAAO,EAKL,KAAK,WAAW,EACjB,MAAM,oBAAoB,CAAC;AAa5B,UAAU,qBAAqB;IAC7B,IAAI,EAAE,WAAW,CAAC;IAClB,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAYD,eAAO,MAAM,gBAAgB,EAAE,EAAE,CAAC,qBAAqB,CAiBtD,CAAC"}
@@ -2,17 +2,19 @@ import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { css } from "@emotion/css";
3
3
  import { Label, Tooltip } from "@patternfly/react-core";
4
4
  import { getSupportTierBadgeColor, getSupportTierBadgeInlineStyle, getSupportTierDefinition, getSupportTierLegendLabel, } from "./osSupportTier.js";
5
- const exportBadgeStyle = css `
5
+ const exportBadgeStyle = (backgroundColor, color) => css `
6
6
  display: inline-block;
7
7
  padding: var(--pf-t--global--spacer--xs) var(--pf-t--global--spacer--sm);
8
8
  border-radius: var(--pf-t--global--border--radius--pill);
9
9
  font-size: var(--pf-t--global--font--size--body--sm);
10
10
  line-height: var(--pf-t--global--font--line-height--body);
11
11
  white-space: nowrap;
12
+ background-color: ${backgroundColor};
13
+ color: ${color};
12
14
  `;
13
15
  const ExportSupportTierBadge = ({ tier }) => {
14
16
  const { backgroundColor, color } = getSupportTierBadgeInlineStyle(tier);
15
- return (_jsx("span", { className: exportBadgeStyle, style: { backgroundColor, color }, children: getSupportTierLegendLabel(tier) }));
17
+ return (_jsx("span", { className: exportBadgeStyle(backgroundColor, color), children: getSupportTierLegendLabel(tier) }));
16
18
  };
17
19
  export const SupportTierBadge = ({ tier, isExportMode = false, }) => {
18
20
  if (isExportMode) {
@@ -0,0 +1,10 @@
1
+ import type { FC } from "react";
2
+ import type { ClusterDetailRow, ClusterDetailsModel } from "./infrastructureSummary.js";
3
+ export interface VCenterClusterDetailsProps {
4
+ isAggregateView: boolean;
5
+ rows: ClusterDetailRow[];
6
+ details?: ClusterDetailsModel;
7
+ isExportMode?: boolean;
8
+ }
9
+ export declare const VCenterClusterDetails: FC<VCenterClusterDetailsProps>;
10
+ //# sourceMappingURL=VCenterClusterDetails.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VCenterClusterDetails.d.ts","sourceRoot":"","sources":["../../src/report/VCenterClusterDetails.tsx"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAEhC,OAAO,KAAK,EACV,gBAAgB,EAChB,mBAAmB,EAEpB,MAAM,4BAA4B,CAAC;AAEpC,MAAM,WAAW,0BAA0B;IACzC,eAAe,EAAE,OAAO,CAAC;IACzB,IAAI,EAAE,gBAAgB,EAAE,CAAC;IACzB,OAAO,CAAC,EAAE,mBAAmB,CAAC;IAC9B,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAmKD,eAAO,MAAM,qBAAqB,EAAE,EAAE,CAAC,0BAA0B,CAgBhE,CAAC"}