Add PDF export functionality and favicon support
- Introduced a new script for exporting the dashboard as a PDF using html2canvas and jsPDF. - Added a favicon.ico file and linked it in the base template. - Updated the base template to include the new PDF export script and modified the button for PDF export functionality. - Enhanced the index template to include an ID for the dashboard content for PDF generation.
This commit is contained in:
BIN
static/favicon.ico
Normal file
BIN
static/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
File diff suppressed because one or more lines are too long
111
static/js/export-pdf.js
Normal file
111
static/js/export-pdf.js
Normal file
@@ -0,0 +1,111 @@
|
||||
/**
|
||||
* Export dashboard as PDF by capturing a screenshot of #dashboard-content
|
||||
* and assembling it into a multi-page PDF (html2canvas + jsPDF).
|
||||
*/
|
||||
function exportDashboardToPdf() {
|
||||
var el = document.getElementById('dashboard-content');
|
||||
if (!el) {
|
||||
if (typeof console !== 'undefined' && console.warn) {
|
||||
console.warn('export-pdf: #dashboard-content not found');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var btn = document.getElementById('pdf-export-btn');
|
||||
var originalText = btn ? btn.innerHTML : '';
|
||||
if (btn) {
|
||||
btn.disabled = true;
|
||||
btn.innerHTML = 'Generating PDF…';
|
||||
}
|
||||
|
||||
var regionEl = document.getElementById('regionBadge');
|
||||
var region = regionEl ? (regionEl.textContent || '').trim() : '';
|
||||
|
||||
if (typeof html2canvas === 'undefined' || typeof jspdf === 'undefined') {
|
||||
if (btn) {
|
||||
btn.disabled = false;
|
||||
btn.innerHTML = originalText;
|
||||
}
|
||||
alert('PDF export requires html2canvas and jsPDF. Please refresh the page.');
|
||||
return;
|
||||
}
|
||||
|
||||
var JsPDFConstructor = (typeof jspdf !== 'undefined' && jspdf.jsPDF) ? jspdf.jsPDF : jspdf;
|
||||
|
||||
var auditSection = el.querySelector('section[aria-label="Audit analysis"]');
|
||||
var auditSectionDisplay = '';
|
||||
if (auditSection) {
|
||||
auditSectionDisplay = auditSection.style.display;
|
||||
auditSection.style.display = 'none';
|
||||
}
|
||||
|
||||
function restoreAuditSection() {
|
||||
if (auditSection) {
|
||||
auditSection.style.display = auditSectionDisplay;
|
||||
}
|
||||
}
|
||||
|
||||
html2canvas(el, {
|
||||
scale: 2,
|
||||
useCORS: true,
|
||||
allowTaint: true,
|
||||
logging: false
|
||||
}).then(function(canvas) {
|
||||
var imgW = canvas.width;
|
||||
var imgH = canvas.height;
|
||||
var dataUrl = canvas.toDataURL('image/png');
|
||||
|
||||
var doc = new JsPDFConstructor({ orientation: 'portrait', unit: 'mm', format: 'a4' });
|
||||
var pageW = 210;
|
||||
var pageH = 297;
|
||||
var margin = 10;
|
||||
var contentW = pageW - 2 * margin;
|
||||
var headerH = 14;
|
||||
var firstPageImgTop = margin + headerH;
|
||||
var firstPageImgH = pageH - firstPageImgTop - margin;
|
||||
var otherPageImgH = pageH - 2 * margin;
|
||||
|
||||
var imgWmm = contentW;
|
||||
var imgHmm = contentW * (imgH / imgW);
|
||||
|
||||
doc.setFontSize(14);
|
||||
doc.text('Dashboard report', margin, margin + 6);
|
||||
doc.setFontSize(10);
|
||||
doc.text(region ? 'Region: ' + region : '', margin, margin + 12);
|
||||
|
||||
var shown = 0;
|
||||
var totalH = imgHmm;
|
||||
var pageNum = 0;
|
||||
var imgYmm = firstPageImgTop;
|
||||
|
||||
while (shown < totalH) {
|
||||
if (pageNum > 0) {
|
||||
doc.addPage();
|
||||
imgYmm = margin;
|
||||
}
|
||||
var sliceH = pageNum === 0 ? firstPageImgH : otherPageImgH;
|
||||
var yOffset = -shown;
|
||||
doc.addImage(dataUrl, 'PNG', margin, imgYmm + yOffset, imgWmm, imgHmm);
|
||||
shown += sliceH;
|
||||
pageNum += 1;
|
||||
}
|
||||
|
||||
doc.save('dashboard-report.pdf');
|
||||
|
||||
restoreAuditSection();
|
||||
if (btn) {
|
||||
btn.disabled = false;
|
||||
btn.innerHTML = originalText;
|
||||
}
|
||||
}).catch(function (err) {
|
||||
if (typeof console !== 'undefined' && console.error) {
|
||||
console.error('export-pdf:', err);
|
||||
}
|
||||
restoreAuditSection();
|
||||
if (btn) {
|
||||
btn.disabled = false;
|
||||
btn.innerHTML = originalText;
|
||||
}
|
||||
alert('Failed to generate PDF. Please try again.');
|
||||
});
|
||||
}
|
||||
10
static/js/html2canvas-pro.min.js
vendored
Normal file
10
static/js/html2canvas-pro.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
397
static/js/jspdf.umd.min.js
vendored
Normal file
397
static/js/jspdf.umd.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user