SIMON Master Console Rebuild
True command center for SIMON + WEB360
This rebuild gives you a cleaner production spine: interactive tree, live viewer, guarded editor, dynamic graphics, architecture map, and note storage. It is designed to sit beside your existing
console.php
and become the stronger replacement path.
Dashboard
Tree
Viewer
System Map
File Registry
Notes
Files
15,338
Folders
408
Scanned Size
3.84 GB
PHP Files
890
Editable Text Files
12,599
File viewer
guarded to /htdocs
/live/jobs_dashboard.php
<?php declare(strict_types=1); require __DIR__ . '/job_engine.php'; $status = simon_jobs_status(); $feeds = $status['feeds']; $runs = $status['runs']; $due = count(array_filter($feeds, fn($f) => !empty($f['due']))); $ok = count(array_filter($feeds, fn($f) => ($f['ok'] ?? null) === true)); $bad = count(array_filter($feeds, fn($f) => ($f['ok'] ?? null) === false)); function h($s){ return htmlspecialchars((string)$s, ENT_QUOTES, 'UTF-8'); } ?> <!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>SIMON Jobs</title> <style> :root{--bg:#05041a;--panel:#10102c;--panel2:#171744;--line:rgba(75,227,255,.22);--text:#eaf2ff;--muted:#9aa3c4;--cyan:#4be3ff;--green:#7cff9e;--red:#ff6b8f;--amber:#ffb347;--vio:#7a5cff}*{box-sizing:border-box}body{margin:0;background:radial-gradient(900px 500px at 10% 0%,rgba(122,92,255,.22),transparent),linear-gradient(180deg,#05041a,#07062a);color:var(--text);font:14px/1.45 system-ui,-apple-system,Segoe UI,sans-serif}.wrap{max-width:1240px;margin:0 auto;padding:24px}a{color:var(--cyan)}.top{display:flex;gap:12px;align-items:center;justify-content:space-between;flex-wrap:wrap}.brand{font-size:28px;font-weight:900;letter-spacing:-.03em}.sub{color:var(--muted)}.cards{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:12px;margin:18px 0}.card,.panel{background:linear-gradient(180deg,rgba(18,16,58,.88),rgba(10,8,30,.92));border:1px solid var(--line);border-radius:18px;box-shadow:0 18px 48px rgba(0,0,0,.35)}.card{padding:16px}.n{font-size:32px;font-weight:900}.l{color:var(--muted);text-transform:uppercase;font-size:11px;letter-spacing:.12em}.actions{display:flex;gap:8px;flex-wrap:wrap}.btn{border:1px solid var(--line);background:linear-gradient(90deg,var(--cyan),var(--vio));color:#06051b;border-radius:999px;padding:9px 14px;font-weight:800;text-decoration:none;cursor:pointer}.btn.ghost{background:transparent;color:var(--text)}table{width:100%;border-collapse:collapse}.panel{overflow:hidden;margin:16px 0}th,td{padding:10px 12px;border-bottom:1px solid rgba(255,255,255,.07);text-align:left;vertical-align:top}th{font-size:11px;text-transform:uppercase;letter-spacing:.12em;color:var(--muted);background:rgba(255,255,255,.03)}tr:hover td{background:rgba(75,227,255,.04)}.pill{display:inline-flex;border:1px solid rgba(255,255,255,.12);border-radius:999px;padding:3px 8px;font-size:11px}.ok{color:var(--green)}.bad{color:var(--red)}.due{color:var(--amber)}.muted{color:var(--muted)}.small{font-size:12px}.mono{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}.toast{position:fixed;right:18px;bottom:18px;max-width:420px;background:#090820;border:1px solid var(--line);border-radius:14px;padding:12px 14px;display:none;white-space:pre-wrap}.toast.on{display:block}@media(max-width:800px){.cards{grid-template-columns:repeat(2,1fr)}.wrap{padding:14px}table{font-size:12px}} </style></head><body><div class="wrap"> <div class="top"><div><div class="brand">SIMON Jobs · Scheduler</div><div class="sub">Phase 5 · background feed refresh, cached snapshots, run logs</div></div><div class="actions"><a class="btn ghost" href="index.php">Dashboard</a><a class="btn ghost" href="feed_manager.php">Feed Manager</a><a class="btn ghost" href="graph_dashboard.php">Graph</a><button class="btn" onclick="runJobs(false)">Run Due</button><button class="btn" onclick="runJobs(true)">Force All</button></div></div> <div class="cards"><div class="card"><div class="n"><?=count($feeds)?></div><div class="l">Feeds</div></div><div class="card"><div class="n due"><?=$due?></div><div class="l">Due Now</div></div><div class="card"><div class="n ok"><?=$ok?></div><div class="l">Last OK</div></div><div class="card"><div class="n bad"><?=$bad?></div><div class="l">Last Failed</div></div></div> <div class="panel"><table><thead><tr><th>Feed</th><th>Status</th><th>Cadence</th><th>Last Run</th><th>Next Run</th><th>Items</th><th>Action</th></tr></thead><tbody> <?php foreach ($feeds as $f): ?><tr><td><b><?=h($f['name'])?></b><br><span class="muted small mono"><?=h($f['id'])?> · <?=h($f['engine'])?> · <?=h($f['category'])?></span></td><td><?php if(!$f['enabled']): ?><span class="pill muted">disabled</span><?php elseif($f['ok']===true): ?><span class="pill ok">ok</span><?php elseif($f['ok']===false): ?><span class="pill bad">failed</span><br><span class="small muted"><?=h($f['error'])?></span><?php else: ?><span class="pill muted">never run</span><?php endif; ?> <?php if($f['due']): ?><span class="pill due">due</span><?php endif; ?></td><td><?=h($f['refresh'])?>s</td><td class="small"><?=h($f['lastRunAt'] ?? '—')?><br><span class="muted"><?=h($f['ms'] ?? '')?>ms</span></td><td class="small"><?=h($f['nextRunAt'] ?? '—')?></td><td><?=h($f['count'] ?? 0)?></td><td><button class="btn ghost" onclick="runFeed('<?=h($f['id'])?>')">Run</button></td></tr><?php endforeach; ?> </tbody></table></div> <div class="panel"><table><thead><tr><th>Recent Runs</th><th>Summary</th></tr></thead><tbody><?php foreach(array_slice($runs,0,20) as $r): ?><tr><td class="mono small"><?=h($r['at'] ?? '')?><br><?=h($r['runId'] ?? '')?></td><td>ran <?=h($r['ran'] ?? 0)?> · ok <?=h($r['ok'] ?? 0)?> · failed <?=h($r['failed'] ?? 0)?> · skipped <?=h($r['skipped'] ?? 0)?> · items <?=h($r['totalItems'] ?? 0)?></td></tr><?php endforeach; ?></tbody></table></div> <div class="panel" style="padding:16px"><b>Cron URL</b><p class="muted">Use this URL from IONOS cron, EasyCron, or any uptime monitor every 5 minutes:</p><pre class="mono" style="white-space:pre-wrap;background:rgba(255,255,255,.04);padding:12px;border-radius:12px">https://www.gaylordsinclair.com/connlink/test1/ui/job_runner.php?action=run_due&limit=20</pre><p class="muted">Instant cached feed endpoint:</p><pre class="mono" style="white-space:pre-wrap;background:rgba(255,255,255,.04);padding:12px;border-radius:12px">/connlink/test1/ui/feed_proxy_cached.php?limit=100</pre></div> </div><div class="toast" id="toast"></div><script> const toast=t=>{const el=document.getElementById('toast');el.textContent=t;el.classList.add('on');setTimeout(()=>el.classList.remove('on'),4500)}; async function runJobs(force){toast('Running jobs...'); const r=await fetch('job_runner.php?action=run_due&limit=50'+(force?'&force=1':'')); const j=await r.json(); toast(JSON.stringify(j.summary||j,null,2)); setTimeout(()=>location.reload(),1000)} async function runFeed(id){toast('Running '+id+'...'); const r=await fetch('job_runner.php?action=run_due&feed='+encodeURIComponent(id)+'&force=1'); const j=await r.json(); toast(JSON.stringify(j.summary||j,null,2)); setTimeout(()=>location.reload(),1000)} </script></body></html>
Save file
Quick jump
open a path
Open