From c02e629a8886adc70cc717bdd8c4d024bb08bd4b Mon Sep 17 00:00:00 2001 From: Suherdy Yacob Date: Mon, 16 Mar 2026 16:57:33 +0700 Subject: [PATCH] feat: Add diagnostic logging and debugging utilities for the sign image field's PDF iframe interactions. --- static/src/js/sign_image_upload.js | 66 +++++++++++++++++++----------- 1 file changed, 43 insertions(+), 23 deletions(-) diff --git a/static/src/js/sign_image_upload.js b/static/src/js/sign_image_upload.js index cd0aac2..a47c1b4 100755 --- a/static/src/js/sign_image_upload.js +++ b/static/src/js/sign_image_upload.js @@ -4,36 +4,30 @@ import { patch } from "@web/core/utils/patch"; import { PDFIframe } from "@sign/components/sign_request/PDF_iframe"; import { SignablePDFIframe } from "@sign/components/sign_request/signable_PDF_iframe"; -console.log("Sign Image Field: Initializing bulletproof stability patches..."); +console.log("Sign Image Field: Initializing diagnostic patches..."); /** - * Bulletproof Bridge Restoration - * Re-connects Odoo parent to PDF viewer iframe on multiple levels to ensure viewer.js - * can always find the refreshSignItemsForPage method. + * Diagnostic Bridge Restoration */ -const restoreBridge = (instance) => { +const restoreBridge = (instance, caller) => { if (!instance || !instance.root || !instance.root.defaultView) return; const iwin = instance.root.defaultView; const iframe = iwin.frameElement; - // 1. Parent-side element (Standard Odoo mechanism) if (iframe && !iframe.odoo_iframe_instance) { - console.log("Sign Image Field: Restoring bridge on iframe element"); + console.log(`[Diagnostic] Restoring bridge on iframe element from ${caller}`); iframe.odoo_iframe_instance = instance; } - // 2. Iframe-side global (In-frame customization) if (!iwin.odoo_iframe_instance) { iwin.odoo_iframe_instance = instance; } - // 3. Document-side global (In-frame customization fallback) if (iwin.document && !iwin.document.odoo_iframe_instance) { iwin.document.odoo_iframe_instance = instance; } - // 4. Attach directly to PDFViewerApplication if ready if (iwin.PDFViewerApplication && !iwin.PDFViewerApplication.odoo_iframe_instance) { iwin.PDFViewerApplication.odoo_iframe_instance = instance; } @@ -66,13 +60,9 @@ const triggerLazyLoad = (el) => { if (lazyImg.complete) finalize(); }; -/** - * Shared logic for setting up an observer. - */ const setupLazyObserver = (el) => { if (!el) return; - // Safety fallback: Force load after 1.5s setTimeout(() => { if (el.classList.contains('o_sign_image_loading_container')) { triggerLazyLoad(el); @@ -94,25 +84,53 @@ const setupLazyObserver = (el) => { } }; +window.diagnosticForceShowFields = () => { + const hiddenItems = document.querySelectorAll('iframe.o_sign_pdf_iframe')?.length ? + document.querySelector('iframe.o_sign_pdf_iframe').contentDocument.querySelectorAll('.o_sign_sign_item.d-none') : []; + + console.log(`[Diagnostic] Forcing show on ${hiddenItems.length} hidden items`); + hiddenItems.forEach(el => el.classList.remove('d-none')); +}; + +const hookCheckSignItemsCompletion = (instance) => { + console.log("[Diagnostic] checkSignItemsCompletion hooked. Total signItems mapped:"); + let totalItems = 0; + for (const page in instance.signItems) { + const items = instance.signItems[page]; + totalItems += Object.keys(items).length; + console.log(` Page ${page}: ${Object.keys(items).length} items`); + } + console.log(`[Diagnostic] Total items managed by PDFIframe: ${totalItems}`); +}; + // 1. Patch PDFIframe (ROOT) patch(PDFIframe.prototype, { enableCustom(signItem) { - restoreBridge(this); + restoreBridge(this, 'PDFIframe.enableCustom'); - // Call original implementation FIRST if (typeof super.enableCustom === 'function') { super.enableCustom(...arguments); } - // Setup lazy loading for images if (signItem && signItem.data && signItem.data.type === 'image' && signItem.el) { setupLazyObserver(signItem.el); } }, + refreshSignItemsForPage(page) { + console.log(`[Diagnostic] refreshSignItemsForPage called for page ${page}`); + restoreBridge(this, 'PDFIframe.refreshSignItemsForPage'); + + try { + return super.refreshSignItemsForPage(...arguments); + } catch (error) { + console.error("[Diagnostic] Error inside refreshSignItemsForPage:", error); + } + }, + refreshSignItems(page = false) { - // Ensure bridge is active during page rendering events - restoreBridge(this); + console.log(`[Diagnostic] refreshSignItems called (page: ${page})`); + restoreBridge(this, 'PDFIframe.refreshSignItems'); return super.refreshSignItems(...arguments); } }); @@ -120,17 +138,14 @@ patch(PDFIframe.prototype, { // 2. Patch SignablePDFIframe (Signer subclass) patch(SignablePDFIframe.prototype, { enableCustom(signItem) { - restoreBridge(this); + restoreBridge(this, 'SignablePDFIframe.enableCustom'); - // Setup image observers early for ALL users if (signItem && signItem.data && signItem.data.type === 'image' && signItem.el) { setupLazyObserver(signItem.el); } - // Call original implementation to populate Nama, NIK, etc. super.enableCustom(...arguments); - // Add upload logic for active signer if (signItem && signItem.data && signItem.data.type === 'image' && signItem.el) { const el = signItem.el; const data = signItem.data; @@ -210,5 +225,10 @@ patch(SignablePDFIframe.prototype, { return item.el.dataset.value || item.data.value || false; } return super.getSignatureValueFromElement(...arguments); + }, + + checkSignItemsCompletion() { + hookCheckSignItemsCompletion(this); + return super.checkSignItemsCompletion(...arguments); } });