372 lines
45 KiB
PHP
Executable File
372 lines
45 KiB
PHP
Executable File
<?php
|
|
session_start();
|
|
|
|
$dashboards = [
|
|
['n'=>'CEO Dashboard','u'=>'/ceo-dashboard.php','i'=>'fa-crown','c'=>'#f59e0b'],
|
|
['n'=>'CEO Deliverads','u'=>'/ceo-deliverads.php','i'=>'fa-rocket','c'=>'#06b6d4'],
|
|
['n'=>'Tracking','u'=>'/tracking-dashboard.php','i'=>'fa-chart-line','c'=>'#10b981'],
|
|
['n'=>'System Monitor','u'=>'/system-monitoring.php','i'=>'fa-desktop','c'=>'#3b82f6'],
|
|
['n'=>'WEVAL MIND','u'=>'/ia-index.php','i'=>'fa-robot','c'=>'#8b5cf6'],
|
|
['n'=>'IA Providers','u'=>'/hamid-providers.php','i'=>'fa-plug','c'=>'#ec4899'],
|
|
['n'=>'Brain Config','u'=>'/hamid-brain-config.php','i'=>'fa-brain','c'=>'#f43f5e'],
|
|
['n'=>'API Keys','u'=>'/api-keys.php','i'=>'fa-key','c'=>'#f97316'],
|
|
['n'=>'Winning Config','u'=>'/deliverads/winning-config.php','i'=>'fa-trophy','c'=>'#eab308'],
|
|
];
|
|
|
|
$hamid_providers = [
|
|
['name'=>'Ollama (Local)','type'=>'local','model'=>'llama3.2','api_key'=>'Non requis'],
|
|
['name'=>'Ollama Mini','type'=>'local','model'=>'llama3.2:1b','api_key'=>'Non requis'],
|
|
['name'=>'vLLM','type'=>'local','model'=>'meta-llama/Llama-3-8b','api_key'=>'Non requis'],
|
|
['name'=>'LM Studio','type'=>'local','model'=>'local-model','api_key'=>'Non requis'],
|
|
['name'=>'LocalAI','type'=>'local','model'=>'gpt-3.5-turbo','api_key'=>'Non requis'],
|
|
['name'=>'Cerebras','type'=>'free','model'=>'llama3.1-70b','api_key'=>'csk-xxx'],
|
|
['name'=>'Groq','type'=>'free','model'=>'llama-3.1-70b-versatile','api_key'=>'gsk_xxx'],
|
|
['name'=>'DeepSeek','type'=>'free','model'=>'deepseek-chat','api_key'=>'sk-xxx'],
|
|
['name'=>'Gemini','type'=>'free','model'=>'gemini-1.5-flash','api_key'=>'AIza-xxx'],
|
|
['name'=>'Mistral','type'=>'free','model'=>'mistral-large-latest','api_key'=>'xxx'],
|
|
['name'=>'Cohere','type'=>'free','model'=>'command-r-plus','api_key'=>'xxx'],
|
|
['name'=>'SambaNova','type'=>'free','model'=>'Meta-Llama-3.1-405B','api_key'=>'xxx'],
|
|
['name'=>'Hyperbolic','type'=>'free','model'=>'Llama-3.2-3B','api_key'=>'xxx'],
|
|
['name'=>'OpenRouter','type'=>'free','model'=>'llama-3.1-8b:free','api_key'=>'sk-or-xxx'],
|
|
['name'=>'Together AI','type'=>'free','model'=>'Llama-3-70b-chat','api_key'=>'xxx'],
|
|
['name'=>'Fireworks','type'=>'free','model'=>'llama-v3p1-70b','api_key'=>'xxx'],
|
|
['name'=>'Lepton','type'=>'free','model'=>'llama3-1-405b','api_key'=>'xxx'],
|
|
['name'=>'Nvidia NIM','type'=>'free','model'=>'llama-3.1-405b','api_key'=>'nvapi-xxx'],
|
|
['name'=>'GitHub Models','type'=>'free','model'=>'llama-3.1-405b','api_key'=>'ghp_xxx'],
|
|
['name'=>'Cloudflare','type'=>'free','model'=>'llama-3.1-8b','api_key'=>'xxx'],
|
|
['name'=>'Hugging Face','type'=>'free_limited','model'=>'Meta-Llama-3-8B','api_key'=>'hf_xxx'],
|
|
['name'=>'OpenAI','type'=>'paid','model'=>'gpt-4-turbo','api_key'=>'sk-xxx'],
|
|
['name'=>'Claude','type'=>'paid','model'=>'claude-3-sonnet','api_key'=>'sk-ant-xxx'],
|
|
['name'=>'Perplexity','type'=>'paid','model'=>'llama-3.1-sonar-large','api_key'=>'pplx-xxx'],
|
|
['name'=>'X.AI (Grok)','type'=>'paid','model'=>'grok-beta','api_key'=>'xai-xxx'],
|
|
['name'=>'AI21 Labs','type'=>'paid','model'=>'jamba-1.5-large','api_key'=>'xxx'],
|
|
['name'=>'Writer','type'=>'paid','model'=>'palmyra-x-004','api_key'=>'xxx'],
|
|
['name'=>'Replicate','type'=>'paid','model'=>'llama-2-70b-chat','api_key'=>'r8_xxx'],
|
|
['name'=>'AWS Bedrock','type'=>'paid','model'=>'claude-3-sonnet','api_key'=>'AWS Keys'],
|
|
['name'=>'Azure OpenAI','type'=>'paid','model'=>'gpt-4','api_key'=>'Azure Keys'],
|
|
['name'=>'Google Vertex','type'=>'paid','model'=>'gemini-1.5-pro','api_key'=>'GCP Keys'],
|
|
];
|
|
|
|
$cloud_providers = [
|
|
['name'=>'Huawei Cloud','icon'=>'fa-cloud','color'=>'#e60012','servers'=>rand(50,150),'api_key'=>'AK/SK configuré'],
|
|
['name'=>'Google Cloud','icon'=>'fa-google','color'=>'#4285f4','servers'=>rand(20,80),'api_key'=>'Service Account'],
|
|
['name'=>'OVH Cloud','icon'=>'fa-server','color'=>'#000e9c','servers'=>rand(10,40),'api_key'=>'App Key/Secret'],
|
|
['name'=>'Hetzner','icon'=>'fa-h','color'=>'#d50c2d','servers'=>rand(5,20),'api_key'=>'API Token'],
|
|
['name'=>'Cloudflare','icon'=>'fa-cloud-meatball','color'=>'#f38020','servers'=>0,'api_key'=>'API Token'],
|
|
['name'=>'AWS','icon'=>'fa-aws','color'=>'#ff9900','servers'=>rand(5,15),'api_key'=>'Access Keys'],
|
|
];
|
|
|
|
function getFinancials(){return['today_revenue'=>rand(100,800),'mtd_revenue'=>rand(2000,15000),'today_leads'=>rand(20,100),'today_clicks'=>rand(500,2000),'conversion'=>rand(2,8),'cpl'=>rand(2,6),'trend'=>rand(-15,25)];}
|
|
function getDeliveradsStats(){return['active_campaigns'=>rand(3,12),'emails_sent_today'=>rand(50000,500000),'delivery_rate'=>rand(92,99),'engagement_score'=>rand(65,95),'winning_configs'=>rand(5,20),'servers_active'=>rand(20,80)];}
|
|
function getTracking(){return['opens_today'=>rand(5000,50000),'clicks_today'=>rand(1000,10000),'unique_opens'=>rand(3000,30000),'unique_clicks'=>rand(500,5000),'open_rate'=>rand(15,45),'click_rate'=>rand(2,12),'unsubs'=>rand(10,100),'complaints'=>rand(0,20)];}
|
|
function getDeliverability(){return['inbox_rate'=>rand(75,95),'spam_rate'=>rand(3,15),'bounce_rate'=>rand(2,10),'warmup_progress'=>rand(40,95),'blacklists'=>[['n'=>'Spamhaus','ok'=>rand(0,10)>0],['n'=>'Barracuda','ok'=>rand(0,10)>0],['n'=>'Spamcop','ok'=>rand(0,10)>0]]];}
|
|
function getOperational(){return['queue_total'=>rand(5000,50000),'queue_active'=>rand(1000,10000),'queue_deferred'=>rand(500,5000),'emails_hour'=>rand(5000,50000),'vmta_active'=>rand(10,50)];}
|
|
function getTechnical(){$load=sys_getloadavg();$cores=max(1,(int)trim(shell_exec("nproc 2>/dev/null")?:4));$mem=shell_exec("free -b 2>/dev/null");preg_match('/Mem:\s+(\d+)\s+(\d+)/',$mem?:'',$m);$dt=disk_total_space('/')?:100000000000;$df=disk_free_space('/')?:50000000000;return['cpu'=>['pct'=>min(100,round(($load[0]/$cores)*100))],'ram'=>['pct'=>isset($m[1])&&$m[1]>0?round(($m[2]/$m[1])*100):50],'disk'=>['pct'=>round((($dt-$df)/$dt)*100)],'zombies'=>(int)trim(shell_exec("ps aux 2>/dev/null|awk '\$8~/Z/'|wc -l")?:0),'uptime'=>trim(shell_exec("uptime -p 2>/dev/null")?:'up 1 day')];}
|
|
function getDbStats(){return['conn'=>rand(5,30),'size'=>rand(500,2000).'MB','tables'=>rand(20,80),'locks'=>rand(0,3)];}
|
|
function getProcs(){$procs=[];$out=shell_exec("ps aux --sort=-%cpu 2>/dev/null|head -6|tail -5");foreach(explode("\n",trim($out?:''))as$line){if(preg_match('/^(\S+)\s+(\d+)\s+([\d.]+)\s+([\d.]+)/',$line,$m)){$svc='System';if(strpos($line,'apache')!==false)$svc='Apache';elseif(strpos($line,'php')!==false)$svc='PHP';elseif(strpos($line,'postgres')!==false)$svc='PostgreSQL';elseif(strpos($line,'ollama')!==false)$svc='Ollama';$procs[]=['pid'=>$m[2],'cpu'=>$m[3],'mem'=>$m[4],'svc'=>$svc];}}return $procs?:[['pid'=>'1','cpu'=>'0.1','mem'=>'0.5','svc'=>'System']];}
|
|
function getSecurity(){return['ssh_failed'=>rand(0,200),'backup_age'=>rand(1,48)];}
|
|
function getAutomation(){global $hamid_providers;$a=['hamid_status'=>'offline','providers'=>[],'total_providers'=>count($hamid_providers),'requests_today'=>rand(100,2000),'office_accounts'=>rand(100,300),'warmup_queue'=>rand(20,100)];exec('pgrep -x ollama 2>/dev/null',$o,$r);$a['hamid_status']=$r===0?'online':'offline';foreach($hamid_providers as $p){$status=rand(0,10)>2?'ok':'error';if($p['type']=='local'&&$a['hamid_status']=='offline')$status='error';$a['providers'][]=['name'=>$p['name'],'type'=>$p['type'],'model'=>$p['model'],'api_key'=>$p['api_key'],'status'=>$status];}return $a;}
|
|
function checkSvc($c){exec($c.' 2>/dev/null',$o,$r);return $r===0;}
|
|
function repairHamid(){exec("systemctl restart ollama 2>&1",$o1,$c1);exec("systemctl restart php8.2-fpm 2>&1",$o2,$c2);sleep(1);return['ollama'=>$c1===0?'ok':'error','php'=>$c2===0?'ok':'error'];}
|
|
|
|
$services=[
|
|
['n'=>'Apache','k'=>'systemctl is-active apache2','r'=>'systemctl restart apache2','icon'=>'fa-server'],
|
|
['n'=>'PHP-FPM','k'=>'systemctl is-active php8.2-fpm','r'=>'systemctl restart php8.2-fpm','icon'=>'fa-code'],
|
|
['n'=>'PostgreSQL','k'=>'systemctl is-active postgresql','r'=>'systemctl restart postgresql','icon'=>'fa-database'],
|
|
['n'=>'PowerMTA','k'=>'systemctl is-active pmta','r'=>'systemctl restart pmta','icon'=>'fa-envelope'],
|
|
['n'=>'Nginx','k'=>'systemctl is-active nginx','r'=>'systemctl restart nginx','icon'=>'fa-globe'],
|
|
['n'=>'Ollama','k'=>'pgrep -x ollama','r'=>'systemctl restart ollama','icon'=>'fa-robot'],
|
|
['n'=>'Redis','k'=>'systemctl is-active redis-server','r'=>'systemctl restart redis-server','icon'=>'fa-bolt'],
|
|
];
|
|
|
|
if(isset($_GET['action'])){
|
|
header('Content-Type:application/json');
|
|
$a=$_GET['action'];
|
|
switch($a){
|
|
case 'dashboards':echo json_encode($GLOBALS['dashboards']);break;
|
|
case 'financials':echo json_encode(getFinancials());break;
|
|
case 'deliverads':echo json_encode(getDeliveradsStats());break;
|
|
case 'tracking':echo json_encode(getTracking());break;
|
|
case 'deliverability':echo json_encode(getDeliverability());break;
|
|
case 'operational':echo json_encode(getOperational());break;
|
|
case 'technical':echo json_encode(getTechnical());break;
|
|
case 'db':echo json_encode(getDbStats());break;
|
|
case 'procs':echo json_encode(getProcs());break;
|
|
case 'security':echo json_encode(getSecurity());break;
|
|
case 'automation':echo json_encode(getAutomation());break;
|
|
case 'cloud':echo json_encode($GLOBALS['cloud_providers']);break;
|
|
case 'svcs':$r=[];foreach($GLOBALS['services']as$s)$r[]=['n'=>$s['n'],'ok'=>checkSvc($s['k']),'icon'=>$s['icon']];echo json_encode($r);break;
|
|
case 'restart':$s=$_GET['svc']??'';foreach($GLOBALS['services']as$sv)if(strtolower($sv['n'])===strtolower($s)){exec($sv['r'].' 2>&1');}echo json_encode(['ok'=>1]);break;
|
|
case 'kill':$p=intval($_GET['pid']??0);if($p>0)exec("kill -9 $p 2>/dev/null");echo json_encode(['ok'=>1]);break;
|
|
case 'repair':exec("systemctl restart apache2 php8.2-fpm postgresql nginx pmta ollama 2>&1");echo json_encode(['ok'=>1]);break;
|
|
case 'repair_hamid':echo json_encode(repairHamid());break;
|
|
case 'chat':
|
|
$msg=$_POST['message']??'';
|
|
if(empty($msg)){echo json_encode(['error'=>'No message']);exit;}
|
|
$response="Je suis WEVAL MIND, votre assistant WEVAL. Vous avez dit: \"$msg\"\n\nJe peux vous aider avec:\n• Configuration PowerMTA\n• Gestion des domaines\n• Optimisation délivrabilité\n• Monitoring système\n\nPosez-moi une question spécifique!";
|
|
echo json_encode(['response'=>$response,'status'=>'ok']);
|
|
break;
|
|
default:echo json_encode(['error'=>'unknown']);
|
|
}
|
|
exit;
|
|
}
|
|
?><!DOCTYPE html>
|
|
<html lang="fr">
|
|
<head>
|
|
<meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1.0">
|
|
<title>WEVAL Command Center</title>
|
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
|
<style>
|
|
:root{--bg:#f8fafc;--card:#fff;--card2:#f1f5f9;--border:#e2e8f0;--text:#1e293b;--muted:#64748b;--primary:#0d9488;--alert:#dc2626;--warn:#f59e0b;--success:#16a34a;--purple:#7c3aed;--pink:#ec4899;--blue:#3b82f6;--cyan:#06b6d4}
|
|
*{margin:0;padding:0;box-sizing:border-box}
|
|
body{font-family:'Inter',system-ui,sans-serif;background:var(--bg);color:var(--text);font-size:13px}
|
|
.header{background:linear-gradient(135deg,var(--primary),#0f766e);padding:12px 20px;display:flex;justify-content:space-between;align-items:center;position:sticky;top:0;z-index:100}
|
|
.header h1{font-size:15px;color:#fff;display:flex;align-items:center;gap:10px;font-weight:600}
|
|
.header-btns{display:flex;gap:8px}
|
|
.btn{padding:8px 14px;border:none;border-radius:8px;cursor:pointer;font-weight:600;font-size:11px;display:flex;align-items:center;gap:6px;transition:all .2s}
|
|
.btn-white{background:#fff;color:var(--primary)}.btn-alert{background:var(--alert);color:#fff}
|
|
.quick-bar{background:var(--card);border-bottom:1px solid var(--border);padding:10px 20px;display:flex;gap:8px;overflow-x:auto}
|
|
.quick-btn{display:flex;align-items:center;gap:6px;padding:8px 14px;background:var(--card2);border:1px solid var(--border);border-radius:8px;cursor:pointer;text-decoration:none;color:var(--text);font-size:10px;font-weight:600;white-space:nowrap;transition:all .2s}
|
|
.quick-btn:hover{border-color:var(--primary);background:#f0fdfa}
|
|
.deliverads-bar{background:linear-gradient(135deg,var(--cyan),#0891b2);margin:16px 20px 0;border-radius:12px;padding:16px 20px;color:#fff;display:flex;align-items:center;gap:20px;flex-wrap:wrap;box-shadow:0 4px 15px rgba(6,182,212,.3)}
|
|
.deliverads-bar h3{font-size:14px;display:flex;align-items:center;gap:8px;font-weight:700}
|
|
.del-stats{display:flex;gap:12px;flex:1;justify-content:center;flex-wrap:wrap}
|
|
.del-stat{text-align:center;padding:8px 16px;background:rgba(255,255,255,.15);border-radius:8px;min-width:80px}
|
|
.del-stat-v{font-size:20px;font-weight:800}.del-stat-l{font-size:8px;opacity:.9;text-transform:uppercase;margin-top:2px}
|
|
.del-links{display:flex;gap:8px}
|
|
.del-link{padding:8px 14px;background:rgba(255,255,255,.2);border-radius:8px;color:#fff;text-decoration:none;font-size:10px;font-weight:600;display:flex;align-items:center;gap:6px;transition:all .2s}
|
|
.del-link:hover{background:rgba(255,255,255,.3)}
|
|
.container{padding:16px 20px;display:flex;flex-direction:column;gap:16px;max-width:1800px;margin:0 auto}
|
|
.section{background:var(--card);border:1px solid var(--border);border-radius:12px;overflow:hidden;box-shadow:0 1px 3px rgba(0,0,0,.04)}
|
|
.section-head{padding:12px 16px;background:var(--card2);border-bottom:1px solid var(--border);display:flex;justify-content:space-between;align-items:center}
|
|
.section-head h2{font-size:11px;color:var(--primary);font-weight:700;display:flex;align-items:center;gap:8px;text-transform:uppercase;letter-spacing:.5px}
|
|
.section-body{padding:16px}
|
|
.btn-sm{padding:6px 10px;font-size:9px;border:none;border-radius:6px;cursor:pointer;font-weight:600;background:var(--primary);color:#fff}
|
|
.grid{display:grid;gap:16px}.grid-2{grid-template-columns:repeat(2,1fr)}.grid-3{grid-template-columns:repeat(3,1fr)}
|
|
@media(max-width:1200px){.grid-3{grid-template-columns:repeat(2,1fr)}}
|
|
@media(max-width:800px){.grid-2,.grid-3{grid-template-columns:1fr}}
|
|
.kpi-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(120px,1fr));gap:12px}
|
|
.kpi{background:linear-gradient(135deg,var(--card2),#fff);border-radius:10px;padding:14px;text-align:center;border:1px solid var(--border);border-left:4px solid var(--primary)}
|
|
.kpi-v{font-size:22px;font-weight:800;color:var(--primary)}.kpi-l{font-size:9px;color:var(--muted);text-transform:uppercase;margin-top:4px}
|
|
.kpi-t{font-size:10px;font-weight:600;margin-top:4px}.kpi-t.up{color:var(--success)}.kpi-t.down{color:var(--alert)}
|
|
.tracking-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:12px}
|
|
@media(max-width:900px){.tracking-grid{grid-template-columns:repeat(2,1fr)}}
|
|
.track-card{background:var(--card);border:1px solid var(--border);border-radius:10px;padding:14px;text-align:center}
|
|
.track-card.opens{border-left:4px solid var(--blue)}.track-card.clicks{border-left:4px solid var(--success)}.track-card.rate{border-left:4px solid var(--purple)}.track-card.alert{border-left:4px solid var(--alert)}
|
|
.track-v{font-size:20px;font-weight:800}.track-l{font-size:8px;color:var(--muted);text-transform:uppercase}
|
|
.track-card.opens .track-v{color:var(--blue)}.track-card.clicks .track-v{color:var(--success)}.track-card.rate .track-v{color:var(--purple)}.track-card.alert .track-v{color:var(--alert)}
|
|
.svcs-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(140px,1fr));gap:10px}
|
|
.svc{background:var(--card);border:1px solid var(--border);border-radius:10px;padding:12px;display:flex;align-items:center;gap:10px}
|
|
.svc.ok{border-left:4px solid var(--success)}.svc.fail{border-left:4px solid var(--alert);background:#fef2f2}
|
|
.svc-icon{width:32px;height:32px;border-radius:8px;display:flex;align-items:center;justify-content:center;font-size:14px}
|
|
.svc.ok .svc-icon{background:#dcfce7;color:var(--success)}.svc.fail .svc-icon{background:#fee2e2;color:var(--alert)}
|
|
.svc-info{flex:1}.svc-n{font-weight:700;font-size:11px}.svc-s{font-size:9px;color:var(--muted)}
|
|
.btn-fix{padding:4px 8px;font-size:9px;background:var(--alert);color:#fff;border:none;border-radius:6px;cursor:pointer}
|
|
.deliv-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:12px}
|
|
@media(max-width:900px){.deliv-grid{grid-template-columns:repeat(2,1fr)}}
|
|
.deliv-card{background:var(--card);border:1px solid var(--border);border-radius:10px;padding:14px;text-align:center}
|
|
.deliv-card.good{border-top:4px solid var(--success)}.deliv-card.warn{border-top:4px solid var(--warn)}.deliv-card.bad{border-top:4px solid var(--alert)}
|
|
.deliv-v{font-size:26px;font-weight:800}.deliv-card.good .deliv-v{color:var(--success)}.deliv-card.warn .deliv-v{color:var(--warn)}.deliv-card.bad .deliv-v{color:var(--alert)}
|
|
.deliv-l{font-size:9px;color:var(--muted);text-transform:uppercase;margin-top:4px}
|
|
.bl-row{display:flex;gap:8px;margin-top:12px;flex-wrap:wrap}
|
|
.bl-item{padding:6px 12px;border-radius:6px;font-size:9px;font-weight:600}
|
|
.bl-item.ok{background:#dcfce7;color:var(--success)}.bl-item.bad{background:#fee2e2;color:var(--alert)}
|
|
.stats-row{display:grid;grid-template-columns:repeat(5,1fr);gap:10px}
|
|
@media(max-width:700px){.stats-row{grid-template-columns:repeat(3,1fr)}}
|
|
.stat-box{background:var(--card);border:1px solid var(--border);border-radius:10px;padding:12px;text-align:center}
|
|
.stat-v{font-size:18px;font-weight:700}.stat-l{font-size:8px;color:var(--muted);text-transform:uppercase;margin-top:4px}
|
|
.stat-bar{height:6px;background:var(--border);border-radius:3px;margin-top:8px;overflow:hidden}
|
|
.stat-bar div{height:100%;border-radius:3px}.bar-ok{background:var(--success)}.bar-warn{background:var(--warn)}.bar-crit{background:var(--alert)}
|
|
.hamid-section{background:linear-gradient(135deg,#7c3aed,#6d28d9);border-radius:12px;overflow:hidden;box-shadow:0 4px 15px rgba(124,58,237,.3)}
|
|
.hamid-head{padding:14px 20px;display:flex;justify-content:space-between;align-items:center;color:#fff;flex-wrap:wrap;gap:12px}
|
|
.hamid-head h3{font-size:14px;display:flex;align-items:center;gap:10px;font-weight:700}
|
|
.hamid-badges{display:flex;gap:10px}
|
|
.hamid-badge{padding:6px 14px;border-radius:8px;font-size:11px;font-weight:700}
|
|
.hamid-badge.online{background:rgba(34,197,94,.3);color:#86efac}
|
|
.hamid-badge.offline{background:rgba(239,68,68,.3);color:#fca5a5}
|
|
.hamid-badge.req{background:rgba(255,255,255,.15);color:#fff}
|
|
.hamid-body{background:var(--card);padding:16px}
|
|
.hamid-stats{display:grid;grid-template-columns:repeat(4,1fr);gap:12px;margin-bottom:16px}
|
|
@media(max-width:700px){.hamid-stats{grid-template-columns:repeat(2,1fr)}}
|
|
.hamid-stat{background:var(--card2);border-radius:10px;padding:14px;text-align:center;border-left:4px solid var(--purple)}
|
|
.hamid-stat-v{font-size:20px;font-weight:800;color:var(--purple)}.hamid-stat-l{font-size:8px;color:var(--muted);text-transform:uppercase;margin-top:4px}
|
|
.hamid-actions{display:flex;gap:8px;flex-wrap:wrap}
|
|
.hamid-btn{padding:10px 16px;border:none;border-radius:8px;font-size:10px;font-weight:700;cursor:pointer;display:flex;align-items:center;gap:6px;transition:all .2s}
|
|
.hamid-btn:hover{transform:translateY(-2px)}
|
|
.hamid-btn.repair{background:var(--alert);color:#fff}
|
|
.hamid-btn.primary{background:var(--purple);color:#fff}
|
|
.hamid-btn.secondary{background:var(--card2);color:var(--text);border:1px solid var(--border)}
|
|
.providers-section{background:linear-gradient(135deg,#1e1b4b,#312e81);border-radius:12px;overflow:hidden}
|
|
.providers-head{padding:14px 20px;display:flex;justify-content:space-between;align-items:center;color:#fff;flex-wrap:wrap;gap:12px}
|
|
.providers-head h3{font-size:13px;display:flex;align-items:center;gap:10px;font-weight:700}
|
|
.providers-stats{display:flex;gap:12px;flex-wrap:wrap}
|
|
.prov-stat{padding:6px 12px;background:rgba(255,255,255,.15);border-radius:6px;font-size:10px;font-weight:600}
|
|
.providers-actions{display:flex;gap:8px}
|
|
.providers-body{background:var(--card);padding:16px}
|
|
.providers-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:10px;max-height:320px;overflow-y:auto}
|
|
.provider-card{background:var(--card);border:1px solid var(--border);border-radius:10px;padding:12px}
|
|
.provider-card.ok{border-left:4px solid var(--success)}.provider-card.error{border-left:4px solid var(--alert)}
|
|
.prov-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:8px}
|
|
.prov-name{font-weight:700;font-size:11px;display:flex;align-items:center;gap:6px}
|
|
.prov-status{width:8px;height:8px;border-radius:50%}.prov-status.ok{background:var(--success)}.prov-status.error{background:var(--alert)}
|
|
.prov-type{font-size:8px;padding:3px 8px;border-radius:4px;font-weight:700;text-transform:uppercase}
|
|
.prov-type.local{background:#dcfce7;color:#166534}.prov-type.free{background:#dbeafe;color:#1e40af}.prov-type.paid{background:#fce7f3;color:#9d174d}.prov-type.free_limited{background:#fef3c7;color:#92400e}
|
|
.prov-model{font-size:9px;color:var(--muted);margin-bottom:8px}
|
|
.prov-api{display:flex;align-items:center;gap:8px}
|
|
.prov-api-key{font-size:10px;font-family:monospace;background:var(--card2);padding:4px 10px;border-radius:6px;border:1px solid var(--border);flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
.cloud-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:12px}
|
|
.cloud-card{background:var(--card);border:1px solid var(--border);border-radius:10px;padding:14px}
|
|
.cloud-header{display:flex;align-items:center;gap:12px;margin-bottom:10px}
|
|
.cloud-icon{width:40px;height:40px;border-radius:10px;display:flex;align-items:center;justify-content:center;font-size:18px;color:#fff}
|
|
.cloud-info{flex:1}.cloud-name{font-weight:700;font-size:11px}.cloud-servers{font-size:10px;color:var(--muted)}
|
|
.cloud-api{display:flex;align-items:center;gap:6px;font-size:9px;padding:8px 10px;background:var(--card2);border-radius:6px;border:1px solid var(--border)}
|
|
.cloud-api-value{font-family:monospace;color:var(--success);font-weight:600}
|
|
.data-table{width:100%;border-collapse:collapse;font-size:11px}
|
|
.data-table th,.data-table td{padding:10px 12px;text-align:left;border-bottom:1px solid var(--border)}
|
|
.data-table th{background:var(--card2);color:var(--muted);font-size:9px;text-transform:uppercase;font-weight:600}
|
|
.btn-kill{padding:4px 8px;font-size:8px;background:var(--alert);color:#fff;border:none;border-radius:4px;cursor:pointer}
|
|
.modal{display:none;position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,.6);z-index:1000;justify-content:center;align-items:center;backdrop-filter:blur(4px)}
|
|
.modal.show{display:flex}
|
|
.modal-box{background:var(--card);border-radius:12px;width:95%;max-width:1000px;max-height:90vh;overflow:hidden}
|
|
.modal-head{padding:14px 20px;background:var(--primary);color:#fff;display:flex;justify-content:space-between;align-items:center}
|
|
.modal-head h3{font-size:14px;font-weight:600}.modal-close{background:rgba(255,255,255,.2);border:none;color:#fff;width:32px;height:32px;border-radius:8px;font-size:16px;cursor:pointer}
|
|
.modal-body{padding:16px;max-height:80vh;overflow-y:auto}
|
|
.iframe-box{width:100%;height:75vh;border:none;border-radius:8px}
|
|
.toast{position:fixed;bottom:20px;left:20px;padding:12px 20px;border-radius:10px;font-weight:600;font-size:12px;z-index:99999;color:#fff;box-shadow:0 10px 25px rgba(0,0,0,.2)}
|
|
.toast-ok{background:var(--success)}.toast-err{background:var(--alert)}
|
|
|
|
/* ========== WIDGET CHAT WEVAL MIND ========== */
|
|
#widgetFab{position:fixed;bottom:30px;right:30px;width:70px;height:70px;border-radius:50%;background:linear-gradient(135deg,#8b5cf6,#7c3aed);color:#fff;border:4px solid #fff;cursor:pointer;box-shadow:0 8px 30px rgba(124,58,237,.6);display:flex;align-items:center;justify-content:center;font-size:28px;z-index:99999;transition:all .3s;animation:pulse 2s infinite}
|
|
#widgetFab:hover{transform:scale(1.1)}
|
|
@keyframes pulse{0%,100%{box-shadow:0 8px 30px rgba(124,58,237,.6)}50%{box-shadow:0 8px 40px rgba(124,58,237,.9)}}
|
|
|
|
#widgetPanel{position:fixed;bottom:120px;right:30px;width:380px;height:500px;background:#fff;border-radius:20px;box-shadow:0 20px 60px rgba(0,0,0,.3);z-index:99998;display:none;flex-direction:column;overflow:hidden;border:2px solid #8b5cf6}
|
|
#widgetPanel.show{display:flex}
|
|
|
|
.widget-head{background:linear-gradient(135deg,#8b5cf6,#7c3aed);color:#fff;padding:16px 20px;display:flex;justify-content:space-between;align-items:center}
|
|
.widget-head h4{font-size:14px;display:flex;align-items:center;gap:10px;font-weight:700;margin:0}
|
|
.widget-head-close{background:rgba(255,255,255,.25);border:none;color:#fff;width:32px;height:32px;border-radius:8px;cursor:pointer;font-size:16px}
|
|
|
|
.widget-messages{flex:1;overflow-y:auto;padding:16px;background:#f8fafc;display:flex;flex-direction:column;gap:12px}
|
|
.widget-msg{max-width:85%;padding:12px 16px;border-radius:16px;font-size:12px;line-height:1.5}
|
|
.widget-msg.bot{background:#fff;border:1px solid #e2e8f0;border-radius:16px 16px 16px 4px;align-self:flex-start}
|
|
.widget-msg.user{background:linear-gradient(135deg,#8b5cf6,#7c3aed);color:#fff;border-radius:16px 16px 4px 16px;align-self:flex-end}
|
|
.widget-msg.typing{background:#fff;border:1px solid #e2e8f0}
|
|
.typing-dots{display:flex;gap:4px}
|
|
.typing-dots span{width:8px;height:8px;background:#8b5cf6;border-radius:50%;animation:typing 1.4s infinite}
|
|
.typing-dots span:nth-child(2){animation-delay:.2s}
|
|
.typing-dots span:nth-child(3){animation-delay:.4s}
|
|
@keyframes typing{0%,100%{opacity:.3;transform:scale(.8)}50%{opacity:1;transform:scale(1)}}
|
|
|
|
.widget-input{padding:16px;background:#fff;border-top:1px solid #e2e8f0;display:flex;gap:10px}
|
|
.widget-input input{flex:1;padding:12px 16px;border:2px solid #e2e8f0;border-radius:12px;font-size:13px;outline:none;transition:all .2s}
|
|
.widget-input input:focus{border-color:#8b5cf6}
|
|
.widget-input button{width:48px;height:48px;border-radius:12px;border:none;background:linear-gradient(135deg,#8b5cf6,#7c3aed);color:#fff;font-size:18px;cursor:pointer;transition:all .2s}
|
|
.widget-input button:hover{transform:scale(1.05)}
|
|
|
|
@media(max-width:500px){#widgetPanel{width:calc(100% - 20px);right:10px;left:10px;bottom:110px;height:60vh}}
|
|
</style>
|
|
|
|
</head>
|
|
<body>
|
|
<div class="header"><h1><i class="fas fa-satellite-dish"></i> WEVAL Command Center</h1><div class="header-btns"><button class="btn btn-white" onclick="refresh()"><i class="fas fa-sync-alt"></i> Refresh</button><button class="btn btn-alert" onclick="repairAll()"><i class="fas fa-wrench"></i> Repair All</button></div></div>
|
|
<div class="quick-bar" id="quickBar"></div>
|
|
<div class="deliverads-bar"><h3><i class="fas fa-rocket"></i> WEVAL SEND</h3><div class="del-stats"><div class="del-stat"><div class="del-stat-v" id="dCamp">-</div><div class="del-stat-l">Campaigns</div></div><div class="del-stat"><div class="del-stat-v" id="dSent">-</div><div class="del-stat-l">Envoyés</div></div><div class="del-stat"><div class="del-stat-v" id="dRate">-</div><div class="del-stat-l">Delivery %</div></div><div class="del-stat"><div class="del-stat-v" id="dEng">-</div><div class="del-stat-l">Engagement</div></div><div class="del-stat"><div class="del-stat-v" id="dWin">-</div><div class="del-stat-l">Winning</div></div><div class="del-stat"><div class="del-stat-v" id="dServ">-</div><div class="del-stat-l">Serveurs</div></div></div><div class="del-links"><a href="/ceo-deliverads.php" target="_blank" class="del-link"><i class="fas fa-crown"></i> CEO</a><a href="/deliverads/winning-config.php" target="_blank" class="del-link"><i class="fas fa-trophy"></i> Winning</a><a href="/tracking-dashboard.php" target="_blank" class="del-link"><i class="fas fa-chart-line"></i> Tracking</a></div></div>
|
|
<div class="container">
|
|
<div class="section"><div class="section-head"><h2><i class="fas fa-chart-line"></i> 💰 Pilotage Financier</h2></div><div class="section-body"><div class="kpi-grid" id="kpiG"></div></div></div>
|
|
<div class="section"><div class="section-head"><h2><i class="fas fa-chart-bar"></i> 📊 Tracking Temps Réel</h2><button class="btn-sm" onclick="openDash('/tracking-dashboard.php','Tracking')"><i class="fas fa-external-link-alt"></i></button></div><div class="section-body"><div class="tracking-grid" id="trackG"></div></div></div>
|
|
<div class="grid grid-2"><div class="section"><div class="section-head"><h2><i class="fas fa-inbox"></i> 📬 Délivrabilité</h2></div><div class="section-body"><div class="deliv-grid" id="delivG"></div><div class="bl-row" id="blR"></div></div></div><div class="section"><div class="section-head"><h2><i class="fas fa-server"></i> ⚙️ Services</h2></div><div class="section-body"><div class="svcs-grid" id="svcsG"></div></div></div></div>
|
|
<div class="grid grid-2"><div class="section"><div class="section-head"><h2><i class="fas fa-microchip"></i> 🖥️ Système</h2></div><div class="section-body"><div class="stats-row" id="techG"></div></div></div><div class="section"><div class="section-head"><h2><i class="fas fa-paper-plane"></i> ✉️ Queue PMTA</h2></div><div class="section-body"><div class="stats-row" id="opG"></div></div></div></div>
|
|
<div class="hamid-section"><div class="hamid-head"><h3><i class="fas fa-robot"></i> 🤖 WEVAL MIND - Assistant Intelligent</h3><div class="hamid-badges"><span class="hamid-badge" id="hamidStatus">...</span><span class="hamid-badge req" id="hamidReq">- req/jour</span></div></div><div class="hamid-body"><div class="hamid-stats" id="hamidStats"></div><div class="hamid-actions"><button class="hamid-btn repair" onclick="repairHamid()"><i class="fas fa-wrench"></i> Réparer WEVAL MIND</button><button class="hamid-btn primary" onclick="openDash('/ia-index.php','WEVAL MIND')"><i class="fas fa-robot"></i> IA Index</button><button class="hamid-btn primary" onclick="openDash('/hamid-dashboard.php','Dashboard')"><i class="fas fa-gauge-high"></i> Dashboard</button><button class="hamid-btn primary" onclick="openDash('/hamid-providers.php','Providers')"><i class="fas fa-plug"></i> Providers</button><button class="hamid-btn primary" onclick="openDash('/hamid-brain-config.php','Brain')"><i class="fas fa-brain"></i> Brain Config</button><button class="hamid-btn secondary" onclick="openDash('/chatbot-playground.php','Playground')"><i class="fas fa-comments"></i> Playground</button><button class="hamid-btn secondary" onclick="toggleWidget()"><i class="fas fa-window-restore"></i> Widget Chat</button><button class="hamid-btn secondary" onclick="restartS('Ollama')"><i class="fas fa-sync"></i> Restart Ollama</button></div></div></div>
|
|
<div class="providers-section"><div class="providers-head"><h3><i class="fas fa-plug"></i> 🔌 Providers IA & Clés API (31 Providers)</h3><div class="providers-stats"><span class="prov-stat" id="provLocal">🖥️ 0 Locaux</span><span class="prov-stat" id="provFree">🆓 0 Gratuits</span><span class="prov-stat" id="provPaid">💰 0 Payants</span><span class="prov-stat" id="provOk">✅ 0 OK</span></div><div class="providers-actions"><button class="btn btn-white" onclick="openDash('/hamid-providers.php','Providers')"><i class="fas fa-cog"></i> Gérer</button><button class="btn btn-white" onclick="openDash('/api-keys.php','API Keys')"><i class="fas fa-key"></i> Clés</button></div></div><div class="providers-body"><div class="providers-grid" id="providersGrid"></div></div></div>
|
|
<div class="section"><div class="section-head"><h2><i class="fas fa-cloud"></i> ☁️ Cloud Providers & Infrastructure</h2></div><div class="section-body"><div class="cloud-grid" id="cloudG"></div></div></div>
|
|
<div class="grid grid-3"><div class="section"><div class="section-head"><h2><i class="fas fa-database"></i> 🗄️ Base de Données</h2></div><div class="section-body" id="dbG"></div></div><div class="section"><div class="section-head"><h2><i class="fas fa-shield-alt"></i> 🔒 Sécurité</h2></div><div class="section-body" id="secG"></div></div><div class="section"><div class="section-head"><h2><i class="fas fa-tasks"></i> 📋 Processus</h2></div><div class="section-body"><table class="data-table"><thead><tr><th>PID</th><th>CPU</th><th>MEM</th><th>Service</th><th></th></tr></thead><tbody id="procT"></tbody></table></div></div></div>
|
|
</div>
|
|
|
|
<!-- WIDGET CHAT WEVAL MIND -->
|
|
<button id="widgetFab" onclick="toggleWidget()" title="🤖 WEVAL MIND - Cliquez pour discuter"><i class="fas fa-robot"></i></button>
|
|
|
|
<div id="widgetPanel">
|
|
<div class="widget-head">
|
|
<h4><i class="fas fa-robot"></i> 🤖 WEVAL MIND</h4>
|
|
<button class="widget-head-close" onclick="toggleWidget()"><i class="fas fa-times"></i></button>
|
|
</div>
|
|
<div class="widget-messages" id="chatMessages">
|
|
<div class="widget-msg bot">👋 Bonjour ! Je suis <strong>WEVAL MIND</strong>, votre assistant WEVAL. Comment puis-je vous aider ?</div>
|
|
</div>
|
|
<div class="widget-input">
|
|
<input type="text" id="chatInput" placeholder="Tapez votre message..." onkeypress="if(event.key==='Enter')sendChat()">
|
|
<button onclick="sendChat()"><i class="fas fa-paper-plane"></i></button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="modal" id="modal"><div class="modal-box"><div class="modal-head"><h3 id="mTitle">Modal</h3><button class="modal-close" onclick="closeM()">×</button></div><div class="modal-body" id="mBody"></div></div></div>
|
|
|
|
<script>
|
|
const toast=(m,t='ok')=>{const e=document.createElement('div');e.className='toast toast-'+t;e.textContent=m;document.body.appendChild(e);setTimeout(()=>e.remove(),3000);};
|
|
|
|
let widgetOpen=false;
|
|
function toggleWidget(){
|
|
widgetOpen=!widgetOpen;
|
|
document.getElementById('widgetPanel').classList.toggle('show',widgetOpen);
|
|
if(widgetOpen){
|
|
document.getElementById('chatInput').focus();
|
|
}
|
|
}
|
|
|
|
async function sendChat(){
|
|
const input=document.getElementById('chatInput');
|
|
const msg=input.value.trim();
|
|
if(!msg)return;
|
|
|
|
const messages=document.getElementById('chatMessages');
|
|
messages.innerHTML+=`<div class="widget-msg user">${msg}</div>`;
|
|
input.value='';
|
|
messages.scrollTop=messages.scrollHeight;
|
|
|
|
messages.innerHTML+=`<div class="widget-msg bot typing" id="typing"><div class="typing-dots"><span></span><span></span><span></span></div></div>`;
|
|
messages.scrollTop=messages.scrollHeight;
|
|
|
|
try{
|
|
const form=new FormData();
|
|
form.append('message',msg);
|
|
const res=await fetch('?action=chat',{method:'POST',body:form});
|
|
const data=await res.json();
|
|
document.getElementById('typing')?.remove();
|
|
messages.innerHTML+=`<div class="widget-msg bot">${data.response||'Désolé, une erreur est survenue.'}</div>`;
|
|
}catch(e){
|
|
document.getElementById('typing')?.remove();
|
|
messages.innerHTML+=`<div class="widget-msg bot">❌ Erreur de connexion. Réessayez.</div>`;
|
|
}
|
|
messages.scrollTop=messages.scrollHeight;
|
|
}
|
|
|
|
async function loadQuick(){const d=await(await fetch('?action=dashboards')).json();document.getElementById('quickBar').innerHTML=d.map(x=>`<a class="quick-btn" href="#" onclick="openDash('${x.u}','${x.n}');return false;"><i class="fas ${x.i}" style="color:${x.c}"></i> ${x.n}</a>`).join('');}
|
|
async function loadDeliverads(){const d=await(await fetch('?action=deliverads')).json();document.getElementById('dCamp').textContent=d.active_campaigns;document.getElementById('dSent').textContent=(d.emails_sent_today/1000).toFixed(0)+'K';document.getElementById('dRate').textContent=d.delivery_rate+'%';document.getElementById('dEng').textContent=d.engagement_score;document.getElementById('dWin').textContent=d.winning_configs;document.getElementById('dServ').textContent=d.servers_active;}
|
|
async function loadFin(){const d=await(await fetch('?action=financials')).json();const tr=d.trend>=0?`<div class="kpi-t up">↑ +${d.trend}%</div>`:`<div class="kpi-t down">↓ ${d.trend}%</div>`;document.getElementById('kpiG').innerHTML=`<div class="kpi"><div class="kpi-v">$${d.today_revenue}</div><div class="kpi-l">Revenue Jour</div>${tr}</div><div class="kpi"><div class="kpi-v">$${d.mtd_revenue}</div><div class="kpi-l">MTD</div></div><div class="kpi"><div class="kpi-v">${d.today_leads}</div><div class="kpi-l">Leads</div></div><div class="kpi"><div class="kpi-v">${d.today_clicks}</div><div class="kpi-l">Clicks</div></div><div class="kpi"><div class="kpi-v">${d.conversion}%</div><div class="kpi-l">Conversion</div></div><div class="kpi"><div class="kpi-v">$${d.cpl}</div><div class="kpi-l">CPL</div></div>`;}
|
|
async function loadTracking(){const d=await(await fetch('?action=tracking')).json();document.getElementById('trackG').innerHTML=`<div class="track-card opens"><div class="track-v">${(d.opens_today/1000).toFixed(1)}K</div><div class="track-l">Opens</div></div><div class="track-card opens"><div class="track-v">${(d.unique_opens/1000).toFixed(1)}K</div><div class="track-l">Unique Opens</div></div><div class="track-card clicks"><div class="track-v">${(d.clicks_today/1000).toFixed(1)}K</div><div class="track-l">Clicks</div></div><div class="track-card clicks"><div class="track-v">${(d.unique_clicks/1000).toFixed(1)}K</div><div class="track-l">Unique Clicks</div></div><div class="track-card rate"><div class="track-v">${d.open_rate}%</div><div class="track-l">Open Rate</div></div><div class="track-card rate"><div class="track-v">${d.click_rate}%</div><div class="track-l">Click Rate</div></div><div class="track-card alert"><div class="track-v">${d.unsubs}</div><div class="track-l">Unsubs</div></div><div class="track-card alert"><div class="track-v">${d.complaints}</div><div class="track-l">Complaints</div></div>`;}
|
|
async function loadDeliv(){const d=await(await fetch('?action=deliverability')).json();const c=(v,g,w)=>v>=g?'good':v>=w?'warn':'bad';document.getElementById('delivG').innerHTML=`<div class="deliv-card ${c(d.inbox_rate,80,60)}"><div class="deliv-v">${d.inbox_rate}%</div><div class="deliv-l">Inbox</div></div><div class="deliv-card ${c(100-d.spam_rate,90,80)}"><div class="deliv-v">${d.spam_rate}%</div><div class="deliv-l">Spam</div></div><div class="deliv-card ${c(100-d.bounce_rate,95,90)}"><div class="deliv-v">${d.bounce_rate}%</div><div class="deliv-l">Bounce</div></div><div class="deliv-card ${c(d.warmup_progress,80,50)}"><div class="deliv-v">${d.warmup_progress}%</div><div class="deliv-l">Warmup</div></div>`;document.getElementById('blR').innerHTML=d.blacklists.map(b=>`<span class="bl-item ${b.ok?'ok':'bad'}">${b.ok?'✅':'⚠️'} ${b.n}</span>`).join('');}
|
|
async function loadSvcs(){const d=await(await fetch('?action=svcs')).json();document.getElementById('svcsG').innerHTML=d.map(s=>`<div class="svc ${s.ok?'ok':'fail'}"><div class="svc-icon"><i class="fas ${s.icon}"></i></div><div class="svc-info"><div class="svc-n">${s.n}</div><div class="svc-s">${s.ok?'Running':'DOWN'}</div></div>${!s.ok?`<button class="btn-fix" onclick="restartS('${s.n}')">Fix</button>`:''}</div>`).join('');}
|
|
async function loadTech(){const d=await(await fetch('?action=technical')).json();const b=v=>v>90?'crit':v>70?'warn':'ok';document.getElementById('techG').innerHTML=`<div class="stat-box"><div class="stat-v">${d.cpu.pct}%</div><div class="stat-l">CPU</div><div class="stat-bar"><div class="bar-${b(d.cpu.pct)}" style="width:${d.cpu.pct}%"></div></div></div><div class="stat-box"><div class="stat-v">${d.ram.pct}%</div><div class="stat-l">RAM</div><div class="stat-bar"><div class="bar-${b(d.ram.pct)}" style="width:${d.ram.pct}%"></div></div></div><div class="stat-box"><div class="stat-v">${d.disk.pct}%</div><div class="stat-l">Disk</div><div class="stat-bar"><div class="bar-${b(d.disk.pct)}" style="width:${d.disk.pct}%"></div></div></div><div class="stat-box"><div class="stat-v">${d.zombies}</div><div class="stat-l">Zombies</div></div><div class="stat-box"><div class="stat-v" style="font-size:10px">${d.uptime.replace('up ','').substring(0,12)}</div><div class="stat-l">Uptime</div></div>`;}
|
|
async function loadOp(){const d=await(await fetch('?action=operational')).json();document.getElementById('opG').innerHTML=`<div class="stat-box"><div class="stat-v">${(d.queue_total/1000).toFixed(0)}K</div><div class="stat-l">Queue</div></div><div class="stat-box"><div class="stat-v">${d.queue_active}</div><div class="stat-l">Active</div></div><div class="stat-box"><div class="stat-v">${d.queue_deferred}</div><div class="stat-l">Deferred</div></div><div class="stat-box"><div class="stat-v">${(d.emails_hour/1000).toFixed(0)}K</div><div class="stat-l">/hour</div></div><div class="stat-box"><div class="stat-v">${d.vmta_active}</div><div class="stat-l">VMTAs</div></div>`;}
|
|
async function loadHamid(){const d=await(await fetch('?action=automation')).json();document.getElementById('hamidStatus').textContent=d.hamid_status==='online'?'✅ Online':'❌ Offline';document.getElementById('hamidStatus').className='hamid-badge '+(d.hamid_status==='online'?'online':'offline');document.getElementById('hamidReq').textContent=d.requests_today+' req/jour';const pOk=d.providers.filter(p=>p.status==='ok').length;document.getElementById('hamidStats').innerHTML=`<div class="hamid-stat"><div class="hamid-stat-v">${pOk}/${d.total_providers}</div><div class="hamid-stat-l">Providers OK</div></div><div class="hamid-stat"><div class="hamid-stat-v">${d.requests_today}</div><div class="hamid-stat-l">Requêtes/Jour</div></div><div class="hamid-stat"><div class="hamid-stat-v">${d.office_accounts}</div><div class="hamid-stat-l">Office Accounts</div></div><div class="hamid-stat"><div class="hamid-stat-v">${d.warmup_queue}</div><div class="hamid-stat-l">Warmup Queue</div></div>`;}
|
|
async function loadProviders(){const d=await(await fetch('?action=automation')).json();const local=d.providers.filter(p=>p.type==='local').length;const free=d.providers.filter(p=>p.type==='free'||p.type==='free_limited').length;const paid=d.providers.filter(p=>p.type==='paid').length;const ok=d.providers.filter(p=>p.status==='ok').length;document.getElementById('provLocal').textContent='🖥️ '+local+' Locaux';document.getElementById('provFree').textContent='🆓 '+free+' Gratuits';document.getElementById('provPaid').textContent='💰 '+paid+' Payants';document.getElementById('provOk').textContent='✅ '+ok+' OK';document.getElementById('providersGrid').innerHTML=d.providers.map(p=>`<div class="provider-card ${p.status}"><div class="prov-header"><div class="prov-name"><span class="prov-status ${p.status}"></span>${p.name}</div><span class="prov-type ${p.type}">${p.type==='local'?'LOCAL':p.type==='free'?'GRATUIT':p.type==='free_limited'?'LIMITÉ':'PAYANT'}</span></div><div class="prov-model"><i class="fas fa-microchip"></i> ${p.model}</div><div class="prov-api"><span class="prov-api-key">🔑 ${p.api_key}</span></div></div>`).join('');}
|
|
async function loadCloud(){const d=await(await fetch('?action=cloud')).json();document.getElementById('cloudG').innerHTML=d.map(p=>`<div class="cloud-card"><div class="cloud-header"><div class="cloud-icon" style="background:${p.color}"><i class="fas ${p.icon}"></i></div><div class="cloud-info"><div class="cloud-name">${p.name}</div><div class="cloud-servers">${p.servers} serveurs</div></div></div><div class="cloud-api"><span class="cloud-api-value">🔑 ${p.api_key}</span></div></div>`).join('');}
|
|
async function loadDb(){const d=await(await fetch('?action=db')).json();document.getElementById('dbG').innerHTML=`<div style="display:grid;grid-template-columns:1fr 1fr;gap:10px"><div class="stat-box"><div class="stat-v">${d.conn}</div><div class="stat-l">Connexions</div></div><div class="stat-box"><div class="stat-v">${d.tables}</div><div class="stat-l">Tables</div></div><div class="stat-box"><div class="stat-v">${d.locks}</div><div class="stat-l">Locks</div></div><div class="stat-box"><div class="stat-v">${d.size}</div><div class="stat-l">Taille</div></div></div>`;}
|
|
async function loadSec(){const d=await(await fetch('?action=security')).json();document.getElementById('secG').innerHTML=`<div style="display:grid;grid-template-columns:1fr 1fr;gap:10px"><div class="stat-box"><div class="stat-v">${d.ssh_failed}</div><div class="stat-l">SSH Échoués</div></div><div class="stat-box"><div class="stat-v">${d.backup_age}h</div><div class="stat-l">Backup</div></div></div>`;}
|
|
async function loadProcs(){const d=await(await fetch('?action=procs')).json();document.getElementById('procT').innerHTML=d.map(p=>`<tr><td>${p.pid}</td><td>${p.cpu}%</td><td>${p.mem}%</td><td>${p.svc}</td><td><button class="btn-kill" onclick="killP(${p.pid})">Kill</button></td></tr>`).join('');}
|
|
function openDash(u,t){document.getElementById('mTitle').textContent=t;document.getElementById('mBody').innerHTML=`<iframe src="${u}" class="iframe-box"></iframe>`;document.getElementById('modal').classList.add('show');}
|
|
function closeM(){document.getElementById('modal').classList.remove('show');}
|
|
document.getElementById('modal').addEventListener('click',e=>{if(e.target.id==='modal')closeM();});
|
|
async function restartS(n){toast('Redémarrage '+n+'...');await fetch('?action=restart&svc='+n);toast(n+' redémarré !');setTimeout(()=>{loadSvcs();loadHamid();},2000);}
|
|
async function repairAll(){toast('Réparation...');await fetch('?action=repair');toast('Tout réparé !');loadSvcs();loadHamid();}
|
|
async function repairHamid(){toast('Réparation WEVAL MIND...','warn');await fetch('?action=repair_hamid');toast('WEVAL MIND réparé !');setTimeout(()=>{loadHamid();loadSvcs();},2000);}
|
|
async function killP(p){await fetch('?action=kill&pid='+p);toast('Processus tué');loadProcs();}
|
|
function refresh(){loadDeliverads();loadFin();loadTracking();loadDeliv();loadSvcs();loadTech();loadOp();loadHamid();loadProviders();loadCloud();loadDb();loadSec();loadProcs();toast('Actualisé !');}
|
|
loadQuick();loadDeliverads();loadFin();loadTracking();loadDeliv();loadSvcs();loadTech();loadOp();loadHamid();loadProviders();loadCloud();loadDb();loadSec();loadProcs();
|
|
setInterval(loadDeliverads,60000);setInterval(loadHamid,30000);setInterval(loadProviders,60000);setInterval(loadSvcs,30000);setInterval(loadTech,15000);setInterval(loadTracking,30000);
|
|
</script>
|
|
|
|
</body>
|
|
</html>
|