2 lines
6.5 KiB
JavaScript
2 lines
6.5 KiB
JavaScript
export const cleanupToolsSource = " function cleanupCountCard(label, value, note=''){\n return `<div class=\"cleanup-card\"><b>${esc(label)}</b><span>${esc(value ?? 0)}</span>${note?`<small>${esc(note)}</small>`:''}</div>`;\n }\n function cleanupRetentionDaysNote(value){ return `retention ${value || '-'} days`; }\n function cleanupOperationLogRetentionNote(data){\n const settings = data.operation_log_retention || {};\n if(data.retention_labels?.operation_logs) return data.retention_labels.operation_logs;\n if(settings.retention_mode === 'lines') return `retention ${settings.retention_lines || '-'} lines`;\n if(settings.retention_mode === 'both') return `retention ${settings.retention_days || '-'} days and ${settings.retention_lines || '-'} lines`;\n if(settings.retention_mode === 'manual') return 'manual cleanup only';\n return cleanupRetentionDaysNote((data.retention_days || {}).operation_logs);\n }\n function renderCleanup(data={}){\n const box=$('cleanupManager'); if(!box) return;\n const retention=data.retention_days||{};\n const db=data.database||{};\n const cache=data.cache||{};\n const cards=[\n cleanupCountCard('Job logs total', data.jobs_total, cleanupRetentionDaysNote(retention.jobs)),\n cleanupCountCard('Job logs clearable', data.jobs_clearable, 'done / failed / cancelled'),\n cleanupCountCard('Smart Queue logs', data.smart_queue_history_total, cleanupRetentionDaysNote(retention.smart_queue_history)),\n cleanupCountCard('Operation logs', data.operation_logs_total, cleanupOperationLogRetentionNote(data)),\n cleanupCountCard('Planner logs', data.planner_history_total, cleanupRetentionDaysNote(retention.planner_history)),\n cleanupCountCard('Automation logs', data.automation_history_total, cleanupRetentionDaysNote(retention.automation_history)),\n cleanupCountCard('Profile cache rows', cache.profile_rows ?? 0, 'tracker + torrent stats cache'),\n cleanupCountCard('Runtime cache', cache.runtime_items ?? 0, 'memory-only profile cache'),\n cleanupCountCard('Database size', db.size_h||db.size||'-', db.path||''),\n cleanupCountCard('SQLite free inside', db.free_inside_h||'0 B', `${db.free_ratio_percent ?? 0}% reusable`),\n cleanupCountCard('SQLite WAL', db.wal_size_h||'0 B', 'write-ahead log')\n ];\n const poller=data.poller_runtime||{};\n const pollerCards=[\n cleanupCountCard('Live poll counter', poller.live_poll_count ?? 0, 'lightweight speed/status loop'),\n cleanupCountCard('List poll counter', poller.list_poll_count ?? 0, 'full snapshot/diff loop'),\n cleanupCountCard('Poller skipped emits', poller.skipped_emissions ?? 0, 'diagnostic counter only')\n ];\n const adminSection = data.admin ? `<div class=\"cleanup-section mt-2\"><div><b>Database compact</b><small>Admin-only SQLite VACUUM. Reclaims free pages after retention cleanup and truncates WAL. It can briefly block database writes.</small></div><button id=\"cleanupDatabaseVacuumBtn\" class=\"btn btn-sm btn-outline-warning\"><i class=\"fa-solid fa-compress\"></i> Compact database</button></div>` : '';\n box.innerHTML=`<div class=\"cleanup-grid\">${cards.join('')}${pollerCards.join('')}</div><div class=\"cleanup-section mt-3\"><div><b>Profile cache</b><small>Clears only the active profile runtime/DB cache. It does not remove torrents, rules, settings or logs.</small></div><button id=\"cleanupProfileCacheBtn\" class=\"btn btn-sm btn-outline-warning\"><i class=\"fa-solid fa-eraser\"></i> Clear profile cache</button></div><div class=\"cleanup-section mt-2\"><div><b>Poller diagnostics</b><small>Resets in-memory live/list poller counters only. Polling, saved settings and torrent data stay unchanged.</small></div><button id=\"cleanupPollerDiagnosticsBtn\" class=\"btn btn-sm btn-outline-warning\"><i class=\"fa-solid fa-gauge-high\"></i> Reset poller diagnostics</button></div>${adminSection}<div class=\"cleanup-section mt-2\"><div><b>Logs and history</b><small>Pending and running jobs are preserved. Operation log cleanup removes only profile-scoped log entries.</small></div><div class=\"cleanup-actions\"><button id=\"cleanupJobsBtn\" class=\"btn btn-sm btn-outline-danger\"><i class=\"fa-solid fa-trash\"></i> Clear job logs</button><button id=\"cleanupSmartQueueBtn\" class=\"btn btn-sm btn-outline-danger\"><i class=\"fa-solid fa-trash\"></i> Clear Smart Queue logs</button><button id=\"cleanupOperationLogsBtn\" class=\"btn btn-sm btn-outline-danger\"><i class=\"fa-solid fa-trash\"></i> Clear operation logs</button><button id=\"cleanupPlannerBtn\" class=\"btn btn-sm btn-outline-danger\"><i class=\"fa-solid fa-trash\"></i> Clear Planner logs</button><button id=\"cleanupAutomationsBtn\" class=\"btn btn-sm btn-outline-danger\"><i class=\"fa-solid fa-trash\"></i> Clear automation logs</button><button id=\"cleanupAllBtn\" class=\"btn btn-sm btn-danger\"><i class=\"fa-solid fa-broom\"></i> Clear all logs</button></div></div><div class=\"cleanup-actions mt-3\"><button id=\"cleanupRefreshBtn\" class=\"btn btn-sm btn-outline-secondary\"><i class=\"fa-solid fa-rotate\"></i> Refresh</button></div>`;\n }\n async function loadCleanup(){\n const box=$('cleanupManager'); if(!box) return;\n box.innerHTML='<span class=\"spinner-border spinner-border-sm\"></span> Loading cleanup data...';\n try{\n const j=await (await fetch('/api/cleanup/summary')).json();\n if(!j.ok) throw new Error(j.error||'Cleanup summary failed');\n renderCleanup(j.cleanup||{});\n }catch(e){ box.innerHTML=`<div class=\"text-danger\">${esc(e.message)}</div>`; }\n }\n async function runCleanupAction(endpoint, label){\n if(!confirm(`${label}?`)) return;\n setBusy(true);\n try{\n const j=await post(endpoint,{});\n const deleted=typeof j.deleted==='object' ? Object.entries(j.deleted).map(([k,v])=>`${k}: ${v}`).join(', ') : String(j.deleted ?? 0);\n toastMessage('toast.cleanupDone','success',{deleted});\n renderCleanup(j.cleanup||{});\n if(endpoint.includes('/jobs')){ jobsPage=0; loadJobs(0).catch(()=>{}); }\n if(endpoint.includes('/smart-queue') || endpoint.includes('/all')) loadSmartQueue().catch(()=>{});\n if(endpoint.includes('/operation-logs') || endpoint.includes('/all')) loadOperationLogs(true).catch(()=>{});\n if(endpoint.includes('/planner') || endpoint.includes('/all')) loadPlannerPreview().catch(()=>{});\n if(endpoint.includes('/automations') || endpoint.includes('/all')) loadAutomations().catch(()=>{});\n }catch(e){ toast(e.message,'danger'); }\n finally{ setBusy(false); }\n }\n";
|