From 90a426bc9e946978218190575a1eb8554c98f3c2 Mon Sep 17 00:00:00 2001 From: Leo Date: Thu, 21 May 2026 23:10:22 -0400 Subject: [PATCH] Fix Cantaloupe Sync: use sys.executable + add Excel file upload button MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Changed subprocess from 'python' to 'sys.executable' (fixes FileNotFoundError in systemd — venv python not in system PATH) - Added '📤 Upload Excel' button to admin frontend sync page - uploadSyncFile() sends file to the same /api/admin/cantaloupe/sync endpoint (which already supported file upload — frontend just didn't expose it) - Users can now use 'Sync Now' for auto-download or 'Upload Excel' for manual --- cantaloupe_sync.py | 3 ++- static/index.html | 24 ++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/cantaloupe_sync.py b/cantaloupe_sync.py index 906e2d4..f118777 100644 --- a/cantaloupe_sync.py +++ b/cantaloupe_sync.py @@ -419,9 +419,10 @@ async def run_sync( # Try subprocess call to cantaloupe export try: import subprocess + import sys cantaloupe_dir = os.path.expanduser("~/projects/cantaloupe-downloader") result = subprocess.run( - ["python", "-m", "cantaloupe", "export", "--scheduled"], + [sys.executable, "-m", "cantaloupe", "export", "--scheduled"], capture_output=True, text=True, timeout=120, cwd=cantaloupe_dir, ) diff --git a/static/index.html b/static/index.html index 141a0c3..30d39e8 100644 --- a/static/index.html +++ b/static/index.html @@ -864,6 +864,8 @@ Cantaloupe Sync
+ +
@@ -2320,6 +2322,28 @@ async function runSync() { } } +// ── Upload Excel File ── +async function uploadSyncFile(event) { + const file = event.target.files?.[0]; + if (!file) return; + const fd = new FormData(); + fd.append('file', file); + const btn = document.getElementById('csSyncBtn'); + btn.disabled = true; + btn.innerHTML = '
Uploading...'; + try { + const result = await api('/api/admin/cantaloupe/sync', { method: 'POST', body: fd }); + showToast('Upload processed — batch #' + result.id); + await loadCantaloupeSync(); + } catch (e) { + showToast('Upload failed: ' + e.message, true); + } finally { + btn.disabled = false; + btn.innerHTML = '🔄 Sync Now'; + event.target.value = ''; // reset so same file can be re-picked + } +} + // ── Approve / Reject ── async function approveBatch(batchId) { const confirmed = await showModal('Approve Batch',