224 lines
17 KiB
HTML
224 lines
17 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="fr"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1">
|
||
<title>WEVAL L99 Command Center</title>
|
||
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;600;800&display=swap" rel="stylesheet">
|
||
<style>
|
||
*{margin:0;padding:0;box-sizing:border-box}body{font-family:'JetBrains Mono',monospace;background:#0a0e1a;color:#e2e8f0;min-height:100vh}
|
||
.w{max-width:1400px;margin:0 auto;padding:16px}.hdr{background:linear-gradient(135deg,#6d28d9,#4338ca);border-radius:16px;padding:24px;margin-bottom:16px;display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:12px}
|
||
.hdr h1{font-size:20px;font-weight:800}.hdr .s{font-size:11px;opacity:0.7}
|
||
.btn{padding:10px 22px;border-radius:8px;border:2px solid rgba(255,255,255,.3);background:rgba(255,255,255,.12);color:#fff;font-size:12px;font-weight:700;cursor:pointer;font-family:inherit}
|
||
.metrics{display:flex;gap:10px;flex-wrap:wrap;margin-bottom:16px}.m{background:#111827;border:1px solid #1e293b;border-radius:10px;padding:12px 16px;text-align:center;flex:1;min-width:90px}
|
||
.m .v{font-size:24px;font-weight:800}.m .l{font-size:9px;color:#64748b;margin-top:2px}.g{color:#10b981}.r{color:#ef4444}.y{color:#f59e0b}.b{color:#3b82f6}.p{color:#8b5cf6}
|
||
.tabs{display:flex;gap:6px;margin-bottom:16px;flex-wrap:wrap}.tab{padding:7px 16px;border-radius:8px;border:none;cursor:pointer;font-size:11px;font-weight:600;font-family:inherit;background:#1e293b;color:#64748b}.tab.a{background:#8b5cf6;color:#fff}
|
||
.card{background:#111827;border:1px solid #1e293b;border-radius:12px;padding:16px;margin-bottom:12px}.card h3{font-size:13px;margin-bottom:10px;color:#a5b4fc}
|
||
table{width:100%;border-collapse:collapse}th,td{text-align:left;padding:5px 10px;border-bottom:1px solid #1e293b;font-size:11px}th{color:#64748b}
|
||
.grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(360px,1fr));gap:12px}.grid3{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:10px}
|
||
.vc{background:#111827;border:1px solid #1e293b;border-radius:12px;overflow:hidden}.vc h4{font-size:12px;color:#a5b4fc;padding:10px 12px 6px}.vc video{width:100%;display:block;background:#000}.vc .info{padding:6px 12px 10px;font-size:10px;color:#64748b}
|
||
.sc{background:#111827;border:1px solid #1e293b;border-radius:10px;overflow:hidden;cursor:pointer}.sc img{width:100%;display:block;background:#0a0e1a;min-height:60px}.sc .sn{padding:4px 8px;font-size:9px;color:#94a3b8;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
||
.bar{height:5px;border-radius:3px;transition:width .5s}.overlay{position:fixed;inset:0;background:rgba(0,0,0,.9);z-index:9999;display:flex;align-items:center;justify-content:center;cursor:pointer}.overlay img{max-width:95vw;max-height:95vh;border-radius:8px}
|
||
.ft{text-align:center;padding:16px;font-size:9px;color:#475569}
|
||
</style></head><body>
|
||
<div class="w">
|
||
<div class="hdr"><div><h1 id="title">L99 COMMAND CENTER</h1><div class="s">Lean Six Sigma | Playwright | Self-Healing</div><div class="s" id="info">Chargement...</div></div>
|
||
<div style="display:flex;gap:10px;align-items:center"><div id="sigma" style="font-size:28px;font-weight:800">--</div><button class="btn" onclick="runL99()">Lancer L99</button> <a href="/wevia.html" id="wevia-chat-link" style="margin-left:10px;padding:8px 16px;background:#22c55e;color:#fff;border-radius:8px;text-decoration:none;font-weight:bold">WEVIA Chat</a></div></div>
|
||
<div class="metrics" id="met"></div>
|
||
<div class="tabs" id="tabs"></div>
|
||
<div id="ct"><div class="card"><h3>Chargement...</h3></div></div>
|
||
</div>
|
||
<div class="ft">WEVAL L99 v7 | /opt/weval-l99/ | Playwright | 3 Serveurs | 21 Apps</div>
|
||
<script>
|
||
var API='/api/l99-api.php';
|
||
var D=null,V=[],S=[],TAB='overview';
|
||
|
||
function init(){
|
||
Promise.all([
|
||
fetch(API+'?action=results').then(function(r){return r.json()}),
|
||
fetch(API+'?action=videos').then(function(r){return r.json()}),
|
||
fetch(API+'?action=screenshots').then(function(r){return r.json()})
|
||
]).then(function(arr){
|
||
D=arr[0];V=arr[1].videos||[];S=arr[2].screenshots||[];
|
||
render();
|
||
}).catch(function(e){
|
||
document.getElementById('ct').innerHTML='<div class="card"><h3>Erreur: '+e.message+'</h3></div>';
|
||
})
|
||
}
|
||
|
||
function render(){
|
||
if(!D||D.error){document.getElementById('ct').innerHTML='<div class="card"><h3>'+(D&&D.error?D.error:'Lancez python3 /opt/weval-l99/l99-master.py')+'</h3></div>';return}
|
||
var p=D.pass||0,f=D.fail||0,w=D.warn||0,t=D.total||0,pct=t?p/t*100:0;
|
||
var sig=(3.4+Math.max(0,(pct-90))*.1).toFixed(1);
|
||
document.getElementById('info').textContent=t+' tests | '+V.length+' videos | '+S.length+' screenshots | '+(D.timestamp||'').substring(0,19);
|
||
document.getElementById('sigma').textContent=sig+'s';
|
||
document.getElementById('sigma').style.color=sig>=4.5?'#10b981':sig>=3.5?'#f59e0b':'#ef4444';
|
||
document.getElementById('met').innerHTML='<div class="m"><div class="v g">'+p+'</div><div class="l">PASS</div></div><div class="m"><div class="v r">'+f+'</div><div class="l">FAIL</div></div><div class="m"><div class="v y">'+w+'</div><div class="l">WARN</div></div><div class="m"><div class="v">'+t+'</div><div class="l">TOTAL</div></div><div class="m"><div class="v '+(pct>=95?'g':pct>=90?'y':'r')+'">'+pct.toFixed(0)+'%</div><div class="l">SCORE</div></div><div class="m"><div class="v b">'+V.length+'</div><div class="l">VIDEOS</div></div><div class="m"><div class="v p">'+S.length+'</div><div class="l">SCREENSHOTS</div></div>';
|
||
var tabList=[['overview','Overview'],['tests','Tests ('+t+')'],['videos','Videos ('+V.length+')'],['screenshots','Screenshots ('+S.length+')'],['cc','Command Centers'],['history','Historique'],['exec','Execution']];
|
||
document.getElementById('tabs').innerHTML=tabList.map(function(tb){return '<button class="tab'+(TAB===tb[0]?' a':'')+'" onclick="TAB=\''+tb[0]+'\';render()">'+tb[1]+'</button>'}).join('');
|
||
var C=document.getElementById('ct');
|
||
if(TAB==='overview')showOverview(C);
|
||
else if(TAB==='tests')showTests(C);
|
||
else if(TAB==='videos')showVideos(C);
|
||
else if(TAB==='screenshots')showSS(C);
|
||
else if(TAB==='cc')showCC(C);
|
||
else if(TAB==='history')showHistory(C);
|
||
else if(TAB==='exec')showExec(C);
|
||
}
|
||
|
||
function showOverview(C){
|
||
var layers={};
|
||
(D.tests||[]).forEach(function(t){var l=t.layer;if(!layers[l])layers[l]={P:0,F:0,W:0};layers[l][t.status]=(layers[l][t.status]||0)+1});
|
||
var lr='',fr='';
|
||
Object.keys(layers).sort().forEach(function(l){var d=layers[l],tot=d.P+d.F+(d.W||0),pct=tot?d.P/tot*100:0;var col=d.F===0?'#10b981':d.F<=1?'#f59e0b':'#ef4444';lr+='<tr><td>'+(d.F===0?'OK':d.F<=1?'WARN':'FAIL')+' '+l+'</td><td style="font-weight:700;color:'+col+'">'+d.P+'/'+tot+'</td><td><div style="background:#1e293b;border-radius:3px;height:5px"><div class="bar" style="width:'+pct+'%;background:'+col+'"></div></div></td><td style="color:'+(d.F?'#ef4444':'#64748b')+'">'+(d.F?d.F+'F':'-')+'</td></tr>'});
|
||
(D.tests||[]).filter(function(t){return t.status==='F'}).forEach(function(t){fr+='<tr><td style="color:#64748b">'+t.layer+'</td><td>FAIL '+t.test+'</td><td style="color:#64748b;max-width:200px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap">'+(t.detail||'')+'</td></tr>'});
|
||
if(!fr)fr='<tr><td colspan=3 style="text-align:center;color:#10b981;padding:20px">Zero failures!</td></tr>';
|
||
C.innerHTML='<div class="grid"><div class="card"><h3>Layers</h3><table><tr><th>Layer</th><th>Score</th><th></th><th></th></tr>'+lr+'</table></div><div class="card"><h3>Failures</h3><table>'+fr+'</table></div></div>'
|
||
}
|
||
|
||
function showTests(C){
|
||
var tests=D.tests||[];
|
||
var html='<div class="card"><div style="max-height:600px;overflow-y:auto"><table>';
|
||
tests.forEach(function(t){html+='<tr><td style="color:#64748b;width:50px">'+t.layer+'</td><td>'+(t.status==='P'?'OK':t.status==='F'?'FAIL':'WARN')+' '+t.test+'</td><td style="color:#64748b;max-width:200px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap">'+(t.detail||'')+'</td></tr>'});
|
||
html+='</table></div></div>';
|
||
C.innerHTML=html
|
||
}
|
||
|
||
function showVideos(C){
|
||
if(!V.length){C.innerHTML='<div class="card"><h3>Aucune video</h3></div>';return}
|
||
var html='<div class="grid">';
|
||
V.forEach(function(v){html+='<div class="vc"><h4>'+v.name+'</h4><video controls preload="metadata"><source src="'+v.url+'" type="video/webm"></video><div class="info">'+v.size_h+'</div></div>'});
|
||
html+='</div>';
|
||
C.innerHTML=html
|
||
}
|
||
|
||
function showSS(C){
|
||
if(!S.length){C.innerHTML='<div class="card"><h3>Aucun screenshot</h3></div>';return}
|
||
var html='<div class="grid3">';
|
||
S.forEach(function(s){html+='<div class="sc" onclick="openImg(\''+s.url+'\')"><img src="'+s.url+'" loading="lazy"><div class="sn">'+s.name+'</div></div>'});
|
||
html+='</div>';
|
||
C.innerHTML=html
|
||
}
|
||
|
||
function showCC(C){
|
||
var ccLinks=[
|
||
{t:'Command Center',u:'/command-center.html',d:'Dashboard principal'},
|
||
{t:'Mega CC',u:'/mega-command-center.html',d:'Vue 360 tous serveurs'},
|
||
{t:'Arsenal CC',u:'http://10.1.0.3:5890/command-center.html',d:'WEVADS Arsenal S95'},
|
||
{t:'Blade AI',u:'/blade-ai.html',d:'IA souveraine'},
|
||
{t:'BPMS',u:'http://10.1.0.3:5890/bpms-command-center.html',d:'Business Process S95'},
|
||
{t:'L99',u:'/l99.html',d:'Ce dashboard'}
|
||
];
|
||
var html='<div class="card"><h3>Command Centers</h3><div class="grid">';
|
||
ccLinks.forEach(function(c){html+='<div style="background:#1e293b;border:1px solid #334155;border-radius:10px;padding:16px"><h4 style="color:#a5b4fc;font-size:13px">'+c.t+'</h4><p style="font-size:10px;color:#64748b;margin:6px 0">'+c.d+'</p><a href="'+c.u+'" target="_blank" style="color:#8b5cf6;font-size:11px">Ouvrir</a></div>'});
|
||
html+='</div>';
|
||
var ccss=S.filter(function(s){return s.name.indexOf('cc-')===0||s.name.indexOf('blade')>=0});
|
||
if(ccss.length){
|
||
html+='<h3 style="margin-top:16px">Screenshots CC</h3><div class="grid3">';
|
||
ccss.forEach(function(s){html+='<div class="sc" onclick="openImg(\''+s.url+'\')"><img src="'+s.url+'" loading="lazy"><div class="sn">'+s.name+'</div></div>'});
|
||
html+='</div>';
|
||
}
|
||
html+='</div>';
|
||
C.innerHTML=html
|
||
}
|
||
|
||
function showHistory(C){
|
||
C.innerHTML='<div class="card"><h3>Chargement...</h3></div>';
|
||
fetch(API+'?action=history').then(function(r){return r.json()}).then(function(h){
|
||
var rows='';
|
||
h.forEach(function(x){var pct=x.pct||0;var col=pct>=95?'#10b981':pct>=90?'#f59e0b':'#ef4444';rows+='<tr><td>'+((x.ts||'').substring(0,19))+'</td><td style="font-weight:700;color:'+col+'">'+pct.toFixed(0)+'%</td><td style="color:#10b981">'+x.pass+'</td><td style="color:#ef4444">'+x.fail+'</td><td>'+x.total+'</td></tr>'});
|
||
if(!rows)rows='<tr><td colspan=5 style="text-align:center;color:#64748b;padding:20px">Vide</td></tr>';
|
||
C.innerHTML='<div class="card"><h3>Historique SPC</h3><table><tr><th>Date</th><th>Score</th><th>Pass</th><th>Fail</th><th>Total</th></tr>'+rows+'</table></div>'
|
||
})
|
||
}
|
||
|
||
function showExec(C){
|
||
C.innerHTML='<div class="card"><h3>Execution</h3><button class="btn" style="width:100%;margin-bottom:16px" onclick="runL99()">Lancer TOUT</button><pre style="background:#0a0e1a;border:1px solid #1e293b;border-radius:8px;padding:12px;font-size:10px;color:#10b981;max-height:300px;overflow:auto">python3 /opt/weval-l99/l99-master.py\nhttps://weval-consulting.com/l99.html\nhttps://weval-consulting.com/api/l99-api.php</pre></div>'
|
||
}
|
||
|
||
function runL99(){fetch(API+'?action=run',{method:'POST'}).then(function(){alert('L99 lance en background. Rechargez dans 10 min.')}).catch(function(e){alert('Erreur: '+e.message)})}
|
||
|
||
function openImg(url){var o=document.createElement('div');o.className='overlay';o.onclick=function(){o.remove()};o.innerHTML='<img src="'+url+'">';document.body.appendChild(o)}
|
||
|
||
init();
|
||
setInterval(init,120000);
|
||
</script>
|
||
<script src=/api/l99-showss-override.js></script><!-- CARTO_REMOVED -->
|
||
<!-- CARTO_BANNER_V1 -->
|
||
<div style="position:fixed;bottom:20px;right:20px;z-index:9999;background:linear-gradient(135deg,#141931,#2d1b5e);border:1px solid #64ffda;border-radius:12px;padding:12px 18px;box-shadow:0 4px 20px rgba(100,255,218,.3);font-family:-apple-system,Segoe UI,sans-serif;font-size:13px">
|
||
<a href="/cartographie-screens.html" style="color:#64ffda;text-decoration:none;font-weight:600;display:flex;align-items:center;gap:8px" title="Cartographie exhaustive de tous les ecrans live">
|
||
<span style="font-size:18px">🗺</span> Cartographie live
|
||
<span id="carto-banner-count" style="color:#8892b0;font-size:11px">3914 ecrans</span>
|
||
</a>
|
||
</div>
|
||
<script>
|
||
(function(){
|
||
fetch('/api/screens-health.php?_='+Date.now(),{cache:'no-store'}).then(r=>r.json()).then(d=>{
|
||
const c=d.counts||{}; const up=c.UP||0; const slow=c.SLOW||0; const br=c.BROKEN||0;
|
||
const el=document.getElementById('carto-banner-count');
|
||
if(el) el.innerHTML=`<span style="color:#22c55e">${up} UP</span> / <span style="color:#f59e0b">${slow} Lent</span> / <span style="color:#ef4444">${br} 5xx</span>`;
|
||
}).catch(()=>{});
|
||
})();
|
||
</script>
|
||
<!-- /CARTO_BANNER_V1 -->
|
||
<!-- WTP-GAP-FILL-V1 (doctrine 90-v2 gap-fill showcase, 18avr 2026) -->
|
||
<style>
|
||
.wtp-gapfill-banner{position:fixed;bottom:0;left:0;right:0;z-index:99999;background:linear-gradient(90deg,#05060a,#0b0d15 20%,#181d2e 50%,#0b0d15 80%,#05060a);border-top:2px solid #14b8a6;color:#e2e8f0;padding:10px 16px;font-family:Inter,system-ui,-apple-system,sans-serif;font-size:11.5px;display:flex;align-items:center;gap:12px;flex-wrap:wrap;box-shadow:0 -10px 30px rgba(20,184,166,.28)}
|
||
.wtp-gapfill-banner a{color:#5eead4;text-decoration:none;font-weight:600;transition:color .15s}
|
||
.wtp-gapfill-banner a:hover{color:#22d3ee}
|
||
.wtp-gapfill-banner .pill{padding:2px 9px;background:rgba(99,102,241,.14);color:#a5b4fc;border-radius:10px;font-size:10.5px;font-family:JetBrains Mono,monospace;font-weight:600}
|
||
.wtp-gapfill-banner .pill.new{background:rgba(20,184,166,.22);color:#5eead4}
|
||
.wtp-gapfill-banner .pill.hot{background:rgba(236,72,153,.22);color:#f472b6}
|
||
.wtp-gapfill-banner .close{margin-left:auto;cursor:pointer;color:#64748b;padding:0 8px;font-size:16px;line-height:1;border:1px solid #334155;border-radius:4px}
|
||
.wtp-gapfill-banner .close:hover{color:#e2e8f0;border-color:#64748b}
|
||
.wtp-gapfill-banner.hidden{display:none}
|
||
@media(max-width:768px){.wtp-gapfill-banner{font-size:10px;padding:7px 10px;gap:8px}}
|
||
</style>
|
||
<div class="wtp-gapfill-banner" id="wtpGapFillBanner">
|
||
<span>🎯 <strong>WEVAL Agents Gap-Fill ERP</strong></span>
|
||
<span class="pill hot">47 gaps</span>
|
||
<span class="pill">SAP · Oracle · NetSuite · Dynamics</span>
|
||
<span class="pill new">🆕 Meeting Rooms</span>
|
||
<span class="pill new">🆕 Lean 6 Sigma</span>
|
||
<span id="wtp-gfb-metrics" class="pill">— chargement —</span>
|
||
<a href="/weval-technology-platform.html">→ WTP Portal (16 mod)</a>
|
||
<a href="/enterprise-model.html">Enterprise Model</a>
|
||
<a href="/api/weval-agents-gap-fill-manifest.json" target="_blank">📋 Manifest</a>
|
||
<span class="close" onclick="document.getElementById("wtpGapFillBanner").classList.add("hidden");localStorage.setItem("wtpGapFillHidden","1")">×</span>
|
||
</div>
|
||
<script>
|
||
(async()=>{
|
||
if(localStorage.getItem("wtpGapFillHidden")==="1"){document.getElementById("wtpGapFillBanner").classList.add("hidden");return;}
|
||
try{
|
||
const r=await fetch("/api/source-of-truth.json?t="+Date.now());
|
||
const d=await r.json();
|
||
const el=document.getElementById("wtp-gfb-metrics");
|
||
if(el)el.textContent=(d.ethica_total||"?")+" HCPs · "+(d.nonreg||"?")+" · "+(d.providers_count||"?")+" IA · "+(d.agents_count||"?")+" agents · "+(d.docker_running||"?")+" 🐳";
|
||
}catch(e){}
|
||
})();
|
||
</script>
|
||
|
||
<!-- WTP-D90V2-ENRICH-BANNER (doctrine 90-v2, 17avr 2026) -->
|
||
<style>
|
||
.wtp-enrich-banner{position:fixed;bottom:0;left:0;right:0;z-index:9999;background:linear-gradient(90deg,#0b0d15,#181d2e,#0b0d15);border-top:2px solid #14b8a6;color:#e2e8f0;padding:9px 18px;font-family:'JetBrains Mono',monospace,-apple-system,system-ui;font-size:11.5px;display:flex;align-items:center;gap:14px;flex-wrap:wrap;box-shadow:0 -8px 24px rgba(20,184,166,.25)}
|
||
.wtp-enrich-banner a{color:#14b8a6;text-decoration:none;font-weight:600}
|
||
.wtp-enrich-banner a:hover{color:#22d3ee}
|
||
.wtp-enrich-banner .pill{padding:2px 8px;background:rgba(99,102,241,.15);color:#a5b4fc;border-radius:10px;font-size:10.5px}
|
||
.wtp-enrich-banner .pill.new{background:rgba(20,184,166,.2);color:#5eead4}
|
||
.wtp-enrich-banner .close{margin-left:auto;cursor:pointer;color:#64748b;padding:0 6px;font-size:14px}
|
||
.wtp-enrich-banner .close:hover{color:#e2e8f0}
|
||
.wtp-enrich-banner.hidden{display:none}
|
||
@media(max-width:768px){.wtp-enrich-banner{font-size:10px;padding:6px 10px}}
|
||
</style>
|
||
<div class="wtp-enrich-banner" id="wtpEnrichBanner">
|
||
<span>🏛️ <strong>Enterprise Model 16 depts</strong></span>
|
||
<span class="pill new">🆕 Meeting Rooms</span>
|
||
<span class="pill new">🆕 Lean 6 Sigma</span>
|
||
<span id="wtp-eb-metrics" class="pill">— chargement —</span>
|
||
<a href="/weval-technology-platform.html">→ WEVAL Technology Platform (16 modules)</a>
|
||
<a href="/enterprise-model.html">Enterprise Model</a>
|
||
<a href="/wevia-master.html">WEVIA Master</a>
|
||
<span class="close" onclick="document.getElementById('wtpEnrichBanner').classList.add('hidden')">×</span>
|
||
</div>
|
||
<script>
|
||
(async()=>{try{const r=await fetch('/api/source-of-truth.json?t='+Date.now());const d=await r.json();const el=document.getElementById('wtp-eb-metrics');if(el)el.textContent=(d.ethica_total||'?')+' HCPs · '+(d.nonreg||'?')+' · '+(d.providers_count||'?')+' IA · '+(d.docker_running||'?')+' 🐳 · '+(d.subdomains_live||'?')+' subdomains';}catch(e){}})();
|
||
</script>
|
||
</body></html>
|