Implement temporary storage monitoring and clean up system maintenance features
This commit is contained in:
+134
@@ -2084,6 +2084,140 @@ async function initializeApp() {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Temporary storage maintenance handlers
|
||||
const refreshTempBtn = document.getElementById("refresh-temp-btn");
|
||||
if (refreshTempBtn) {
|
||||
refreshTempBtn.addEventListener("click", loadTempInfo);
|
||||
}
|
||||
|
||||
const cleanupTempBtn = document.getElementById("cleanup-temp-btn");
|
||||
if (cleanupTempBtn) {
|
||||
cleanupTempBtn.addEventListener("click", async () => {
|
||||
if (confirm("Are you sure you want to clean up all inactive temporary directories?\nThis will clear any completed, cancelled, failed, or orphaned job frames. Paused or interrupted jobs will have to restart from the beginning on resume.")) {
|
||||
try {
|
||||
const cleanRes = await fetch("/api/system/temp-cleanup", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ paths: null })
|
||||
});
|
||||
if (cleanRes.ok) {
|
||||
loadTempInfo();
|
||||
loadQueue();
|
||||
} else {
|
||||
alert("Cleanup failed.");
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Refresh queue button should also refresh temp files info
|
||||
const refreshQueueBtn = document.getElementById("refresh-queue-btn");
|
||||
if (refreshQueueBtn) {
|
||||
refreshQueueBtn.addEventListener("click", loadTempInfo);
|
||||
}
|
||||
|
||||
// Load initial temp info
|
||||
loadTempInfo();
|
||||
}
|
||||
|
||||
async function loadTempInfo() {
|
||||
const listContainer = document.getElementById("temp-files-list");
|
||||
const totalSizeBadge = document.getElementById("temp-total-size");
|
||||
const folderCountBadge = document.getElementById("temp-folder-count");
|
||||
if (!listContainer) return;
|
||||
|
||||
try {
|
||||
const res = await fetch("/api/system/temp-info");
|
||||
if (!res.ok) return;
|
||||
const data = await res.json();
|
||||
const folders = data.temp_folders || [];
|
||||
|
||||
let totalSize = 0;
|
||||
folders.forEach(f => totalSize += (f.size_bytes || 0));
|
||||
|
||||
if (totalSizeBadge) totalSizeBadge.textContent = formatBytes(totalSize);
|
||||
if (folderCountBadge) folderCountBadge.textContent = folders.length;
|
||||
|
||||
if (folders.length === 0) {
|
||||
listContainer.innerHTML = `
|
||||
<div style="text-align: center; padding: 2rem; border: 1px dashed var(--border-color); border-radius: 12px; color: var(--text-muted);">
|
||||
<p>No temporary directories found.</p>
|
||||
</div>
|
||||
`;
|
||||
return;
|
||||
}
|
||||
|
||||
listContainer.innerHTML = "";
|
||||
|
||||
folders.forEach(f => {
|
||||
const item = document.createElement("div");
|
||||
item.className = "queue-item";
|
||||
|
||||
const sizeStr = formatBytes(f.size_bytes || 0);
|
||||
const isActive = ["analyzing", "extracting", "upscaling", "restoring_faces", "interpolating", "assembling"].includes(f.status);
|
||||
|
||||
let statusLabel = f.status.toUpperCase();
|
||||
let statusClass = f.status;
|
||||
if (f.status === "orphaned") {
|
||||
statusLabel = "Orphaned (No Job)";
|
||||
statusClass = "interrupted";
|
||||
}
|
||||
|
||||
item.innerHTML = `
|
||||
<div style="display: flex; align-items: center; gap: 1rem; width: 100%; flex-wrap: wrap;">
|
||||
<div class="queue-item-details" style="flex: 1; min-width: 200px;">
|
||||
<div class="queue-item-title" style="word-break: break-all; font-size: 0.88rem;">
|
||||
<i class="fa-solid fa-folder-open" style="color: var(--primary);"></i> ${f.path}
|
||||
</div>
|
||||
<div class="queue-item-meta" style="margin-top: 0.25rem;">
|
||||
<span><i class="fa-solid fa-file-video"></i> Video: ${f.video_name}</span>
|
||||
<span>Size: ${sizeStr} (${f.file_count} files)</span>
|
||||
</div>
|
||||
</div>
|
||||
<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">
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
const deleteBtn = item.querySelector(".btn-delete-temp");
|
||||
if (deleteBtn && !isActive) {
|
||||
deleteBtn.addEventListener("click", async (e) => {
|
||||
e.stopPropagation();
|
||||
if (confirm(`Are you sure you want to delete this temporary folder?\nPath: ${f.path}`)) {
|
||||
try {
|
||||
const cleanRes = await fetch("/api/system/temp-cleanup", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ paths: [f.path] })
|
||||
});
|
||||
if (cleanRes.ok) {
|
||||
loadTempInfo();
|
||||
loadQueue();
|
||||
} else {
|
||||
alert("Failed to delete temp folder.");
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
listContainer.appendChild(item);
|
||||
});
|
||||
} catch (err) {
|
||||
console.error("Error loading temp files info:", err);
|
||||
}
|
||||
}
|
||||
|
||||
initializeApp();
|
||||
|
||||
@@ -564,6 +564,42 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Temporary Storage & Maintenance Section -->
|
||||
<section class="maintenance-section glass-card" style="margin-top: 3rem;">
|
||||
<div class="queue-header">
|
||||
<h2><i class="fa-solid fa-hard-drive"></i> Temporary Storage & Maintenance</h2>
|
||||
<div style="display: flex; gap: 0.5rem;">
|
||||
<button type="button" id="refresh-temp-btn" class="btn btn-secondary btn-small">
|
||||
<i class="fa-solid fa-arrows-rotate"></i> Refresh
|
||||
</button>
|
||||
<button type="button" id="cleanup-temp-btn" class="btn btn-danger btn-small">
|
||||
<i class="fa-solid fa-broom"></i> Clean Up Inactive Temp
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<p style="color: var(--text-muted); font-size: 0.9rem; margin-bottom: 1.5rem;">
|
||||
Monitor temporary image frames created during upscaling. Running jobs cannot be cleared.
|
||||
</p>
|
||||
|
||||
<div class="temp-stats-summary" style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 1rem; margin-bottom: 1.5rem;">
|
||||
<div class="glass-card" style="padding: 1rem; background: rgba(255,255,255,0.01); text-align: center;">
|
||||
<span style="font-size: 0.75rem; color: var(--text-muted); text-transform: uppercase; display: block;">Total Temp Size</span>
|
||||
<strong id="temp-total-size" style="font-size: 1.5rem; color: var(--primary);">0 Bytes</strong>
|
||||
</div>
|
||||
<div class="glass-card" style="padding: 1rem; background: rgba(255,255,255,0.01); text-align: center;">
|
||||
<span style="font-size: 0.75rem; color: var(--text-muted); text-transform: uppercase; display: block;">Temp Folders Count</span>
|
||||
<strong id="temp-folder-count" style="font-size: 1.5rem; color: var(--primary);">0</strong>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="temp-files-list" style="display: flex; flex-direction: column; gap: 0.75rem;">
|
||||
<!-- Temp files populated dynamically -->
|
||||
<div style="text-align: center; padding: 2rem; border: 1px dashed var(--border-color); border-radius: 12px; color: var(--text-muted);">
|
||||
<p>No temporary directories found.</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Completed Video Gallery -->
|
||||
<section class="gallery-section glass-card" style="margin-top: 3rem;">
|
||||
<div class="gallery-header">
|
||||
|
||||
Reference in New Issue
Block a user