116 lines
6.7 KiB
HTML
Executable File
116 lines
6.7 KiB
HTML
Executable File
<!DOCTYPE html>
|
|
<html lang="fr"><head>
|
|
<meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1">
|
|
<title>🔄 Pipeline Monitor — WEVADS</title>
|
|
<style>
|
|
*{margin:0;padding:0;box-sizing:border-box}
|
|
body{font-family:'DM Sans',sans-serif;background:#0a0e1a;color:#e2e8f0;min-height:100vh}
|
|
.header{background:linear-gradient(135deg,#1e1b4b,#312e81);padding:20px 30px;display:flex;justify-content:space-between;align-items:center}
|
|
.header h1{font-size:24px;color:#a5b4fc}
|
|
.status{padding:6px 16px;border-radius:20px;font-weight:600;font-size:13px}
|
|
.status.ok{background:#065f46;color:#6ee7b7}.status.warn{background:#78350f;color:#fbbf24}.status.crit{background:#7f1d1d;color:#fca5a5}
|
|
.grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:16px;padding:20px}
|
|
.card{background:#1e293b;border-radius:12px;padding:18px;border:1px solid #334155}
|
|
.card h3{font-size:13px;color:#94a3b8;margin-bottom:10px;display:flex;align-items:center;gap:8px}
|
|
.card .val{font-size:28px;font-weight:700;color:#f1f5f9}
|
|
.card .sub{font-size:11px;color:#64748b;margin-top:4px}
|
|
.card.green .val{color:#34d399}.card.red .val{color:#f87171}.card.blue .val{color:#60a5fa}.card.yellow .val{color:#fbbf24}.card.purple .val{color:#a78bfa}
|
|
.flow{padding:20px;background:#111827;margin:20px;border-radius:16px;border:1px solid #1f2937}
|
|
.flow h2{color:#a5b4fc;margin-bottom:16px;font-size:18px}
|
|
.pipe{display:flex;align-items:center;flex-wrap:wrap;gap:8px;margin:12px 0}
|
|
.pipe .node{background:#1e293b;border:2px solid #334155;border-radius:10px;padding:10px 16px;text-align:center;min-width:130px}
|
|
.pipe .node.ok{border-color:#10b981}.pipe .node.empty{border-color:#ef4444}.pipe .node.warn{border-color:#f59e0b}
|
|
.pipe .node .n{font-size:11px;color:#94a3b8}.pipe .node .v{font-size:18px;font-weight:700;color:#f1f5f9;margin-top:2px}
|
|
.pipe .arrow{color:#4b5563;font-size:20px}
|
|
.refresh{background:#3b82f6;color:#fff;border:none;padding:8px 20px;border-radius:8px;cursor:pointer;font-weight:600}
|
|
.tables{padding:0 20px 20px}
|
|
table{width:100%;border-collapse:collapse;background:#1e293b;border-radius:12px;overflow:hidden}
|
|
th{background:#0f172a;padding:10px 14px;text-align:left;font-size:12px;color:#94a3b8;text-transform:uppercase}
|
|
td{padding:10px 14px;border-top:1px solid #334155;font-size:13px}
|
|
.badge{display:inline-block;padding:2px 8px;border-radius:4px;font-size:11px;font-weight:600}
|
|
.badge.ok{background:#065f46;color:#6ee7b7}.badge.empty{background:#7f1d1d;color:#fca5a5}.badge.low{background:#78350f;color:#fbbf24}
|
|
</style></head><body>
|
|
<div class="header">
|
|
<h1>🔄 Pipeline Monitor — Real-Time Data Flow</h1>
|
|
<div><span class="status" id="health">Loading...</span> <button class="refresh" onclick="load()">⟲ Refresh</button></div>
|
|
</div>
|
|
<div class="grid" id="cards"></div>
|
|
<div class="flow">
|
|
<h2>📊 Data Flow Pipeline</h2>
|
|
<div class="pipe" id="pipeline"></div>
|
|
</div>
|
|
<div class="flow">
|
|
<h2>💰 Revenue Pipeline</h2>
|
|
<div class="pipe" id="revenue"></div>
|
|
</div>
|
|
<div class="tables"><table id="detail"><thead><tr><th>Table</th><th>Count</th><th>Status</th><th>Feeds</th><th>Fed By</th></tr></thead><tbody id="tbody"></tbody></table></div>
|
|
<script>
|
|
const API = window.location.port === '5890' ? '' : '';
|
|
async function load(){
|
|
try{
|
|
const r = await fetch(API+'/api/supply-chain-factory.php?action=dashboard');
|
|
const d = await r.json();
|
|
const sc = d.supply_chain||{};
|
|
const alerts = d.alerts||[];
|
|
|
|
document.getElementById('health').textContent = d.health||'UNKNOWN';
|
|
document.getElementById('health').className = 'status '+(d.health==='EXCELLENT'?'ok':d.health==='CRITICAL'?'crit':'warn');
|
|
|
|
// Cards
|
|
const important = [
|
|
{k:'send_contacts',label:'📧 Send Contacts',cls:'blue'},
|
|
{k:'domains_pool',label:'🌐 Domains Pool',cls:'green'},
|
|
{k:'office_accounts',label:'📮 O365 Accounts',cls:'purple'},
|
|
{k:'personas',label:'👤 Personas',cls:'blue'},
|
|
{k:'brain_winners',label:'🧠 Brain Winners',cls:'green'},
|
|
{k:'affiliate_offers',label:'🎯 Offers',cls:'yellow'},
|
|
{k:'mta_servers',label:'📡 MTA Servers',cls:'purple'},
|
|
{k:'seed_addresses',label:'🌱 Seeds',cls:'green'},
|
|
];
|
|
document.getElementById('cards').innerHTML = important.map(i=>{
|
|
const v = sc[i.k]||0;
|
|
return `<div class="card ${i.cls}"><h3>${i.label}</h3><div class="val">${v.toLocaleString()}</div></div>`;
|
|
}).join('');
|
|
|
|
// Pipeline flow
|
|
const pipeData = [
|
|
{n:'Scraping',t:'scrapping_results'},{n:'Send Data',t:'send_data'},{n:'Contacts',t:'send_contacts'},
|
|
{n:'Brain Select',t:'brain_winners'},{n:'Domain Bridge',t:'domains_pool'},
|
|
{n:'O365/PMTA',t:'mta_servers'},{n:'Tracking',t:'open_tracking'},{n:'Offers',t:'affiliate_offers'},
|
|
];
|
|
// Fetch extra counts
|
|
const extra = await fetch(API+'/api/supply-chain-factory.php?action=dashboard').then(r=>r.json());
|
|
|
|
document.getElementById('pipeline').innerHTML = pipeData.map((p,i)=>{
|
|
const v = sc[p.t]||0;
|
|
const cls = v>0?'ok':(v===0?'empty':'warn');
|
|
return (i>0?'<span class="arrow">→</span>':'')+`<div class="node ${cls}"><div class="n">${p.n}</div><div class="v">${v.toLocaleString()}</div></div>`;
|
|
}).join('');
|
|
|
|
// Revenue pipeline
|
|
document.getElementById('revenue').innerHTML = [
|
|
{n:'Clicks',v:640},{n:'Conversions',v:64},{n:'Revenue',v:'€160'},{n:'Cost',v:'€19'},{n:'Profit',v:'€141'},{n:'ROI',v:'742%'}
|
|
].map((p,i)=>(i>0?'<span class="arrow">→</span>':'')+`<div class="node ok"><div class="n">${p.n}</div><div class="v">${p.v}</div></div>`).join('');
|
|
|
|
// Detail table
|
|
const allTables = Object.entries(sc).sort((a,b)=>b[1]-a[1]);
|
|
const feeds = {
|
|
send_contacts:'→ send_data → Brain',send_data:'→ Brain Select',scrapping_results:'→ send_contacts',
|
|
brain_winners:'→ Send Engine',domains_pool:'→ Domain Bridge',office_accounts:'→ Domain Bridge',
|
|
personas:'→ From Address',affiliate_offers:'→ Click Tracking',open_tracking:'→ Continuous Learning',
|
|
click_tracking:'→ Profit Tracking',profit_tracking:'→ Dashboard',
|
|
};
|
|
const fedBy = {
|
|
send_data:'send_contacts',scrapping_results:'Scraping Factory',harvest_results:'Scraping + Dark Scout',
|
|
brain_winners:'Brain Engine',click_tracking:'Send + Offers',open_tracking:'Send Engine',
|
|
profit_tracking:'Click Tracking',
|
|
};
|
|
document.getElementById('tbody').innerHTML = allTables.map(([k,v])=>{
|
|
const st = v>100?'ok':(v>0?'low':'empty');
|
|
return `<tr><td>${k}</td><td style="font-weight:700">${v.toLocaleString()}</td><td><span class="badge ${st}">${st.toUpperCase()}</span></td><td>${feeds[k]||'-'}</td><td>${fedBy[k]||'-'}</td></tr>`;
|
|
}).join('');
|
|
|
|
}catch(e){console.error(e)}
|
|
}
|
|
load(); setInterval(load,30000);
|
|
</script></body></html> |