Files
gh-christianlouis-docuelevate/frontend/templates/upload.html
T
2026-02-13 09:12:11 +00:00

237 lines
7.4 KiB
HTML

{% extends "base.html" %}
{% block title %}Upload Document{% endblock %}
{% block content %}
<div class="flex flex-col items-center justify-center p-8">
<h1 class="text-3xl font-bold mb-8">Upload Files</h1>
<!-- File Upload Section -->
<div class="w-full max-w-2xl mb-8">
<h2 class="text-xl font-semibold mb-4">Upload from Computer</h2>
<form action="/api/ui-upload" method="POST" enctype="multipart/form-data">
<div
id="dropZone"
class="border-4 border-dashed border-gray-300 rounded-lg p-8 bg-white text-center w-full"
ondrop="handleDrop(event)"
ondragover="handleDragOver(event)"
ondragleave="handleDragLeave(event)"
>
<p class="text-gray-500 mb-4">
Drag & drop files here, or click to select files.
</p>
<input
id="fileInput"
type="file"
class="hidden"
onchange="handleFileSelect(event)"
name="files"
multiple
/>
<div class="text-sm text-gray-500 mt-2">
<p>Allowed types: PDF, Office documents (Word, Excel, PowerPoint, etc.), Images</p>
<p>Maximum size: 500MB per file</p>
</div>
</div>
</form>
</div>
<!-- URL Upload Section -->
<div class="w-full max-w-2xl mb-8">
<h2 class="text-xl font-semibold mb-4">Upload from URL</h2>
<div class="bg-white border border-gray-300 rounded-lg p-6">
<form id="urlUploadForm" class="space-y-4">
<div>
<label for="urlInput" class="block text-sm font-medium text-gray-700 mb-2">
File URL
</label>
<input
type="url"
id="urlInput"
name="url"
placeholder="https://example.com/document.pdf"
class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
required
/>
<p class="text-sm text-gray-500 mt-1">
Enter a direct link to a file (PDF, Office documents, or images)
</p>
</div>
<div>
<label for="urlFilename" class="block text-sm font-medium text-gray-700 mb-2">
Filename (optional)
</label>
<input
type="text"
id="urlFilename"
name="filename"
placeholder="my-document.pdf"
class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
/>
<p class="text-sm text-gray-500 mt-1">
Leave empty to use filename from URL
</p>
</div>
<button
type="submit"
class="w-full bg-blue-500 hover:bg-blue-700 text-white font-bold py-3 px-4 rounded-lg transition duration-200"
>
Download and Process
</button>
</form>
<div id="urlStatusMessage" class="mt-4"></div>
</div>
</div>
<div id="statusMessage" class="mt-4 text-gray-700"></div>
<div id="uploadProgress" class="mt-4 w-full max-w-2xl"></div>
</div>
{% endblock %}
{% block scripts %}
<script src="/static/js/upload.js"></script>
<script>
// Drag-and-drop / file input logic
const dropZone = document.getElementById("dropZone");
const fileInput = document.getElementById("fileInput");
const statusMessage = document.getElementById("statusMessage");
const uploadProgress = document.getElementById("uploadProgress");
dropZone.addEventListener("click", () => fileInput.click());
function handleDragOver(e) {
e.preventDefault();
e.dataTransfer.dropEffect = "copy";
dropZone.classList.add("bg-gray-100");
}
function handleDragLeave(e) {
e.preventDefault();
dropZone.classList.remove("bg-gray-100");
}
function handleDrop(e) {
e.preventDefault();
dropZone.classList.remove("bg-gray-100");
if (e.dataTransfer.files.length) {
// Clear previous upload progress
uploadProgress.innerHTML = "";
// Create progress container
const progressContainer = document.createElement("div");
progressContainer.className = "space-y-2";
uploadProgress.appendChild(progressContainer);
// Use the shared processFiles function
processFiles(e.dataTransfer.files, progressContainer, statusMessage);
}
}
function handleFileSelect(e) {
if (e.target.files.length) {
// Clear previous upload progress
uploadProgress.innerHTML = "";
// Create progress container
const progressContainer = document.createElement("div");
progressContainer.className = "space-y-2";
uploadProgress.appendChild(progressContainer);
// Use the shared processFiles function
processFiles(e.target.files, progressContainer, statusMessage);
}
}
// URL Upload handling
const urlUploadForm = document.getElementById("urlUploadForm");
const urlStatusMessage = document.getElementById("urlStatusMessage");
urlUploadForm.addEventListener("submit", async (e) => {
e.preventDefault();
const urlInput = document.getElementById("urlInput");
const urlFilename = document.getElementById("urlFilename");
const url = urlInput.value.trim();
const filename = urlFilename.value.trim();
if (!url) {
showUrlStatus("Please enter a URL", "error");
return;
}
// Validate URL format
try {
new URL(url);
} catch (error) {
showUrlStatus("Invalid URL format", "error");
return;
}
// Show loading state
showUrlStatus("Downloading file from URL...", "info");
const submitButton = urlUploadForm.querySelector('button[type="submit"]');
const originalButtonText = submitButton.textContent;
submitButton.textContent = "Processing...";
submitButton.disabled = true;
try {
const requestBody = { url };
if (filename) {
requestBody.filename = filename;
}
const response = await fetch("/api/process-url", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(requestBody),
});
const data = await response.json();
if (response.ok) {
showUrlStatus(
`Success! File "${data.filename}" (${formatBytes(data.size)}) downloaded and queued for processing.`,
"success"
);
// Clear form
urlInput.value = "";
urlFilename.value = "";
// Optionally redirect to files page after short delay
setTimeout(() => {
window.location.href = "/files";
}, 2000);
} else {
showUrlStatus(`Error: ${data.detail || "Failed to process URL"}`, "error");
}
} catch (error) {
showUrlStatus(`Network error: ${error.message}`, "error");
} finally {
submitButton.textContent = originalButtonText;
submitButton.disabled = false;
}
});
function showUrlStatus(message, type) {
urlStatusMessage.innerHTML = "";
const alertDiv = document.createElement("div");
alertDiv.className = `px-4 py-3 rounded ${
type === "success"
? "bg-green-100 border border-green-400 text-green-700"
: type === "error"
? "bg-red-100 border border-red-400 text-red-700"
: "bg-blue-100 border border-blue-400 text-blue-700"
}`;
alertDiv.textContent = message;
urlStatusMessage.appendChild(alertDiv);
}
function formatBytes(bytes) {
// Reuse the existing formatFileSize function from upload.js
return formatFileSize(bytes);
}
</script>
{% endblock %}