diff --git a/add_modal_to_template.js b/add_modal_to_template.js new file mode 100644 index 0000000..3a4cb90 --- /dev/null +++ b/add_modal_to_template.js @@ -0,0 +1,56 @@ +// Add modal section to the end of the template, before closing +const modalHTML = ` + + +`; + +console.log("Modal HTML to add:", modalHTML); diff --git a/deploy-manual.sh b/deploy-manual.sh new file mode 100755 index 0000000..9642ed9 --- /dev/null +++ b/deploy-manual.sh @@ -0,0 +1,41 @@ +#!/bin/bash + +echo "🚀 Manual Salesforce Deployment Instructions" +echo "=============================================" +echo "" +echo "Since we don't have Salesforce CLI authentication set up, here are the manual steps:" +echo "" +echo "1. 📋 FILES TO DEPLOY:" +echo " - force-app/main/default/classes/PDFGenerationProxy.cls" +echo " - force-app/main/default/classes/PDFGenerationProxy.cls-meta.xml" +echo " - force-app/main/default/lwc/propertyTemplateSelector/" +echo "" +echo "2. 🔐 AUTHENTICATION OPTIONS:" +echo "" +echo " OPTION A - Web Login (Recommended):" +echo " sf org login web --alias myorg" +echo "" +echo " OPTION B - JWT Authentication:" +echo " sf org login jwt --client-id YOUR_CLIENT_ID --jwt-key-file server.key --username YOUR_USERNAME --alias myorg" +echo "" +echo "3. 🚀 DEPLOYMENT COMMANDS:" +echo " sf project deploy start --source-dir force-app/main/default/classes --target-org myorg" +echo " sf project deploy start --source-dir force-app/main/default/lwc --target-org myorg" +echo "" +echo "4. ✅ VERIFICATION:" +echo " sf org display --target-org myorg" +echo "" +echo "📁 Current files ready for deployment:" +echo "======================================" +find force-app -name "*.cls" -o -name "*.js" -o -name "*.xml" | sort +echo "" +echo "🎯 The PDFGenerationProxy.cls is already updated with:" +echo " ✅ return_download_link: true support" +echo " ✅ Proper error handling" +echo " ✅ Node.js API integration" +echo " ✅ 6MB size limit handling" +echo "" +echo "💡 After deployment, test with:" +echo " - Generate a PDF with return_download_link: true" +echo " - Verify the download link is returned" +echo " - Test the download endpoint" diff --git a/force-app/main/default/classes/PDFGenerationProxy.cls b/force-app/main/default/classes/PDFGenerationProxy.cls index bcf9cb2..4068939 100644 --- a/force-app/main/default/classes/PDFGenerationProxy.cls +++ b/force-app/main/default/classes/PDFGenerationProxy.cls @@ -8,40 +8,63 @@ public with sharing class PDFGenerationProxy { throw new AuraHandledException('HTML content cannot be empty. Please provide valid HTML content.'); } - System.debug('=== PDF GENERATION DEBUG (TEMPORARY FIX) ==='); + System.debug('=== PDF GENERATION DEBUG ==='); System.debug('HTML Content Length: ' + htmlContent.length()); System.debug('Page Size: ' + pageSize); - // Generate unique PDF ID for tracking - String pdfId = 'PDF_' + DateTime.now().getTime() + '_' + Math.random(); + // Call the Node.js API with return_download_link: true + Http http = new Http(); + HttpRequest request = new HttpRequest(); - // TEMPORARY FIX: Return download link without calling Python server - // This eliminates the 6MB limit issue immediately - Map result = new Map(); - result.put('success', true); - result.put('pdf_id', pdfId); - result.put('status', 'download_ready'); - result.put('message', 'PDF generation request received. Download link will be available shortly.'); + // Set the endpoint URL + request.setEndpoint('https://salesforce.tech4biz.io/generate-pdf'); + request.setMethod('POST'); + request.setHeader('Content-Type', 'application/json'); + request.setTimeout(120000); // 2 minutes timeout - // Create a temporary download URL (replace with actual Python server URL when ready) - result.put('download_url', 'https://salesforce.tech4biz.io/download-pdf/' + pdfId); + // Prepare the request body + Map requestBody = new Map(); + requestBody.put('input', htmlContent); + requestBody.put('return_download_link', true); + if (String.isNotBlank(pageSize)) { + requestBody.put('page_size', pageSize); + } - // Add additional information - result.put('page_size', pageSize != null ? pageSize : 'A4'); - result.put('generated_at', Datetime.now().format('yyyy-MM-dd HH:mm:ss')); - result.put('compression_applied', true); - result.put('file_size_mb', 'TBD'); - result.put('expires_at', Datetime.now().addDays(7).format('yyyy-MM-dd HH:mm:ss')); - result.put('pdf_stored', true); - result.put('temp_folder_path', '/temp/pdfs/' + pdfId); - result.put('backend_status', 'TEMPORARY_FIX_ACTIVE'); - result.put('note', 'This is a temporary fix to eliminate 6MB limit. Python server integration pending.'); + String jsonBody = JSON.serialize(requestBody); + request.setBody(jsonBody); - System.debug('Temporary fix applied - returning download link without API call'); - return result; + System.debug('Request body: ' + jsonBody); + + // Make the HTTP call + HttpResponse response = http.send(request); + + System.debug('Response status: ' + response.getStatusCode()); + System.debug('Response body: ' + response.getBody()); + + if (response.getStatusCode() == 200) { + // Parse the response + Map result = (Map) JSON.deserializeUntyped(response.getBody()); + + // Add additional metadata + result.put('salesforce_generated_at', Datetime.now().format('yyyy-MM-dd HH:mm:ss')); + result.put('api_version', '7.0.0'); + result.put('backend_status', 'NODE_JS_API_ACTIVE'); + + return result; + } else { + // Handle error response + Map errorResult = new Map(); + errorResult.put('success', false); + errorResult.put('error', 'PDF generation failed: HTTP ' + response.getStatusCode()); + errorResult.put('message', response.getBody()); + errorResult.put('pdf_id', 'ERROR_' + DateTime.now().getTime()); + + return errorResult; + } } catch (Exception e) { System.debug('Exception in generatePDFFromHTML: ' + e.getMessage()); + System.debug('Exception stack trace: ' + e.getStackTraceString()); Map errorResult = new Map(); errorResult.put('success', false); @@ -61,37 +84,66 @@ public with sharing class PDFGenerationProxy { throw new AuraHandledException('HTML content cannot be empty. Please provide valid HTML content.'); } - System.debug('=== COMPRESSED PDF GENERATION DEBUG (TEMPORARY FIX) ==='); + System.debug('=== COMPRESSED PDF GENERATION DEBUG ==='); System.debug('HTML Content Length: ' + htmlContent.length()); System.debug('Page Size: ' + pageSize); - // Generate unique PDF ID for tracking - String pdfId = 'COMPRESSED_PDF_' + DateTime.now().getTime() + '_' + Math.random(); + // Call the Node.js API with return_download_link: true + Http http = new Http(); + HttpRequest request = new HttpRequest(); - // TEMPORARY FIX: Return download link without calling Python server - Map result = new Map(); - result.put('success', true); - result.put('pdf_id', pdfId); - result.put('status', 'compressed_download_ready'); - result.put('message', 'Compressed PDF generation request received. Download link will be available shortly.'); + // Set the endpoint URL + request.setEndpoint('https://salesforce.tech4biz.io/generate-pdf'); + request.setMethod('POST'); + request.setHeader('Content-Type', 'application/json'); + request.setTimeout(120000); // 2 minutes timeout - // Create a temporary download URL - result.put('download_url', 'https://salesforce.tech4biz.io/download-pdf/' + pdfId); + // Prepare the request body + Map requestBody = new Map(); + requestBody.put('input', htmlContent); + requestBody.put('return_download_link', true); + if (String.isNotBlank(pageSize)) { + requestBody.put('page_size', pageSize); + } - result.put('page_size', pageSize != null ? pageSize : 'A4'); - result.put('generated_at', Datetime.now().format('yyyy-MM-dd HH:mm:ss')); - result.put('compression_applied', true); - result.put('compression_level', 'aggressive'); - result.put('file_size_mb', 'TBD'); - result.put('expires_at', Datetime.now().addDays(7).format('yyyy-MM-dd HH:mm:ss')); - result.put('pdf_stored', true); - result.put('temp_folder_path', '/temp/pdfs/' + pdfId); - result.put('backend_status', 'TEMPORARY_FIX_ACTIVE'); - result.put('note', 'This is a temporary fix to eliminate 6MB limit. Python server integration pending.'); + String jsonBody = JSON.serialize(requestBody); + request.setBody(jsonBody); + + System.debug('Request body: ' + jsonBody); + + // Make the HTTP call + HttpResponse response = http.send(request); + + System.debug('Response status: ' + response.getStatusCode()); + System.debug('Response body: ' + response.getBody()); + + if (response.getStatusCode() == 200) { + // Parse the response + Map result = (Map) JSON.deserializeUntyped(response.getBody()); + + // Add compression-specific metadata + result.put('compression_applied', true); + result.put('compression_level', 'aggressive'); + result.put('status', 'compressed_download_ready'); + result.put('salesforce_generated_at', Datetime.now().format('yyyy-MM-dd HH:mm:ss')); + result.put('api_version', '7.0.0'); + result.put('backend_status', 'NODE_JS_API_ACTIVE'); + + return result; + } else { + // Handle error response + Map errorResult = new Map(); + errorResult.put('success', false); + errorResult.put('error', 'Compressed PDF generation failed: HTTP ' + response.getStatusCode()); + errorResult.put('message', response.getBody()); + errorResult.put('pdf_id', 'ERROR_' + DateTime.now().getTime()); + + return errorResult; + } - return result; } catch (Exception e) { System.debug('Exception in generateCompressedPDF: ' + e.getMessage()); + System.debug('Exception stack trace: ' + e.getStackTraceString()); Map errorResult = new Map(); errorResult.put('success', false); diff --git a/force-app/main/default/lwc/propertyTemplateSelector/propertyTemplateSelector.css b/force-app/main/default/lwc/propertyTemplateSelector/propertyTemplateSelector.css index 141973d..038f682 100644 --- a/force-app/main/default/lwc/propertyTemplateSelector/propertyTemplateSelector.css +++ b/force-app/main/default/lwc/propertyTemplateSelector/propertyTemplateSelector.css @@ -8790,3 +8790,239 @@ ol li:before { } + +/* PDF Download Modal Styles */ +.pdf-download-modal-overlay { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(0, 0, 0, 0.8); + z-index: 9999; + display: flex; + align-items: center; + justify-content: center; + backdrop-filter: blur(5px); +} + +.pdf-download-modal { + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + border-radius: 20px; + padding: 30px; + max-width: 600px; + width: 90%; + box-shadow: 0 20px 40px rgba(0, 0, 0, 0.3); + position: relative; + color: white; + border: 1px solid rgba(255, 255, 255, 0.2); + max-height: 90vh; + overflow-y: auto; +} + +.pdf-download-modal .modal-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 25px; + padding-bottom: 15px; + border-bottom: 1px solid rgba(255, 255, 255, 0.2); +} + +.pdf-download-modal .modal-header h2 { + color: white; + margin: 0; + font-size: 2rem; + font-weight: 300; +} + +.pdf-download-modal .close-btn { + background: none; + border: none; + font-size: 28px; + cursor: pointer; + color: white; + transition: color 0.3s ease; + padding: 0; + width: 30px; + height: 30px; + display: flex; + align-items: center; + justify-content: center; +} + +.pdf-download-modal .close-btn:hover { + color: #ff6b6b; +} + +.pdf-download-modal .download-info { + background: rgba(255, 255, 255, 0.1); + border-radius: 15px; + padding: 20px; + margin: 20px 0; + border: 1px solid rgba(255, 255, 255, 0.2); +} + +.pdf-download-modal .download-info h3 { + color: #4CAF50; + margin-bottom: 15px; + font-size: 1.3rem; +} + +.pdf-download-modal .file-details { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); + gap: 15px; + margin: 15px 0; +} + +.pdf-download-modal .file-detail { + text-align: center; + background: rgba(255, 255, 255, 0.05); + padding: 15px; + border-radius: 10px; + border: 1px solid rgba(255, 255, 255, 0.1); +} + +.pdf-download-modal .file-detail .label { + font-size: 0.9rem; + color: rgba(255, 255, 255, 0.8); + margin-bottom: 5px; + font-weight: 500; +} + +.pdf-download-modal .file-detail .value { + font-weight: bold; + color: white; + font-size: 1rem; +} + +.pdf-download-modal .file-detail:nth-child(2) .value { + color: #4CAF50; +} + +.pdf-download-modal .file-detail:nth-child(4) .value { + color: #ffc107; +} + +.pdf-download-modal .download-link-section { + margin: 20px 0; +} + +.pdf-download-modal .download-link-section label { + display: block; + margin-bottom: 8px; + font-weight: bold; + color: white; + font-size: 1.1rem; +} + +.pdf-download-modal .download-link { + background: rgba(255, 255, 255, 0.9); + color: #333; + padding: 12px; + border-radius: 6px; + word-break: break-all; + font-family: 'Courier New', monospace; + font-size: 12px; + border: 2px solid #4CAF50; + margin-bottom: 10px; + line-height: 1.4; +} + +.pdf-download-modal .copy-btn { + background: #ffc107; + color: #333; + border: none; + padding: 8px 15px; + border-radius: 20px; + cursor: pointer; + font-size: 0.9rem; + margin-right: 10px; + transition: all 0.3s ease; + font-weight: 500; +} + +.pdf-download-modal .copy-btn:hover { + background: #ffb300; + transform: translateY(-1px); +} + +.pdf-download-modal .copy-btn.copied { + background: #4CAF50; + color: white; +} + +.pdf-download-modal .modal-actions { + text-align: center; + margin-top: 25px; + display: flex; + gap: 15px; + justify-content: center; + flex-wrap: wrap; +} + +.pdf-download-modal .download-btn { + background: linear-gradient(45deg, #4CAF50, #45a049); + color: white; + padding: 12px 25px; + border-radius: 25px; + text-decoration: none; + font-weight: bold; + display: inline-block; + transition: all 0.3s ease; + box-shadow: 0 4px 15px rgba(76, 175, 80, 0.3); + border: none; + cursor: pointer; + font-size: 1rem; +} + +.pdf-download-modal .download-btn:hover { + transform: translateY(-2px); + box-shadow: 0 6px 20px rgba(76, 175, 80, 0.4); + text-decoration: none; + color: white; +} + +.pdf-download-modal .open-tab-btn { + background: linear-gradient(45deg, #2196F3, #1976D2); + color: white; + border: none; + padding: 12px 25px; + border-radius: 25px; + cursor: pointer; + font-weight: bold; + transition: all 0.3s ease; + box-shadow: 0 4px 15px rgba(33, 150, 243, 0.3); + font-size: 1rem; +} + +.pdf-download-modal .open-tab-btn:hover { + transform: translateY(-2px); + box-shadow: 0 6px 20px rgba(33, 150, 243, 0.4); +} + +/* Responsive Design */ +@media (max-width: 768px) { + .pdf-download-modal { + margin: 10px; + padding: 20px; + width: calc(100% - 20px); + max-width: none; + } + + .pdf-download-modal .file-details { + grid-template-columns: repeat(2, 1fr); + } + + .pdf-download-modal .modal-actions { + flex-direction: column; + align-items: center; + } + + .pdf-download-modal .download-btn, + .pdf-download-modal .open-tab-btn { + width: 100%; + max-width: 250px; + } +} diff --git a/force-app/main/default/lwc/propertyTemplateSelector/propertyTemplateSelector.html.backup b/force-app/main/default/lwc/propertyTemplateSelector/propertyTemplateSelector.html.backup new file mode 100644 index 0000000..1c7746a --- /dev/null +++ b/force-app/main/default/lwc/propertyTemplateSelector/propertyTemplateSelector.html.backup @@ -0,0 +1,1291 @@ + + + \ No newline at end of file diff --git a/force-app/main/default/lwc/propertyTemplateSelector/propertyTemplateSelector.js b/force-app/main/default/lwc/propertyTemplateSelector/propertyTemplateSelector.js index 46e00bc..1b18d3c 100644 --- a/force-app/main/default/lwc/propertyTemplateSelector/propertyTemplateSelector.js +++ b/force-app/main/default/lwc/propertyTemplateSelector/propertyTemplateSelector.js @@ -132,6 +132,8 @@ export default class PropertyTemplateSelector extends LightningElement { @track isDraggingTable = false; @track draggedTableData = null; @track selectorMode = false; + @track showDownloadModal = false; + @track downloadInfo = {}; @track selectedElement = null; // Undo functionality @@ -1560,87 +1562,71 @@ export default class PropertyTemplateSelector extends LightningElement { this.isLoading = false; this.hideProgress(); - // Create download message based on compression level - let message = ""; + // Set the download info for the modal + this.downloadInfo = { + filename: pdfResult.filename || "Unknown", + fileSize: pdfResult.file_size_mb ? pdfResult.file_size_mb + " MB" : "Unknown", + generatedAt: this.formatDate(pdfResult.generated_at), + expiresAt: this.formatDate(pdfResult.expires_at), + downloadUrl: pdfResult.download_url + }; + // Automatically open download URL in new tab + console.log("Opening download URL:", pdfResult.download_url); + window.open(pdfResult.download_url, "_blank"); - if (pdfResult.status === "compressed_download_ready") { - message = ` -
-

📦 Compressed PDF Ready!

-

PDF ID: ${pdfResult.pdf_id}

-

Page Size: ${pdfResult.page_size}

-

Generated: ${pdfResult.generated_at}

-

This is a compressed version optimized for smaller file size.

- -
- -
- -
-

💡 About Compressed PDFs

-
    -
  • Images are optimized for smaller file size
  • -
  • All content is preserved but with reduced quality
  • -
  • Perfect for email sharing and quick downloads
  • -
-
-
- `; - } else { - message = ` -
-

📄 PDF Ready for Download!

-

PDF ID: ${pdfResult.pdf_id}

-

Page Size: ${pdfResult.page_size}

-

Generated: ${pdfResult.generated_at}

-

Your PDF has been generated successfully and is ready for download.

- -
- -
- -
-

✅ Download Instructions

-
    -
  • Click the download button above
  • -
  • Your PDF will open in a new tab
  • -
  • Use your browser's save function to download
  • -
-
-
- `; - } - - this.showSuccess(message); - - // Also provide a direct download link as fallback - setTimeout(() => { - if (this.template.querySelector('.success-message')) { - const successMsg = this.template.querySelector('.success-message'); - - // Add a fallback download link - const fallbackLink = document.createElement('a'); - fallbackLink.href = pdfResult.download_url; - fallbackLink.textContent = '🔗 Direct Download Link'; - fallbackLink.className = 'slds-button slds-button_neutral'; - fallbackLink.style.marginTop = '10px'; - fallbackLink.style.display = 'inline-block'; - fallbackLink.target = '_blank'; - - successMsg.appendChild(fallbackLink); - } - }, 1000); + // Show simple success message + this.showSuccess(`✅ PDF generated successfully! File: ${pdfResult.filename} (${pdfResult.file_size_mb} MB) - Download opened in new tab.`); + this.showSuccess(`✅ PDF generated successfully! File: ${pdfResult.filename} (${pdfResult.file_size_mb} MB)`); } catch (error) { - console.error('Error handling PDF download ready:', error); - this.showError('Error handling PDF download: ' + error.message); + console.error("Error handling PDF download ready:", error); + this.showError("Error handling PDF download: " + error.message); } } + // Modal control methods + closeDownloadModal() { + this.showDownloadModal = false; + } + + stopPropagation(event) { + event.stopPropagation(); + } + + copyDownloadLink() { + if (navigator.clipboard && this.downloadInfo) { + navigator.clipboard.writeText(this.downloadInfo.downloadUrl).then(() => { + // Show feedback + const copyBtn = this.template.querySelector(".copy-btn"); + if (copyBtn) { + const originalText = copyBtn.textContent; + copyBtn.textContent = "✅ Copied!"; + copyBtn.classList.add("copied"); + + setTimeout(() => { + copyBtn.textContent = originalText; + copyBtn.classList.remove("copied"); + }, 2000); + } + }).catch(err => { + console.error("Failed to copy: ", err); + alert("Failed to copy link to clipboard"); + }); + } + } + + openInNewTab() { + if (this.downloadInfo && this.downloadInfo.downloadUrl) { + window.open(this.downloadInfo.downloadUrl, "_blank"); + } + } + + // Helper method to format dates + formatDate(dateString) { + if (!dateString) return "Unknown"; + const date = new Date(dateString); + return date.toLocaleString(); + } // Create template HTML based on selection createTemplateHTML() { console.log('=== CREATE TEMPLATE HTML DEBUG ==='); diff --git a/force-app/main/default/lwc/propertyTemplateSelector/propertyTemplateSelector.js.backup b/force-app/main/default/lwc/propertyTemplateSelector/propertyTemplateSelector.js.backup index 0e38098..46e00bc 100644 --- a/force-app/main/default/lwc/propertyTemplateSelector/propertyTemplateSelector.js.backup +++ b/force-app/main/default/lwc/propertyTemplateSelector/propertyTemplateSelector.js.backup @@ -1551,6 +1551,96 @@ export default class PropertyTemplateSelector extends LightningElement { } } + // Handle PDF download ready response + async handlePDFDownloadReady(pdfResult) { + try { + console.log("Handling PDF download ready:", pdfResult); + + // Hide loading state + this.isLoading = false; + this.hideProgress(); + + // Create download message based on compression level + let message = ""; + + if (pdfResult.status === "compressed_download_ready") { + message = ` +
+

📦 Compressed PDF Ready!

+

PDF ID: ${pdfResult.pdf_id}

+

Page Size: ${pdfResult.page_size}

+

Generated: ${pdfResult.generated_at}

+

This is a compressed version optimized for smaller file size.

+ +
+ +
+ +
+

💡 About Compressed PDFs

+
    +
  • Images are optimized for smaller file size
  • +
  • All content is preserved but with reduced quality
  • +
  • Perfect for email sharing and quick downloads
  • +
+
+
+ `; + } else { + message = ` +
+

📄 PDF Ready for Download!

+

PDF ID: ${pdfResult.pdf_id}

+

Page Size: ${pdfResult.page_size}

+

Generated: ${pdfResult.generated_at}

+

Your PDF has been generated successfully and is ready for download.

+ +
+ +
+ +
+

✅ Download Instructions

+
    +
  • Click the download button above
  • +
  • Your PDF will open in a new tab
  • +
  • Use your browser's save function to download
  • +
+
+
+ `; + } + + this.showSuccess(message); + + // Also provide a direct download link as fallback + setTimeout(() => { + if (this.template.querySelector('.success-message')) { + const successMsg = this.template.querySelector('.success-message'); + + // Add a fallback download link + const fallbackLink = document.createElement('a'); + fallbackLink.href = pdfResult.download_url; + fallbackLink.textContent = '🔗 Direct Download Link'; + fallbackLink.className = 'slds-button slds-button_neutral'; + fallbackLink.style.marginTop = '10px'; + fallbackLink.style.display = 'inline-block'; + fallbackLink.target = '_blank'; + + successMsg.appendChild(fallbackLink); + } + }, 1000); + + } catch (error) { + console.error('Error handling PDF download ready:', error); + this.showError('Error handling PDF download: ' + error.message); + } + } + // Create template HTML based on selection createTemplateHTML() { console.log('=== CREATE TEMPLATE HTML DEBUG ==='); diff --git a/replace_method.py b/replace_method.py new file mode 100644 index 0000000..5b7bc55 --- /dev/null +++ b/replace_method.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python3 + +# Read the original file +with open('force-app/main/default/lwc/propertyTemplateSelector/propertyTemplateSelector.js', 'r') as f: + lines = f.readlines() + +# Read the new method +with open('update_popup_method.js', 'r') as f: + new_method = f.read() + +# Find the start and end of the handlePDFDownloadReady method +start_line = 1555 - 1 # Convert to 0-based index +end_line = 1643 - 1 # Convert to 0-based index + +# Replace the method +new_lines = lines[:start_line] + [new_method + '\n\n'] + lines[end_line:] + +# Write the updated file +with open('force-app/main/default/lwc/propertyTemplateSelector/propertyTemplateSelector.js', 'w') as f: + f.writelines(new_lines) + +print("✅ Successfully updated the handlePDFDownloadReady method with popup functionality!") diff --git a/update_popup_method.js b/update_popup_method.js new file mode 100644 index 0000000..1ce45a9 --- /dev/null +++ b/update_popup_method.js @@ -0,0 +1,182 @@ +// Updated handlePDFDownloadReady method with popup functionality +async handlePDFDownloadReady(pdfResult) { + try { + console.log("Handling PDF download ready:", pdfResult); + + // Hide loading state + this.isLoading = false; + this.hideProgress(); + + // Show the beautiful popup modal + this.showDownloadPopup(pdfResult); + + // Also show a success message + this.showSuccess('✅ PDF generated successfully! Click the popup to download.'); + + } catch (error) { + console.error('Error handling PDF download ready:', error); + this.showError('Error handling PDF download: ' + error.message); + } +} + +// New method to show download popup +showDownloadPopup(pdfResult) { + // Create modal HTML + const modalHTML = ` +
+ +
+ `; + + // Add modal to page + document.body.insertAdjacentHTML('beforeend', modalHTML); + + // Close modal when clicking outside + const modal = document.querySelector('.pdf-download-modal'); + if (modal) { + modal.addEventListener('click', function(event) { + if (event.target === modal) { + modal.remove(); + } + }); + } + + // Close modal with Escape key + const escapeHandler = function(event) { + if (event.key === 'Escape') { + const modal = document.querySelector('.pdf-download-modal'); + if (modal) { + modal.remove(); + document.removeEventListener('keydown', escapeHandler); + } + } + }; + document.addEventListener('keydown', escapeHandler); +} + +// Helper method to format dates +formatDate(dateString) { + if (!dateString) return 'Unknown'; + const date = new Date(dateString); + return date.toLocaleString(); +}