taler-typescript-core

Wallet core logic and WebUIs for various components
Log | Files | Refs | Submodules | README | LICENSE

commit b70a7bb1318d28ac6686a3f8427eb9a3e237a969
parent 32adf5bd5b672fd26e0fe8bbbbb161c39bbabdae
Author: Sebastian <sebasjm@gmail.com>
Date:   Tue, 18 Nov 2025 11:24:13 -0300

fix #9772

Diffstat:
Mpackages/merchant-backoffice-ui/src/index.dev.html | 2+-
Mpackages/merchant-backoffice-ui/src/index.prod.html | 2+-
Mpackages/merchant-backoffice-ui/src/paths/instance/templates/qr/QrPage.tsx | 42++++++++++++++++++++++++------------------
3 files changed, 26 insertions(+), 20 deletions(-)

diff --git a/packages/merchant-backoffice-ui/src/index.dev.html b/packages/merchant-backoffice-ui/src/index.dev.html @@ -27,7 +27,7 @@ <meta name="mobile-web-app-capable" content="yes" /> <meta name="apple-mobile-web-app-capable" content="yes" /> <meta name="taler-support" content="uri,api" /> - <meta http-equiv="Content-Security-Policy" content="default-src 'none'; script-src 'self'; connect-src *; img-src 'self' data:; style-src 'self';font-src 'self';base-uri 'self';form-action 'self'"> + <meta http-equiv="Content-Security-Policy" content="default-src 'none'; frame-src blob:; script-src 'self'; connect-src *; img-src 'self' data:; style-src 'self';font-src 'self';base-uri 'self';form-action 'self'"> <link rel="icon" diff --git a/packages/merchant-backoffice-ui/src/index.prod.html b/packages/merchant-backoffice-ui/src/index.prod.html @@ -27,7 +27,7 @@ <meta name="mobile-web-app-capable" content="yes" /> <meta name="apple-mobile-web-app-capable" content="yes" /> <meta name="taler-support" content="uri,api" /> - <meta http-equiv="Content-Security-Policy" content="default-src 'none'; script-src 'self'; connect-src *; img-src 'self' data:; style-src 'self';font-src 'self';base-uri 'self';form-action 'self'"> + <meta http-equiv="Content-Security-Policy" content="default-src 'none'; frame-src blob:; script-src 'self'; connect-src *; img-src 'self' data:; style-src 'self';font-src 'self';base-uri 'self';form-action 'self'"> <link rel="icon" diff --git a/packages/merchant-backoffice-ui/src/paths/instance/templates/qr/QrPage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/templates/qr/QrPage.tsx @@ -28,6 +28,7 @@ import { useTranslationContext } from "@gnu-taler/web-util/browser"; import { VNode, h } from "preact"; import { QR } from "../../../../components/exception/QR.js"; import { useSessionContext } from "../../../../context/session.js"; +import { useRef } from "preact/hooks"; // type Entity = TalerMerchantApi.UsingTemplateDetails; @@ -49,10 +50,11 @@ export function QrPage({ id: templateId, onBack }: Props): VNode { // FIXME! //templateParams: {}, }); + const printThis = useRef<HTMLElement>(null); return ( <div> - <section id="printThis"> + <section id="printThis" ref={printThis}> <QR text={payTemplateUri} /> <pre style={{ textAlign: "center" }}> <a target="_blank" rel="noreferrer" href={payTemplateUri}> @@ -67,13 +69,14 @@ export function QrPage({ id: templateId, onBack }: Props): VNode { <div class="column is-four-fifths"> <div class="buttons is-right mt-5"> {onBack && ( - <button type="button"class="button" onClick={onBack}> + <button type="button" class="button" onClick={onBack}> <i18n.Translate>Cancel</i18n.Translate> </button> )} - <button type="button" + <button + type="button" class="button is-info" - onClick={() => saveAsPDF(templateId)} + onClick={() => saveAsPDF(templateId, printThis.current!)} > <i18n.Translate>Print</i18n.Translate> </button> @@ -86,13 +89,8 @@ export function QrPage({ id: templateId, onBack }: Props): VNode { ); } -function saveAsPDF(name: string): void { - // TODO: Look into using media queries in the current page, to print the current page, instead of opening a new window - - const divContents = document.getElementById("printThis"); - if (!divContents) return; - - let dom = `<!DOCTYPE html> +function saveAsPDF(name: string, divContents: HTMLElement): void { + const dom = `<!DOCTYPE html> <html> <head> <title>Order template for ${name}</title> @@ -106,12 +104,20 @@ function saveAsPDF(name: string): void { ${divContents.outerHTML} </body> </html>`; - const blobUrl = URL.createObjectURL(new Blob([dom])); - const printWindow = window.open(blobUrl, "", "height=400,width=800"); - if (!printWindow) return; - printWindow.addEventListener("load", () => { - printWindow.print(); - printWindow.close(); + const blobUrl = URL.createObjectURL(new Blob([dom], { type: "text/html" })); + const f = document.createElement("iframe"); + f.src = blobUrl; + f.style.display = "none"; + function onComplete() { + document.body.removeChild(f); URL.revokeObjectURL(blobUrl); - }); + } + f.onload = () => { + if (!f.contentWindow) return; + f.contentWindow.onbeforeunload = onComplete; + f.contentWindow.onafterprint = onComplete; + f.contentWindow.print(); + }; + + document.body.appendChild(f); }