diff --git a/assets/css/admin-order-bulk.css b/assets/css/admin-order-bulk.css
index 73f1b3b7..dbf7f773 100644
--- a/assets/css/admin-order-bulk.css
+++ b/assets/css/admin-order-bulk.css
@@ -28,7 +28,8 @@
display: none;
}
.postnl-action-create-label:after,
-.postnl-action-download-label:after {
+.postnl-action-download-label:after,
+.postnl-action-print-label:after {
content: "";
background-size: 20px !important;
display: inline-block;
@@ -40,6 +41,10 @@
.postnl-action-download-label:after {
background: url(../images/post-download-label.png) no-repeat center center;
}
+.postnl-action-print-label:after {
+ background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3E%3Cpath fill='%23f46d0a' d='M5 2h10v4H5zM4 7h12a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-1v2H5v-2H4a2 2 0 0 1-2-2V9a2 2 0 0 1 2-2zm1 7v3h10v-3H5zm9-4a1 1 0 1 0 0-2 1 1 0 0 0 0 2z'/%3E%3C/svg%3E") no-repeat center center;
+ background-size: 18px !important;
+}
.postnl_eligible_auto_letterbox {
font-size: 18px;
}
diff --git a/assets/css/admin-order-single.css b/assets/css/admin-order-single.css
index 1cab6e88..657001b3 100644
--- a/assets/css/admin-order-single.css
+++ b/assets/css/admin-order-single.css
@@ -32,10 +32,6 @@
display:none;
}
-#shipment-postnl-label-form.generated .button-download-label {
- display:inline-block;
-}
-
#shipment-postnl-label-form .delete-label {
display:none;
}
@@ -63,11 +59,30 @@
}
#shipment-postnl-label-form.generated .delete-label {
- display:inline-block;
+ display: flex;
+ align-items: center;
+}
+
+#shipment-postnl-label-form.generated .button-download-label {
+ display: flex;
+ align-items: center;
}
#shipment-postnl-label-form #shipment-postnl-error-text {
margin-top:15px;
color:#ff0000;
font-weight:700;
+}
+
+#shipment-postnl-label-form .button-container {
+ display: flex;
+ flex-direction: column;
+ align-items: stretch;
+ gap: 6px;
+}
+
+#shipment-postnl-label-form .button-container .button {
+ margin: 0;
+ text-align: center;
+ justify-content: center;
}
\ No newline at end of file
diff --git a/assets/js/admin-print-label.js b/assets/js/admin-print-label.js
new file mode 100644
index 00000000..353bef0f
--- /dev/null
+++ b/assets/js/admin-print-label.js
@@ -0,0 +1,81 @@
+( function () {
+ 'use strict';
+
+ // Set the pdf.js worker URL from the localized PHP data.
+ if ( typeof postnlPrintLabelData !== 'undefined' && postnlPrintLabelData.workerSrc ) {
+ pdfjsLib.GlobalWorkerOptions.workerSrc = postnlPrintLabelData.workerSrc;
+ }
+
+ /**
+ * Fetch a PDF from `url`, render every page to a canvas, then open a print window.
+ *
+ * @param {string} url Absolute URL to the PDF label.
+ */
+ function postnlPrintLabel( url ) {
+ pdfjsLib.getDocument( url ).promise
+ .then( function ( pdf ) {
+ var renderPromises = [];
+
+ for ( var i = 1; i <= pdf.numPages; i++ ) {
+ renderPromises.push(
+ pdf.getPage( i ).then( function ( page ) {
+ var viewport = page.getViewport( { scale: 2 } );
+ var canvas = document.createElement( 'canvas' );
+ canvas.width = viewport.width;
+ canvas.height = viewport.height;
+
+ return page.render( {
+ canvasContext: canvas.getContext( '2d' ),
+ viewport: viewport,
+ } ).promise.then( function () {
+ return canvas.toDataURL( 'image/png' );
+ } );
+ } )
+ );
+ }
+
+ return Promise.all( renderPromises );
+ } )
+ .then( function ( dataUrls ) {
+ var imgs = dataUrls.map( function ( src, i ) {
+ return '
';
+ } ).join( '' );
+
+ var html = '
Print Label'
+ + ''
+ + '' + imgs + '';
+
+ var printWindow = window.open( '', '_blank' );
+ printWindow.document.open();
+ printWindow.document.write( html );
+ printWindow.document.close();
+
+ printWindow.onload = function () {
+ printWindow.focus();
+ printWindow.print();
+ };
+ } )
+ .catch( function ( err ) {
+ console.error( 'PostNL print failed:', err );
+ } );
+ }
+
+ // Event delegation — works for buttons rendered at any time (single order & orders list).
+ document.addEventListener( 'click', function ( e ) {
+ // Matches the meta-box print button (data-label-url) and the WC action icon (.postnl-action-print-label).
+ var btn = e.target.closest( '.button-print-label, .postnl-action-print-label' );
+ if ( ! btn ) {
+ return;
+ }
+ e.preventDefault();
+ var url = btn.getAttribute( 'data-label-url' ) || btn.getAttribute( 'href' );
+ if ( url ) {
+ postnlPrintLabel( url );
+ }
+ } );
+
+ // Expose globally for programmatic use.
+ window.postnlPrintLabel = postnlPrintLabel;
+} )();
diff --git a/src/Order/Bulk.php b/src/Order/Bulk.php
index 945d896a..1410ec44 100644
--- a/src/Order/Bulk.php
+++ b/src/Order/Bulk.php
@@ -263,8 +263,14 @@ public function merge_bulk_labels( $gen_labels ) {
$bulk_download_label_url = $this->get_download_bulk_url();
return array(
- // translators: %1$s is anchor tag opener. %2$s is anchor tag closer.
- 'message' => sprintf( esc_html__( 'Bulk PostNL labels file created - %1$sdownload file%2$s', 'postnl-for-woocommerce' ), '', '' ),
+ // translators: %1$s is print button opener, %2$s is print button closer, %3$s is download link opener, %4$s is anchor tag closer.
+ 'message' => sprintf(
+ esc_html__( 'Bulk PostNL labels file created - %1$sprint label%2$s - %3$sdownload file%4$s', 'postnl-for-woocommerce' ),
+ '',
+ '',
+ '',
+ ''
+ ),
'type' => 'success',
);
}
@@ -355,6 +361,30 @@ public function enqueue_bulk_assets() {
true
);
+ wp_enqueue_script(
+ 'postnl-pdfjs',
+ 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.min.js',
+ array(),
+ null,
+ true
+ );
+
+ wp_enqueue_script(
+ 'postnl-admin-print-label',
+ POSTNL_WC_PLUGIN_DIR_URL . '/assets/js/admin-print-label.js',
+ array( 'postnl-pdfjs' ),
+ POSTNL_WC_VERSION,
+ true
+ );
+
+ wp_localize_script(
+ 'postnl-admin-print-label',
+ 'postnlPrintLabelData',
+ array(
+ 'workerSrc' => 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.worker.min.js',
+ )
+ );
+
}
}
@@ -630,9 +660,14 @@ public function add_create_label_actions_button( array $actions, \WC_Order $orde
}
if ( $this->have_label_file( $order ) ) {
- $actions['postnl-label'] = array(
+ $actions['postnl-print-label'] = array(
'url' => $this->get_download_label_url( $order->get_id() ),
'name' => esc_html__( 'PostNL Print Label', 'postnl-for-woocommerce' ),
+ 'action' => 'postnl-action-print-label',
+ );
+ $actions['postnl-label'] = array(
+ 'url' => $this->get_download_label_url( $order->get_id() ),
+ 'name' => esc_html__( 'PostNL Download Label', 'postnl-for-woocommerce' ),
'action' => 'postnl-action-download-label',
);
} else {
@@ -698,10 +733,12 @@ public function generate_label_and_notes( $order_id, $post_data ) {
$order->add_order_note( $tracking_note, $customer_note );
$label_link = esc_url( $this->get_download_label_url( $order_id ) );
$result['message'] = array(
- // Translators: %1$s is the order ID, %2$s is the link to download the file, %3$s is the closing link tag.
+ // Translators: %1$s is the order ID, %2$s is the print button opener, %3$s is the print button closer, %4$s is the download link opener, %5$s is the closing link tag.
'message' => sprintf(
- esc_html__( '#%1$s : PostNL label has been created - %2$sdownload file%3$s', 'postnl-for-woocommerce' ),
+ esc_html__( '#%1$s : PostNL label has been created - %2$sprint label%3$s - %4$sdownload file%5$s', 'postnl-for-woocommerce' ),
$order_id,
+ '',
+ '',
'',
''
),
diff --git a/src/Order/Single.php b/src/Order/Single.php
index e4feb083..5b016a0d 100644
--- a/src/Order/Single.php
+++ b/src/Order/Single.php
@@ -100,6 +100,30 @@ public function enqueue_order_single_css_script() {
true
);
+ wp_enqueue_script(
+ 'postnl-pdfjs',
+ 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.min.js',
+ array(),
+ null,
+ true
+ );
+
+ wp_enqueue_script(
+ 'postnl-admin-print-label',
+ POSTNL_WC_PLUGIN_DIR_URL . '/assets/js/admin-print-label.js',
+ array( 'postnl-pdfjs' ),
+ POSTNL_WC_VERSION,
+ true
+ );
+
+ wp_localize_script(
+ 'postnl-admin-print-label',
+ 'postnlPrintLabelData',
+ array(
+ 'workerSrc' => 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.worker.min.js',
+ )
+ );
+
wp_localize_script(
'postnl-admin-order-single',
'postnl_admin_order_obj',
@@ -420,23 +444,19 @@ public function meta_box_html( $post_or_order_object ) {
activate_return_function_html( $order ); ?>
send_smart_return_email_html( $order ); ?>
-
-