mitai-jinkendo/frontend/src/utils/dashboardPdfExport.js
Lars 62729d0648
All checks were successful
Deploy Development / deploy (push) Successful in 1m4s
Build Test / pytest-backend (push) Successful in 5s
Build Test / lint-backend (push) Successful in 1s
Build Test / build-frontend (push) Successful in 19s
feat: add report_export widget and enhance report generation capabilities
- Introduced the `report_export` widget to the dashboard, allowing users to generate structured PDF reports.
- Updated widget configuration to include `report_export` in the allowed widgets and added validation for its configuration.
- Enhanced the widget catalog with details for the new `report_export` entry.
- Implemented API endpoints for managing report profiles and generating PDFs.
- Added frontend components for configuring and displaying report settings.
- Updated tests to ensure proper validation and functionality of the new report generation features.
- Bumped application version to reflect the addition of the new widget and related functionalities.
2026-04-29 11:28:04 +02:00

70 lines
2.1 KiB
JavaScript

export const DASHBOARD_PDF_CAPTURE_ROOT_ID = 'dashboard-pdf-capture-root'
/**
* @param {{ scale?: number, filenameBase?: string }} [opts]
*/
export async function exportDashboardToPdf(opts = {}) {
const scale = opts.scale ?? 2
const filenameBase = opts.filenameBase ?? 'mitai-uebersicht'
const [{ default: html2canvas }, { jsPDF }] = await Promise.all([
import('html2canvas'),
import('jspdf'),
])
const el = document.getElementById(DASHBOARD_PDF_CAPTURE_ROOT_ID)
if (!el) throw new Error('Dashboard-Inhalt nicht gefunden (interner Fehler).')
const prevScroll = window.scrollY
window.scrollTo(0, 0)
await new Promise((r) => requestAnimationFrame(r))
await new Promise((r) => requestAnimationFrame(r))
await new Promise((r) => setTimeout(r, 320))
try {
const canvas = await html2canvas(el, {
scale,
useCORS: true,
allowTaint: true,
logging: false,
backgroundColor: '#ffffff',
ignoreElements: (node) => node?.getAttribute?.('data-dashboard-pdf-exclude') === 'true',
scrollX: 0,
scrollY: 0,
width: el.scrollWidth,
height: el.scrollHeight,
windowWidth: el.scrollWidth,
windowHeight: el.scrollHeight,
})
const imgData = canvas.toDataURL('image/png', 1.0)
const pdf = new jsPDF({ orientation: 'p', unit: 'mm', format: 'a4', compress: true })
const pageW = pdf.internal.pageSize.getWidth()
const pageH = pdf.internal.pageSize.getHeight()
const margin = 8
const innerW = pageW - 2 * margin
const innerH = pageH - 2 * margin
const imgW = innerW
const imgH = (canvas.height * imgW) / canvas.width
let position = margin
pdf.addImage(imgData, 'PNG', margin, position, imgW, imgH, undefined, 'FAST')
let heightLeft = imgH - innerH
while (heightLeft > 0) {
position = margin - (imgH - heightLeft)
pdf.addPage()
pdf.addImage(imgData, 'PNG', margin, position, imgW, imgH, undefined, 'FAST')
heightLeft -= innerH
}
const safe = String(filenameBase)
.replace(/[\\/:*?"<>|]+/g, '')
.trim()
pdf.save(`${safe || 'bericht'}.pdf`)
} finally {
window.scrollTo(0, prevScroll)
}
}