From 2c10ebe286726520dbf7eb058dc9f0601b0ade7b Mon Sep 17 00:00:00 2001 From: Flatlogic Bot Date: Wed, 25 Feb 2026 00:08:13 +0000 Subject: [PATCH] Uptime --- assets/pasted-20260225-000344-14072fd8.jpg | Bin 0 -> 11030 bytes index.php | 324 ++++++++------------- 2 files changed, 127 insertions(+), 197 deletions(-) create mode 100644 assets/pasted-20260225-000344-14072fd8.jpg diff --git a/assets/pasted-20260225-000344-14072fd8.jpg b/assets/pasted-20260225-000344-14072fd8.jpg new file mode 100644 index 0000000000000000000000000000000000000000..525a8bd435bed26a0bf53cce18c16ce7794d6eba GIT binary patch literal 11030 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 @@ -10,7 +11,7 @@ declare(strict_types=1); 𝐌𝐨𝐧𝐢𝐭𝐨𝐫 𝐔𝐩𝐭𝐢𝐦𝐞 𝐛𝐲 𝐘𝐮𝐦𝐞𝐞 - + @@ -25,7 +26,6 @@ declare(strict_types=1); --dark-sidebar: #1e2329; --text-main: #eaecef; --text-dim: #848e9c; - --neon-glow: 0 0 10px rgba(0, 255, 136, 0.5); --border: #2b3139; } @@ -54,14 +54,9 @@ declare(strict_types=1); z-index: 100; } - .sidebar-header { - padding: 1.5rem; - border-bottom: 1px solid var(--border); - } - + .sidebar-header { padding: 1.5rem; border-bottom: 1px solid var(--border); } .sidebar-header h1 { - font-size: 1.1rem; - margin: 0; + font-size: 1.1rem; margin: 0; background: linear-gradient(90deg, #fff, var(--crypto-blue)); -webkit-background-clip: text; -webkit-text-fill-color: transparent; @@ -86,149 +81,75 @@ declare(strict_types=1); } /* Main Content */ - main { - flex: 1; - display: flex; - flex-direction: column; - overflow-y: auto; - } - + main { flex: 1; display: flex; flex-direction: column; overflow-y: auto; } .top-bar { - height: 60px; - border-bottom: 1px solid var(--border); - display: flex; - align-items: center; - justify-content: space-between; - padding: 0 2rem; - background: var(--dark-bg); - position: sticky; - top: 0; - z-index: 99; + height: 60px; border-bottom: 1px solid var(--border); + display: flex; align-items: center; justify-content: space-between; + padding: 0 2rem; background: var(--dark-bg); + position: sticky; top: 0; z-index: 99; } - .content-area { padding: 2rem; max-width: 1400px; width: 100%; margin: 0 auto; } - /* Cards & Components */ - .dashboard-grid { - display: grid; - grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); - gap: 20px; - margin-bottom: 2rem; - } - - .card { - background: var(--dark-card); - border-radius: 12px; - padding: 1.5rem; - border: 1px solid var(--border); - position: relative; - } - + /* Cards */ + .dashboard-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 20px; margin-bottom: 2rem; } + .card { background: var(--dark-card); border-radius: 12px; padding: 1.5rem; border: 1px solid var(--border); position: relative; } .stat-val { font-family: 'JetBrains Mono', monospace; font-size: 1.8rem; font-weight: 700; display: block; margin-top: 5px; } .stat-label { color: var(--text-dim); font-size: 0.8rem; text-transform: uppercase; letter-spacing: 1px; } - /* Battery Bars */ - .battery-container { display: flex; gap: 2px; height: 20px; margin-top: 10px; } - .battery-bar { flex: 1; background: #2b3139; border-radius: 2px; position: relative; } - .battery-bar.ok { background: var(--crypto-green); box-shadow: 0 0 5px rgba(0, 255, 136, 0.3); } - .battery-bar.err { background: var(--crypto-red); } - - /* Mobile Monitor Specific (CRYPTO STYLE) */ + /* Mobile Monitor Specific (CRYPTO CANDLE STYLE) */ #mobile-monitor { - position: fixed; - top: 0; left: 0; right: 0; bottom: 0; - background: #000; - z-index: 2000; - display: none; - flex-direction: column; - padding: 5px; + position: fixed; top: 0; left: 0; right: 0; bottom: 0; + background: #000; z-index: 2000; display: none; + flex-direction: column; padding: 4px; } #mobile-monitor.active { display: flex; } .mm-header { - display: flex; - justify-content: space-between; - align-items: center; - background: #111; - padding: 8px 12px; - border-radius: 8px; - margin-bottom: 5px; - } - .mm-grid { - display: grid; - grid-template-columns: 1fr; - gap: 5px; - flex: 1; - overflow-y: auto; + display: flex; justify-content: space-between; align-items: center; + background: #111; padding: 6px 10px; border-radius: 6px; margin-bottom: 4px; } + .mm-grid { display: grid; grid-template-columns: 1fr; gap: 4px; flex: 1; overflow-y: auto; } .mm-row { - background: #080808; - padding: 10px; - border-radius: 8px; - border: 1px solid #1a1a1a; - display: flex; - flex-direction: column; - gap: 5px; + background: #080808; padding: 8px; border-radius: 6px; + border: 1px solid #1a1a1a; display: flex; flex-direction: column; gap: 4px; } - .mm-info { - display: flex; - justify-content: space-between; - align-items: center; - font-family: 'JetBrains Mono'; - } - .mm-url-text { font-size: 0.6rem; color: #888; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 60%; } + .mm-info { display: flex; justify-content: space-between; align-items: center; font-family: 'JetBrains Mono'; } + .mm-url-text { font-size: 0.55rem; color: #aaa; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 70%; } .mm-lat-text { font-size: 0.7rem; font-weight: bold; } .mm-spark-container { - height: 60px; - width: 100%; - position: relative; - background: rgba(255,255,255,0.02); - border-radius: 4px; - overflow: hidden; - } - .mm-canvas { - position: absolute; - top: 0; left: 0; width: 100%; height: 100%; + height: 80px; width: 100%; position: relative; + background: #050505; border-radius: 4px; overflow: hidden; } + .mm-canvas { position: absolute; top: 0; left: 0; width: 100%; height: 100%; } - /* List Tables */ .data-table { width: 100%; border-collapse: collapse; } .data-table th { text-align: left; color: var(--text-dim); padding: 12px; border-bottom: 1px solid var(--border); font-size: 0.8rem; } .data-table td { padding: 12px; border-bottom: 1px solid var(--border); font-size: 0.9rem; } - .status-badge { padding: 4px 8px; border-radius: 4px; font-size: 0.7rem; font-weight: bold; text-transform: uppercase; } .bg-ok { background: rgba(0, 255, 136, 0.1); color: var(--crypto-green); } .bg-err { background: rgba(255, 51, 102, 0.1); color: var(--crypto-red); } - /* Inputs & Buttons */ - input, select { - background: #1e2329; - border: 1px solid var(--border); - color: #fff; - padding: 10px 12px; - border-radius: 4px; - outline: none; - width: 100%; - } - button { - padding: 10px 20px; - border-radius: 4px; - border: none; - font-weight: 700; - cursor: pointer; - transition: all 0.2s; - } + input, select { background: #1e2329; border: 1px solid var(--border); color: #fff; padding: 10px 12px; border-radius: 4px; outline: none; width: 100%; } + button { padding: 10px 20px; border-radius: 4px; border: none; font-weight: 700; cursor: pointer; transition: all 0.2s; } .btn-glow { background: var(--crypto-blue); color: #000; box-shadow: 0 0 15px rgba(0, 212, 255, 0.2); } - - /* Sections */ .section { display: none; } .section.active { display: block; } - /* Responsive */ + /* Floating Button for Mobile */ + .fab { + position: fixed; bottom: 20px; right: 20px; + width: 60px; height: 60px; border-radius: 50%; + background: var(--crypto-blue); color: #000; + display: none; align-items: center; justify-content: center; + box-shadow: 0 4px 20px rgba(0, 212, 255, 0.4); + z-index: 1000; cursor: pointer; font-size: 1.5rem; + } + @media (max-width: 768px) { aside { display: none; } .top-bar { padding: 0 1rem; } .content-area { padding: 1rem; } - .dashboard-grid { grid-template-columns: 1fr !important; } + .fab { display: flex; } + .top-candle-btn { display: flex !important; } } @@ -246,28 +167,31 @@ declare(strict_types=1);
- +
-
- [NETWORK HEALTH: 100%] [NODES ACTIVE: 12] +
+ +
+ [NET: 100%] +
-
- - 00:00:00 +
+ + 00:00:00
-
- Total Assets - 0 +
+ Click for Candle View + 0 Assets
Avg Latency @@ -279,14 +203,9 @@ declare(strict_types=1);
-
-

Asset Status (Battery View)

-
-
-

Latency Graph

- +
@@ -306,17 +225,19 @@ declare(strict_types=1);
-

Team Management

Manage your monitoring teams here.

-

API Keys

Generate keys for external integrations.

+

Team Management

Manage monitoring teams.

+

API Keys

External integrations.

- + +
🕯️
+
- REALTIME MONITOR + REALTIME CANDLES
@@ -324,9 +245,9 @@ declare(strict_types=1);
-
-
00:00:00
-
100% HEALTH
+
+
00:00:00
+
100% HEALTH
@@ -336,17 +257,32 @@ declare(strict_types=1); const sparklines = {}; class CryptoSparkline { - constructor(canvasId, initialData = []) { + constructor(canvasId) { this.canvas = document.getElementById(canvasId); this.ctx = this.canvas.getContext('2d'); - this.data = initialData.length ? initialData : Array(30).fill(0); - this.color = '#00ff88'; + this.data = []; + this.lastVal = Math.random() * 50 + 20; + // Pre-fill dummy data + for(let i=0; i<45; i++) { + this.addCandle(this.lastVal + (Math.random()*10-5), 'ok'); + } this.resize(); window.addEventListener('resize', () => this.resize()); } + addCandle(val, status) { + const open = this.lastVal; + const close = val; + const high = Math.max(open, close) + Math.random() * 4; + const low = Math.max(0, Math.min(open, close) - Math.random() * 4); + this.data.push({ open, close, high, low, ok: status === 'ok' }); + this.lastVal = val; + if (this.data.length > 55) this.data.shift(); + } + resize() { const rect = this.canvas.parentElement.getBoundingClientRect(); + if (!rect.width) return; this.canvas.width = rect.width * window.devicePixelRatio; this.canvas.height = rect.height * window.devicePixelRatio; this.ctx.scale(window.devicePixelRatio, window.devicePixelRatio); @@ -354,9 +290,7 @@ declare(strict_types=1); } update(val, status) { - this.data.push(val); - if (this.data.length > 50) this.data.shift(); - this.color = status === 'ok' ? '#00ff88' : '#ff3366'; + this.addCandle(val, status); this.draw(); } @@ -365,36 +299,47 @@ declare(strict_types=1); const h = this.canvas.height / window.devicePixelRatio; this.ctx.clearRect(0, 0, w, h); - if (this.data.length < 2) return; - - const min = Math.min(...this.data) * 0.8; - const max = Math.max(...this.data) * 1.2 || 100; - const range = max - min; - - this.ctx.beginPath(); - this.ctx.strokeStyle = this.color; - this.ctx.lineWidth = 2; - this.ctx.lineJoin = 'round'; - this.ctx.lineCap = 'round'; - - const step = w / (this.data.length - 1); - - for (let i = 0; i < this.data.length; i++) { - const x = i * step; - const y = h - ((this.data[i] - min) / range * h); - if (i === 0) this.ctx.moveTo(x, y); - else this.ctx.lineTo(x, y); + this.ctx.strokeStyle = '#111'; + this.ctx.lineWidth = 0.5; + for(let i=0; i [d.high, d.low]); + const minV = Math.min(...allVals) * 0.8; + const maxV = Math.max(...allVals) * 1.2 || 100; + const range = maxV - minV; + + const step = w / this.data.length; + const candleW = Math.max(2, step * 0.7); + + this.data.forEach((d, i) => { + const x = i * step + (step/2); + const color = d.ok ? '#00ff88' : '#ff3366'; + + const yO = h - ((d.open - minV) / range * h); + const yC = h - ((d.close - minV) / range * h); + const yH = h - ((d.high - minV) / range * h); + const yL = h - ((d.low - minV) / range * h); + + this.ctx.beginPath(); + this.ctx.strokeStyle = color; + this.ctx.lineWidth = 1; + this.ctx.moveTo(x, yH); + this.ctx.lineTo(x, yL); + this.ctx.stroke(); + + const bY = Math.min(yO, yC); + const bH = Math.max(1, Math.abs(yO - yC)); + + this.ctx.fillStyle = color; + this.ctx.fillRect(x - candleW/2, bY, candleW, bH); + }); } } @@ -419,6 +364,8 @@ declare(strict_types=1); function enterMobileMonitor() { document.getElementById('mobile-monitor').style.display = 'flex'; + // Force refresh sparklines + Object.values(sparklines).forEach(s => s.resize()); refreshData(); } @@ -428,7 +375,7 @@ declare(strict_types=1); } async function init() { - const resp = await fetch('api/uptime.php?action=settings'); + const resp = await fetch('api/uptime.php?action=settings&v='); const data = await resp.json(); isMonitoring = data.monitoring_enabled; updateStatusUI(); @@ -484,9 +431,9 @@ declare(strict_types=1); } async function refreshData() { - const statResp = await fetch('api/uptime.php?action=stats'); + const statResp = await fetch('api/uptime.php?action=stats&v='); const stats = await statResp.json(); - document.getElementById('stat-total').innerText = stats.total; + document.getElementById('stat-total').innerText = stats.total + ' Assets'; document.getElementById('stat-latency').innerText = Math.round(stats.avg_latency) + 'ms'; const health = stats.total > 0 ? ((stats.up / stats.total) * 100).toFixed(1) : 100; document.getElementById('stat-health').innerText = health + '%'; @@ -499,42 +446,25 @@ declare(strict_types=1); mainChart.update('none'); } - const listResp = await fetch('api/uptime.php?action=list'); + const listResp = await fetch('api/uptime.php?action=list&v='); const assets = await listResp.json(); const inventory = document.getElementById('inventory-list'); - const batteryRows = document.getElementById('battery-rows'); const mmCryptoGrid = document.getElementById('mm-crypto-grid'); inventory.innerHTML = ''; - batteryRows.innerHTML = ''; assets.forEach(u => { const isOk = u.last_status === 'ok'; inventory.innerHTML += `${u.url}${u.last_status}${u.last_latency}ms`; - // Dashboard Battery Rows - const brow = document.createElement('div'); - brow.style.marginBottom = '10px'; - brow.innerHTML = `
${u.url}${u.last_latency}ms
`; - const bcont = document.createElement('div'); - bcont.className = 'battery-container'; - for(let i=0; i<24; i++) { - const b = document.createElement('div'); - b.className = 'battery-bar' + (isOk ? ' ok' : ' err'); - bcont.appendChild(b); - } - brow.appendChild(bcont); - batteryRows.appendChild(brow); - - // Mobile Crypto Grid if (!document.getElementById(`mm-row-${u.id}`)) { const mrow = document.createElement('div'); mrow.id = `mm-row-${u.id}`; mrow.className = 'mm-row'; mrow.innerHTML = `
- ${u.url.split('//')[1]} + ${u.url.replace('https://','').replace('http://','')} ${u.last_latency}ms