Updated to print service power shell
This commit is contained in:
@@ -1,103 +1,250 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}Chrome Extension Download{% endblock %}
|
||||
{% block title %}Quality Recticel Print Service Downloads{% 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>
|
||||
<!-- Header Section -->
|
||||
<div class="row justify-content-center mb-4">
|
||||
<div class="col-md-12">
|
||||
<div class="text-center">
|
||||
<h1 class="display-4">🖨️ Quality Recticel Print Service</h1>
|
||||
<p class="lead">Professional Silent Printing Solution for Windows</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Overview Card -->
|
||||
<div class="row justify-content-center mb-4">
|
||||
<div class="col-md-10">
|
||||
<div class="card border-primary">
|
||||
<div class="card-header bg-primary text-white">
|
||||
<h3 class="mb-0"><EFBFBD> Complete Printing Solution</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 class="row">
|
||||
<div class="col-md-6">
|
||||
<h5>🏆 What You Get:</h5>
|
||||
<ul>
|
||||
<li>✅ <strong>Silent PDF Printing</strong> - No manual downloads</li>
|
||||
<li>✅ <strong>Automatic Detection</strong> - Smart service fallback</li>
|
||||
<li>✅ <strong>Zero Configuration</strong> - Works out of the box</li>
|
||||
<li>✅ <strong>Auto-Start Service</strong> - Boots with Windows</li>
|
||||
<li>✅ <strong>Professional Integration</strong> - Seamless workflow</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<h5>🔧 System Components:</h5>
|
||||
<ul>
|
||||
<li>🖥️ <strong>Windows Print Service</strong> - Local API (localhost:8765)</li>
|
||||
<li>🌐 <strong>Chrome Extension</strong> - Browser integration</li>
|
||||
<li>📄 <strong>Web Integration</strong> - Smart button detection</li>
|
||||
<li>🔄 <strong>Fallback System</strong> - PDF download backup</li>
|
||||
<li>🛡️ <strong>Security</strong> - Local-only connections</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Download Cards Row -->
|
||||
<div class="row justify-content-center">
|
||||
<!-- Windows Service Card -->
|
||||
<div class="col-md-5 mb-4">
|
||||
<div class="card h-100 border-success">
|
||||
<div class="card-header bg-success text-white text-center">
|
||||
<h4 class="mb-0">🖥️ Windows Print Service</h4>
|
||||
<small>Core printing engine</small>
|
||||
</div>
|
||||
<div class="card-body d-flex flex-column">
|
||||
<div class="alert alert-success">
|
||||
<strong>🚀 Install First:</strong> The Windows service provides the printing API and must be installed before the Chrome extension.
|
||||
</div>
|
||||
|
||||
<h4>Features:</h4>
|
||||
<h5>📦 Package Contents:</h5>
|
||||
<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>
|
||||
<li>🔧 <code>install_service.bat</code> - One-click installer</li>
|
||||
<li>🖥️ <code>print_service.py</code> - Main service application</li>
|
||||
<li>⚙️ <code>service_manager.py</code> - Service management</li>
|
||||
<li>🌐 <code>chrome_extension/</code> - Browser extension</li>
|
||||
<li>📚 Complete documentation package</li>
|
||||
</ul>
|
||||
|
||||
<h4>Installation Instructions:</h4>
|
||||
<h5>⚡ Quick Install:</h5>
|
||||
<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>
|
||||
<li>Download and extract the service package</li>
|
||||
<li><strong>Right-click</strong> <code>install_service.bat</code></li>
|
||||
<li>Select <strong>"Run as administrator"</strong></li>
|
||||
<li>Wait for installation to complete</li>
|
||||
</ol>
|
||||
|
||||
<div class="text-center mt-auto">
|
||||
<button class="btn btn-success btn-lg mb-2" id="download-service-btn">
|
||||
📥 Download Windows Service
|
||||
</button>
|
||||
<br>
|
||||
<small class="text-muted">Complete package (~50KB)</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Chrome Extension Card -->
|
||||
<div class="col-md-5 mb-4">
|
||||
<div class="card h-100 border-info">
|
||||
<div class="card-header bg-info text-white text-center">
|
||||
<h4 class="mb-0">🌐 Chrome Extension</h4>
|
||||
<small>Browser integration</small>
|
||||
</div>
|
||||
<div class="card-body d-flex flex-column">
|
||||
<div class="alert alert-info">
|
||||
<strong>🔗 Install Second:</strong> The Chrome extension connects your browser to the Windows service for seamless printing.
|
||||
</div>
|
||||
|
||||
<h5>🎯 Features:</h5>
|
||||
<ul>
|
||||
<li>🖨️ Silent printing via native messaging</li>
|
||||
<li>🔍 Automatic service detection</li>
|
||||
<li>📊 Print status monitoring</li>
|
||||
<li>🔄 Graceful fallback to PDF download</li>
|
||||
<li>⚙️ Printer management interface</li>
|
||||
</ul>
|
||||
|
||||
<h5>🚀 Quick Install:</h5>
|
||||
<ol>
|
||||
<li>Download and extract extension files</li>
|
||||
<li>Open Chrome → <code>chrome://extensions/</code></li>
|
||||
<li>Enable <strong>"Developer mode"</strong></li>
|
||||
<li>Click <strong>"Load unpacked"</strong> → Select folder</li>
|
||||
</ol>
|
||||
|
||||
<div class="text-center mt-auto">
|
||||
<button class="btn btn-info btn-lg mb-2" id="download-extension-btn">
|
||||
📥 Download Chrome Extension
|
||||
</button>
|
||||
<br>
|
||||
<small class="text-muted">Extension package (~15KB)</small>
|
||||
|
||||
<hr>
|
||||
<div class="text-center">
|
||||
<small class="text-muted">Individual files:</small><br>
|
||||
<a href="{{ url_for('main.extension_files', filename='manifest.json') }}" target="_blank" class="btn btn-sm btn-outline-secondary">manifest.json</a>
|
||||
<a href="{{ url_for('main.extension_files', filename='background.js') }}" target="_blank" class="btn btn-sm btn-outline-secondary">background.js</a>
|
||||
<a href="{{ url_for('main.extension_files', filename='content.js') }}" target="_blank" class="btn btn-sm btn-outline-secondary">content.js</a>
|
||||
<a href="{{ url_for('main.extension_files', filename='popup.html') }}" target="_blank" class="btn btn-sm btn-outline-secondary">popup.html</a>
|
||||
<a href="{{ url_for('main.extension_files', filename='popup.js') }}" target="_blank" class="btn btn-sm btn-outline-secondary">popup.js</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Documentation Section -->
|
||||
<div class="row justify-content-center mb-4">
|
||||
<div class="col-md-10">
|
||||
<div class="card border-warning">
|
||||
<div class="card-header bg-warning text-dark">
|
||||
<h4 class="mb-0">📚 Documentation & Support</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<div class="card h-100">
|
||||
<div class="card-header bg-success text-white text-center">
|
||||
<h6 class="mb-0">⚡ Quick Setup Guide</h6>
|
||||
</div>
|
||||
<div class="card-body text-center">
|
||||
<p class="card-text">2-minute installation guide with visual steps and troubleshooting tips.</p>
|
||||
<a href="/static/documentation/QUICK_SETUP.md" target="_blank" class="btn btn-success">
|
||||
📖 Quick Setup
|
||||
</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="col-md-4">
|
||||
<div class="card h-100">
|
||||
<div class="card-header bg-primary text-white text-center">
|
||||
<h6 class="mb-0">📋 Complete Guide</h6>
|
||||
</div>
|
||||
<div class="card-body text-center">
|
||||
<p class="card-text">Comprehensive installation documentation with troubleshooting and API reference.</p>
|
||||
<a href="/static/documentation/INSTALLATION_GUIDE.md" target="_blank" class="btn btn-primary">
|
||||
📚 Full Documentation
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="card h-100">
|
||||
<div class="card-header bg-info text-white text-center">
|
||||
<h6 class="mb-0">🛠️ Technical Reference</h6>
|
||||
</div>
|
||||
<div class="card-body text-center">
|
||||
<p class="card-text">Developer documentation with API specs and customization examples.</p>
|
||||
<a href="/static/documentation/README.md" target="_blank" class="btn btn-info">
|
||||
🔧 Developer Docs
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</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>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- System Requirements -->
|
||||
<div class="row justify-content-center mb-4">
|
||||
<div class="col-md-10">
|
||||
<div class="card border-secondary">
|
||||
<div class="card-header bg-secondary text-white">
|
||||
<h4 class="mb-0">⚙️ System Requirements & Information</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<h5>💻 Requirements:</h5>
|
||||
<ul>
|
||||
<li><strong>OS:</strong> Windows 10/11 (64-bit)</li>
|
||||
<li><strong>Python:</strong> 3.8+ (auto-installed if missing)</li>
|
||||
<li><strong>Browser:</strong> Google Chrome (latest)</li>
|
||||
<li><strong>Privileges:</strong> Administrator (for installation only)</li>
|
||||
<li><strong>Network:</strong> Localhost access (no internet required)</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<h5>🔍 How It Works:</h5>
|
||||
<div class="alert alert-light">
|
||||
<ol class="mb-0">
|
||||
<li>🌐 Web page detects service status</li>
|
||||
<li>🖨️ <strong>Service Available</strong> → Green "Print Labels (Silent)" button</li>
|
||||
<li>📄 <strong>Service Unavailable</strong> → Blue "Generate PDF" button</li>
|
||||
<li>🔄 Automatic fallback ensures printing always works</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-4 text-center">
|
||||
<a href="{{ url_for('main.print_module') }}" class="btn btn-success">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<div class="row justify-content-center mb-5">
|
||||
<div class="col-md-8 text-center">
|
||||
<div class="card border-dark">
|
||||
<div class="card-body">
|
||||
<h5>🚀 Ready to Start?</h5>
|
||||
<p class="text-muted">Installation takes ~5 minutes • Zero maintenance required</p>
|
||||
<div class="btn-group-vertical btn-group-lg" role="group">
|
||||
<a href="{{ url_for('main.print_module') }}" class="btn btn-success btn-lg">
|
||||
🖨️ Go to Print Module
|
||||
</a>
|
||||
<button class="btn btn-secondary" onclick="window.close()">
|
||||
✖️ Close
|
||||
↩️ Close Window
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -107,12 +254,53 @@
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Create ZIP file dynamically when download is requested
|
||||
// Windows Service Download Handler
|
||||
document.getElementById('download-service-btn').addEventListener('click', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
// Show loading state
|
||||
const originalText = this.innerHTML;
|
||||
this.innerHTML = '⏳ Preparing Windows Service Package...';
|
||||
this.disabled = true;
|
||||
|
||||
// Create the Windows service package
|
||||
fetch('/create_service_package', {method: 'POST'})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
// Start download
|
||||
window.location.href = data.download_url;
|
||||
|
||||
// Show success message
|
||||
setTimeout(() => {
|
||||
this.innerHTML = '✅ Download Started!';
|
||||
}, 500);
|
||||
|
||||
// Reset button
|
||||
setTimeout(() => {
|
||||
this.innerHTML = originalText;
|
||||
this.disabled = false;
|
||||
}, 3000);
|
||||
} else {
|
||||
alert('Error creating Windows service package: ' + data.error);
|
||||
this.innerHTML = originalText;
|
||||
this.disabled = false;
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
alert('Error: ' + error.message);
|
||||
this.innerHTML = originalText;
|
||||
this.disabled = false;
|
||||
});
|
||||
});
|
||||
|
||||
// Chrome Extension Download Handler
|
||||
document.getElementById('download-extension-btn').addEventListener('click', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
// Show loading state
|
||||
this.innerHTML = '⏳ Preparing Download...';
|
||||
const originalText = this.innerHTML;
|
||||
this.innerHTML = '⏳ Preparing Chrome Extension Package...';
|
||||
this.disabled = true;
|
||||
|
||||
// Create the extension package
|
||||
@@ -123,22 +311,78 @@ document.getElementById('download-extension-btn').addEventListener('click', func
|
||||
// Start download
|
||||
window.location.href = data.download_url;
|
||||
|
||||
// Show success message
|
||||
setTimeout(() => {
|
||||
this.innerHTML = '✅ Download Started!';
|
||||
}, 500);
|
||||
|
||||
// Reset button
|
||||
setTimeout(() => {
|
||||
this.innerHTML = '📥 Download Chrome Extension (.zip)';
|
||||
this.innerHTML = originalText;
|
||||
this.disabled = false;
|
||||
}, 2000);
|
||||
}, 3000);
|
||||
} else {
|
||||
alert('Error creating extension package: ' + data.error);
|
||||
this.innerHTML = '📥 Download Chrome Extension (.zip)';
|
||||
this.innerHTML = originalText;
|
||||
this.disabled = false;
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
alert('Error: ' + error.message);
|
||||
this.innerHTML = '📥 Download Chrome Extension (.zip)';
|
||||
this.innerHTML = originalText;
|
||||
this.disabled = false;
|
||||
});
|
||||
});
|
||||
|
||||
// Documentation links - track clicks for analytics
|
||||
document.querySelectorAll('a[href*="/static/documentation/"]').forEach(link => {
|
||||
link.addEventListener('click', function(e) {
|
||||
// Could add analytics tracking here
|
||||
console.log('Documentation accessed:', this.href);
|
||||
});
|
||||
});
|
||||
|
||||
// Show installation progress tips
|
||||
function showInstallationTips() {
|
||||
const tips = [
|
||||
'💡 Tip: The Windows service automatically starts with your computer',
|
||||
'💡 Tip: Both components work together - install the service first',
|
||||
'💡 Tip: Check the documentation for troubleshooting common issues',
|
||||
'💡 Tip: The system gracefully falls back to PDF downloads if needed'
|
||||
];
|
||||
|
||||
let tipIndex = 0;
|
||||
const tipContainer = document.createElement('div');
|
||||
tipContainer.className = 'alert alert-info position-fixed';
|
||||
tipContainer.style.cssText = 'bottom: 20px; right: 20px; max-width: 300px; z-index: 1000;';
|
||||
|
||||
function showNextTip() {
|
||||
if (tipIndex < tips.length) {
|
||||
tipContainer.innerHTML = `
|
||||
<button type="button" class="btn-close float-end" onclick="this.parentElement.remove()"></button>
|
||||
${tips[tipIndex]}
|
||||
`;
|
||||
|
||||
if (!document.body.contains(tipContainer)) {
|
||||
document.body.appendChild(tipContainer);
|
||||
}
|
||||
|
||||
tipIndex++;
|
||||
setTimeout(showNextTip, 8000); // Show next tip after 8 seconds
|
||||
} else {
|
||||
setTimeout(() => {
|
||||
if (document.body.contains(tipContainer)) {
|
||||
tipContainer.remove();
|
||||
}
|
||||
}, 5000);
|
||||
}
|
||||
}
|
||||
|
||||
// Start showing tips after 3 seconds
|
||||
setTimeout(showNextTip, 3000);
|
||||
}
|
||||
|
||||
// Initialize tips when page loads
|
||||
document.addEventListener('DOMContentLoaded', showInstallationTips);
|
||||
</script>
|
||||
{% endblock %}
|
||||
@@ -236,12 +236,35 @@ table tbody tr.selected td {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- PDF Information -->
|
||||
<div style="width: 100%; margin-top: 15px; padding: 0 15px; text-align: center;">
|
||||
<div style="background: #e8f4f8; border: 1px solid #bee5eb; border-radius: 6px; padding: 12px; font-size: 11px; color: #0c5460;">
|
||||
<strong>📄 PDF Label Generation</strong><br>
|
||||
Labels will be generated as PDF files for universal printing compatibility.<br>
|
||||
<small style="color: #6c757d;">Works with any browser and printer - no extensions needed!</small>
|
||||
<!-- Printer Selection and Service Setup -->
|
||||
<div style="width: 100%; margin-top: 15px; padding: 0 15px;">
|
||||
<!-- Printer Selection -->
|
||||
<div class="mb-3">
|
||||
<label for="printer-select" class="form-label" style="font-size: 13px; font-weight: 600; color: #495057; margin-bottom: 5px;">
|
||||
🖨️ Choose Printer
|
||||
</label>
|
||||
<select id="printer-select" class="form-control" style="font-size: 12px; padding: 6px 10px;">
|
||||
<option value="default">Default Printer</option>
|
||||
<option value="detecting" disabled>Detecting printers...</option>
|
||||
</select>
|
||||
<small id="printer-status" class="text-muted" style="font-size: 10px;">
|
||||
Checking for available printers...
|
||||
</small>
|
||||
</div>
|
||||
|
||||
<!-- Service Installation Link -->
|
||||
<div class="text-center">
|
||||
<div style="background: #fff3cd; border: 1px solid #ffeaa7; border-radius: 6px; padding: 10px; margin-bottom: 10px;">
|
||||
<div style="font-size: 11px; color: #856404; margin-bottom: 8px;">
|
||||
<strong><EFBFBD> Upgrade to Silent Printing</strong>
|
||||
</div>
|
||||
<a href="{{ url_for('main.download_extension') }}" class="btn btn-warning btn-sm" target="_blank" style="font-size: 11px; padding: 4px 12px;">
|
||||
📥 Install Print Service & Extension
|
||||
</a>
|
||||
<div style="font-size: 9px; color: #6c757d; margin-top: 5px;">
|
||||
5-minute setup • Auto-starts with Windows • Silent printing
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -568,12 +591,242 @@ function addFallbackPrintHandler() {
|
||||
}
|
||||
}
|
||||
|
||||
// Windows Print Service Integration
|
||||
const PRINT_SERVICE_URL = 'http://localhost:8765';
|
||||
let printServiceAvailable = false;
|
||||
let availablePrinters = [];
|
||||
|
||||
// Check print service availability on page load
|
||||
window.addEventListener('DOMContentLoaded', function() {
|
||||
checkPrintServiceAvailability();
|
||||
initializePrinterDropdown();
|
||||
});
|
||||
|
||||
function initializePrinterDropdown() {
|
||||
const select = document.getElementById('printer-select');
|
||||
if (!select) return;
|
||||
|
||||
select.innerHTML = `
|
||||
<option value="default">Default Printer</option>
|
||||
<option value="detecting" disabled>Detecting printers...</option>
|
||||
`;
|
||||
}
|
||||
|
||||
async function checkPrintServiceAvailability() {
|
||||
const printerStatus = document.getElementById('printer-status');
|
||||
|
||||
try {
|
||||
printerStatus.textContent = 'Checking Windows Print Service...';
|
||||
|
||||
const response = await fetch(`${PRINT_SERVICE_URL}/health`, {
|
||||
method: 'GET',
|
||||
signal: AbortSignal.timeout(3000)
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
printServiceAvailable = true;
|
||||
console.log('✅ Windows Print Service is available');
|
||||
updatePrintButtonForService(true);
|
||||
await loadAvailablePrinters();
|
||||
} else {
|
||||
throw new Error('Service not responding');
|
||||
}
|
||||
} catch (error) {
|
||||
printServiceAvailable = false;
|
||||
console.log('⚠️ Windows Print Service not available, using fallback PDF download');
|
||||
updatePrintButtonForService(false);
|
||||
updatePrinterStatus('Windows Print Service not detected - PDF download mode');
|
||||
}
|
||||
}
|
||||
|
||||
async function loadAvailablePrinters() {
|
||||
try {
|
||||
const response = await fetch(`${PRINT_SERVICE_URL}/printers`);
|
||||
if (response.ok) {
|
||||
const data = await response.json();
|
||||
availablePrinters = data.printers || [];
|
||||
updatePrinterDropdown();
|
||||
updatePrinterStatus(`${availablePrinters.length} printer(s) detected via Windows service`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('Failed to load printers:', error);
|
||||
updatePrinterStatus('Failed to detect printers - using default');
|
||||
}
|
||||
}
|
||||
|
||||
function updatePrinterDropdown() {
|
||||
const select = document.getElementById('printer-select');
|
||||
if (!select) return;
|
||||
|
||||
// Clear and rebuild options
|
||||
select.innerHTML = '<option value="default">Default Printer (Recommended)</option>';
|
||||
|
||||
availablePrinters.forEach((printer, index) => {
|
||||
const option = document.createElement('option');
|
||||
option.value = printer.name || printer;
|
||||
option.textContent = `${printer.name || printer}`;
|
||||
if (printer.is_default) {
|
||||
option.textContent += ' (Default)';
|
||||
option.selected = true;
|
||||
}
|
||||
select.appendChild(option);
|
||||
});
|
||||
|
||||
if (availablePrinters.length === 0) {
|
||||
const option = document.createElement('option');
|
||||
option.value = 'none';
|
||||
option.textContent = 'No printers detected';
|
||||
option.disabled = true;
|
||||
select.appendChild(option);
|
||||
}
|
||||
}
|
||||
|
||||
function updatePrinterStatus(message) {
|
||||
const status = document.getElementById('printer-status');
|
||||
if (status) {
|
||||
status.textContent = message;
|
||||
}
|
||||
}
|
||||
|
||||
function getSelectedPrinter() {
|
||||
const select = document.getElementById('printer-select');
|
||||
return select ? select.value : 'default';
|
||||
}
|
||||
|
||||
function updatePrintButtonForService(serviceAvailable) {
|
||||
const printButton = document.getElementById('print-label-btn');
|
||||
if (!printButton) return;
|
||||
|
||||
if (serviceAvailable) {
|
||||
printButton.innerHTML = '🖨️ Print Labels (Silent)';
|
||||
printButton.title = 'Print labels directly to selected printer using Windows service';
|
||||
printButton.style.background = '#28a745'; // Green for direct print
|
||||
} else {
|
||||
printButton.innerHTML = '📄 Generate PDF';
|
||||
printButton.title = 'Generate PDF for manual printing (Windows service not available)';
|
||||
printButton.style.background = '#007bff'; // Blue for PDF download
|
||||
}
|
||||
}
|
||||
|
||||
// Enhanced print function with Windows service support
|
||||
async function printLabelsWithService(orderId, prodOrder, quantity) {
|
||||
try {
|
||||
// Generate PDF URL
|
||||
const pdfUrl = `${window.location.origin}/generate_labels_pdf/${orderId}`;
|
||||
|
||||
// Get selected printer from dropdown
|
||||
const selectedPrinter = getSelectedPrinter();
|
||||
|
||||
// Prepare print data for service
|
||||
const printData = {
|
||||
pdf_url: pdfUrl,
|
||||
printer_name: selectedPrinter,
|
||||
copies: 1,
|
||||
silent: true,
|
||||
order_id: orderId,
|
||||
quantity: quantity
|
||||
};
|
||||
|
||||
// Send to Windows service
|
||||
const response = await fetch(`${PRINT_SERVICE_URL}/print/silent`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(printData)
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (response.ok && result.success) {
|
||||
// Success - labels printed silently
|
||||
const printerName = selectedPrinter === 'default' ? 'default printer' : selectedPrinter;
|
||||
alert(`✅ Labels printed successfully!\n\n📊 Order: ${prodOrder}\n📦 Quantity: ${quantity} labels\n🖨️ Printer: ${printerName}\n📋 Sequential: ${prodOrder}-001 to ${prodOrder}-${String(quantity).padStart(3, '0')}\n\n🎯 Printed silently via Windows service!`);
|
||||
|
||||
// Update order status in database
|
||||
await updatePrintedStatus(orderId);
|
||||
|
||||
return true;
|
||||
} else {
|
||||
throw new Error(result.error || 'Print service failed');
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('Windows service print error:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback PDF download function
|
||||
async function downloadPDFLabels(orderId, prodOrder, quantity) {
|
||||
try {
|
||||
// Generate PDF
|
||||
const response = await fetch(`/generate_labels_pdf/${orderId}`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' }
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const data = await response.json().catch(() => ({}));
|
||||
throw new Error(data.error || `HTTP ${response.status}`);
|
||||
}
|
||||
|
||||
// Get filename from response headers
|
||||
const contentDisposition = response.headers.get('Content-Disposition');
|
||||
let filename = `labels_${prodOrder}_qty${quantity}.pdf`;
|
||||
if (contentDisposition) {
|
||||
const matches = contentDisposition.match(/filename="?([^"]+)"?/);
|
||||
if (matches) filename = matches[1];
|
||||
}
|
||||
|
||||
const blob = await response.blob();
|
||||
|
||||
// Download PDF
|
||||
const url = window.URL.createObjectURL(blob);
|
||||
const a = document.createElement('a');
|
||||
a.href = url;
|
||||
a.download = filename;
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
window.URL.revokeObjectURL(url);
|
||||
document.body.removeChild(a);
|
||||
|
||||
// Show success message
|
||||
alert(`📄 PDF downloaded successfully!\n\n📊 Order: ${prodOrder}\n📦 Quantity: ${quantity} labels\n📁 File: ${filename}\n📋 Sequential: ${prodOrder}-001 to ${prodOrder}-${String(quantity).padStart(3, '0')}\n\n➡️ Please print the PDF manually`);
|
||||
|
||||
return true;
|
||||
|
||||
} catch (error) {
|
||||
console.error('PDF download error:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
// Update printed status in database
|
||||
async function updatePrintedStatus(orderId) {
|
||||
try {
|
||||
const response = await fetch(`/update_printed_status/${orderId}`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' }
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
// Refresh the orders table
|
||||
setTimeout(() => {
|
||||
document.getElementById('check-db-btn').click();
|
||||
}, 1000);
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('Failed to update printed status:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// PDF generation handler
|
||||
function addPDFGenerationHandler() {
|
||||
const printButton = document.getElementById('print-label-btn');
|
||||
|
||||
if (printButton) {
|
||||
printButton.addEventListener('click', function(e) {
|
||||
printButton.addEventListener('click', async function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
// Get selected order
|
||||
@@ -594,61 +847,41 @@ function addPDFGenerationHandler() {
|
||||
|
||||
// Show loading state
|
||||
const originalText = printButton.innerHTML;
|
||||
printButton.innerHTML = '⏳ Generating PDF...';
|
||||
const originalColor = printButton.style.background;
|
||||
printButton.innerHTML = '⏳ Processing...';
|
||||
printButton.disabled = true;
|
||||
|
||||
// Generate PDF
|
||||
fetch(`/generate_labels_pdf/${orderId}`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
}
|
||||
})
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
return response.json().then(data => {
|
||||
throw new Error(data.error || `HTTP ${response.status}`);
|
||||
});
|
||||
try {
|
||||
let success = false;
|
||||
|
||||
// Try Windows service first if available
|
||||
if (printServiceAvailable) {
|
||||
try {
|
||||
success = await printLabelsWithService(orderId, prodOrder, quantity);
|
||||
} catch (serviceError) {
|
||||
console.warn('Windows service failed, falling back to PDF download:', serviceError);
|
||||
printServiceAvailable = false; // Mark as unavailable for this session
|
||||
updatePrintButtonForService(false);
|
||||
}
|
||||
}
|
||||
|
||||
// Get filename from response headers or create default
|
||||
const contentDisposition = response.headers.get('Content-Disposition');
|
||||
let filename = `labels_${prodOrder}_qty${quantity}.pdf`;
|
||||
if (contentDisposition) {
|
||||
const matches = contentDisposition.match(/filename="?([^"]+)"?/);
|
||||
if (matches) filename = matches[1];
|
||||
// Fallback to PDF download if service failed or unavailable
|
||||
if (!success) {
|
||||
success = await downloadPDFLabels(orderId, prodOrder, quantity);
|
||||
}
|
||||
|
||||
return response.blob().then(blob => ({ blob, filename }));
|
||||
})
|
||||
.then(({ blob, filename }) => {
|
||||
// Create download link
|
||||
const url = window.URL.createObjectURL(blob);
|
||||
const a = document.createElement('a');
|
||||
a.href = url;
|
||||
a.download = filename;
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
window.URL.revokeObjectURL(url);
|
||||
document.body.removeChild(a);
|
||||
|
||||
// Show success message
|
||||
alert(`✅ PDF generated successfully!\n\n📄 ${quantity} labels created for ${prodOrder}\n📋 Sequential numbering: ${prodOrder}-001 to ${prodOrder}-${String(quantity).padStart(3, '0')}\n📁 File: ${filename}\n\n➡️ The PDF is ready to print from your browser!`);
|
||||
|
||||
// Refresh the orders table to show updated print status
|
||||
setTimeout(() => {
|
||||
document.getElementById('check-db-btn').click();
|
||||
}, 1000);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('PDF generation error:', error);
|
||||
alert(`❌ Error generating PDF: ${error.message}\n\nPlease try again or contact support.`);
|
||||
})
|
||||
.finally(() => {
|
||||
} catch (error) {
|
||||
console.error('Print operation failed:', error);
|
||||
alert(`❌ Print operation failed: ${error.message}\n\nPlease check:\n• Windows Print Service is running\n• Chrome extension is installed\n• Network connectivity\n• PDF generation permissions`);
|
||||
} finally {
|
||||
// Reset button state
|
||||
printButton.innerHTML = originalText;
|
||||
printButton.style.background = originalColor;
|
||||
printButton.disabled = false;
|
||||
});
|
||||
|
||||
// Recheck service availability for next operation
|
||||
setTimeout(checkPrintServiceAvailability, 2000);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user