OpenClinica / enketo-oc

OpenClinica's fork of the Enketo web forms monorepo
Apache License 2.0
0 stars 5 forks source link

Printed PDFs not including contents of image fields/drawing widgets #59

Open malcjackson opened 1 year ago

malcjackson commented 1 year ago

Describe the bug When printing participant casebooks from formprint.openclinica-dev.io, the contents of fields that contain images (Signature widgets, drawing widgets, annotated images) are not appearing in the resulting PDF. The fields are blank.

To Reproduce Create a from with a signature item, drawing item, or image upload item, fill it in, and print the PDF casebook. The casebook includes these items but the image fields are blank.

Expected behavior The filled in images appear in the resulting PDF.

Screenshots

blankwidgets
MartijnR commented 1 year ago

view:

curl --user enketorules: -d "server_url=https://api.ona.io/enketo&form_id=widgets&instance=<widgets><text_widgets><text>mart</text></text_widgets><media_widgets><signature>test.jpg</signature></media_widgets></widgets>&instance_id=someUUID&instance_attachments[test.jpg]=https://upload.wikimedia.org/wikipedia/commons/a/a9/Example.jpg" http://localhost:8005/api/v2/instance/view

pdf:

curl --user enketorules: -d "server_url=https://api.ona.io/enketo&form_id=widgets&instance=<widgets><text_widgets><text>mart</text></text_widgets><media_widgets><signature>test.jpg</signature></media_widgets></widgets>&instance_id=someUUID&instance_attachments[test.jpg]=https://upload.wikimedia.org/wikipedia/commons/a/a9/Example.jpg" http://localhost:8005/api/v2/instance/view/pdf > ~/Downloads/pdf1.pdf

Likely an issue with using canvas headlessly.

This is a workaround that works but it causes a big slowdown:

        const canvases = await page.$$('canvas');
        for (const canvas of canvases) {
            const str = await canvas.screenshot({ encoding: 'base64' });
            const dataUrl = `data:image/png;base64,${str}`;
            await canvas.evaluate((canvas, dataUrl) => {
                const newDiv = document.createElement('div');
                newDiv.innerHTML = `<img src="${dataUrl}">`;
                canvas.parentNode.replaceChild(newDiv, canvas);
            }, dataUrl);
        }

A similar solution that does the same on the client directly will likely work too. Would be better to resolve the issue though.

https://bugs.chromium.org/p/chromium/issues/detail?id=809065 https://github.com/puppeteer/puppeteer/issues/1731

Tried setting alpha: true in getContext by monkey patching HTMLCanvasElement.prototype.getContext but that did not fix it. Just adding it here in case we want to go back to this (naughty signature_pad workaround) approach:

const originalGetContext = HTMLCanvasElement.prototype.getContext;

HTMLCanvasElement.prototype.getContext = function (a, b) {
    return originalGetContext.call(this, a, b || { alpha: true });
};
MartijnR commented 1 year ago

copied issue here: https://github.com/enketo/enketo/issues/969

MartijnR commented 1 year ago

Internal PR: https://github.com/OpenClinica/enketo-express-oc/pull/627