Bug fixes, arr cleanup API-driven scan, shared JS formatters
Bug fixes: - fallback.sh: escape sed metacharacters (\ & |) in state_set values - common.sh: parse PID from lock file content correctly (handles pid:metadata format) - unraid_api_key_renew.sh: fix path depth (../../../) and sync registry key to conf when stale - stop.php: only clear pid/status if process is actually dead — D-state survives SIGKILL - array_started.sh: check ARRAY_START_SCRIPTS empty before printing launch header Arr cleanup: - radarr_cleanup.sh / sonarr_cleanup.sh: fetch root folders from arr API instead of reverse-looking up the path map — handles multi-root-folder setups correctly UI: - varaverk.js: extract shared formatters (_relTime, _fmtBytes, _sz, _uptime, _gb, _tb, _n) - arrs.php / partnership.php: use shared formatters, remove duplicates - arrs.php / fallback.php: show error message on fetch failure instead of silent empty - docker.php: disable rename input during request, restore original value on failure - setup.php: abort controller timeout on detect fetch - partnership.php: remove Re-run Phase 2 button opacity dimming
This commit is contained in:
@@ -96,26 +96,6 @@
|
||||
<script>
|
||||
(function() {
|
||||
|
||||
// ── Helpers ───────────────────────────────────────────────────────────────────
|
||||
function _rel(ts) {
|
||||
if (!ts) return '—';
|
||||
const d = Math.floor(Date.now() / 1000) - ts;
|
||||
if (d < 60) return 'just now';
|
||||
if (d < 3600) return Math.floor(d/60) + 'm ago';
|
||||
if (d < 86400) return Math.floor(d/3600) + 'h ago';
|
||||
if (d < 172800)return 'yesterday';
|
||||
return Math.floor(d/86400) + 'd ago';
|
||||
}
|
||||
function _n(v) { return v == null ? '—' : Number(v).toLocaleString(); }
|
||||
function _gb(b) { if (!b) return '—'; return (b / 1073741824).toFixed(1) + ' GB'; }
|
||||
function _tb(b) { if (!b) return '—'; return (b / 1099511627776).toFixed(2) + ' TB'; }
|
||||
function _sz(b) {
|
||||
if (!b) return '—';
|
||||
if (b >= 1099511627776) return (b/1099511627776).toFixed(1) + ' TB';
|
||||
if (b >= 1073741824) return (b/1073741824).toFixed(1) + ' GB';
|
||||
return (b/1048576).toFixed(0) + ' MB';
|
||||
}
|
||||
|
||||
// ── Arr card ──────────────────────────────────────────────────────────────────
|
||||
function _arrCard(arr) {
|
||||
const LABELS = { sonarr:'Sonarr', radarr:'Radarr', lidarr:'Lidarr' };
|
||||
@@ -209,7 +189,7 @@ function _arrCard(arr) {
|
||||
cleanup = `
|
||||
<div class="vv-arr-meta">
|
||||
<span class="vv-arr-meta-lbl">Cleanup</span>
|
||||
<span class="vv-arr-meta-val">${_rel(cl.last_run)} ${st}</span>
|
||||
<span class="vv-arr-meta-val">${_relTime(cl.last_run)} ${st}</span>
|
||||
</div>
|
||||
${cl.tracked != null ? `<div class="vv-arr-meta-sub" style="${orCol}">
|
||||
${_n(cl.tracked)} files · ${orph} orphans${junk ? ' · ' + junk + ' junk' : ''}
|
||||
@@ -223,7 +203,7 @@ function _arrCard(arr) {
|
||||
const added = dsc.added != null ? ` <span style="color:#6fcf97">+${dsc.added}</span>` : '';
|
||||
disc = `<div class="vv-arr-meta">
|
||||
<span class="vv-arr-meta-lbl">Discovery</span>
|
||||
<span class="vv-arr-meta-val">${_rel(dsc.last_run)}${added}</span>
|
||||
<span class="vv-arr-meta-val">${_relTime(dsc.last_run)}${added}</span>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
@@ -295,7 +275,7 @@ function _syncSection(sync, recovery, settings) {
|
||||
const pillTxt = !data.last_run ? 'never run' : ok ? 'ok' : data.status || 'error';
|
||||
let body = '';
|
||||
if (data.last_run) {
|
||||
body += `<div style="font-size:11px;color:#555;margin-bottom:10px;">${_rel(data.last_run)}</div>`;
|
||||
body += `<div style="font-size:11px;color:#555;margin-bottom:10px;">${_relTime(data.last_run)}</div>`;
|
||||
}
|
||||
body += `<div class="vv-arr-sr-row">${items}</div>`;
|
||||
if (extra) body += extra;
|
||||
@@ -410,7 +390,12 @@ function _render(data) {
|
||||
|
||||
function vvArrsLoad() {
|
||||
fetch('/plugins/varaverk/api/arrs.php')
|
||||
.then(r => r.json()).then(_render).catch(() => {});
|
||||
.then(r => r.json())
|
||||
.then(_render)
|
||||
.catch(() => {
|
||||
document.getElementById('vv-arrs-grid').innerHTML =
|
||||
'<div style="grid-column:1/-1;color:#555;font-size:12px;padding:24px 0;text-align:center;">Error loading arrs data — check API</div>';
|
||||
});
|
||||
}
|
||||
|
||||
vvArrsLoad();
|
||||
|
||||
@@ -291,7 +291,11 @@ function _bindEvents() {
|
||||
if (!fid || !name) return;
|
||||
const f = (_data.folders||[]).find(x=>x.id===fid);
|
||||
if (f && name===f.name) return;
|
||||
_api({action:'rename_folder',folder_id:fid,name}, r => { if(r.ok) _reload(); else alert('Rename failed: '+(r.error||'?')); });
|
||||
el.disabled = true; el.style.opacity = '0.5';
|
||||
_api({action:'rename_folder',folder_id:fid,name}, r => {
|
||||
el.disabled = false; el.style.opacity = '';
|
||||
if (r.ok) _reload(); else { alert('Rename failed: '+(r.error||'?')); el.value = f?.name ?? name; }
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -233,7 +233,10 @@ function vvFbLoad() {
|
||||
fetch('/plugins/varaverk/api/fallback.php')
|
||||
.then(r => r.json())
|
||||
.then(_render)
|
||||
.catch(() => {});
|
||||
.catch(() => {
|
||||
document.getElementById('vv-fb-grid').innerHTML =
|
||||
'<div style="grid-column:1/-1;color:#555;font-size:12px;padding:24px 0;text-align:center;">Error loading fallback data — check API</div>';
|
||||
});
|
||||
}
|
||||
|
||||
vvFbLoad();
|
||||
|
||||
@@ -593,24 +593,6 @@ function vvPtSaveSettings(btn) {
|
||||
|
||||
// ── Helpers ───────────────────────────────────────────────────────────────────
|
||||
|
||||
function _relTime(ts) {
|
||||
if (!ts) return '—';
|
||||
const d = Math.floor(Date.now() / 1000) - ts;
|
||||
if (d < 60) return 'just now';
|
||||
if (d < 3600) return Math.floor(d / 60) + 'm ago';
|
||||
if (d < 86400) return Math.floor(d / 3600) + 'h ago';
|
||||
if (d < 172800) return 'yesterday';
|
||||
return Math.floor(d / 86400) + 'd ago';
|
||||
}
|
||||
|
||||
function _uptime(sec) {
|
||||
if (!sec) return '—';
|
||||
const d = Math.floor(sec / 86400);
|
||||
const h = Math.floor((sec % 86400) / 3600);
|
||||
const m = Math.floor((sec % 3600) / 60);
|
||||
return d > 0 ? `${d}d ${h}h ${m}m` : h > 0 ? `${h}h ${m}m` : `${m}m`;
|
||||
}
|
||||
|
||||
function _row(lbl, val) {
|
||||
return `<div class="vv-pt-row"><span class="vv-pt-lbl">${lbl}</span><span class="vv-pt-val">${val}</span></div>`;
|
||||
}
|
||||
@@ -1083,7 +1065,7 @@ function _renderActions(nodes, cfg) {
|
||||
</div>
|
||||
<div style="display:flex;flex-direction:column;gap:5px;align-items:flex-end;">
|
||||
<button class="vv-pt-action-btn info" onclick="vvPtPhase2(this,'${remote.id}')"
|
||||
style="opacity:.35;font-size:10px;" title="Re-run Phase 2">↻ Re-run</button>
|
||||
style="font-size:10px;" title="Re-run Phase 2">↻ Re-run</button>
|
||||
<button class="vv-pt-action-btn warn" onclick="vvPtShowDeleteKeys('${remote.id}')"
|
||||
style="opacity:.4;font-size:10px;">🗑 Keys</button>
|
||||
</div>
|
||||
|
||||
@@ -178,7 +178,9 @@ let _vvRedirect = '?tab=scheduler';
|
||||
|
||||
// ── Detection banner ──────────────────────────────────────────────────────────
|
||||
(function() {
|
||||
fetch('/plugins/varaverk/api/setup.php?action=detect&_=' + Date.now())
|
||||
const _ac = new AbortController();
|
||||
setTimeout(() => _ac.abort(), 6000);
|
||||
fetch('/plugins/varaverk/api/setup.php?action=detect&_=' + Date.now(), {signal: _ac.signal})
|
||||
.then(r => r.json()).then(d => {
|
||||
const b = document.getElementById('vv-detect-banner');
|
||||
if (!d.ok) { b.innerHTML = '<span style="color:#555">Detection unavailable</span>'; return; }
|
||||
|
||||
Reference in New Issue
Block a user