Implement orphaned temporary folder re-import and resume feature with web UI modal
This commit is contained in:
+132
@@ -2726,6 +2726,11 @@ async function loadTempInfo() {
|
||||
<div class="queue-item-status-bar" style="border: none; padding: 0;">
|
||||
<span class="status-badge ${statusClass}" style="font-size: 0.7rem; padding: 0.15rem 0.5rem; margin-right: 0.5rem;">${statusLabel}</span>
|
||||
<div class="queue-item-actions">
|
||||
${f.status === "orphaned" ? `
|
||||
<button class="btn btn-primary btn-small btn-reimport-temp" data-job-id="${f.job_id}" data-path="${f.path}">
|
||||
<i class="fa-solid fa-cloud-arrow-down"></i> Re-import
|
||||
</button>
|
||||
` : ''}
|
||||
<button class="btn btn-danger btn-small btn-delete-temp" data-path="${f.path}" ${isActive ? 'disabled style="opacity: 0.5; cursor: not-allowed;" title="Cannot delete active job frames"' : ''}>
|
||||
<i class="fa-solid fa-trash"></i> Delete
|
||||
</button>
|
||||
@@ -2756,6 +2761,13 @@ async function loadTempInfo() {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const reimportBtn = item.querySelector(".btn-reimport-temp");
|
||||
if (reimportBtn) {
|
||||
reimportBtn.addEventListener("click", async (e) => {
|
||||
e.stopPropagation();
|
||||
showReimportModal(f.job_id, f.path);
|
||||
});
|
||||
}
|
||||
|
||||
listContainer.appendChild(item);
|
||||
@@ -2912,4 +2924,124 @@ async function loadDefaultTempDir() {
|
||||
}
|
||||
}
|
||||
|
||||
async function showReimportModal(jobId, tempPath) {
|
||||
const modal = document.getElementById("reimport-modal");
|
||||
const jobIdInput = document.getElementById("reimport-job-id");
|
||||
const tempDirInput = document.getElementById("reimport-temp-dir");
|
||||
const videoSelect = document.getElementById("reimport-video-select");
|
||||
|
||||
if (!modal || !jobIdInput || !tempDirInput || !videoSelect) return;
|
||||
|
||||
jobIdInput.value = jobId;
|
||||
|
||||
// Resolve custom parent directory if tempPath contains jobId
|
||||
const parentDir = tempPath.substring(0, tempPath.lastIndexOf("/" + jobId));
|
||||
tempDirInput.value = parentDir;
|
||||
|
||||
// Populate video files dropdown
|
||||
videoSelect.innerHTML = '<option value="">-- Loading Uploaded Videos --</option>';
|
||||
|
||||
try {
|
||||
const res = await fetch("/api/uploads");
|
||||
if (res.ok) {
|
||||
const uploads = await res.json();
|
||||
if (uploads.length === 0) {
|
||||
videoSelect.innerHTML = '<option value="">No uploaded videos found. Upload one first.</option>';
|
||||
} else {
|
||||
videoSelect.innerHTML = '<option value="">-- Select a Video File --</option>';
|
||||
|
||||
uploads.forEach(u => {
|
||||
// Reimport requires the absolute path to the uploaded video file
|
||||
const videoPath = `/var/home/david/Documents/vscode/video_upscaler/uploads/${u.original_filename}`;
|
||||
const opt = document.createElement("option");
|
||||
opt.value = videoPath;
|
||||
opt.textContent = `${u.original_filename} (${formatBytes(u.size_bytes)})`;
|
||||
videoSelect.appendChild(opt);
|
||||
});
|
||||
|
||||
// Try to auto-match files by looking for standard uploaded prefix or creation time
|
||||
try {
|
||||
const matches = Array.from(videoSelect.options).filter(opt => opt.value.includes("8d4d3e0e-e5a5-4101-9e2d-550f96c1674f"));
|
||||
if (matches.length > 0) {
|
||||
matches[0].selected = true;
|
||||
}
|
||||
} catch(e) {}
|
||||
}
|
||||
} else {
|
||||
videoSelect.innerHTML = '<option value="">Error loading uploads.</option>';
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
videoSelect.innerHTML = '<option value="">Error loading uploads.</option>';
|
||||
}
|
||||
|
||||
modal.style.display = "flex";
|
||||
document.body.style.overflow = "hidden";
|
||||
}
|
||||
|
||||
// Re-import modal close event
|
||||
const reimportModal = document.getElementById("reimport-modal");
|
||||
const reimportCloseBtn = document.getElementById("reimport-modal-close-btn");
|
||||
if (reimportModal && reimportCloseBtn) {
|
||||
reimportCloseBtn.addEventListener("click", () => {
|
||||
reimportModal.style.display = "none";
|
||||
document.body.style.overflow = "";
|
||||
});
|
||||
reimportModal.addEventListener("click", (e) => {
|
||||
if (e.target === reimportModal) {
|
||||
reimportModal.style.display = "none";
|
||||
document.body.style.overflow = "";
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Re-import form submission handler
|
||||
const reimportForm = document.getElementById("reimport-form");
|
||||
if (reimportForm) {
|
||||
reimportForm.addEventListener("submit", async (e) => {
|
||||
e.preventDefault();
|
||||
const jobId = document.getElementById("reimport-job-id").value;
|
||||
const tempDir = document.getElementById("reimport-temp-dir").value;
|
||||
const videoPath = document.getElementById("reimport-video-select").value;
|
||||
const model = document.getElementById("reimport-model-select").value;
|
||||
const faceRestoration = document.getElementById("reimport-face-restoration").checked;
|
||||
const rifeInterpolation = document.getElementById("reimport-rife-interpolation").checked;
|
||||
const audioDenoise = document.getElementById("reimport-audio-denoise").checked;
|
||||
|
||||
if (!videoPath) {
|
||||
alert("Please select a video file.");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const res = await fetch(`/api/system/temp-reimport/${jobId}`, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({
|
||||
video_path: videoPath,
|
||||
model: model,
|
||||
scale: 4,
|
||||
ai_face_restoration: faceRestoration,
|
||||
ai_rife_interpolation: rifeInterpolation,
|
||||
ai_audio_denoise: audioDenoise,
|
||||
temp_dir: tempDir
|
||||
})
|
||||
});
|
||||
|
||||
if (res.ok) {
|
||||
reimportModal.style.display = "none";
|
||||
document.body.style.overflow = "";
|
||||
loadQueue();
|
||||
loadTempInfo();
|
||||
} else {
|
||||
const err = await res.json();
|
||||
alert("Failed to reimport job: " + (err.detail || "unknown error"));
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
alert("Network error occurred.");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
initializeApp();
|
||||
|
||||
Reference in New Issue
Block a user