upfdated to ptint plugin

This commit is contained in:
2025-09-20 13:56:57 +03:00
parent c4d82e36f2
commit beeaa02c35
14 changed files with 1062 additions and 0 deletions

View File

@@ -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')

View 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 %}

View File

@@ -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 %}

View 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);
});

View 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);

View 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

View 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

View File

@@ -0,0 +1,4 @@
# Placeholder for 128x128 icon
# This is a text file placeholder
# Replace with actual icon128.png file
🖨️

View File

@@ -0,0 +1,4 @@
# Placeholder for 16x16 icon
# This is a text file placeholder
# Replace with actual icon16.png file
🖨️

View File

@@ -0,0 +1,4 @@
# Placeholder for 48x48 icon
# This is a text file placeholder
# Replace with actual icon48.png file
🖨️

View 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>"]
}
]
}

View 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>

View 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'});
});
});