add drag-and-drop support to print upload area

This commit is contained in:
Connor Rhodes 2026-05-22 15:59:21 -05:00
parent d3aa992d65
commit 01e6cf6300

View file

@ -0,0 +1,108 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Web Print Service</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
<style>
body {
font-family: 'Inter', sans-serif;
}
</style>
</head>
<body class="bg-gray-100 text-gray-800 flex items-center justify-center min-h-screen">
<div class="w-full max-w-lg mx-auto p-4 md:p-8">
<div class="bg-white rounded-2xl shadow-lg p-8">
<div class="text-center mb-8">
<svg xmlns="http://www.w3.org/2000/svg" class="w-16 h-16 mx-auto text-blue-500 mb-4" viewBox="0 0 24 24" fill="currentColor"><path d="M19 8H5c-1.66 0-3 1.34-3 3v6h4v4h12v-4h4v-6c0-1.66-1.34-3-3-3zm-3 11H8v-5h8v5zm3-7c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1zm-1-9H6v4h12V3z"/></svg>
<h1 class="text-3xl font-bold text-gray-900">PDF Web Print</h1>
<p class="text-gray-500 mt-2">Upload a PDF to print to <strong>{{ printer_name }}</strong>.</p>
<p class="text-sm text-gray-500 mt-1">(Max {{ max_pages }} pages)</p>
</div>
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
<div class="mb-6 space-y-3">
{% for category, message in messages %}
<div class="p-4 rounded-lg text-sm {% if category == 'error' %} bg-red-100 text-red-800 {% else %} bg-green-100 text-green-800 {% endif %}" role="alert">
<span class="font-medium">{% if category == 'error' %}Oops!{% else %}Success!{% endif %}</span> {{ message }}
</div>
{% endfor %}
</div>
{% endif %}
{% endwith %}
<form action="{{ url_for('upload_and_print') }}" method="post" enctype="multipart/form-data">
<div id="drop-zone" class="border-2 border-dashed border-gray-300 rounded-lg p-8 text-center bg-gray-50 hover:border-blue-500 transition-colors duration-300 cursor-pointer">
<label for="file-upload" class="cursor-pointer">
<svg xmlns="http://www.w3.org/2000/svg" class="w-12 h-12 mx-auto text-gray-400" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1">
<path stroke-linecap="round" stroke-linejoin="round" d="M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12" />
</svg>
<p id="file-name" class="mt-4 text-gray-600">
<span class="font-semibold text-blue-600">Click to upload</span> or drag and drop.
</p>
<p class="text-xs text-gray-500 mt-1">PDF only, max 16MB.</p>
</label>
<input id="file-upload" name="file" type="file" class="sr-only" accept=".pdf">
</div>
<div class="mt-8">
<button type="submit" class="w-full bg-blue-600 text-white font-bold py-3 px-4 rounded-lg hover:bg-blue-700 focus:outline-none focus:ring-4 focus:ring-blue-300 transition-all duration-300 transform hover:scale-105">
Print File
</button>
</div>
</form>
</div>
<footer class="text-center mt-6 text-sm text-gray-500">
<p>A simple Flask web app for local printing.</p>
</footer>
</div>
<script>
const fileUpload = document.getElementById('file-upload');
const fileNameDisplay = document.getElementById('file-name');
const dropZone = document.getElementById('drop-zone');
function setFile(file) {
const dt = new DataTransfer();
dt.items.add(file);
fileUpload.files = dt.files;
fileNameDisplay.innerHTML = `<span class="font-semibold text-gray-800">${file.name}</span>`;
}
fileUpload.addEventListener('change', () => {
if (fileUpload.files.length > 0) {
fileNameDisplay.innerHTML = `<span class="font-semibold text-gray-800">${fileUpload.files[0].name}</span>`;
} else {
fileNameDisplay.innerHTML = `<span class="font-semibold text-blue-600">Click to upload</span> or drag and drop.`;
}
});
dropZone.addEventListener('dragover', (e) => {
e.preventDefault();
dropZone.classList.add('border-blue-500', 'bg-blue-50');
});
dropZone.addEventListener('dragleave', (e) => {
if (!dropZone.contains(e.relatedTarget)) {
dropZone.classList.remove('border-blue-500', 'bg-blue-50');
}
});
dropZone.addEventListener('drop', (e) => {
e.preventDefault();
dropZone.classList.remove('border-blue-500', 'bg-blue-50');
const file = e.dataTransfer.files[0];
if (file) setFile(file);
});
</script>
</body>
</html>