Plugin: common.php library, watchdog expansion, monitor + scheduler improvements

PHP architecture:
- Extract common.php from monitor.php — shared system functions (vv_system_info,
  vv_memory_breakdown, vv_remote_hosts_stats, disk/GPU/UPS/network/docker/parity, etc.)
  now live in one place; monitor.php and watchdog.php both require common.php
- Add unraid_api.php as explicit include (was implicit via config.php chain)
- confform.php: add missing require_once config.php (implicit dep made explicit)
- Delete orphaned pages/docs.php and pages/config.php (absorbed into scheduler)

Watchdog page:
- Add Storage watchdog card (growth + log strikes, baseline age, suppress ceilings)
- Add Network watchdog card (NPM strikes, DDNS domain/container, NPM URL)
- One host per row layout — all 5 watchdog cards equally spaced via inner grid
- Watchdog now uses Unraid API for local system stats; remote nodes with API key
  but no SSH get system info from vv_remote_hosts_stats() with api_only flag
- SSH bundle: /proc/meminfo passed as raw section instead of awk-parsed header
  fields — fixes RAM showing 0 on remote hosts where awk quoting was unreliable
- vv_wd_local_system() rewritten as thin wrapper over vv_system_info() + vv_memory_breakdown()

Monitor page:
- Watchdog card: add stability strikes, storage watchdog strikes, network NPM status,
  live system stats (rootfs/log/tmp %, RAM free, load, CPU temp, zombies, NIC, sshd)
- Row height: switch from max-height on cards to minmax(0, calc(...)) on grid track —
  all cards in a row now fill to the tallest card's height correctly (fixes Pools card
  being shorter than neighbours)

Scheduler page:
- Add Tools section above Custom Scripts — lists Tools/*.sh with run/dry-run/cron/log
- vv_tools_scripts() function in scheduler.php include

Tools:
- Add docker_prune_images.sh — removes dangling Docker images; --dry-run and --status modes
This commit is contained in:
Gmer4Lfe
2026-05-29 23:33:52 -04:00
parent 8f05f0d27c
commit 86048b32d3
13 changed files with 2072 additions and 898 deletions
+59 -2
View File
@@ -2,6 +2,7 @@
require_once dirname(__DIR__) . '/include/scheduler.php';
$tree = vv_job_tree();
$customs = vv_custom_scripts();
$tools = vv_tools_scripts();
$_library = vv_script_library();
$_folders = vv_folders_load();
@@ -195,6 +196,54 @@ $runningScripts = array_unique($runningScripts);
</div>
<?php endforeach; ?>
<!-- Tools container -->
<div class="vv-card vv-wide vv-sched-card vv-tools-card">
<div class="vv-job-row">
<span class="vv-job-label" style="font-weight:bold;">Tools</span>
<span class="vv-custom-count"><?= count($tools) ?> tool<?= count($tools) !== 1 ? 's' : '' ?></span>
<button class="vv-advanced-toggle" style="margin-left:auto;width:100px" onclick="vvToggleTools(this)">Tools ▸</button>
</div>
<div class="vv-children" id="vv-tools-children" style="display:none;">
<?php if (empty($tools)): ?>
<p class="vv-custom-empty">No scripts found in Tools/.</p>
<?php else: ?>
<?php foreach ($tools as $ts): $tsid = htmlspecialchars($ts['id']); ?>
<div class="vv-script" data-id="<?= $tsid ?>">
<div class="vv-job-row">
<label class="vv-toggle" title="Enable/disable cron">
<input type="checkbox" class="vv-enabled"
<?= $ts['enabled'] ? 'checked' : '' ?>
onchange="vvSaveJob(this)">
<span class="vv-slider"></span>
</label>
<span class="vv-job-label"><?= htmlspecialchars($ts['label']) ?></span>
<input type="text" class="vv-cron" value="<?= htmlspecialchars($ts['cron']) ?>"
placeholder="cron expression"
onblur="vvSaveCronBlur(this)">
<span class="vv-save-check"></span>
</div>
<?php if (!empty($ts['desc'])): ?>
<div class="vv-job-desc" title="<?= htmlspecialchars($ts['desc']) ?>"><?= htmlspecialchars($ts['desc']) ?></div>
<?php endif; ?>
<div class="vv-job-actions">
<button class="vv-btn-sm vv-run-btn" onclick="vvRunJob(this)">&#9654; Run</button>
<button class="vv-btn-sm vv-dry-btn" onclick="vvDryRun(this)">&#9654; Dry Run</button>
<?php $tsLog = vv_job_log_path($ts['id']); ?>
<button class="vv-btn-sm vv-log-btn<?= (file_exists($tsLog) && filesize($tsLog) > 0) ? ' vv-has-log' : '' ?>" onclick="vvSelectLog(this)">Log</button>
<label class="vv-log-label" title="Enable verbose --log output">
<input type="checkbox" class="vv-log-enabled"
<?= $ts['log_enabled'] ? 'checked' : '' ?>
onchange="vvSaveJob(this)">
<span>Verbose</span>
</label>
<span class="vv-job-dot"></span>
</div>
</div>
<?php endforeach; ?>
<?php endif; ?>
</div>
</div>
<!-- Custom Scripts container -->
<?php
// Build set of IDs that belong to a folder
@@ -1406,6 +1455,14 @@ function vvToggleAdvanced(btn) {
btn.textContent = visible ? 'Advanced ▸' : 'Advanced ▾';
}
function vvToggleTools(btn) {
const card = btn.closest('.vv-tools-card');
const children = card.querySelector('.vv-children');
const visible = children.style.display !== 'none';
children.style.display = visible ? 'none' : 'block';
btn.textContent = visible ? 'Tools ▸' : 'Tools ▾';
}
function vvToggleCustom(btn) {
const card = btn.closest('.vv-custom-card');
const children = card.querySelector('.vv-children');
@@ -1818,8 +1875,8 @@ function vvBuildNextRuns() {
const next = vvCronNext(cron);
if (next) rows.push({ label, cron, next, diffMs: next - now });
});
// Custom scripts with their own cron
document.querySelectorAll('.vv-custom-card .vv-script').forEach(script => {
// Tools and custom scripts with their own cron
document.querySelectorAll('.vv-tools-card .vv-script, .vv-custom-card .vv-script').forEach(script => {
const enabled = script.querySelector('.vv-enabled')?.checked;
if (!enabled) return;
const cronEl = script.querySelector('input.vv-cron');