initial commit
This commit is contained in:
131
packages/extractor/upload.html
Normal file
131
packages/extractor/upload.html
Normal file
@@ -0,0 +1,131 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Extractor — Test Upload</title>
|
||||
<style>
|
||||
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
||||
:root {
|
||||
--bg: #0d0d0d; --surface: #161616; --border: #2a2a2a;
|
||||
--text: #e0e0e0; --muted: #666; --accent: #2563eb; --green: #16a34a; --red: #dc2626;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
||||
font-size: 14px;
|
||||
}
|
||||
body { background: var(--bg); color: var(--text); min-height: 100vh; display: flex; align-items: center; justify-content: center; padding: 24px; }
|
||||
.card { background: var(--surface); border: 1px solid var(--border); border-radius: 10px; padding: 28px; width: 100%; max-width: 520px; display: flex; flex-direction: column; gap: 18px; }
|
||||
h1 { font-size: 15px; font-weight: 600; }
|
||||
.drop-zone {
|
||||
border: 2px dashed var(--border); border-radius: 7px; padding: 36px 20px;
|
||||
text-align: center; cursor: pointer; transition: border-color 0.15s, background 0.15s;
|
||||
color: var(--muted); font-size: 13px;
|
||||
}
|
||||
.drop-zone:hover, .drop-zone.over { border-color: var(--accent); background: rgba(37,99,235,0.05); color: var(--text); }
|
||||
.drop-zone.has-file { border-color: var(--green); color: var(--green); }
|
||||
input[type=file] { display: none; }
|
||||
button {
|
||||
padding: 8px 16px; border-radius: 6px; border: none; background: var(--accent);
|
||||
color: #fff; font-size: 13px; cursor: pointer; transition: background 0.12s;
|
||||
}
|
||||
button:hover:not(:disabled) { background: #1d4ed8; }
|
||||
button:disabled { opacity: 0.4; cursor: not-allowed; }
|
||||
.result {
|
||||
background: var(--bg); border: 1px solid var(--border); border-radius: 6px;
|
||||
padding: 14px; font-family: "SF Mono", "Fira Mono", monospace; font-size: 11px;
|
||||
white-space: pre-wrap; word-break: break-all; max-height: 320px; overflow-y: auto;
|
||||
color: var(--text); display: none;
|
||||
}
|
||||
.result.error { border-color: var(--red); color: #f87171; }
|
||||
.result.success { border-color: var(--green); }
|
||||
.status { font-size: 12px; color: var(--muted); min-height: 16px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="card">
|
||||
<h1>Extractor — Test Upload</h1>
|
||||
|
||||
<div class="drop-zone" id="drop-zone">
|
||||
<input type="file" id="file-input" accept=".pdf">
|
||||
<span id="drop-label">Drop a PDF here, or click to select</span>
|
||||
</div>
|
||||
|
||||
<button id="submit-btn" disabled>Extract</button>
|
||||
|
||||
<p class="status" id="status"></p>
|
||||
<pre class="result" id="result"></pre>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const dropZone = document.getElementById("drop-zone");
|
||||
const fileInput = document.getElementById("file-input");
|
||||
const dropLabel = document.getElementById("drop-label");
|
||||
const submitBtn = document.getElementById("submit-btn");
|
||||
const statusEl = document.getElementById("status");
|
||||
const resultEl = document.getElementById("result");
|
||||
|
||||
let selectedFile = null;
|
||||
|
||||
function csrfHeaders(extra = {}) {
|
||||
const csrf = document.cookie
|
||||
.split("; ")
|
||||
.find((part) => part.startsWith("bmp_demo_csrf="))
|
||||
?.slice("bmp_demo_csrf=".length);
|
||||
return csrf ? { ...extra, "X-BMP-CSRF": decodeURIComponent(csrf) } : extra;
|
||||
}
|
||||
|
||||
dropZone.addEventListener("click", () => fileInput.click());
|
||||
|
||||
fileInput.addEventListener("change", () => setFile(fileInput.files[0]));
|
||||
|
||||
dropZone.addEventListener("dragover", e => { e.preventDefault(); dropZone.classList.add("over"); });
|
||||
dropZone.addEventListener("dragleave", () => dropZone.classList.remove("over"));
|
||||
dropZone.addEventListener("drop", e => {
|
||||
e.preventDefault();
|
||||
dropZone.classList.remove("over");
|
||||
setFile(e.dataTransfer.files[0]);
|
||||
});
|
||||
|
||||
function setFile(file) {
|
||||
if (!file || file.type !== "application/pdf") {
|
||||
statusEl.textContent = "Please select a PDF file.";
|
||||
return;
|
||||
}
|
||||
selectedFile = file;
|
||||
dropLabel.textContent = file.name;
|
||||
dropZone.classList.add("has-file");
|
||||
submitBtn.disabled = false;
|
||||
statusEl.textContent = "";
|
||||
resultEl.style.display = "none";
|
||||
}
|
||||
|
||||
submitBtn.addEventListener("click", async () => {
|
||||
if (!selectedFile) return;
|
||||
|
||||
submitBtn.disabled = true;
|
||||
statusEl.textContent = "Extracting…";
|
||||
resultEl.style.display = "none";
|
||||
|
||||
const form = new FormData();
|
||||
form.append("pdf", selectedFile);
|
||||
|
||||
try {
|
||||
const res = await fetch("/extract", { method: "POST", headers: csrfHeaders(), body: form });
|
||||
const json = await res.json();
|
||||
|
||||
resultEl.textContent = JSON.stringify(json, null, 2);
|
||||
resultEl.className = "result " + (res.ok ? "success" : "error");
|
||||
resultEl.style.display = "block";
|
||||
statusEl.textContent = res.ok
|
||||
? `Written → ${json.files?.json || json.stem}`
|
||||
: `Error ${res.status}`;
|
||||
} catch (err) {
|
||||
resultEl.textContent = String(err);
|
||||
resultEl.className = "result error";
|
||||
resultEl.style.display = "block";
|
||||
statusEl.textContent = "Request failed.";
|
||||
} finally {
|
||||
submitBtn.disabled = false;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user