Skip to content

Commit

Permalink
Changes related with Download PDF in Discovery Report step (#82)
Browse files Browse the repository at this point in the history
Signed-off-by: Montse Ortega <[email protected]>
  • Loading branch information
ammont82 authored Jan 30, 2025
1 parent 6f8595e commit 6ca4333
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 74 deletions.
2 changes: 1 addition & 1 deletion apps/demo/src/migration-wizard/MigrationWizard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ export const MigrationWizard: React.FC = () => {
discoverSourcesContext.agentSelected?.status === "up-to-date";

return (
<Wizard height={computedHeight}>
<Wizard height={computedHeight} style={{ overflow: "hidden" }}>
<WizardStep
name="Connect"
id="connect-step"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,10 +99,6 @@ export const SourcesTable: React.FC = () => {

}, [memoizedAgents, hasAgents, discoverySourcesContext, firstAgent]);


console.log("---------");
console.log(hasAgents);
console.log("----------");
// Show spinner until all data is loaded
if ((isLoading) ) {
return (
Expand Down
16 changes: 3 additions & 13 deletions apps/demo/src/migration-wizard/steps/discovery/DiscoveryStep.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ import { ReportPieChart } from "./ReportPieChart";
import DownloadPDFButton from "./DownloadPDFButton";

export const DiscoveryStep: React.FC = () => {
const [forceExpand, setForceExpand] = React.useState(false);
const discoverSourcesContext = useDiscoverySources();
const { inventory } = discoverSourcesContext.sourceSelected as Source;
const { infra, vms } = inventory!;
Expand Down Expand Up @@ -333,18 +332,10 @@ export const DiscoveryStep: React.FC = () => {
networksViewData,
storageViewData,
operatingSystemsViewData,
];

// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
const handleForceExpand = async (callback: () => Promise<void>) => {
setForceExpand(true); // Forzar la expansión
await new Promise((resolve) => setTimeout(resolve, 100)); // Espera que React renderice
await callback(); // Llama al callback para generar el PDF
setForceExpand(false); // Restaura el estado
};
];

return (
<Stack hasGutter id="discovery-report">
<Stack hasGutter id="discovery-report" >
<StackItem>
<TextContent>
<Flex alignItems={{ default: "alignItemsCenter" }} justifyContent={{ default: "justifyContentSpaceBetween" }}>
Expand All @@ -354,7 +345,7 @@ export const DiscoveryStep: React.FC = () => {
</TextContent>
</FlexItem>
<FlexItem spacer={{ default: "spacerMd" }}>
<DownloadPDFButton elementId="discovery-report" onBeforeDownload={(callback) => handleForceExpand(callback)}/>
<DownloadPDFButton elementId="discovery-report" treeViewData={treeViewData}/>
</FlexItem>
</Flex>
<Text component="p">
Expand All @@ -368,7 +359,6 @@ export const DiscoveryStep: React.FC = () => {
aria-label="Discovery report"
variant="compactNoBackground"
data={treeViewData}
allExpanded={forceExpand}
/>
</StackItem>
</Stack>
Expand Down
148 changes: 96 additions & 52 deletions apps/demo/src/migration-wizard/steps/discovery/DownloadPDFButton.tsx
Original file line number Diff line number Diff line change
@@ -1,67 +1,111 @@
import React from "react";
import React, { useRef } from "react";
import jsPDF from "jspdf";
import html2canvas from "html2canvas";
import { Button } from "@patternfly/react-core";
import { Button, TreeView, TreeViewDataItem } from "@patternfly/react-core";
import { createRoot } from "react-dom/client";

interface DownloadPDFButtonProps {
elementId: string;
onBeforeDownload: (callback: () => Promise<void>) => void;
}

const DownloadPDFButton: React.FC<DownloadPDFButtonProps> = ({ elementId, onBeforeDownload }) => {
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
const handleDownloadPDF = async () => {
elementId: string;
treeViewData: TreeViewDataItem[];
}

const DownloadPDFButton: React.FC<DownloadPDFButtonProps> = ({
elementId,
treeViewData,
}) => {
const hiddenContainerRef = useRef<HTMLDivElement | null>(null);

const assignUniqueIds = (
data: TreeViewDataItem[],
parentId: string = "download"
): TreeViewDataItem[] => {
return data.map((item, index) => {
const uniqueId = `${item.id}-${parentId}-${index}`;
return {
...item,
id: uniqueId,
key: uniqueId,
children: item.children
? assignUniqueIds(item.children, uniqueId)
: undefined,
};
});
};
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
const handleDownloadPDF = async () => {
try {
const originalWarn = console.warn;
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
const generatePDF = async () => {
const element = document.getElementById(elementId);
if (!element) return;
console.warn = () => {};
const hiddenContainer = hiddenContainerRef.current;

if (!hiddenContainer) return;
hiddenContainer.innerHTML = "";
const treeClone = (
<TreeView
id={`${elementId}-clone`}
aria-label="Cloned Discovery Report"
variant="compactNoBackground"
data={assignUniqueIds(treeViewData, elementId)}
allExpanded={true}
/>
);

// Hide download button
const button = document.getElementById("download-pdf-button");
if (button) button.style.display = "none";

const canvas = await html2canvas(element);
const imgData = canvas.toDataURL("image/png");
const pdf = new jsPDF("p", "mm", "a4");

const pageWidth = pdf.internal.pageSize.getWidth();
const pageHeight = pdf.internal.pageSize.getHeight();
const margin = 10;
const tempDiv = document.createElement("div");
hiddenContainer.appendChild(tempDiv);
const root = createRoot(tempDiv);
root.render(treeClone);

const contentWidth = pageWidth - margin * 2;
const contentHeight = pageHeight - margin * 2;

await new Promise((resolve) => setTimeout(resolve, 500));

const imgWidth = canvas.width;
const imgHeight = canvas.height;

const scaleFactor = Math.min(contentWidth / imgWidth, contentHeight / imgHeight);
const canvas = await html2canvas(hiddenContainer, { useCORS: true });
const imgData = canvas.toDataURL("image/png");
const pdf = new jsPDF("p", "mm", "a4");

const imgX = margin;
const imgY = margin;

pdf.addImage(
imgData,
"PNG",
imgX,
imgY,
imgWidth * scaleFactor,
imgHeight * scaleFactor
);
pdf.save("Discovery_Report.pdf");
const pageWidth = pdf.internal.pageSize.getWidth();
const pageHeight = pdf.internal.pageSize.getHeight();
const margin = 10;

// Show download button
if (button) button.style.display = "block";
};

// Llama al callback para forzar la expansión antes de generar el PDF
onBeforeDownload(generatePDF);

};
const contentWidth = pageWidth - margin * 2;
const contentHeight = pageHeight - margin * 2;

const imgWidth = canvas.width;
const imgHeight = canvas.height;

const scaleFactor = Math.min(
contentWidth / imgWidth,
contentHeight / imgHeight
);

pdf.addImage(
imgData,
"PNG",
margin,
margin,
imgWidth * scaleFactor,
imgHeight * scaleFactor
);
pdf.save("Discovery_Report.pdf");

hiddenContainer.innerHTML = "";
console.warn = originalWarn;
} catch (error) {
console.error("Error generating PDF:", error);
}
};

return (
<Button variant="secondary" onClick={handleDownloadPDF} id="download-pdf-button" >
Export to PDF
</Button>
<>
<Button variant="secondary" onClick={handleDownloadPDF}>
Export PDF
</Button>
<div
id="hidden-container"
ref={hiddenContainerRef}
style={{ position: "absolute", left: "-9999px", visibility: "visible" }}
/>
</>
);
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,16 @@ export function ReportTable<DataItem>(
>
<Thead>
<Tr>
{columns.map((name) => (
<Th hasRightBorder>{name}</Th>
{columns.map((name,index) => (
<Th key={index} hasRightBorder>{name}</Th>
))}
</Tr>
</Thead>
<Tbody>
{data.map((item, idx) => (
<Tr key={idx}>
{fields.map((f) => (
<Td hasRightBorder> {item[f] === "" ? "-" : (item[f] as React.ReactNode)}</Td>
{fields.map((f,fieldIdx) => (
<Td key={fieldIdx} hasRightBorder> {item[f] === "" ? "-" : (item[f] as React.ReactNode)}</Td>
))}
</Tr>
))}
Expand Down

0 comments on commit 6ca4333

Please sign in to comment.