upfdated to ptint plugin
This commit is contained in:
Binary file not shown.
@@ -932,6 +932,162 @@ def upload_data():
|
|||||||
def print_module():
|
def print_module():
|
||||||
return render_template('print_module.html')
|
return render_template('print_module.html')
|
||||||
|
|
||||||
|
@bp.route('/download_extension')
|
||||||
|
def download_extension():
|
||||||
|
"""Route for downloading the Chrome extension"""
|
||||||
|
return render_template('download_extension.html')
|
||||||
|
|
||||||
|
@bp.route('/extension_files/<path:filename>')
|
||||||
|
def extension_files(filename):
|
||||||
|
"""Serve Chrome extension files for download"""
|
||||||
|
import os
|
||||||
|
from flask import send_from_directory, current_app
|
||||||
|
|
||||||
|
extension_dir = os.path.join(os.path.dirname(current_app.root_path), 'chrome_extension')
|
||||||
|
return send_from_directory(extension_dir, filename)
|
||||||
|
|
||||||
|
@bp.route('/create_extension_package', methods=['POST'])
|
||||||
|
def create_extension_package():
|
||||||
|
"""Create and serve ZIP package of Chrome extension"""
|
||||||
|
import os
|
||||||
|
import zipfile
|
||||||
|
from flask import current_app, jsonify, send_file
|
||||||
|
import tempfile
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Use correct path to chrome_extension directory (it's in py_app, not py_app/app)
|
||||||
|
extension_dir = os.path.join(os.path.dirname(current_app.root_path), 'chrome_extension')
|
||||||
|
print(f"Looking for extension files in: {extension_dir}")
|
||||||
|
|
||||||
|
if not os.path.exists(extension_dir):
|
||||||
|
return jsonify({
|
||||||
|
'success': False,
|
||||||
|
'error': f'Extension directory not found: {extension_dir}'
|
||||||
|
}), 500
|
||||||
|
|
||||||
|
# List files in extension directory for debugging
|
||||||
|
all_files = []
|
||||||
|
for root, dirs, files in os.walk(extension_dir):
|
||||||
|
for file in files:
|
||||||
|
file_path = os.path.join(root, file)
|
||||||
|
all_files.append(file_path)
|
||||||
|
|
||||||
|
print(f"Found files: {all_files}")
|
||||||
|
|
||||||
|
# Create static directory if it doesn't exist
|
||||||
|
static_dir = os.path.join(current_app.root_path, 'static')
|
||||||
|
os.makedirs(static_dir, exist_ok=True)
|
||||||
|
|
||||||
|
zip_filename = 'quality_recticel_print_helper.zip'
|
||||||
|
zip_path = os.path.join(static_dir, zip_filename)
|
||||||
|
|
||||||
|
# Create ZIP file directly in static directory
|
||||||
|
with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
|
||||||
|
files_added = 0
|
||||||
|
|
||||||
|
# Add all extension files to ZIP
|
||||||
|
for root, dirs, files in os.walk(extension_dir):
|
||||||
|
for file in files:
|
||||||
|
# Include all relevant files
|
||||||
|
if file.endswith(('.json', '.js', '.html', '.css', '.png', '.md', '.txt')):
|
||||||
|
file_path = os.path.join(root, file)
|
||||||
|
# Create relative path for archive
|
||||||
|
arcname = os.path.relpath(file_path, extension_dir)
|
||||||
|
|
||||||
|
print(f"Adding file: {file_path} as {arcname}")
|
||||||
|
zipf.write(file_path, arcname)
|
||||||
|
files_added += 1
|
||||||
|
|
||||||
|
# Add a README file with installation instructions
|
||||||
|
readme_content = """# Quality Recticel Print Helper Chrome Extension
|
||||||
|
|
||||||
|
## Installation Instructions:
|
||||||
|
|
||||||
|
1. Extract this ZIP file to a folder on your computer
|
||||||
|
2. Open Chrome and go to: chrome://extensions/
|
||||||
|
3. Enable "Developer mode" in the top right
|
||||||
|
4. Click "Load unpacked" and select the extracted folder
|
||||||
|
5. The extension icon 🖨️ should appear in your toolbar
|
||||||
|
|
||||||
|
## Usage:
|
||||||
|
|
||||||
|
1. Go to the Print Module in the Quality Recticel application
|
||||||
|
2. Select an order from the table
|
||||||
|
3. Click the "🖨️ Print Direct" button
|
||||||
|
4. The label will print automatically to your default printer
|
||||||
|
|
||||||
|
## Troubleshooting:
|
||||||
|
|
||||||
|
- Make sure your default printer is set up correctly
|
||||||
|
- Click the extension icon to test printer connection
|
||||||
|
- Check Chrome printer settings: chrome://settings/printing
|
||||||
|
|
||||||
|
For support, contact your system administrator.
|
||||||
|
"""
|
||||||
|
zipf.writestr('README.txt', readme_content)
|
||||||
|
files_added += 1
|
||||||
|
|
||||||
|
print(f"Total files added to ZIP: {files_added}")
|
||||||
|
|
||||||
|
# Verify ZIP was created and has content
|
||||||
|
if os.path.exists(zip_path):
|
||||||
|
zip_size = os.path.getsize(zip_path)
|
||||||
|
print(f"ZIP file created: {zip_path}, size: {zip_size} bytes")
|
||||||
|
|
||||||
|
if zip_size > 0:
|
||||||
|
return jsonify({
|
||||||
|
'success': True,
|
||||||
|
'download_url': f'/static/{zip_filename}',
|
||||||
|
'files_included': files_added,
|
||||||
|
'zip_size': zip_size
|
||||||
|
})
|
||||||
|
else:
|
||||||
|
return jsonify({
|
||||||
|
'success': False,
|
||||||
|
'error': 'ZIP file was created but is empty'
|
||||||
|
}), 500
|
||||||
|
else:
|
||||||
|
return jsonify({
|
||||||
|
'success': False,
|
||||||
|
'error': 'Failed to create ZIP file'
|
||||||
|
}), 500
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error creating extension package: {e}")
|
||||||
|
import traceback
|
||||||
|
traceback.print_exc()
|
||||||
|
return jsonify({
|
||||||
|
'success': False,
|
||||||
|
'error': str(e)
|
||||||
|
}), 500
|
||||||
|
|
||||||
|
@bp.route('/test_extension_files')
|
||||||
|
def test_extension_files():
|
||||||
|
"""Test route to check extension files"""
|
||||||
|
import os
|
||||||
|
from flask import current_app, jsonify
|
||||||
|
|
||||||
|
extension_dir = os.path.join(os.path.dirname(current_app.root_path), 'chrome_extension')
|
||||||
|
|
||||||
|
result = {
|
||||||
|
'extension_dir': extension_dir,
|
||||||
|
'dir_exists': os.path.exists(extension_dir),
|
||||||
|
'files': []
|
||||||
|
}
|
||||||
|
|
||||||
|
if os.path.exists(extension_dir):
|
||||||
|
for root, dirs, files in os.walk(extension_dir):
|
||||||
|
for file in files:
|
||||||
|
file_path = os.path.join(root, file)
|
||||||
|
file_size = os.path.getsize(file_path)
|
||||||
|
result['files'].append({
|
||||||
|
'path': file_path,
|
||||||
|
'relative_path': os.path.relpath(file_path, extension_dir),
|
||||||
|
'size': file_size
|
||||||
|
})
|
||||||
|
|
||||||
|
return jsonify(result)
|
||||||
|
|
||||||
@bp.route('/label_templates')
|
@bp.route('/label_templates')
|
||||||
def label_templates():
|
def label_templates():
|
||||||
return render_template('label_templates.html')
|
return render_template('label_templates.html')
|
||||||
|
|||||||
144
py_app/app/templates/download_extension.html
Normal file
144
py_app/app/templates/download_extension.html
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block title %}Chrome Extension Download{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<div class="col-md-8">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">
|
||||||
|
<h3 class="mb-0">🖨️ Quality Recticel Print Helper - Chrome Extension</h3>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="alert alert-info">
|
||||||
|
<strong>Direct Printing Solution:</strong> This Chrome extension enables direct printing from the Print Module to your default printer without browser dialogs.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h4>Features:</h4>
|
||||||
|
<ul>
|
||||||
|
<li>✅ Print labels directly to default printer</li>
|
||||||
|
<li>✅ No browser print dialogs</li>
|
||||||
|
<li>✅ Automatic printer detection</li>
|
||||||
|
<li>✅ Print status notifications</li>
|
||||||
|
<li>✅ Enhanced print button with visual feedback</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h4>Installation Instructions:</h4>
|
||||||
|
<ol>
|
||||||
|
<li><strong>Download Extension Files:</strong>
|
||||||
|
<div class="mt-2 mb-3">
|
||||||
|
<button class="btn btn-primary" id="download-extension-btn">
|
||||||
|
📥 Download Chrome Extension (.zip)
|
||||||
|
</button>
|
||||||
|
<br><br>
|
||||||
|
<div class="alert alert-info" style="font-size: 12px;">
|
||||||
|
<strong>Alternative:</strong> Download individual files:
|
||||||
|
<br>
|
||||||
|
<a href="{{ url_for('main.extension_files', filename='manifest.json') }}" target="_blank">manifest.json</a> |
|
||||||
|
<a href="{{ url_for('main.extension_files', filename='background.js') }}" target="_blank">background.js</a> |
|
||||||
|
<a href="{{ url_for('main.extension_files', filename='content.js') }}" target="_blank">content.js</a> |
|
||||||
|
<a href="{{ url_for('main.extension_files', filename='popup.html') }}" target="_blank">popup.html</a> |
|
||||||
|
<a href="{{ url_for('main.extension_files', filename='popup.js') }}" target="_blank">popup.js</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li><strong>Extract Files:</strong>
|
||||||
|
<p>Extract the downloaded ZIP file to a folder on your computer (e.g., Desktop/print_extension)</p>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li><strong>Open Chrome Extensions:</strong>
|
||||||
|
<p>In Google Chrome, go to: <code>chrome://extensions/</code></p>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li><strong>Enable Developer Mode:</strong>
|
||||||
|
<p>Toggle the "Developer mode" switch in the top-right corner</p>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li><strong>Load Extension:</strong>
|
||||||
|
<p>Click "Load unpacked" and select the folder where you extracted the files</p>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li><strong>Verify Installation:</strong>
|
||||||
|
<p>The extension icon 🖨️ should appear in your Chrome toolbar</p>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<h4>Usage:</h4>
|
||||||
|
<ol>
|
||||||
|
<li>Navigate to the <a href="{{ url_for('main.print_module') }}" target="_blank">Print Module</a></li>
|
||||||
|
<li>Select an order from the table</li>
|
||||||
|
<li>Click the enhanced "🖨️ Print Direct" button</li>
|
||||||
|
<li>The label will print automatically to your default printer</li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<div class="alert alert-warning">
|
||||||
|
<strong>System Requirements:</strong>
|
||||||
|
<ul class="mb-0">
|
||||||
|
<li>Google Chrome browser (version 88 or higher)</li>
|
||||||
|
<li>Default printer configured on your system</li>
|
||||||
|
<li>Printer drivers installed and working</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="alert alert-success">
|
||||||
|
<strong>Troubleshooting:</strong>
|
||||||
|
<ul class="mb-0">
|
||||||
|
<li>Click the extension icon 🖨️ to test printer connection</li>
|
||||||
|
<li>Check Chrome's printer settings: <code>chrome://settings/printing</code></li>
|
||||||
|
<li>Ensure your default printer is set correctly</li>
|
||||||
|
<li>Reload the Print Module page after installing the extension</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-4 text-center">
|
||||||
|
<a href="{{ url_for('main.print_module') }}" class="btn btn-success">
|
||||||
|
🖨️ Go to Print Module
|
||||||
|
</a>
|
||||||
|
<button class="btn btn-secondary" onclick="window.close()">
|
||||||
|
✖️ Close
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// Create ZIP file dynamically when download is requested
|
||||||
|
document.getElementById('download-extension-btn').addEventListener('click', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
// Show loading state
|
||||||
|
this.innerHTML = '⏳ Preparing Download...';
|
||||||
|
this.disabled = true;
|
||||||
|
|
||||||
|
// Create the extension package
|
||||||
|
fetch('/create_extension_package', {method: 'POST'})
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
if (data.success) {
|
||||||
|
// Start download
|
||||||
|
window.location.href = data.download_url;
|
||||||
|
|
||||||
|
// Reset button
|
||||||
|
setTimeout(() => {
|
||||||
|
this.innerHTML = '📥 Download Chrome Extension (.zip)';
|
||||||
|
this.disabled = false;
|
||||||
|
}, 2000);
|
||||||
|
} else {
|
||||||
|
alert('Error creating extension package: ' + data.error);
|
||||||
|
this.innerHTML = '📥 Download Chrome Extension (.zip)';
|
||||||
|
this.disabled = false;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
alert('Error: ' + error.message);
|
||||||
|
this.innerHTML = '📥 Download Chrome Extension (.zip)';
|
||||||
|
this.disabled = false;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
||||||
@@ -239,6 +239,11 @@ table tbody tr.selected td {
|
|||||||
<label for="print-label-btn" style="font-size: 14px; font-weight: 500; color: var(--app-card-text); margin-bottom: 0;">Print selected order</label>
|
<label for="print-label-btn" style="font-size: 14px; font-weight: 500; color: var(--app-card-text); margin-bottom: 0;">Print selected order</label>
|
||||||
<button id="print-label-btn" class="btn btn-primary" style="font-size: 14px; padding: 6px 24px;">Print</button>
|
<button id="print-label-btn" class="btn btn-primary" style="font-size: 14px; padding: 6px 24px;">Print</button>
|
||||||
</div>
|
</div>
|
||||||
|
<div style="width: 100%; text-align: center; margin-top: 12px;">
|
||||||
|
<a href="{{ url_for('main.download_extension') }}" target="_blank" style="font-size: 12px; color: #007bff; text-decoration: none;">
|
||||||
|
🔗 Install Direct Print Extension
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Data Preview Card -->
|
<!-- Data Preview Card -->
|
||||||
@@ -349,6 +354,9 @@ document.getElementById('check-db-btn').addEventListener('click', function() {
|
|||||||
if (data.length > 0) {
|
if (data.length > 0) {
|
||||||
updateLabelPreview(data[0]);
|
updateLabelPreview(data[0]);
|
||||||
|
|
||||||
|
// Add fallback print functionality if extension is not available
|
||||||
|
addFallbackPrintHandler();
|
||||||
|
|
||||||
// Auto-select first row
|
// Auto-select first row
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
const firstRow = document.querySelector('.print-module-table tbody tr');
|
const firstRow = document.querySelector('.print-module-table tbody tr');
|
||||||
@@ -428,5 +436,81 @@ function updateLabelPreview(order) {
|
|||||||
// Update barcode with the same prod order data
|
// Update barcode with the same prod order data
|
||||||
document.getElementById('barcode-text').textContent = prodOrder;
|
document.getElementById('barcode-text').textContent = prodOrder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fallback print handler for when Chrome extension is not available
|
||||||
|
function addFallbackPrintHandler() {
|
||||||
|
// Check if Chrome extension modified the button
|
||||||
|
setTimeout(() => {
|
||||||
|
const printButton = document.getElementById('print-label-btn');
|
||||||
|
|
||||||
|
// If button text hasn't changed, extension is not active
|
||||||
|
if (printButton && !printButton.innerHTML.includes('🖨️ Print Direct')) {
|
||||||
|
console.log('Chrome extension not detected, adding fallback print handler');
|
||||||
|
|
||||||
|
// Add fallback event listener
|
||||||
|
printButton.addEventListener('click', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
const labelPreview = document.getElementById('label-preview');
|
||||||
|
if (!labelPreview) {
|
||||||
|
alert('Please select an order first.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new window for printing
|
||||||
|
const printWindow = window.open('', '_blank');
|
||||||
|
const printContent = `
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Quality Recticel Label</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 20px;
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
}
|
||||||
|
.print-container {
|
||||||
|
width: 210mm;
|
||||||
|
height: 297mm;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
.label-wrapper {
|
||||||
|
transform: scale(1.2);
|
||||||
|
transform-origin: top left;
|
||||||
|
}
|
||||||
|
@media print {
|
||||||
|
body { padding: 0; }
|
||||||
|
.print-container { margin: 0; }
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="print-container">
|
||||||
|
<div class="label-wrapper">
|
||||||
|
${labelPreview.outerHTML}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
`;
|
||||||
|
|
||||||
|
printWindow.document.write(printContent);
|
||||||
|
printWindow.document.close();
|
||||||
|
|
||||||
|
// Wait for content to load, then print
|
||||||
|
printWindow.onload = function() {
|
||||||
|
printWindow.focus();
|
||||||
|
printWindow.print();
|
||||||
|
printWindow.close();
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
// Update button text to indicate fallback mode
|
||||||
|
printButton.innerHTML = '🖨️ Print (Browser)';
|
||||||
|
printButton.title = 'Print using browser dialog - Install Chrome Extension for direct printing';
|
||||||
|
}
|
||||||
|
}, 2000); // Wait 2 seconds for extension to load
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
185
py_app/chrome_extension/background.js
Normal file
185
py_app/chrome_extension/background.js
Normal file
@@ -0,0 +1,185 @@
|
|||||||
|
// Background service worker for Chrome extension
|
||||||
|
console.log('Quality Recticel Print Helper - Background script loaded');
|
||||||
|
|
||||||
|
// Listen for messages from content script
|
||||||
|
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
|
||||||
|
console.log('Background received message:', request);
|
||||||
|
|
||||||
|
if (request.action === 'print_label') {
|
||||||
|
handlePrintLabel(request.data, sendResponse);
|
||||||
|
return true; // Keep message channel open for async response
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request.action === 'fallback_print') {
|
||||||
|
handleFallbackPrint(request.data, sendResponse);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request.action === 'get_printers') {
|
||||||
|
getPrinters(sendResponse);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request.action === 'check_extension') {
|
||||||
|
sendResponse({status: 'installed', version: chrome.runtime.getManifest().version});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Function to handle label printing
|
||||||
|
async function handlePrintLabel(printData, sendResponse) {
|
||||||
|
try {
|
||||||
|
console.log('Attempting to print label with data:', printData);
|
||||||
|
|
||||||
|
// Check if printing API is available
|
||||||
|
if (!chrome.printing || !chrome.printing.getPrinters) {
|
||||||
|
console.error('Chrome printing API not available');
|
||||||
|
sendResponse({
|
||||||
|
success: false,
|
||||||
|
error: 'Chrome printing API not available. Please ensure you are using Chrome 85+ and the extension has proper permissions.'
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get available printers
|
||||||
|
const printers = await chrome.printing.getPrinters();
|
||||||
|
console.log('Available printers:', printers);
|
||||||
|
|
||||||
|
if (printers.length === 0) {
|
||||||
|
sendResponse({success: false, error: 'No printers found. Please ensure a printer is installed and set as default.'});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find default printer or use first available
|
||||||
|
const defaultPrinter = printers.find(p => p.isDefault) || printers[0];
|
||||||
|
console.log('Using printer:', defaultPrinter);
|
||||||
|
|
||||||
|
// Create print job
|
||||||
|
const printJob = {
|
||||||
|
printerId: defaultPrinter.id,
|
||||||
|
ticket: {
|
||||||
|
version: '1.0',
|
||||||
|
print: {
|
||||||
|
color: {
|
||||||
|
type: 'STANDARD_MONOCHROME'
|
||||||
|
},
|
||||||
|
duplex: {
|
||||||
|
type: 'NO_DUPLEX'
|
||||||
|
},
|
||||||
|
page_orientation: {
|
||||||
|
type: 'PORTRAIT'
|
||||||
|
},
|
||||||
|
copies: {
|
||||||
|
copies: 1
|
||||||
|
},
|
||||||
|
dpi: {
|
||||||
|
horizontal_dpi: 300,
|
||||||
|
vertical_dpi: 300
|
||||||
|
},
|
||||||
|
media_size: {
|
||||||
|
width_microns: 210000, // A4 width
|
||||||
|
height_microns: 297000 // A4 height
|
||||||
|
},
|
||||||
|
collate: {
|
||||||
|
collate: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
documentBlob: new Blob([printData.html], {type: 'text/html'})
|
||||||
|
};
|
||||||
|
|
||||||
|
// Submit print job
|
||||||
|
const result = await chrome.printing.submitJob(printJob);
|
||||||
|
console.log('Print job result:', result);
|
||||||
|
|
||||||
|
if (result.status === 'OK') {
|
||||||
|
sendResponse({success: true, jobId: result.jobId});
|
||||||
|
|
||||||
|
// Store successful print in extension storage
|
||||||
|
chrome.storage.local.set({
|
||||||
|
lastPrint: {
|
||||||
|
timestamp: Date.now(),
|
||||||
|
jobId: result.jobId,
|
||||||
|
printer: defaultPrinter.displayName
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
sendResponse({success: false, error: result.status});
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Print error:', error);
|
||||||
|
sendResponse({success: false, error: error.message});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to get available printers
|
||||||
|
async function getPrinters(sendResponse) {
|
||||||
|
try {
|
||||||
|
// Check if printing API is available
|
||||||
|
if (!chrome.printing || !chrome.printing.getPrinters) {
|
||||||
|
sendResponse({
|
||||||
|
success: false,
|
||||||
|
error: 'Chrome printing API not available'
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const printers = await chrome.printing.getPrinters();
|
||||||
|
sendResponse({success: true, printers: printers});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error getting printers:', error);
|
||||||
|
sendResponse({success: false, error: error.message});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extension installation/startup
|
||||||
|
chrome.runtime.onInstalled.addListener((details) => {
|
||||||
|
console.log('Quality Recticel Print Helper installed:', details);
|
||||||
|
|
||||||
|
// Set initial storage values
|
||||||
|
chrome.storage.local.set({
|
||||||
|
extensionVersion: chrome.runtime.getManifest().version,
|
||||||
|
installDate: Date.now()
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Fallback print method using tabs API
|
||||||
|
async function handleFallbackPrint(printData, sendResponse) {
|
||||||
|
try {
|
||||||
|
console.log('Using fallback print method');
|
||||||
|
|
||||||
|
// Create a new tab with the print content
|
||||||
|
const tab = await chrome.tabs.create({
|
||||||
|
url: 'data:text/html,' + encodeURIComponent(printData.html),
|
||||||
|
active: false
|
||||||
|
});
|
||||||
|
|
||||||
|
// Wait for tab to load, then print
|
||||||
|
setTimeout(async () => {
|
||||||
|
try {
|
||||||
|
await chrome.tabs.executeScript(tab.id, {
|
||||||
|
code: 'window.print();'
|
||||||
|
});
|
||||||
|
|
||||||
|
// Close the tab after printing
|
||||||
|
setTimeout(() => {
|
||||||
|
chrome.tabs.remove(tab.id);
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
|
sendResponse({success: true, method: 'fallback'});
|
||||||
|
} catch (error) {
|
||||||
|
sendResponse({success: false, error: 'Fallback print failed: ' + error.message});
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Fallback print error:', error);
|
||||||
|
sendResponse({success: false, error: error.message});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keep service worker alive
|
||||||
|
chrome.runtime.onConnect.addListener((port) => {
|
||||||
|
console.log('Port connected:', port.name);
|
||||||
|
});
|
||||||
272
py_app/chrome_extension/content.js
Normal file
272
py_app/chrome_extension/content.js
Normal file
@@ -0,0 +1,272 @@
|
|||||||
|
// Content script for Quality Recticel Print Helper
|
||||||
|
console.log('Quality Recticel Print Helper - Content script loaded');
|
||||||
|
|
||||||
|
// Check if we're on the print module page
|
||||||
|
if (window.location.pathname.includes('print_module')) {
|
||||||
|
console.log('Print module page detected, initializing extension features');
|
||||||
|
|
||||||
|
// Wait for DOM to be ready
|
||||||
|
if (document.readyState === 'loading') {
|
||||||
|
document.addEventListener('DOMContentLoaded', initializePrintExtension);
|
||||||
|
} else {
|
||||||
|
initializePrintExtension();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function initializePrintExtension() {
|
||||||
|
console.log('Initializing print extension features');
|
||||||
|
|
||||||
|
// Add extension status indicator
|
||||||
|
addExtensionStatusIndicator();
|
||||||
|
|
||||||
|
// Override the print button functionality
|
||||||
|
overridePrintButton();
|
||||||
|
|
||||||
|
// Add printer selection dropdown
|
||||||
|
addPrinterSelection();
|
||||||
|
|
||||||
|
// Check extension status
|
||||||
|
checkExtensionStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
function addExtensionStatusIndicator() {
|
||||||
|
// Create status indicator element
|
||||||
|
const statusIndicator = document.createElement('div');
|
||||||
|
statusIndicator.id = 'extension-status';
|
||||||
|
statusIndicator.style.cssText = `
|
||||||
|
position: fixed;
|
||||||
|
top: 10px;
|
||||||
|
right: 10px;
|
||||||
|
background: #28a745;
|
||||||
|
color: white;
|
||||||
|
padding: 5px 10px;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 12px;
|
||||||
|
z-index: 9999;
|
||||||
|
box-shadow: 0 2px 4px rgba(0,0,0,0.2);
|
||||||
|
`;
|
||||||
|
statusIndicator.textContent = '🖨️ Print Extension Active';
|
||||||
|
|
||||||
|
document.body.appendChild(statusIndicator);
|
||||||
|
|
||||||
|
// Hide after 3 seconds
|
||||||
|
setTimeout(() => {
|
||||||
|
statusIndicator.style.opacity = '0';
|
||||||
|
statusIndicator.style.transition = 'opacity 0.5s';
|
||||||
|
setTimeout(() => statusIndicator.remove(), 500);
|
||||||
|
}, 3000);
|
||||||
|
}
|
||||||
|
|
||||||
|
function overridePrintButton() {
|
||||||
|
// Find the print button
|
||||||
|
const printButton = document.getElementById('print-label-btn');
|
||||||
|
|
||||||
|
if (printButton) {
|
||||||
|
console.log('Found print button, overriding functionality');
|
||||||
|
|
||||||
|
// Remove existing event listeners by cloning the element
|
||||||
|
const newPrintButton = printButton.cloneNode(true);
|
||||||
|
printButton.parentNode.replaceChild(newPrintButton, printButton);
|
||||||
|
|
||||||
|
// Add new event listener for extension printing
|
||||||
|
newPrintButton.addEventListener('click', handleExtensionPrint);
|
||||||
|
|
||||||
|
// Update button text to indicate direct printing
|
||||||
|
newPrintButton.innerHTML = '🖨️ Print Direct';
|
||||||
|
newPrintButton.title = 'Print directly to default printer (Chrome Extension)';
|
||||||
|
|
||||||
|
console.log('Print button override complete');
|
||||||
|
} else {
|
||||||
|
console.log('Print button not found, will retry...');
|
||||||
|
// Retry after 1 second if button not found yet
|
||||||
|
setTimeout(overridePrintButton, 1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleExtensionPrint(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
|
||||||
|
console.log('Extension print button clicked');
|
||||||
|
|
||||||
|
// Get the label preview element
|
||||||
|
const labelPreview = document.getElementById('label-preview');
|
||||||
|
|
||||||
|
if (!labelPreview) {
|
||||||
|
alert('Label preview not found. Please select an order first.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show printing status
|
||||||
|
showPrintStatus('Preparing to print...', 'info');
|
||||||
|
|
||||||
|
// Create complete HTML for printing
|
||||||
|
const printHTML = createPrintableHTML(labelPreview);
|
||||||
|
|
||||||
|
// Try direct printing first, then fallback
|
||||||
|
chrome.runtime.sendMessage({
|
||||||
|
action: 'print_label',
|
||||||
|
data: {
|
||||||
|
html: printHTML,
|
||||||
|
timestamp: Date.now()
|
||||||
|
}
|
||||||
|
}, (response) => {
|
||||||
|
if (response && response.success) {
|
||||||
|
handlePrintResponse(response);
|
||||||
|
} else {
|
||||||
|
console.log('Direct printing failed, trying fallback method');
|
||||||
|
showPrintStatus('Direct printing unavailable, using browser print...', 'info');
|
||||||
|
|
||||||
|
// Try fallback method
|
||||||
|
chrome.runtime.sendMessage({
|
||||||
|
action: 'fallback_print',
|
||||||
|
data: {
|
||||||
|
html: printHTML,
|
||||||
|
timestamp: Date.now()
|
||||||
|
}
|
||||||
|
}, handlePrintResponse);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function createPrintableHTML(labelElement) {
|
||||||
|
// Get the computed styles and create a complete HTML document
|
||||||
|
const styles = `
|
||||||
|
<style>
|
||||||
|
body { margin: 0; padding: 20px; font-family: Arial, sans-serif; }
|
||||||
|
.print-container { width: 210mm; height: 297mm; margin: 0 auto; }
|
||||||
|
.label-wrapper { transform: scale(1); transform-origin: top left; }
|
||||||
|
</style>
|
||||||
|
`;
|
||||||
|
|
||||||
|
const bodyContent = `
|
||||||
|
<div class="print-container">
|
||||||
|
<div class="label-wrapper">
|
||||||
|
${labelElement.outerHTML}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
return `
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Quality Recticel Label</title>
|
||||||
|
${styles}
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
${bodyContent}
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function handlePrintResponse(response) {
|
||||||
|
console.log('Print response:', response);
|
||||||
|
|
||||||
|
if (response && response.success) {
|
||||||
|
showPrintStatus('✅ Label sent to printer successfully!', 'success');
|
||||||
|
|
||||||
|
// Update the order status in the table if possible
|
||||||
|
updateOrderPrintStatus();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
const errorMsg = response?.error || 'Unknown error occurred';
|
||||||
|
showPrintStatus(`❌ Print failed: ${errorMsg}`, 'error');
|
||||||
|
|
||||||
|
// Fallback to browser print dialog
|
||||||
|
setTimeout(() => {
|
||||||
|
if (confirm('Direct printing failed. Open browser print dialog?')) {
|
||||||
|
window.print();
|
||||||
|
}
|
||||||
|
}, 2000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function showPrintStatus(message, type) {
|
||||||
|
// Remove existing status messages
|
||||||
|
const existingStatus = document.getElementById('print-status-message');
|
||||||
|
if (existingStatus) {
|
||||||
|
existingStatus.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create status message
|
||||||
|
const statusDiv = document.createElement('div');
|
||||||
|
statusDiv.id = 'print-status-message';
|
||||||
|
statusDiv.style.cssText = `
|
||||||
|
position: fixed;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
background: ${type === 'success' ? '#28a745' : type === 'error' ? '#dc3545' : '#17a2b8'};
|
||||||
|
color: white;
|
||||||
|
padding: 15px 25px;
|
||||||
|
border-radius: 8px;
|
||||||
|
font-size: 14px;
|
||||||
|
z-index: 10000;
|
||||||
|
box-shadow: 0 4px 8px rgba(0,0,0,0.3);
|
||||||
|
text-align: center;
|
||||||
|
min-width: 300px;
|
||||||
|
`;
|
||||||
|
statusDiv.textContent = message;
|
||||||
|
|
||||||
|
document.body.appendChild(statusDiv);
|
||||||
|
|
||||||
|
// Auto-remove after 3 seconds for success/info, 5 seconds for errors
|
||||||
|
const timeout = type === 'error' ? 5000 : 3000;
|
||||||
|
setTimeout(() => {
|
||||||
|
statusDiv.style.opacity = '0';
|
||||||
|
statusDiv.style.transition = 'opacity 0.5s';
|
||||||
|
setTimeout(() => statusDiv.remove(), 500);
|
||||||
|
}, timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
function addPrinterSelection() {
|
||||||
|
// Get available printers and add selection dropdown
|
||||||
|
chrome.runtime.sendMessage({action: 'get_printers'}, (response) => {
|
||||||
|
if (response && response.success && response.printers.length > 0) {
|
||||||
|
console.log('Available printers:', response.printers);
|
||||||
|
// Could add printer selection UI here if needed
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateOrderPrintStatus() {
|
||||||
|
// Find selected row in table and update print status
|
||||||
|
const selectedRow = document.querySelector('.print-module-table tbody tr.selected');
|
||||||
|
if (selectedRow) {
|
||||||
|
const printStatusCell = selectedRow.querySelector('td:nth-last-child(2)'); // Second to last column
|
||||||
|
if (printStatusCell) {
|
||||||
|
printStatusCell.innerHTML = '<span style="color: #28a745; font-weight: bold;">✓ Yes</span>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkExtensionStatus() {
|
||||||
|
// Verify extension is working
|
||||||
|
chrome.runtime.sendMessage({action: 'check_extension'}, (response) => {
|
||||||
|
if (response) {
|
||||||
|
console.log('Extension status:', response);
|
||||||
|
} else {
|
||||||
|
console.error('Extension communication failed');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add CSS for extension-specific styling
|
||||||
|
const extensionStyles = document.createElement('style');
|
||||||
|
extensionStyles.textContent = `
|
||||||
|
#print-label-btn {
|
||||||
|
background: linear-gradient(45deg, #28a745, #20c997) !important;
|
||||||
|
border: none !important;
|
||||||
|
transition: all 0.3s ease !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#print-label-btn:hover {
|
||||||
|
background: linear-gradient(45deg, #218838, #1ea97c) !important;
|
||||||
|
transform: translateY(-1px) !important;
|
||||||
|
box-shadow: 0 4px 8px rgba(0,0,0,0.2) !important;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
document.head.appendChild(extensionStyles);
|
||||||
7
py_app/chrome_extension/icons/README.md
Normal file
7
py_app/chrome_extension/icons/README.md
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
# Placeholder for icon files - in production, add actual PNG icons:
|
||||||
|
# - icon16.png (16x16 pixels)
|
||||||
|
# - icon48.png (48x48 pixels)
|
||||||
|
# - icon128.png (128x128 pixels)
|
||||||
|
|
||||||
|
# For now, create simple text-based icons using SVG converted to PNG
|
||||||
|
# These should be replaced with proper icons later
|
||||||
27
py_app/chrome_extension/icons/create_icons.py
Normal file
27
py_app/chrome_extension/icons/create_icons.py
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
# Simple text-based icons for the Chrome extension
|
||||||
|
# These are placeholder files - replace with actual PNG icons for production
|
||||||
|
|
||||||
|
# Create simple SVG icons that can be converted to PNG
|
||||||
|
ICON_16_SVG = '''
|
||||||
|
<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<rect width="16" height="16" fill="#007bff"/>
|
||||||
|
<text x="8" y="12" font-family="Arial" font-size="10" fill="white" text-anchor="middle">🖨</text>
|
||||||
|
</svg>
|
||||||
|
'''
|
||||||
|
|
||||||
|
ICON_48_SVG = '''
|
||||||
|
<svg width="48" height="48" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<rect width="48" height="48" fill="#007bff" rx="8"/>
|
||||||
|
<text x="24" y="32" font-family="Arial" font-size="24" fill="white" text-anchor="middle">🖨️</text>
|
||||||
|
</svg>
|
||||||
|
'''
|
||||||
|
|
||||||
|
ICON_128_SVG = '''
|
||||||
|
<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<rect width="128" height="128" fill="#007bff" rx="16"/>
|
||||||
|
<text x="64" y="84" font-family="Arial" font-size="48" fill="white" text-anchor="middle">🖨️</text>
|
||||||
|
</svg>
|
||||||
|
'''
|
||||||
|
|
||||||
|
# For now, create simple text placeholders
|
||||||
|
# In production, convert these SVGs to PNG files
|
||||||
4
py_app/chrome_extension/icons/icon128.txt
Normal file
4
py_app/chrome_extension/icons/icon128.txt
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
# Placeholder for 128x128 icon
|
||||||
|
# This is a text file placeholder
|
||||||
|
# Replace with actual icon128.png file
|
||||||
|
🖨️
|
||||||
4
py_app/chrome_extension/icons/icon16.txt
Normal file
4
py_app/chrome_extension/icons/icon16.txt
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
# Placeholder for 16x16 icon
|
||||||
|
# This is a text file placeholder
|
||||||
|
# Replace with actual icon16.png file
|
||||||
|
🖨️
|
||||||
4
py_app/chrome_extension/icons/icon48.txt
Normal file
4
py_app/chrome_extension/icons/icon48.txt
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
# Placeholder for 48x48 icon
|
||||||
|
# This is a text file placeholder
|
||||||
|
# Replace with actual icon48.png file
|
||||||
|
🖨️
|
||||||
44
py_app/chrome_extension/manifest.json
Normal file
44
py_app/chrome_extension/manifest.json
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
{
|
||||||
|
"manifest_version": 3,
|
||||||
|
"name": "Quality Recticel Print Helper",
|
||||||
|
"version": "1.0",
|
||||||
|
"description": "Direct printing extension for Quality Recticel label printing system",
|
||||||
|
"permissions": [
|
||||||
|
"activeTab",
|
||||||
|
"storage",
|
||||||
|
"tabs"
|
||||||
|
],
|
||||||
|
"optional_permissions": [
|
||||||
|
"printing"
|
||||||
|
],
|
||||||
|
"host_permissions": [
|
||||||
|
"http://localhost:*/*",
|
||||||
|
"http://127.0.0.1:*/*",
|
||||||
|
"*://*/print_module*"
|
||||||
|
],
|
||||||
|
"background": {
|
||||||
|
"service_worker": "background.js"
|
||||||
|
},
|
||||||
|
"content_scripts": [
|
||||||
|
{
|
||||||
|
"matches": [
|
||||||
|
"http://localhost:*/print_module*",
|
||||||
|
"http://127.0.0.1:*/print_module*",
|
||||||
|
"*://*/print_module*"
|
||||||
|
],
|
||||||
|
"js": ["content.js"],
|
||||||
|
"run_at": "document_end"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"action": {
|
||||||
|
"default_popup": "popup.html",
|
||||||
|
"default_title": "Quality Recticel Print Helper"
|
||||||
|
},
|
||||||
|
|
||||||
|
"web_accessible_resources": [
|
||||||
|
{
|
||||||
|
"resources": ["content.js"],
|
||||||
|
"matches": ["<all_urls>"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
102
py_app/chrome_extension/popup.html
Normal file
102
py_app/chrome_extension/popup.html
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Quality Recticel Print Helper</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
width: 300px;
|
||||||
|
padding: 15px;
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo {
|
||||||
|
font-size: 24px;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 14px;
|
||||||
|
margin-bottom: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.version {
|
||||||
|
font-size: 11px;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status {
|
||||||
|
background: #e8f5e8;
|
||||||
|
border: 1px solid #28a745;
|
||||||
|
color: #28a745;
|
||||||
|
padding: 8px;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 12px;
|
||||||
|
text-align: center;
|
||||||
|
margin: 10px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info {
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 1.4;
|
||||||
|
color: #555;
|
||||||
|
margin: 10px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button {
|
||||||
|
width: 100%;
|
||||||
|
padding: 8px;
|
||||||
|
background: #007bff;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
margin: 5px 0;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button:hover {
|
||||||
|
background: #0056b3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button.secondary {
|
||||||
|
background: #6c757d;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button.secondary:hover {
|
||||||
|
background: #545b62;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="header">
|
||||||
|
<div class="logo">🖨️</div>
|
||||||
|
<div class="title">Quality Recticel Print Helper</div>
|
||||||
|
<div class="version">Version 1.0</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="status">
|
||||||
|
✅ Extension Active
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="info">
|
||||||
|
This extension enables direct printing from the Quality Recticel label system to your default printer without browser dialogs.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button class="button" id="test-print">Test Print Connection</button>
|
||||||
|
<button class="button secondary" id="open-settings">Printer Settings</button>
|
||||||
|
|
||||||
|
<div class="info">
|
||||||
|
<strong>Usage:</strong> Navigate to the Print Module page and use the enhanced print button for direct printing.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="popup.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
29
py_app/chrome_extension/popup.js
Normal file
29
py_app/chrome_extension/popup.js
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
// Popup script for Quality Recticel Print Helper
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
console.log('Popup loaded');
|
||||||
|
|
||||||
|
// Test print button
|
||||||
|
document.getElementById('test-print').addEventListener('click', function() {
|
||||||
|
chrome.runtime.sendMessage({action: 'get_printers'}, function(response) {
|
||||||
|
if (response && response.success) {
|
||||||
|
if (response.printers.length > 0) {
|
||||||
|
alert(`✅ Found ${response.printers.length} printer(s):\n${response.printers.map(p => p.displayName).join('\n')}`);
|
||||||
|
} else {
|
||||||
|
alert('⚠️ No printers found. Please ensure a printer is installed and set as default.');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const error = response?.error || 'Unknown error';
|
||||||
|
if (error.includes('Chrome printing API not available')) {
|
||||||
|
alert('⚠️ Chrome Printing API not available.\n\nThis may be due to:\n• Chrome version too old (need 85+)\n• Extension permissions not granted\n• Corporate/managed Chrome installation\n\nThe extension will use browser print dialog as fallback.');
|
||||||
|
} else {
|
||||||
|
alert('❌ Error getting printers: ' + error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Settings button
|
||||||
|
document.getElementById('open-settings').addEventListener('click', function() {
|
||||||
|
chrome.tabs.create({url: 'chrome://settings/printing'});
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user