@openshift-migration-advisor/shared-components 0.25.0 → 0.27.0-5d0cc20d809e
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/README.md +25 -0
- package/dist/report/ChartDownloadButton.d.ts +11 -0
- package/dist/report/ChartDownloadButton.d.ts.map +1 -0
- package/dist/report/ChartDownloadButton.js +24 -0
- package/dist/report/ChartExportProvider.d.ts +23 -0
- package/dist/report/ChartExportProvider.d.ts.map +1 -0
- package/dist/report/ChartExportProvider.js +222 -0
- package/dist/report/ChartExportSurface.d.ts +12 -0
- package/dist/report/ChartExportSurface.d.ts.map +1 -0
- package/dist/report/ChartExportSurface.js +32 -0
- package/dist/report/CpuAndMemoryOverview.d.ts +19 -0
- package/dist/report/CpuAndMemoryOverview.d.ts.map +1 -0
- package/dist/report/CpuAndMemoryOverview.js +112 -0
- package/dist/report/ErrorTable.d.ts +18 -0
- package/dist/report/ErrorTable.d.ts.map +1 -0
- package/dist/report/ErrorTable.js +20 -0
- package/dist/report/HostPowerStates.d.ts +0 -1
- package/dist/report/HostPowerStates.d.ts.map +1 -1
- package/dist/report/HostPowerStates.js +2 -2
- package/dist/report/HostsOverview.d.ts +13 -0
- package/dist/report/HostsOverview.d.ts.map +1 -0
- package/dist/report/HostsOverview.js +84 -0
- package/dist/report/InfrastructureSummary.d.ts.map +1 -1
- package/dist/report/InfrastructureSummary.js +6 -2
- package/dist/report/NetworkOverview.d.ts +31 -0
- package/dist/report/NetworkOverview.d.ts.map +1 -0
- package/dist/report/NetworkOverview.js +201 -0
- package/dist/report/OSDistribution.d.ts +0 -2
- package/dist/report/OSDistribution.d.ts.map +1 -1
- package/dist/report/OSDistribution.js +8 -5
- package/dist/report/OsUpgradeRecommendationPopover.d.ts +0 -1
- package/dist/report/OsUpgradeRecommendationPopover.d.ts.map +1 -1
- package/dist/report/OsUpgradeRecommendationPopover.js +4 -3
- package/dist/report/PowerStateCard.d.ts +0 -1
- package/dist/report/PowerStateCard.d.ts.map +1 -1
- package/dist/report/PowerStateCard.js +4 -2
- package/dist/report/ReportExportMenu.d.ts +19 -0
- package/dist/report/ReportExportMenu.d.ts.map +1 -0
- package/dist/report/ReportExportMenu.js +31 -0
- package/dist/report/ReportTable.d.ts +14 -0
- package/dist/report/ReportTable.d.ts.map +1 -0
- package/dist/report/ReportTable.js +23 -0
- package/dist/report/SupportTierBadge.d.ts +0 -1
- package/dist/report/SupportTierBadge.d.ts.map +1 -1
- package/dist/report/SupportTierBadge.js +1 -21
- package/dist/report/VCenterClusterDetails.d.ts +0 -1
- package/dist/report/VCenterClusterDetails.d.ts.map +1 -1
- package/dist/report/VCenterClusterDetails.js +9 -4
- package/dist/report/VmPowerStates.d.ts +0 -1
- package/dist/report/VmPowerStates.d.ts.map +1 -1
- package/dist/report/VmPowerStates.js +2 -2
- package/dist/report/WarningsTable.d.ts +9 -0
- package/dist/report/WarningsTable.d.ts.map +1 -0
- package/dist/report/WarningsTable.js +20 -0
- package/dist/report/captureChartElement.d.ts +8 -0
- package/dist/report/captureChartElement.d.ts.map +1 -0
- package/dist/report/captureChartElement.js +304 -0
- package/dist/report/chartExport.d.ts +80 -0
- package/dist/report/chartExport.d.ts.map +1 -0
- package/dist/report/chartExport.js +182 -0
- package/dist/report/chartExportContext.d.ts +32 -0
- package/dist/report/chartExportContext.d.ts.map +1 -0
- package/dist/report/chartExportContext.js +36 -0
- package/dist/report/chartExportFilenames.d.ts +4 -0
- package/dist/report/chartExportFilenames.d.ts.map +1 -0
- package/dist/report/chartExportFilenames.js +16 -0
- package/dist/report/constants.d.ts +2 -0
- package/dist/report/constants.d.ts.map +1 -1
- package/dist/report/constants.js +2 -0
- package/dist/report/dashboardStyles.d.ts +0 -4
- package/dist/report/dashboardStyles.d.ts.map +1 -1
- package/dist/report/dashboardStyles.js +0 -19
- package/dist/report/htmlExport.d.ts +9 -0
- package/dist/report/htmlExport.d.ts.map +1 -0
- package/dist/report/htmlExport.js +65 -0
- package/dist/report/index.d.ts +19 -0
- package/dist/report/index.d.ts.map +1 -1
- package/dist/report/index.js +19 -0
- package/dist/report/pdfExport.d.ts +3 -0
- package/dist/report/pdfExport.d.ts.map +1 -0
- package/dist/report/pdfExport.js +131 -0
- package/dist/report/pdfPage.d.ts +15 -0
- package/dist/report/pdfPage.d.ts.map +1 -0
- package/dist/report/pdfPage.js +44 -0
- package/dist/report/reportExportOptions.d.ts +17 -0
- package/dist/report/reportExportOptions.d.ts.map +1 -0
- package/dist/report/reportExportOptions.js +31 -0
- package/dist/report/zipChartPngs.d.ts +3 -0
- package/dist/report/zipChartPngs.d.ts.map +1 -0
- package/dist/report/zipChartPngs.js +8 -0
- package/package.json +7 -2
- package/src/report/ChartDownloadButton.tsx +59 -0
- package/src/report/ChartExportProvider.tsx +392 -0
- package/src/report/ChartExportSurface.tsx +60 -0
- package/src/report/CpuAndMemoryOverview.tsx +277 -0
- package/src/report/ErrorTable.tsx +85 -0
- package/src/report/HostPowerStates.tsx +0 -3
- package/src/report/HostsOverview.tsx +185 -0
- package/src/report/InfrastructureSummary.tsx +48 -31
- package/src/report/NetworkOverview.tsx +405 -0
- package/src/report/OSDistribution.tsx +46 -42
- package/src/report/OsUpgradeRecommendationPopover.tsx +3 -4
- package/src/report/PowerStateCard.tsx +49 -36
- package/src/report/ReportExportMenu.tsx +119 -0
- package/src/report/ReportTable.tsx +81 -0
- package/src/report/SupportTierBadge.tsx +12 -40
- package/src/report/VCenterClusterDetails.tsx +38 -16
- package/src/report/VmPowerStates.tsx +0 -3
- package/src/report/WarningsTable.tsx +75 -0
- package/src/report/__tests__/ChartExportProvider.test.tsx +582 -0
- package/src/report/__tests__/CpuAndMemoryOverview.test.tsx +200 -0
- package/src/report/__tests__/HostsOverview.test.tsx +145 -0
- package/src/report/__tests__/InfrastructureSummary.test.tsx +0 -22
- package/src/report/__tests__/NetworkOverview.test.tsx +269 -0
- package/src/report/__tests__/OSDistribution.test.tsx +10 -11
- package/src/report/__tests__/captureChartElement.test.ts +205 -0
- package/src/report/__tests__/chartExportPackagers.test.ts +299 -0
- package/src/report/captureChartElement.ts +398 -0
- package/src/report/chartExport.ts +277 -0
- package/src/report/chartExportContext.tsx +92 -0
- package/src/report/chartExportFilenames.ts +21 -0
- package/src/report/constants.ts +2 -0
- package/src/report/dashboardStyles.ts +0 -23
- package/src/report/htmlExport.ts +83 -0
- package/src/report/index.ts +102 -0
- package/src/report/pdfExport.ts +233 -0
- package/src/report/pdfPage.ts +83 -0
- package/src/report/reportExportOptions.ts +53 -0
- package/src/report/zipChartPngs.ts +10 -0
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type FC,
|
|
3
|
+
type ReactNode,
|
|
4
|
+
useCallback,
|
|
5
|
+
useMemo,
|
|
6
|
+
useRef,
|
|
7
|
+
useState,
|
|
8
|
+
} from "react";
|
|
9
|
+
import {
|
|
10
|
+
type ChartCaptureSource,
|
|
11
|
+
type ChartExportFile,
|
|
12
|
+
canvasToBlob,
|
|
13
|
+
downloadBlob,
|
|
14
|
+
type PdfTextPage,
|
|
15
|
+
type RegisteredChart,
|
|
16
|
+
releaseCanvas,
|
|
17
|
+
restoreChartExportViews,
|
|
18
|
+
sortRegisteredChartsByDocumentOrder,
|
|
19
|
+
toBulkChartCaptureSources,
|
|
20
|
+
} from "./chartExport.js";
|
|
21
|
+
import {
|
|
22
|
+
type ChartExportApi,
|
|
23
|
+
ChartExportApiContext,
|
|
24
|
+
type ChartExportFormat,
|
|
25
|
+
type ChartExportRegistry,
|
|
26
|
+
ChartExportRegistryContext,
|
|
27
|
+
} from "./chartExportContext.js";
|
|
28
|
+
import { getChartExportFilename } from "./chartExportFilenames.js";
|
|
29
|
+
|
|
30
|
+
export type CaptureChartElement = (
|
|
31
|
+
element: HTMLElement,
|
|
32
|
+
) => Promise<HTMLCanvasElement>;
|
|
33
|
+
export type ZipChartFiles = (files: ChartExportFile[]) => Promise<Blob>;
|
|
34
|
+
export type EncodeChartPng = (canvas: HTMLCanvasElement) => Promise<Blob>;
|
|
35
|
+
export type BuildChartDocument = (
|
|
36
|
+
charts: ChartCaptureSource[],
|
|
37
|
+
documentTitle: string,
|
|
38
|
+
) => Promise<Blob>;
|
|
39
|
+
|
|
40
|
+
export type BuildPdfDocument = (
|
|
41
|
+
charts: ChartCaptureSource[],
|
|
42
|
+
documentTitle: string,
|
|
43
|
+
extraPages?: PdfTextPage[],
|
|
44
|
+
) => Promise<Blob>;
|
|
45
|
+
|
|
46
|
+
export type {
|
|
47
|
+
ChartExportApi,
|
|
48
|
+
ChartExportFormat,
|
|
49
|
+
} from "./chartExportContext.js";
|
|
50
|
+
export { useChartExport, useRegisterChart } from "./chartExportContext.js";
|
|
51
|
+
|
|
52
|
+
export interface ChartExportProviderProps {
|
|
53
|
+
children: ReactNode;
|
|
54
|
+
capture?: CaptureChartElement;
|
|
55
|
+
zipFiles?: ZipChartFiles;
|
|
56
|
+
encodePng?: EncodeChartPng;
|
|
57
|
+
buildPdf?: BuildPdfDocument;
|
|
58
|
+
buildHtml?: BuildChartDocument;
|
|
59
|
+
downloadFile?: (blob: Blob, filename: string) => void;
|
|
60
|
+
getZipFilename?: () => string;
|
|
61
|
+
getPdfFilename?: () => string;
|
|
62
|
+
getHtmlFilename?: () => string;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const EXPORT_LOADING_LABELS: Record<ChartExportFormat, string> = {
|
|
66
|
+
pdf: "Generating PDF...",
|
|
67
|
+
png: "Generating PNG...",
|
|
68
|
+
html: "Generating HTML...",
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const defaultZipFilename = (): string => getChartExportFilename("zip");
|
|
72
|
+
const defaultPdfFilename = (): string => getChartExportFilename("pdf");
|
|
73
|
+
const defaultHtmlFilename = (): string => getChartExportFilename("html");
|
|
74
|
+
|
|
75
|
+
async function resolveCapture(
|
|
76
|
+
override?: CaptureChartElement,
|
|
77
|
+
): Promise<CaptureChartElement> {
|
|
78
|
+
if (override) {
|
|
79
|
+
return override;
|
|
80
|
+
}
|
|
81
|
+
const { captureChartElement } = await import("./captureChartElement.js");
|
|
82
|
+
return captureChartElement;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
async function resolvePrepareElement(
|
|
86
|
+
overrideCapture?: CaptureChartElement,
|
|
87
|
+
): Promise<((element: HTMLElement) => () => void) | undefined> {
|
|
88
|
+
if (overrideCapture) {
|
|
89
|
+
return undefined;
|
|
90
|
+
}
|
|
91
|
+
const { revealHiddenChartAncestors } = await import(
|
|
92
|
+
"./captureChartElement.js"
|
|
93
|
+
);
|
|
94
|
+
return revealHiddenChartAncestors;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
async function resolveZip(override?: ZipChartFiles): Promise<ZipChartFiles> {
|
|
98
|
+
if (override) {
|
|
99
|
+
return override;
|
|
100
|
+
}
|
|
101
|
+
const { zipChartPngs } = await import("./zipChartPngs.js");
|
|
102
|
+
return zipChartPngs;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
async function resolvePdf(
|
|
106
|
+
override?: BuildPdfDocument,
|
|
107
|
+
): Promise<BuildPdfDocument> {
|
|
108
|
+
if (override) {
|
|
109
|
+
return override;
|
|
110
|
+
}
|
|
111
|
+
const { buildPdfFromCharts } = await import("./pdfExport.js");
|
|
112
|
+
return buildPdfFromCharts;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
async function resolveHtml(
|
|
116
|
+
override?: BuildChartDocument,
|
|
117
|
+
): Promise<BuildChartDocument> {
|
|
118
|
+
if (override) {
|
|
119
|
+
return override;
|
|
120
|
+
}
|
|
121
|
+
const { buildHtmlFromCharts } = await import("./htmlExport.js");
|
|
122
|
+
return buildHtmlFromCharts;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function toCaptureSources(
|
|
126
|
+
charts: RegisteredChart[],
|
|
127
|
+
capture: CaptureChartElement,
|
|
128
|
+
prepareElement?: (element: HTMLElement) => () => void,
|
|
129
|
+
): ChartCaptureSource[] {
|
|
130
|
+
return toBulkChartCaptureSources(charts, capture, prepareElement);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export const ChartExportProvider: FC<ChartExportProviderProps> = ({
|
|
134
|
+
children,
|
|
135
|
+
capture,
|
|
136
|
+
zipFiles,
|
|
137
|
+
encodePng = canvasToBlob,
|
|
138
|
+
buildPdf,
|
|
139
|
+
buildHtml,
|
|
140
|
+
downloadFile = downloadBlob,
|
|
141
|
+
getZipFilename = defaultZipFilename,
|
|
142
|
+
getPdfFilename = defaultPdfFilename,
|
|
143
|
+
getHtmlFilename = defaultHtmlFilename,
|
|
144
|
+
}) => {
|
|
145
|
+
const chartsRef = useRef(new Map<string, RegisteredChart>());
|
|
146
|
+
const isBusyRef = useRef(false);
|
|
147
|
+
const [downloadingChartId, setDownloadingChartId] = useState<string | null>(
|
|
148
|
+
null,
|
|
149
|
+
);
|
|
150
|
+
const [exportingFormat, setExportingFormat] =
|
|
151
|
+
useState<ChartExportFormat | null>(null);
|
|
152
|
+
const [exportError, setExportError] = useState<string | null>(null);
|
|
153
|
+
|
|
154
|
+
const registry = useMemo<ChartExportRegistry>(
|
|
155
|
+
() => ({
|
|
156
|
+
register(chart) {
|
|
157
|
+
const existing = chartsRef.current.get(chart.id);
|
|
158
|
+
if (
|
|
159
|
+
existing &&
|
|
160
|
+
existing.element !== chart.element &&
|
|
161
|
+
existing.element.isConnected
|
|
162
|
+
) {
|
|
163
|
+
console.warn(
|
|
164
|
+
`Duplicate chart export id "${chart.id}". The previous chart will not be exported.`,
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
chartsRef.current.set(chart.id, chart);
|
|
168
|
+
return () => {
|
|
169
|
+
const current = chartsRef.current.get(chart.id);
|
|
170
|
+
if (current?.element === chart.element) {
|
|
171
|
+
chartsRef.current.delete(chart.id);
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
},
|
|
175
|
+
}),
|
|
176
|
+
[],
|
|
177
|
+
);
|
|
178
|
+
|
|
179
|
+
const listCharts = useCallback((): RegisteredChart[] => {
|
|
180
|
+
return sortRegisteredChartsByDocumentOrder(
|
|
181
|
+
Array.from(chartsRef.current.values()).filter(
|
|
182
|
+
(chart) => chart.element.isConnected,
|
|
183
|
+
),
|
|
184
|
+
);
|
|
185
|
+
}, []);
|
|
186
|
+
|
|
187
|
+
const runCapture = useCallback(
|
|
188
|
+
async (
|
|
189
|
+
work: () => Promise<void>,
|
|
190
|
+
chartId: string | null,
|
|
191
|
+
format: ChartExportFormat,
|
|
192
|
+
) => {
|
|
193
|
+
if (isBusyRef.current) {
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
isBusyRef.current = true;
|
|
198
|
+
setExportError(null);
|
|
199
|
+
if (chartId) {
|
|
200
|
+
setDownloadingChartId(chartId);
|
|
201
|
+
} else {
|
|
202
|
+
setExportingFormat(format);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
try {
|
|
206
|
+
await work();
|
|
207
|
+
} catch (error) {
|
|
208
|
+
console.error(`Error exporting ${format}:`, error);
|
|
209
|
+
setExportError(
|
|
210
|
+
`Failed to export ${format.toUpperCase()}. Please try again.`,
|
|
211
|
+
);
|
|
212
|
+
} finally {
|
|
213
|
+
isBusyRef.current = false;
|
|
214
|
+
setDownloadingChartId(null);
|
|
215
|
+
setExportingFormat(null);
|
|
216
|
+
}
|
|
217
|
+
},
|
|
218
|
+
[],
|
|
219
|
+
);
|
|
220
|
+
|
|
221
|
+
const downloadChart = useCallback(
|
|
222
|
+
async (id: string) => {
|
|
223
|
+
await runCapture(
|
|
224
|
+
async () => {
|
|
225
|
+
const chart = chartsRef.current.get(id);
|
|
226
|
+
if (!chart?.element.isConnected) {
|
|
227
|
+
throw new Error("The chart is not ready to export yet.");
|
|
228
|
+
}
|
|
229
|
+
const captureFn = await resolveCapture(capture);
|
|
230
|
+
const canvas = await captureFn(chart.element);
|
|
231
|
+
try {
|
|
232
|
+
downloadFile(await encodePng(canvas), chart.filename);
|
|
233
|
+
} finally {
|
|
234
|
+
releaseCanvas(canvas);
|
|
235
|
+
}
|
|
236
|
+
},
|
|
237
|
+
id,
|
|
238
|
+
"png",
|
|
239
|
+
);
|
|
240
|
+
},
|
|
241
|
+
[capture, downloadFile, encodePng, runCapture],
|
|
242
|
+
);
|
|
243
|
+
|
|
244
|
+
const downloadAll = useCallback(async () => {
|
|
245
|
+
await runCapture(
|
|
246
|
+
async () => {
|
|
247
|
+
const charts = listCharts();
|
|
248
|
+
if (charts.length === 0) {
|
|
249
|
+
throw new Error("The report is not ready to export yet.");
|
|
250
|
+
}
|
|
251
|
+
const captureFn = await resolveCapture(capture);
|
|
252
|
+
const prepareElement = await resolvePrepareElement(capture);
|
|
253
|
+
const zipFn = await resolveZip(zipFiles);
|
|
254
|
+
const files: ChartExportFile[] = [];
|
|
255
|
+
const sources = toBulkChartCaptureSources(
|
|
256
|
+
charts,
|
|
257
|
+
captureFn,
|
|
258
|
+
prepareElement,
|
|
259
|
+
);
|
|
260
|
+
try {
|
|
261
|
+
for (const [index, source] of sources.entries()) {
|
|
262
|
+
const canvas = await source.capture();
|
|
263
|
+
try {
|
|
264
|
+
files.push({
|
|
265
|
+
filename: `${String(index + 1).padStart(2, "0")}-${source.filename}`,
|
|
266
|
+
blob: await encodePng(canvas),
|
|
267
|
+
});
|
|
268
|
+
} finally {
|
|
269
|
+
releaseCanvas(canvas);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
} finally {
|
|
273
|
+
await restoreChartExportViews(charts);
|
|
274
|
+
}
|
|
275
|
+
downloadFile(await zipFn(files), getZipFilename());
|
|
276
|
+
},
|
|
277
|
+
null,
|
|
278
|
+
"png",
|
|
279
|
+
);
|
|
280
|
+
}, [
|
|
281
|
+
capture,
|
|
282
|
+
downloadFile,
|
|
283
|
+
encodePng,
|
|
284
|
+
getZipFilename,
|
|
285
|
+
listCharts,
|
|
286
|
+
runCapture,
|
|
287
|
+
zipFiles,
|
|
288
|
+
]);
|
|
289
|
+
|
|
290
|
+
const downloadPdf = useCallback(
|
|
291
|
+
async (documentTitle: string, extraPages?: PdfTextPage[]) => {
|
|
292
|
+
await runCapture(
|
|
293
|
+
async () => {
|
|
294
|
+
const charts = listCharts();
|
|
295
|
+
if (charts.length === 0 && (extraPages?.length ?? 0) === 0) {
|
|
296
|
+
throw new Error("The report is not ready to export yet.");
|
|
297
|
+
}
|
|
298
|
+
const captureFn = await resolveCapture(capture);
|
|
299
|
+
const prepareElement = await resolvePrepareElement(capture);
|
|
300
|
+
const build = await resolvePdf(buildPdf);
|
|
301
|
+
try {
|
|
302
|
+
downloadFile(
|
|
303
|
+
await build(
|
|
304
|
+
toCaptureSources(charts, captureFn, prepareElement),
|
|
305
|
+
documentTitle,
|
|
306
|
+
extraPages,
|
|
307
|
+
),
|
|
308
|
+
getPdfFilename(),
|
|
309
|
+
);
|
|
310
|
+
} finally {
|
|
311
|
+
await restoreChartExportViews(charts);
|
|
312
|
+
}
|
|
313
|
+
},
|
|
314
|
+
null,
|
|
315
|
+
"pdf",
|
|
316
|
+
);
|
|
317
|
+
},
|
|
318
|
+
[buildPdf, capture, downloadFile, getPdfFilename, listCharts, runCapture],
|
|
319
|
+
);
|
|
320
|
+
|
|
321
|
+
const downloadHtml = useCallback(
|
|
322
|
+
async (documentTitle: string) => {
|
|
323
|
+
await runCapture(
|
|
324
|
+
async () => {
|
|
325
|
+
const charts = listCharts();
|
|
326
|
+
if (charts.length === 0) {
|
|
327
|
+
throw new Error("The report is not ready to export yet.");
|
|
328
|
+
}
|
|
329
|
+
const captureFn = await resolveCapture(capture);
|
|
330
|
+
const prepareElement = await resolvePrepareElement(capture);
|
|
331
|
+
const build = await resolveHtml(buildHtml);
|
|
332
|
+
try {
|
|
333
|
+
downloadFile(
|
|
334
|
+
await build(
|
|
335
|
+
toCaptureSources(charts, captureFn, prepareElement),
|
|
336
|
+
documentTitle,
|
|
337
|
+
),
|
|
338
|
+
getHtmlFilename(),
|
|
339
|
+
);
|
|
340
|
+
} finally {
|
|
341
|
+
await restoreChartExportViews(charts);
|
|
342
|
+
}
|
|
343
|
+
},
|
|
344
|
+
null,
|
|
345
|
+
"html",
|
|
346
|
+
);
|
|
347
|
+
},
|
|
348
|
+
[buildHtml, capture, downloadFile, getHtmlFilename, listCharts, runCapture],
|
|
349
|
+
);
|
|
350
|
+
|
|
351
|
+
const clearExportError = useCallback(() => {
|
|
352
|
+
setExportError(null);
|
|
353
|
+
}, []);
|
|
354
|
+
|
|
355
|
+
const api = useMemo<ChartExportApi>(
|
|
356
|
+
() => ({
|
|
357
|
+
downloadChart,
|
|
358
|
+
downloadAll,
|
|
359
|
+
downloadPdf,
|
|
360
|
+
downloadHtml,
|
|
361
|
+
downloadingChartId,
|
|
362
|
+
exportingFormat,
|
|
363
|
+
exportLoadingLabel: exportingFormat
|
|
364
|
+
? EXPORT_LOADING_LABELS[exportingFormat]
|
|
365
|
+
: null,
|
|
366
|
+
isExportingAll: exportingFormat !== null,
|
|
367
|
+
isBusy: downloadingChartId !== null || exportingFormat !== null,
|
|
368
|
+
exportError,
|
|
369
|
+
clearExportError,
|
|
370
|
+
}),
|
|
371
|
+
[
|
|
372
|
+
clearExportError,
|
|
373
|
+
downloadAll,
|
|
374
|
+
downloadChart,
|
|
375
|
+
downloadHtml,
|
|
376
|
+
downloadPdf,
|
|
377
|
+
downloadingChartId,
|
|
378
|
+
exportError,
|
|
379
|
+
exportingFormat,
|
|
380
|
+
],
|
|
381
|
+
);
|
|
382
|
+
|
|
383
|
+
return (
|
|
384
|
+
<ChartExportRegistryContext.Provider value={registry}>
|
|
385
|
+
<ChartExportApiContext.Provider value={api}>
|
|
386
|
+
{children}
|
|
387
|
+
</ChartExportApiContext.Provider>
|
|
388
|
+
</ChartExportRegistryContext.Provider>
|
|
389
|
+
);
|
|
390
|
+
};
|
|
391
|
+
|
|
392
|
+
ChartExportProvider.displayName = "ChartExportProvider";
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { type FC, type ReactNode, useCallback, useRef } from "react";
|
|
2
|
+
import {
|
|
3
|
+
type ChartExportView,
|
|
4
|
+
chartExportRootStyle,
|
|
5
|
+
waitForChartExportPaint,
|
|
6
|
+
} from "./chartExport.js";
|
|
7
|
+
import { useRegisterChart } from "./chartExportContext.js";
|
|
8
|
+
|
|
9
|
+
export const ChartExportSurface: FC<{
|
|
10
|
+
id: string;
|
|
11
|
+
title: string;
|
|
12
|
+
filename?: string;
|
|
13
|
+
exportViews?: ChartExportView[];
|
|
14
|
+
activeExportViewId?: string;
|
|
15
|
+
onExportViewChange?: (viewId: string) => void;
|
|
16
|
+
children: ReactNode;
|
|
17
|
+
}> = ({
|
|
18
|
+
id,
|
|
19
|
+
title,
|
|
20
|
+
filename,
|
|
21
|
+
exportViews,
|
|
22
|
+
activeExportViewId,
|
|
23
|
+
onExportViewChange,
|
|
24
|
+
children,
|
|
25
|
+
}) => {
|
|
26
|
+
const activeViewRef = useRef(activeExportViewId);
|
|
27
|
+
activeViewRef.current = activeExportViewId;
|
|
28
|
+
const onExportViewChangeRef = useRef(onExportViewChange);
|
|
29
|
+
onExportViewChangeRef.current = onExportViewChange;
|
|
30
|
+
|
|
31
|
+
const setExportView = useCallback(async (viewId: string) => {
|
|
32
|
+
const change = onExportViewChangeRef.current;
|
|
33
|
+
if (change && activeViewRef.current !== viewId) {
|
|
34
|
+
change(viewId);
|
|
35
|
+
await new Promise<void>((resolve) => {
|
|
36
|
+
window.setTimeout(resolve, 0);
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
await waitForChartExportPaint();
|
|
40
|
+
}, []);
|
|
41
|
+
|
|
42
|
+
const ref = useRegisterChart({
|
|
43
|
+
id,
|
|
44
|
+
title,
|
|
45
|
+
filename,
|
|
46
|
+
exportViews,
|
|
47
|
+
activeExportViewId,
|
|
48
|
+
setExportView:
|
|
49
|
+
exportViews && exportViews.length > 1 && onExportViewChange
|
|
50
|
+
? setExportView
|
|
51
|
+
: undefined,
|
|
52
|
+
});
|
|
53
|
+
return (
|
|
54
|
+
<div ref={ref} id={id} style={chartExportRootStyle}>
|
|
55
|
+
{children}
|
|
56
|
+
</div>
|
|
57
|
+
);
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
ChartExportSurface.displayName = "ChartExportSurface";
|