@openshift-migration-advisor/shared-components 0.28.0 → 0.29.0-8024400889ad
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.
- package/dist/charts/MigrationDonutChart.d.ts.map +1 -1
- package/dist/charts/MigrationDonutChart.js +15 -4
- package/dist/report/ChartExportProvider.d.ts +1 -1
- package/dist/report/ChartExportProvider.d.ts.map +1 -1
- package/dist/report/ChartExportProvider.js +4 -1
- package/dist/report/FeatureStatusBadge.js +1 -1
- package/dist/report/OsUpgradeRecommendationPopover.d.ts.map +1 -1
- package/dist/report/OsUpgradeRecommendationPopover.js +1 -7
- package/dist/report/ReportExportMenu.d.ts +1 -0
- package/dist/report/ReportExportMenu.d.ts.map +1 -1
- package/dist/report/ReportExportMenu.js +38 -4
- package/dist/report/StorageOverview.d.ts +27 -0
- package/dist/report/StorageOverview.d.ts.map +1 -0
- package/dist/report/StorageOverview.js +331 -0
- package/dist/report/VMMigrationStatus.d.ts +33 -0
- package/dist/report/VMMigrationStatus.d.ts.map +1 -0
- package/dist/report/VMMigrationStatus.js +129 -0
- package/dist/report/captureChartElement.d.ts +6 -1
- package/dist/report/captureChartElement.d.ts.map +1 -1
- package/dist/report/captureChartElement.js +13 -4
- package/dist/report/chartExport.js +1 -1
- package/dist/report/dashboardStyles.d.ts +6 -0
- package/dist/report/dashboardStyles.d.ts.map +1 -1
- package/dist/report/dashboardStyles.js +7 -4
- package/dist/report/index.d.ts +3 -1
- package/dist/report/index.d.ts.map +1 -1
- package/dist/report/index.js +2 -0
- package/dist/report/reportExportOptions.d.ts +13 -2
- package/dist/report/reportExportOptions.d.ts.map +1 -1
- package/dist/report/reportExportOptions.js +13 -5
- package/package.json +2 -2
- package/src/charts/MigrationDonutChart.tsx +27 -6
- package/src/charts/__tests__/MigrationDonutChart.test.tsx +53 -0
- package/src/report/ChartExportProvider.tsx +5 -1
- package/src/report/FeatureStatusBadge.tsx +1 -1
- package/src/report/OsUpgradeRecommendationPopover.tsx +0 -8
- package/src/report/ReportExportMenu.tsx +69 -13
- package/src/report/StorageOverview.tsx +646 -0
- package/src/report/VMMigrationStatus.tsx +358 -0
- package/src/report/__tests__/StorageOverview.test.tsx +267 -0
- package/src/report/__tests__/VMMigrationStatus.test.tsx +178 -0
- package/src/report/__tests__/captureChartElement.test.ts +47 -0
- package/src/report/captureChartElement.ts +18 -3
- package/src/report/chartExport.ts +1 -1
- package/src/report/dashboardStyles.ts +7 -4
- package/src/report/index.ts +12 -0
- package/src/report/reportExportOptions.ts +28 -5
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { css } from "@emotion/css";
|
|
3
|
+
import { Card, CardBody, CardTitle, Content, Dropdown, DropdownItem, DropdownList, Flex, FlexItem, MenuToggle, } from "@patternfly/react-core";
|
|
4
|
+
import { VirtualMachineIcon } from "@patternfly/react-icons";
|
|
5
|
+
import { chart_color_blue_300, chart_color_purple_100, chart_color_purple_300, chart_color_teal_200, chart_color_yellow_400, } from "@patternfly/react-tokens";
|
|
6
|
+
import { useMemo, useState } from "react";
|
|
7
|
+
import { MigrationDonutChart, } from "../charts/MigrationDonutChart.js";
|
|
8
|
+
import { CardEmptyState } from "./CardEmptyState.js";
|
|
9
|
+
import { ChartHeaderActions } from "./ChartDownloadButton.js";
|
|
10
|
+
import { ChartExportSurface } from "./ChartExportSurface.js";
|
|
11
|
+
import { chartExportViewsFromLabels } from "./chartExport.js";
|
|
12
|
+
import { chartColorFailure, chartColorSuccess, REPORT_CARD_EMPTY_STATE_TITLES, } from "./constants.js";
|
|
13
|
+
import { dashboardStyles } from "./dashboardStyles.js";
|
|
14
|
+
const VIEW_MODE_LABELS = {
|
|
15
|
+
issuesVsNoIssues: "No issues vs with issues",
|
|
16
|
+
issuesBreakdown: "With issues breakdown",
|
|
17
|
+
};
|
|
18
|
+
const CHART_ID = "vm-migration-status";
|
|
19
|
+
const CHART_TITLE = "VM migration status";
|
|
20
|
+
const MIGRATABLE_LABEL = "Migratable";
|
|
21
|
+
const NOT_MIGRATABLE_LABEL = "Not ready for migration";
|
|
22
|
+
const CATEGORY_ORDER = [
|
|
23
|
+
{ label: "Critical", key: "critical" },
|
|
24
|
+
{ label: "Error", key: "error" },
|
|
25
|
+
{ label: "Warning", key: "warning" },
|
|
26
|
+
{ label: "Information", key: "information" },
|
|
27
|
+
{ label: "Advisory", key: "advisory" },
|
|
28
|
+
];
|
|
29
|
+
/**
|
|
30
|
+
* Same categorical order as the previous breakdown hex palette, mapped onto
|
|
31
|
+
* PatternFly `chart_color_*` tokens (nearest token where the old hex was not
|
|
32
|
+
* itself a token).
|
|
33
|
+
*/
|
|
34
|
+
const CATEGORY_COLORS = {
|
|
35
|
+
Critical: chart_color_blue_300.value,
|
|
36
|
+
Error: chart_color_purple_300.value,
|
|
37
|
+
Warning: chart_color_purple_100.value,
|
|
38
|
+
Information: chart_color_teal_200.value,
|
|
39
|
+
Advisory: chart_color_yellow_400.value,
|
|
40
|
+
};
|
|
41
|
+
const menuToggleMinWidth = css `
|
|
42
|
+
min-width: 250px;
|
|
43
|
+
`;
|
|
44
|
+
const isViewMode = (value) => value === "issuesVsNoIssues" || value === "issuesBreakdown";
|
|
45
|
+
const toCount = (value) => typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : 0;
|
|
46
|
+
export const VMMigrationStatus = ({ data, issuesBreakdown, onReadinessSelect, onCategorySelect, onTitleClick, legendVariant = "html", }) => {
|
|
47
|
+
const [viewMode, setViewMode] = useState("issuesVsNoIssues");
|
|
48
|
+
const [isDropdownOpen, setIsDropdownOpen] = useState(false);
|
|
49
|
+
const totalVMs = data.migratable + data.nonMigratable;
|
|
50
|
+
const donutData = [
|
|
51
|
+
{
|
|
52
|
+
name: MIGRATABLE_LABEL,
|
|
53
|
+
count: data.migratable,
|
|
54
|
+
countDisplay: `${data.migratable} VMs`,
|
|
55
|
+
legendCategory: MIGRATABLE_LABEL,
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
name: NOT_MIGRATABLE_LABEL,
|
|
59
|
+
count: data.nonMigratable,
|
|
60
|
+
countDisplay: `${data.nonMigratable} VMs`,
|
|
61
|
+
legendCategory: NOT_MIGRATABLE_LABEL,
|
|
62
|
+
},
|
|
63
|
+
];
|
|
64
|
+
const legend = {
|
|
65
|
+
[MIGRATABLE_LABEL]: chartColorSuccess,
|
|
66
|
+
[NOT_MIGRATABLE_LABEL]: chartColorFailure,
|
|
67
|
+
};
|
|
68
|
+
const breakdownData = useMemo(() => {
|
|
69
|
+
if (!issuesBreakdown) {
|
|
70
|
+
return [];
|
|
71
|
+
}
|
|
72
|
+
return CATEGORY_ORDER.map(({ label, key }) => ({
|
|
73
|
+
name: label,
|
|
74
|
+
count: toCount(issuesBreakdown[key]),
|
|
75
|
+
}));
|
|
76
|
+
}, [issuesBreakdown]);
|
|
77
|
+
const maxCount = useMemo(() => breakdownData.length > 0
|
|
78
|
+
? Math.max(...breakdownData.map((d) => d.count))
|
|
79
|
+
: 0, [breakdownData]);
|
|
80
|
+
const chartTitle = `${CHART_TITLE} — ${VIEW_MODE_LABELS[viewMode]}`;
|
|
81
|
+
return (_jsx(ChartExportSurface, { id: CHART_ID, title: chartTitle, exportViews: chartExportViewsFromLabels(CHART_TITLE, VIEW_MODE_LABELS), activeExportViewId: viewMode, onExportViewChange: (viewId) => {
|
|
82
|
+
if (isViewMode(viewId)) {
|
|
83
|
+
setViewMode(viewId);
|
|
84
|
+
}
|
|
85
|
+
}, children: _jsxs(Card, { className: dashboardStyles.card, children: [_jsx(CardTitle, { children: _jsxs(Flex, { alignItems: { default: "alignItemsCenter" }, justifyContent: { default: "justifyContentSpaceBetween" }, children: [_jsxs(FlexItem, { children: [_jsx(VirtualMachineIcon, {}), " VM Migration Status"] }), _jsx(ChartHeaderActions, { chartId: CHART_ID, title: chartTitle, children: _jsx(Dropdown, { isOpen: isDropdownOpen, onSelect: (_event, value) => {
|
|
86
|
+
if (isViewMode(value)) {
|
|
87
|
+
setViewMode(value);
|
|
88
|
+
}
|
|
89
|
+
setIsDropdownOpen(false);
|
|
90
|
+
}, onOpenChange: setIsDropdownOpen, toggle: (toggleRef) => (_jsx(MenuToggle, { ref: toggleRef, onClick: () => setIsDropdownOpen((open) => !open), isExpanded: isDropdownOpen, className: menuToggleMinWidth, children: VIEW_MODE_LABELS[viewMode] })), children: _jsxs(DropdownList, { children: [_jsx(DropdownItem, { value: "issuesVsNoIssues", children: VIEW_MODE_LABELS.issuesVsNoIssues }, "issuesVsNoIssues"), _jsx(DropdownItem, { value: "issuesBreakdown", children: VIEW_MODE_LABELS.issuesBreakdown }, "issuesBreakdown")] }) }) })] }) }), _jsx(CardBody, { className: dashboardStyles.cardBodyScrollable, children: viewMode === "issuesVsNoIssues" ? (totalVMs === 0 ? (_jsx(CardEmptyState, { title: REPORT_CARD_EMPTY_STATE_TITLES.migrationStatus })) : (_jsx(MigrationDonutChart, { legendVariant: legendVariant, data: donutData, legend: legend, height: 300, width: 420, donutThickness: 18, padAngle: 1, title: `${totalVMs}`, subTitle: "VMs", subTitleColor: "var(--pf-t--global--text--color--subtle)", titleFontSize: 34, legendLabelFormatter: ({ x, countDisplay }) => `${x} (${countDisplay})`, onItemClick: onReadinessSelect
|
|
91
|
+
? (item) => onReadinessSelect(item.name === MIGRATABLE_LABEL)
|
|
92
|
+
: undefined, onTitleClick: onTitleClick }))) : breakdownData.length === 0 ? (_jsx(CardEmptyState, { title: REPORT_CARD_EMPTY_STATE_TITLES.issuesBreakdown })) : (_jsxs("div", { children: [_jsx("div", { className: dashboardStyles.storageChartWrapper, children: _jsx(Flex, { direction: { default: "row" }, alignItems: { default: "alignItemsFlexEnd" }, justifyContent: { default: "justifyContentCenter" }, spaceItems: { default: "spaceItemsMd" }, style: {
|
|
93
|
+
height: "250px",
|
|
94
|
+
width: "100%",
|
|
95
|
+
}, children: breakdownData.map((item) => {
|
|
96
|
+
const heightPercentage = maxCount > 0 ? (item.count / maxCount) * 100 : 0;
|
|
97
|
+
const minHeightPercentage = item.count > 0 ? 20 : 0;
|
|
98
|
+
const finalHeightPercentage = Math.max(heightPercentage, minHeightPercentage);
|
|
99
|
+
const barColor = CATEGORY_COLORS[item.name] || CATEGORY_COLORS.Critical;
|
|
100
|
+
return (_jsxs(Flex, { direction: { default: "column" }, alignItems: { default: "alignItemsCenter" }, spaceItems: { default: "spaceItemsSm" }, style: { flex: "1", maxWidth: "120px" }, children: [_jsx(FlexItem, { style: {
|
|
101
|
+
height: "200px",
|
|
102
|
+
display: "flex",
|
|
103
|
+
alignItems: "flex-end",
|
|
104
|
+
width: "100%",
|
|
105
|
+
justifyContent: "center",
|
|
106
|
+
}, children: _jsx("button", { type: "button", onClick: () => onCategorySelect?.(item.name), title: `${item.name}: ${item.count} VMs`, style: {
|
|
107
|
+
width: "60px",
|
|
108
|
+
height: `${finalHeightPercentage}%`,
|
|
109
|
+
backgroundColor: barColor,
|
|
110
|
+
transition: "height 0.3s ease",
|
|
111
|
+
borderRadius: "4px 4px 0 0",
|
|
112
|
+
cursor: "pointer",
|
|
113
|
+
border: "none",
|
|
114
|
+
padding: 0,
|
|
115
|
+
} }) }), _jsx(FlexItem, { children: _jsxs(Content, { component: "small", style: {
|
|
116
|
+
fontSize: "12px",
|
|
117
|
+
textAlign: "center",
|
|
118
|
+
wordBreak: "break-word",
|
|
119
|
+
color: "var(--pf-t--global--text--color--regular)",
|
|
120
|
+
}, children: [item.name, _jsx("br", {}), "(", item.count, " VMs)"] }) })] }, item.name));
|
|
121
|
+
}) }) }), _jsx("div", { children: _jsx(Content, { component: "small", style: {
|
|
122
|
+
fontSize: "12px",
|
|
123
|
+
color: "var(--pf-t--global--text--color--subtle)",
|
|
124
|
+
marginTop: "16px",
|
|
125
|
+
textAlign: "center",
|
|
126
|
+
display: "block",
|
|
127
|
+
}, children: "Totals may exceed the unique VM count because a VM can appear in multiple categories" }) })] })) })] }) }));
|
|
128
|
+
};
|
|
129
|
+
VMMigrationStatus.displayName = "VMMigrationStatus";
|
|
@@ -1,8 +1,13 @@
|
|
|
1
|
+
export declare const CHART_CAPTURE_SCALE_SINGLE = 2;
|
|
2
|
+
export type CaptureChartElementOptions = {
|
|
3
|
+
/** Higher scale sharpens text in PNG exports; keep at 1 for bulk PDF/zip. */
|
|
4
|
+
scale?: number;
|
|
5
|
+
};
|
|
1
6
|
/**
|
|
2
7
|
* Tab panels stay mounted with `hidden` / `display:none` when another tab is
|
|
3
8
|
* active. html2canvas then measures a 0×0 box. Reveal those ancestors off-screen
|
|
4
9
|
* for the duration of the capture, then restore.
|
|
5
10
|
*/
|
|
6
11
|
export declare function revealHiddenChartAncestors(element: HTMLElement): () => void;
|
|
7
|
-
export declare function captureChartElement(element: HTMLElement): Promise<HTMLCanvasElement>;
|
|
12
|
+
export declare function captureChartElement(element: HTMLElement, options?: CaptureChartElementOptions): Promise<HTMLCanvasElement>;
|
|
8
13
|
//# sourceMappingURL=captureChartElement.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"captureChartElement.d.ts","sourceRoot":"","sources":["../../src/report/captureChartElement.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"captureChartElement.d.ts","sourceRoot":"","sources":["../../src/report/captureChartElement.ts"],"names":[],"mappings":"AAeA,eAAO,MAAM,0BAA0B,IAAI,CAAC;AAG5C,MAAM,MAAM,0BAA0B,GAAG;IACvC,6EAA6E;IAC7E,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAwBF;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,IAAI,CAqD3E;AAwQD,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,WAAW,EACpB,OAAO,GAAE,0BAA+B,GACvC,OAAO,CAAC,iBAAiB,CAAC,CA0C5B"}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { t_color_gray_20, t_color_white, t_global_text_color_regular, } from "@patternfly/react-tokens";
|
|
2
2
|
import html2canvas from "html2canvas-pro";
|
|
3
3
|
import { applyLightThemeToDocument, CHART_EXPORT_CAPTURING_ATTR, CHART_EXPORT_SCROLL_ATTR, shouldIgnoreChartExportElement, } from "./chartExport.js";
|
|
4
|
-
/**
|
|
5
|
-
const
|
|
4
|
+
/** Default scale for bulk exports; single-chart PNG uses a higher scale. */
|
|
5
|
+
const CHART_CAPTURE_SCALE_DEFAULT = 1;
|
|
6
|
+
export const CHART_CAPTURE_SCALE_SINGLE = 2;
|
|
7
|
+
const EXPORT_FONT_FAMILY = "RedHatText, Overpass, Helvetica, Arial, sans-serif";
|
|
6
8
|
const HIDDEN_LAYOUT_STYLE_KEYS = [
|
|
7
9
|
"display",
|
|
8
10
|
"position",
|
|
@@ -140,6 +142,7 @@ function applyLightThemeSvgText(root) {
|
|
|
140
142
|
}
|
|
141
143
|
node.style.fill = LIGHT_EXPORT_TEXT;
|
|
142
144
|
node.style.color = LIGHT_EXPORT_TEXT;
|
|
145
|
+
node.style.fontFamily = EXPORT_FONT_FAMILY;
|
|
143
146
|
}
|
|
144
147
|
}
|
|
145
148
|
function hideCardBeforePseudo() {
|
|
@@ -266,7 +269,8 @@ function prepareCaptureLayout(element) {
|
|
|
266
269
|
}
|
|
267
270
|
};
|
|
268
271
|
}
|
|
269
|
-
export async function captureChartElement(element) {
|
|
272
|
+
export async function captureChartElement(element, options = {}) {
|
|
273
|
+
const scale = options.scale ?? CHART_CAPTURE_SCALE_DEFAULT;
|
|
270
274
|
const restoreHidden = revealHiddenChartAncestors(element);
|
|
271
275
|
const restoreLayout = prepareCaptureLayout(element);
|
|
272
276
|
element.setAttribute(CHART_EXPORT_CAPTURING_ATTR, "");
|
|
@@ -284,14 +288,19 @@ export async function captureChartElement(element) {
|
|
|
284
288
|
useCORS: true,
|
|
285
289
|
backgroundColor: LIGHT_EXPORT_BACKGROUND,
|
|
286
290
|
logging: false,
|
|
287
|
-
scale
|
|
291
|
+
scale,
|
|
288
292
|
imageTimeout: 0,
|
|
289
293
|
ignoreElements: (node) => node instanceof Element &&
|
|
290
294
|
shouldIgnoreChartExportElement(node, element),
|
|
291
295
|
onclone: (clonedDoc, clonedElement) => {
|
|
296
|
+
// Dropping the dark-theme class off the clone root makes every
|
|
297
|
+
// PatternFly CSS-variable surface (cards, tables, labels) resolve to
|
|
298
|
+
// light automatically — html2canvas reads computed styles from this
|
|
299
|
+
// clone. Only Victory's inlined SVG text needs explicit recoloring.
|
|
292
300
|
applyLightThemeToDocument(clonedDoc);
|
|
293
301
|
applyComputedStylesToClone(element, clonedElement);
|
|
294
302
|
applyLightThemeSvgText(clonedElement);
|
|
303
|
+
clonedElement.style.fontFamily = EXPORT_FONT_FAMILY;
|
|
295
304
|
},
|
|
296
305
|
});
|
|
297
306
|
}
|
|
@@ -3,6 +3,12 @@ export declare const dashboardStyles: {
|
|
|
3
3
|
cardScroll: string;
|
|
4
4
|
equalHeightRow: string;
|
|
5
5
|
equalHeight: string;
|
|
6
|
+
/**
|
|
7
|
+
* Flex child of {@link dashboardStyles.card}. `min-height: 0` lets the body
|
|
8
|
+
* shrink inside the card max-height; `overflow: auto` scrolls tables and tall
|
|
9
|
+
* charts when needed (phantom scrollbars on donut cards are avoided by the
|
|
10
|
+
* card layout and ChartExportSurface sizing, not a second body class).
|
|
11
|
+
*/
|
|
6
12
|
cardBodyScrollable: string;
|
|
7
13
|
card: string;
|
|
8
14
|
storageCardOverflowHidden: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dashboardStyles.d.ts","sourceRoot":"","sources":["../../src/report/dashboardStyles.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,eAAe
|
|
1
|
+
{"version":3,"file":"dashboardStyles.d.ts","sourceRoot":"","sources":["../../src/report/dashboardStyles.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,eAAe;;;;;IA8B1B;;;;;OAKG;;;;;;;;;CAkDJ,CAAC;AAEF,eAAO,MAAM,mBAAmB,QAM/B,CAAC"}
|
|
@@ -25,6 +25,12 @@ export const dashboardStyles = {
|
|
|
25
25
|
flex: 1 1 0;
|
|
26
26
|
height: 100%;
|
|
27
27
|
`,
|
|
28
|
+
/**
|
|
29
|
+
* Flex child of {@link dashboardStyles.card}. `min-height: 0` lets the body
|
|
30
|
+
* shrink inside the card max-height; `overflow: auto` scrolls tables and tall
|
|
31
|
+
* charts when needed (phantom scrollbars on donut cards are avoided by the
|
|
32
|
+
* card layout and ChartExportSurface sizing, not a second body class).
|
|
33
|
+
*/
|
|
28
34
|
cardBodyScrollable: css `
|
|
29
35
|
overflow: auto;
|
|
30
36
|
`,
|
|
@@ -32,12 +38,9 @@ export const dashboardStyles = {
|
|
|
32
38
|
// at the same specificity, which wins in the production build due to stylesheet
|
|
33
39
|
// injection order. `!important` forces `hidden` regardless of that order.
|
|
34
40
|
card: css `
|
|
35
|
-
|
|
36
|
-
max-height: 520px;
|
|
37
|
-
height: 100%;
|
|
41
|
+
height: 520px;
|
|
38
42
|
display: flex;
|
|
39
43
|
flex-direction: column;
|
|
40
|
-
justify-content: space-between;
|
|
41
44
|
overflow: hidden !important;
|
|
42
45
|
`,
|
|
43
46
|
storageCardOverflowHidden: css `
|
package/dist/report/index.d.ts
CHANGED
|
@@ -35,10 +35,12 @@ export type { PowerStateChartModel } from "./powerStates.js";
|
|
|
35
35
|
export { buildHostPowerStateChart, buildVmPowerStateChart, HOST_POWER_COLORS, VM_POWER_COLORS, } from "./powerStates.js";
|
|
36
36
|
export { ExportReportButton, type ExportReportButtonProps, ReportExportMenu, type ReportExportMenuProps, } from "./ReportExportMenu.js";
|
|
37
37
|
export { ReportTable, type ReportTableProps } from "./ReportTable.js";
|
|
38
|
-
export { type ReportExportOption, type StandardReportExportHandlers, standardReportExportOptions, } from "./reportExportOptions.js";
|
|
38
|
+
export { type ReportExportOption, type ReportExportSection, type StandardReportExportHandlers, type StandardReportExportOptionsConfig, standardReportExportOptions, } from "./reportExportOptions.js";
|
|
39
|
+
export { type StorageDiskTierData, StorageOverview, type StorageOverviewProps, } from "./StorageOverview.js";
|
|
39
40
|
export { SupportTierBadge } from "./SupportTierBadge.js";
|
|
40
41
|
export { ALL_TIERS_FILTER, type OsBarChartViewModel, type OsTableRow, useOsBarChartViewModel, } from "./useOsBarChartViewModel.js";
|
|
41
42
|
export { VCenterClusterDetails, type VCenterClusterDetailsProps, } from "./VCenterClusterDetails.js";
|
|
43
|
+
export { type IssuesBreakdownLike, VMMigrationStatus, type VMMigrationStatusProps, } from "./VMMigrationStatus.js";
|
|
42
44
|
export { VmPowerStates, type VmPowerStatesProps, } from "./VmPowerStates.js";
|
|
43
45
|
export { WarningsTable, type WarningsTableProps, } from "./WarningsTable.js";
|
|
44
46
|
export { zipChartPngs } from "./zipChartPngs.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/report/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/report/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,4BAA4B,EAC5B,cAAc,EACd,KAAK,mBAAmB,GACzB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,mBAAmB,EACnB,kBAAkB,GACnB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,EACxB,mBAAmB,EACnB,KAAK,wBAAwB,EAC7B,KAAK,cAAc,EACnB,KAAK,aAAa,GACnB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EACL,gBAAgB,EAChB,KAAK,qBAAqB,EAC1B,KAAK,iBAAiB,GACvB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,oBAAoB,EACpB,KAAK,yBAAyB,GAC/B,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EACL,2BAA2B,EAC3B,sBAAsB,EACtB,wBAAwB,EACxB,KAAK,kBAAkB,EACvB,KAAK,eAAe,EACpB,KAAK,eAAe,EACpB,KAAK,eAAe,EACpB,YAAY,EACZ,oBAAoB,EACpB,oBAAoB,EACpB,sBAAsB,EACtB,0BAA0B,EAC1B,gBAAgB,EAChB,YAAY,EACZ,KAAK,WAAW,EAChB,KAAK,eAAe,EACpB,KAAK,eAAe,EACpB,aAAa,EACb,uBAAuB,EACvB,8BAA8B,EAC9B,iBAAiB,EACjB,mCAAmC,EACnC,yBAAyB,GAC1B,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,iBAAiB,EACtB,cAAc,EACd,gBAAgB,GACjB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,sBAAsB,EACtB,mBAAmB,EACnB,2BAA2B,GAC5B,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,8BAA8B,GAC/B,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,uBAAuB,EACvB,KAAK,4BAA4B,GAClC,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAC5E,OAAO,EACL,kBAAkB,EAClB,KAAK,uBAAuB,GAC7B,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,UAAU,EACV,KAAK,eAAe,EACpB,KAAK,kBAAkB,GACxB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,kBAAkB,EAClB,KAAK,uBAAuB,GAC7B,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,eAAe,EACf,KAAK,oBAAoB,GAC1B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,KAAK,QAAQ,EACb,aAAa,EACb,KAAK,kBAAkB,GACxB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,mBAAmB,EACnB,eAAe,EACf,UAAU,EACV,KAAK,eAAe,GACrB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,qBAAqB,EACrB,KAAK,0BAA0B,GAChC,MAAM,4BAA4B,CAAC;AACpC,YAAY,EACV,gBAAgB,EAChB,mBAAmB,EACnB,aAAa,EACb,cAAc,EACd,0BAA0B,EAC1B,gBAAgB,EAChB,kBAAkB,EAClB,aAAa,EACb,cAAc,EACd,gBAAgB,EAChB,YAAY,EACZ,YAAY,GACb,MAAM,iCAAiC,CAAC;AACzC,OAAO,EACL,sBAAsB,EACtB,sBAAsB,EACtB,mBAAmB,EACnB,0BAA0B,EAC1B,aAAa,EACb,oBAAoB,EACpB,oBAAoB,EACpB,eAAe,EACf,UAAU,GACX,MAAM,iCAAiC,CAAC;AACzC,OAAO,EACL,KAAK,gBAAgB,EACrB,KAAK,WAAW,EAChB,eAAe,EACf,KAAK,oBAAoB,EACzB,KAAK,iBAAiB,EACtB,KAAK,eAAe,GACrB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACjE,OAAO,EAAE,yBAAyB,EAAE,MAAM,gCAAgC,CAAC;AAC3E,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EACL,UAAU,EACV,8BAA8B,GAC/B,MAAM,qCAAqC,CAAC;AAC7C,YAAY,EACV,mBAAmB,EACnB,qBAAqB,GACtB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,wBAAwB,EACxB,8BAA8B,EAC9B,wBAAwB,EACxB,yBAAyB,EACzB,uBAAuB,EACvB,kBAAkB,EAClB,qBAAqB,EACrB,kBAAkB,EAClB,yBAAyB,EACzB,gCAAgC,EAChC,wBAAwB,EACxB,mBAAmB,EACnB,2BAA2B,EAC3B,WAAW,GACZ,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,EACL,cAAc,EACd,KAAK,mBAAmB,GACzB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EACL,KAAK,gBAAgB,EACrB,WAAW,EACX,yBAAyB,GAC1B,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAC7D,OAAO,EACL,wBAAwB,EACxB,sBAAsB,EACtB,iBAAiB,EACjB,eAAe,GAChB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,kBAAkB,EAClB,KAAK,uBAAuB,EAC5B,gBAAgB,EAChB,KAAK,qBAAqB,GAC3B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACtE,OAAO,EACL,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACxB,KAAK,4BAA4B,EACjC,KAAK,iCAAiC,EACtC,2BAA2B,GAC5B,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,KAAK,mBAAmB,EACxB,eAAe,EACf,KAAK,oBAAoB,GAC1B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EACL,gBAAgB,EAChB,KAAK,mBAAmB,EACxB,KAAK,UAAU,EACf,sBAAsB,GACvB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,qBAAqB,EACrB,KAAK,0BAA0B,GAChC,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,KAAK,mBAAmB,EACxB,iBAAiB,EACjB,KAAK,sBAAsB,GAC5B,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,aAAa,EACb,KAAK,kBAAkB,GACxB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,aAAa,EACb,KAAK,kBAAkB,GACxB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC"}
|
package/dist/report/index.js
CHANGED
|
@@ -33,9 +33,11 @@ export { buildHostPowerStateChart, buildVmPowerStateChart, HOST_POWER_COLORS, VM
|
|
|
33
33
|
export { ExportReportButton, ReportExportMenu, } from "./ReportExportMenu.js";
|
|
34
34
|
export { ReportTable } from "./ReportTable.js";
|
|
35
35
|
export { standardReportExportOptions, } from "./reportExportOptions.js";
|
|
36
|
+
export { StorageOverview, } from "./StorageOverview.js";
|
|
36
37
|
export { SupportTierBadge } from "./SupportTierBadge.js";
|
|
37
38
|
export { ALL_TIERS_FILTER, useOsBarChartViewModel, } from "./useOsBarChartViewModel.js";
|
|
38
39
|
export { VCenterClusterDetails, } from "./VCenterClusterDetails.js";
|
|
40
|
+
export { VMMigrationStatus, } from "./VMMigrationStatus.js";
|
|
39
41
|
export { VmPowerStates, } from "./VmPowerStates.js";
|
|
40
42
|
export { WarningsTable, } from "./WarningsTable.js";
|
|
41
43
|
export { zipChartPngs } from "./zipChartPngs.js";
|
|
@@ -1,17 +1,28 @@
|
|
|
1
|
+
export interface ReportExportSection {
|
|
2
|
+
id: string;
|
|
3
|
+
label: string;
|
|
4
|
+
}
|
|
1
5
|
export interface ReportExportOption {
|
|
2
6
|
key: string;
|
|
3
7
|
label: string;
|
|
4
8
|
description?: string;
|
|
5
9
|
onSelect: () => void;
|
|
6
10
|
isDisabled?: boolean;
|
|
11
|
+
/** When set, the menu groups rows and shows `label` as the group heading. */
|
|
12
|
+
section?: ReportExportSection;
|
|
7
13
|
}
|
|
8
14
|
export interface StandardReportExportHandlers {
|
|
9
15
|
onExportPdf?: () => void;
|
|
10
16
|
onExportPng?: () => void;
|
|
11
17
|
onExportHtml?: () => void;
|
|
12
18
|
}
|
|
19
|
+
export type StandardReportExportOptionsConfig = StandardReportExportHandlers & {
|
|
20
|
+
/** Dropdown group label for PDF / HTML / PNG. Default: `"Assessment report"`. */
|
|
21
|
+
assessmentSectionLabel?: string;
|
|
22
|
+
};
|
|
13
23
|
/**
|
|
14
|
-
*
|
|
24
|
+
* Optional helper for chart-based assessment downloads. Omit a handler to hide
|
|
25
|
+
* that format. Override `assessmentSectionLabel` if product copy differs per app.
|
|
15
26
|
*/
|
|
16
|
-
export declare const standardReportExportOptions: ({ onExportPdf, onExportPng, onExportHtml, }:
|
|
27
|
+
export declare const standardReportExportOptions: ({ onExportPdf, onExportPng, onExportHtml, assessmentSectionLabel, }: StandardReportExportOptionsConfig) => ReportExportOption[];
|
|
17
28
|
//# sourceMappingURL=reportExportOptions.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reportExportOptions.d.ts","sourceRoot":"","sources":["../../src/report/reportExportOptions.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,kBAAkB;IACjC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"reportExportOptions.d.ts","sourceRoot":"","sources":["../../src/report/reportExportOptions.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,kBAAkB;IACjC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,6EAA6E;IAC7E,OAAO,CAAC,EAAE,mBAAmB,CAAC;CAC/B;AAED,MAAM,WAAW,4BAA4B;IAC3C,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;CAC3B;AAED,MAAM,MAAM,iCAAiC,GAAG,4BAA4B,GAAG;IAC7E,iFAAiF;IACjF,sBAAsB,CAAC,EAAE,MAAM,CAAC;CACjC,CAAC;AAOF;;;GAGG;AACH,eAAO,MAAM,2BAA2B,GAAI,qEAKzC,iCAAiC,KAAG,kBAAkB,EAmCxD,CAAC"}
|
|
@@ -1,30 +1,38 @@
|
|
|
1
|
+
const DEFAULT_ASSESSMENT_SECTION = {
|
|
2
|
+
id: "assessment-report",
|
|
3
|
+
label: "Assessment report",
|
|
4
|
+
};
|
|
1
5
|
/**
|
|
2
|
-
*
|
|
6
|
+
* Optional helper for chart-based assessment downloads. Omit a handler to hide
|
|
7
|
+
* that format. Override `assessmentSectionLabel` if product copy differs per app.
|
|
3
8
|
*/
|
|
4
|
-
export const standardReportExportOptions = ({ onExportPdf, onExportPng, onExportHtml, }) => {
|
|
9
|
+
export const standardReportExportOptions = ({ onExportPdf, onExportPng, onExportHtml, assessmentSectionLabel, }) => {
|
|
10
|
+
const section = assessmentSectionLabel
|
|
11
|
+
? { ...DEFAULT_ASSESSMENT_SECTION, label: assessmentSectionLabel }
|
|
12
|
+
: DEFAULT_ASSESSMENT_SECTION;
|
|
5
13
|
const options = [];
|
|
6
14
|
if (onExportPdf) {
|
|
7
15
|
options.push({
|
|
8
16
|
key: "pdf",
|
|
9
17
|
label: "PDF",
|
|
10
|
-
description: "Export the report as a PDF",
|
|
11
18
|
onSelect: onExportPdf,
|
|
19
|
+
section,
|
|
12
20
|
});
|
|
13
21
|
}
|
|
14
22
|
if (onExportHtml) {
|
|
15
23
|
options.push({
|
|
16
24
|
key: "html",
|
|
17
25
|
label: "HTML",
|
|
18
|
-
description: "Export the report as HTML",
|
|
19
26
|
onSelect: onExportHtml,
|
|
27
|
+
section,
|
|
20
28
|
});
|
|
21
29
|
}
|
|
22
30
|
if (onExportPng) {
|
|
23
31
|
options.push({
|
|
24
32
|
key: "png",
|
|
25
33
|
label: "PNG",
|
|
26
|
-
description: "Download all charts as PNG files",
|
|
27
34
|
onSelect: onExportPng,
|
|
35
|
+
section,
|
|
28
36
|
});
|
|
29
37
|
}
|
|
30
38
|
return options;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openshift-migration-advisor/shared-components",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.29.0-8024400889ad",
|
|
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",
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"README.md"
|
|
47
47
|
],
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"html2canvas-pro": "^2.5.
|
|
49
|
+
"html2canvas-pro": "^2.5.2",
|
|
50
50
|
"jspdf": "^4.2.1",
|
|
51
51
|
"jszip": "^3.10.2"
|
|
52
52
|
}
|
|
@@ -108,6 +108,10 @@ const themedChartTooltipFlyoutPadding = {
|
|
|
108
108
|
right: 10,
|
|
109
109
|
} as const;
|
|
110
110
|
|
|
111
|
+
/** Victory SVG text defaults to a serif face; match PatternFly / html2canvas export. */
|
|
112
|
+
const chartTextFontFamily =
|
|
113
|
+
"RedHatText, Overpass, Helvetica, Arial, sans-serif";
|
|
114
|
+
|
|
111
115
|
const styles = {
|
|
112
116
|
legendIcon: css`
|
|
113
117
|
margin-right: 4px;
|
|
@@ -136,6 +140,7 @@ const styles = {
|
|
|
136
140
|
background: none;
|
|
137
141
|
padding: var(--pf-t--global--spacer--xs) var(--pf-t--global--spacer--ml);
|
|
138
142
|
margin: 0;
|
|
143
|
+
font-family: ${chartTextFontFamily};
|
|
139
144
|
transition: opacity var(--pf-t--global--motion--duration--short);
|
|
140
145
|
white-space: nowrap;
|
|
141
146
|
|
|
@@ -146,6 +151,7 @@ const styles = {
|
|
|
146
151
|
legendLabel: css`
|
|
147
152
|
gap: var(--pf-t--global--spacer--lg);
|
|
148
153
|
padding: var(--pf-t--global--spacer--xs) var(--pf-t--global--spacer--ml);
|
|
154
|
+
font-family: ${chartTextFontFamily};
|
|
149
155
|
white-space: nowrap;
|
|
150
156
|
`,
|
|
151
157
|
legendInner: css`
|
|
@@ -214,9 +220,21 @@ export const MigrationDonutChart: FC<MigrationDonutChartProps> = ({
|
|
|
214
220
|
}));
|
|
215
221
|
}, [data]);
|
|
216
222
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
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;
|
|
220
238
|
|
|
221
239
|
const legendData = useMemo(() => {
|
|
222
240
|
return chartData.map((item) => ({
|
|
@@ -422,6 +440,7 @@ export const MigrationDonutChart: FC<MigrationDonutChartProps> = ({
|
|
|
422
440
|
labels: {
|
|
423
441
|
fontSize: labelFontSize,
|
|
424
442
|
fill: "var(--pf-t--global--text--color--regular)",
|
|
443
|
+
fontFamily: chartTextFontFamily,
|
|
425
444
|
},
|
|
426
445
|
}}
|
|
427
446
|
/>
|
|
@@ -439,7 +458,7 @@ export const MigrationDonutChart: FC<MigrationDonutChartProps> = ({
|
|
|
439
458
|
<div className={styles.donutWrapper}>
|
|
440
459
|
<ChartDonut
|
|
441
460
|
ariaDesc="Migration data donut chart"
|
|
442
|
-
data={
|
|
461
|
+
data={donutChartData}
|
|
443
462
|
events={chartEvents}
|
|
444
463
|
labelComponent={donutTooltip}
|
|
445
464
|
labels={({
|
|
@@ -452,10 +471,10 @@ export const MigrationDonutChart: FC<MigrationDonutChartProps> = ({
|
|
|
452
471
|
countDisplay?: string | number;
|
|
453
472
|
};
|
|
454
473
|
}) => formatLabel(datum)}
|
|
455
|
-
colorScale={
|
|
474
|
+
colorScale={donutColorScale}
|
|
456
475
|
constrainToVisibleArea
|
|
457
476
|
innerRadius={innerRadius}
|
|
458
|
-
padAngle={
|
|
477
|
+
padAngle={effectivePadAngle}
|
|
459
478
|
title={title}
|
|
460
479
|
subTitle={subTitle}
|
|
461
480
|
height={height}
|
|
@@ -474,6 +493,7 @@ export const MigrationDonutChart: FC<MigrationDonutChartProps> = ({
|
|
|
474
493
|
fill: titleColor,
|
|
475
494
|
fontSize: titleFontSize,
|
|
476
495
|
fontWeight: "bold",
|
|
496
|
+
fontFamily: chartTextFontFamily,
|
|
477
497
|
},
|
|
478
498
|
]}
|
|
479
499
|
/>
|
|
@@ -487,6 +507,7 @@ export const MigrationDonutChart: FC<MigrationDonutChartProps> = ({
|
|
|
487
507
|
{
|
|
488
508
|
fill: subTitleColor,
|
|
489
509
|
fontSize: subTitleFontSize,
|
|
510
|
+
fontFamily: chartTextFontFamily,
|
|
490
511
|
},
|
|
491
512
|
]}
|
|
492
513
|
/>
|
|
@@ -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
|
+
});
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
useRef,
|
|
7
7
|
useState,
|
|
8
8
|
} from "react";
|
|
9
|
+
import { CHART_CAPTURE_SCALE_SINGLE } from "./captureChartElement.js";
|
|
9
10
|
import {
|
|
10
11
|
type ChartCaptureSource,
|
|
11
12
|
type ChartExportFile,
|
|
@@ -29,6 +30,7 @@ import { getChartExportFilename } from "./chartExportFilenames.js";
|
|
|
29
30
|
|
|
30
31
|
export type CaptureChartElement = (
|
|
31
32
|
element: HTMLElement,
|
|
33
|
+
options?: import("./captureChartElement.js").CaptureChartElementOptions,
|
|
32
34
|
) => Promise<HTMLCanvasElement>;
|
|
33
35
|
export type ZipChartFiles = (files: ChartExportFile[]) => Promise<Blob>;
|
|
34
36
|
export type EncodeChartPng = (canvas: HTMLCanvasElement) => Promise<Blob>;
|
|
@@ -227,7 +229,9 @@ export const ChartExportProvider: FC<ChartExportProviderProps> = ({
|
|
|
227
229
|
throw new Error("The chart is not ready to export yet.");
|
|
228
230
|
}
|
|
229
231
|
const captureFn = await resolveCapture(capture);
|
|
230
|
-
const canvas = await captureFn(chart.element
|
|
232
|
+
const canvas = await captureFn(chart.element, {
|
|
233
|
+
scale: CHART_CAPTURE_SCALE_SINGLE,
|
|
234
|
+
});
|
|
231
235
|
try {
|
|
232
236
|
downloadFile(await encodePng(canvas), chart.filename);
|
|
233
237
|
} finally {
|
|
@@ -4,13 +4,6 @@ import { InfoCircleIcon } from "@patternfly/react-icons";
|
|
|
4
4
|
import type { FC } from "react";
|
|
5
5
|
import { chartExportHideProps } from "./chartExport.js";
|
|
6
6
|
|
|
7
|
-
const upgradeRecommendationPopoverCloseButton = css`
|
|
8
|
-
.pf-v6-c-popover__close .pf-v6-c-button.pf-m-plain,
|
|
9
|
-
.pf-v6-c-popover__close .pf-v6-c-button.pf-m-plain:hover {
|
|
10
|
-
color: var(--pf-t--global--text--color--regular);
|
|
11
|
-
}
|
|
12
|
-
`;
|
|
13
|
-
|
|
14
7
|
const infoButtonStyle = css`
|
|
15
8
|
padding: 0;
|
|
16
9
|
vertical-align: middle;
|
|
@@ -24,7 +17,6 @@ export const OsUpgradeRecommendationPopover: FC<
|
|
|
24
17
|
OsUpgradeRecommendationPopoverProps
|
|
25
18
|
> = ({ upgradeRecommendation }) => (
|
|
26
19
|
<Popover
|
|
27
|
-
className={upgradeRecommendationPopoverCloseButton}
|
|
28
20
|
position="bottom"
|
|
29
21
|
headerContent="Upgrade to get support"
|
|
30
22
|
bodyContent={<div>{upgradeRecommendation}</div>}
|