Files
html/wtp-udock-coverage.html
opus d5edaa769c
Some checks failed
WEVAL NonReg / nonreg (push) Has been cancelled
auto-sync via WEVIA git_sync_all intent 2026-04-21T14:56:43+02:00
2026-04-21 14:56:43 +02:00

243 lines
13 KiB
HTML

<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>WTP UDOCK Coverage Dashboard · WEVAL</title>
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600&family=Outfit:wght@300;400;500;600;700;800&display=swap" rel="stylesheet">
<style>
:root{
--bg:#0a0a0f; --bg2:#12121a; --bg3:#1a1a2e; --brd:#2a2a3e;
--t1:#e8e8f0; --t2:#8888aa; --t3:#555570;
--green:#22c55e; --cyan:#06b6d4; --purple:#8b5cf6; --pink:#ec4899; --amber:#f59e0b; --red:#ef4444; --indigo:#6366f1;
--r:10px; --mono:'JetBrains Mono',monospace; --sans:'Outfit',sans-serif;
}
*{margin:0;padding:0;box-sizing:border-box}
html,body{background:var(--bg);color:var(--t1);font-family:var(--sans);min-height:100vh}
.page{max-width:1400px;margin:0 auto;padding:24px}
.hdr{display:flex;justify-content:space-between;align-items:center;margin-bottom:24px;padding-bottom:16px;border-bottom:1px solid var(--brd)}
.hdr h1{font-size:24px;font-weight:700;background:linear-gradient(135deg,var(--green),var(--cyan));-webkit-background-clip:text;-webkit-text-fill-color:transparent}
.hdr .meta{color:var(--t2);font-size:12px;font-family:var(--mono)}
.hero{display:grid;grid-template-columns:2fr 1fr;gap:16px;margin-bottom:24px}
.hero-big{background:linear-gradient(135deg,rgba(34,197,94,0.08),rgba(99,102,241,0.08));border:1px solid var(--brd);border-radius:var(--r);padding:32px;text-align:center;position:relative;overflow:hidden}
.hero-big::before{content:'';position:absolute;inset:0;background:radial-gradient(circle at 30% 30%,rgba(34,197,94,0.15),transparent 60%);pointer-events:none}
.coverage-num{font-size:84px;font-weight:800;line-height:1;background:linear-gradient(135deg,var(--green),var(--cyan));-webkit-background-clip:text;-webkit-text-fill-color:transparent;position:relative;font-family:var(--sans)}
.coverage-lbl{color:var(--t2);font-size:14px;margin-top:8px;letter-spacing:.1em;text-transform:uppercase;position:relative}
.progress{height:8px;background:var(--bg3);border-radius:4px;overflow:hidden;margin-top:20px;position:relative}
.progress-fill{height:100%;background:linear-gradient(90deg,var(--green),var(--cyan),var(--purple));transition:width 1s cubic-bezier(.4,0,.2,1);border-radius:4px}
.mini-stats{display:flex;gap:24px;justify-content:center;margin-top:18px;font-size:13px;color:var(--t2);position:relative}
.mini-stats strong{color:var(--t1);font-weight:600}
.hero-side{display:flex;flex-direction:column;gap:12px}
.mini-card{background:var(--bg2);border:1px solid var(--brd);border-radius:var(--r);padding:16px;transition:.2s}
.mini-card:hover{border-color:var(--cyan);transform:translateX(-2px)}
.mini-card .label{font-size:11px;color:var(--t3);text-transform:uppercase;letter-spacing:.1em;font-weight:600}
.mini-card .value{font-size:28px;font-weight:700;color:var(--t1);margin-top:4px;line-height:1}
.mini-card .sub{font-size:11px;color:var(--t2);margin-top:4px}
.section{margin-bottom:24px}
.section-title{display:flex;align-items:center;gap:8px;font-size:14px;font-weight:600;color:var(--t1);margin-bottom:12px;text-transform:uppercase;letter-spacing:.1em}
.section-title::after{content:'';flex:1;height:1px;background:var(--brd);margin-left:8px}
.pattern-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:12px}
.pattern-card{background:var(--bg2);border:1px solid var(--brd);border-radius:var(--r);padding:18px;transition:.2s}
.pattern-card:hover{border-color:var(--cyan)}
.pattern-card .pc-pat{font-family:var(--mono);font-size:11px;color:var(--t3);margin-bottom:6px;word-break:break-all}
.pattern-card .pc-val{font-size:32px;font-weight:700}
.pattern-card .pc-desc{font-size:11px;color:var(--t2);margin-top:4px}
.pc-green{border-left:3px solid var(--green)}.pc-green .pc-val{color:var(--green)}
.pc-cyan{border-left:3px solid var(--cyan)}.pc-cyan .pc-val{color:var(--cyan)}
.pc-purple{border-left:3px solid var(--purple)}.pc-purple .pc-val{color:var(--purple)}
.pc-amber{border-left:3px solid var(--amber)}.pc-amber .pc-val{color:var(--amber)}
.uncovered-grid{background:var(--bg2);border:1px solid var(--brd);border-radius:var(--r);padding:18px}
.uncovered-list{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:8px;max-height:500px;overflow-y:auto}
.unc-item{display:flex;justify-content:space-between;align-items:center;padding:8px 12px;background:var(--bg3);border-radius:6px;font-size:12px;border-left:2px solid transparent}
.unc-item.unc-imm{border-left-color:var(--red)}
.unc-item .name{font-family:var(--mono);color:var(--t1)}
.unc-item .size{color:var(--t2);font-size:10px}
.unc-item.unc-imm::after{content:'🔒';margin-left:6px}
.timeline{background:var(--bg2);border:1px solid var(--brd);border-radius:var(--r);padding:18px;font-family:var(--mono);font-size:11px}
.tl-row{display:flex;gap:12px;padding:6px 0;border-bottom:1px dashed var(--brd)}
.tl-row:last-child{border-bottom:none}
.tl-col1{width:80px;color:var(--t3)}
.tl-col2{width:120px;color:var(--t1)}
.tl-col3{flex:1;color:var(--t2)}
.tl-bar{height:8px;background:var(--bg3);border-radius:4px;flex:1;max-width:300px;overflow:hidden;margin-top:2px}
.tl-bar>div{height:100%;background:linear-gradient(90deg,var(--green),var(--cyan))}
.loading{display:flex;align-items:center;justify-content:center;padding:40px;color:var(--t2);font-style:italic}
.refresh-btn{background:transparent;border:1px solid var(--brd);color:var(--t2);padding:6px 12px;border-radius:6px;cursor:pointer;font-size:11px;font-family:var(--mono)}
.refresh-btn:hover{border-color:var(--cyan);color:var(--cyan)}
.badge{display:inline-block;padding:2px 8px;border-radius:10px;font-size:10px;font-weight:600;font-family:var(--mono)}
.badge-green{background:rgba(34,197,94,0.15);color:var(--green)}
.badge-amber{background:rgba(245,158,11,0.15);color:var(--amber)}
.badge-red{background:rgba(239,68,68,0.15);color:var(--red)}
</style>
</head>
<body>
<div class="page">
<div class="hdr">
<div>
<h1>🔗 WTP UDOCK Coverage Dashboard</h1>
<div class="meta" id="meta">Chargement en cours...</div>
</div>
<div style="display:flex;gap:8px">
<button class="refresh-btn" onclick="loadData()">🔄 Refresh</button>
<button class="refresh-btn" onclick="loadData(true)">📋 Détails</button>
</div>
</div>
<div class="hero">
<div class="hero-big">
<div class="coverage-num" id="cov-num"></div>
<div class="coverage-lbl">Pages couvertes · Navigation unifiée ERP</div>
<div class="progress"><div class="progress-fill" id="progress-fill" style="width:0"></div></div>
<div class="mini-stats">
<div><strong id="stat-covered"></strong> couvertes</div>
<div><strong id="stat-uncovered"></strong> restantes</div>
<div><strong id="stat-total"></strong> total</div>
</div>
</div>
<div class="hero-side">
<div class="mini-card">
<div class="label">Immutable bloquées</div>
<div class="value" id="stat-imm"></div>
<div class="sub">chattr+i · attend sudo whitelist IP</div>
</div>
<div class="mini-card">
<div class="label">Cible 100%</div>
<div class="value" id="stat-goal"></div>
<div class="sub">pages à propager</div>
</div>
<div class="mini-card">
<div class="label">Source unique</div>
<div class="value" style="font-size:14px;font-family:var(--mono);color:var(--cyan)">wtp-unified-dock.js</div>
<div class="sub">5548 bytes · HTTP 200</div>
</div>
</div>
</div>
<div class="section">
<div class="section-title">📊 Breakdown par pattern de navigation</div>
<div class="pattern-grid">
<div class="pattern-card pc-green">
<div class="pc-pat">wtp-unified-dock.js</div>
<div class="pc-val" id="pat-udock"></div>
<div class="pc-desc">Source unique doctrine (tour 29+)</div>
</div>
<div class="pattern-card pc-cyan">
<div class="pc-pat">opus-xlinks</div>
<div class="pc-val" id="pat-xlinks"></div>
<div class="pc-desc">Legacy inline (Master + WevCode)</div>
</div>
<div class="pattern-card pc-purple">
<div class="pc-pat">wtp-sidebar</div>
<div class="pc-val" id="pat-sidebar"></div>
<div class="pc-desc">WTP Platform native</div>
</div>
<div class="pattern-card pc-amber">
<div class="pc-pat">v130-xnav</div>
<div class="pc-val" id="pat-xnav"></div>
<div class="pc-desc">All-IA Hub breadcrumb</div>
</div>
</div>
</div>
<div class="section">
<div class="section-title">📈 Timeline session UX polish</div>
<div class="timeline">
<div class="tl-row">
<div class="tl-col1">Avant</div>
<div class="tl-col2">4 / 294 (1.4%)</div>
<div class="tl-col3"><div class="tl-bar"><div style="width:1.4%"></div></div></div>
</div>
<div class="tl-row">
<div class="tl-col1">Tour 29</div>
<div class="tl-col2">10 / 294 (3.4%)</div>
<div class="tl-col3"><div class="tl-bar"><div style="width:3.4%"></div></div></div>
</div>
<div class="tl-row">
<div class="tl-col1">Tour 30</div>
<div class="tl-col2">22 / 294 (7.5%)</div>
<div class="tl-col3"><div class="tl-bar"><div style="width:7.5%"></div></div></div>
</div>
<div class="tl-row">
<div class="tl-col1">Tour 31</div>
<div class="tl-col2">46 / 294 (15.6%)</div>
<div class="tl-col3"><div class="tl-bar"><div style="width:15.6%"></div></div></div>
</div>
<div class="tl-row">
<div class="tl-col1">Tour 32</div>
<div class="tl-col2">77 / 294 (26.2%)</div>
<div class="tl-col3"><div class="tl-bar"><div style="width:26.2%"></div></div></div>
</div>
<div class="tl-row">
<div class="tl-col1">Tour 33</div>
<div class="tl-col2">153 / 294 (52.0%)</div>
<div class="tl-col3"><div class="tl-bar"><div style="width:52%"></div></div></div>
</div>
<div class="tl-row">
<div class="tl-col1" style="color:var(--green)">Tour 34</div>
<div class="tl-col2" style="color:var(--green)">276 / 294 (93.9%)</div>
<div class="tl-col3"><div class="tl-bar"><div style="width:93.9%"></div></div></div>
</div>
<div class="tl-row" id="current-row">
<div class="tl-col1" style="color:var(--cyan)">Live</div>
<div class="tl-col2" style="color:var(--cyan)" id="live-val">loading...</div>
<div class="tl-col3"><div class="tl-bar"><div id="live-bar" style="width:0"></div></div></div>
</div>
</div>
</div>
<div class="section" id="detail-section" style="display:none">
<div class="section-title">🔒 Pages non couvertes (top 30)</div>
<div class="uncovered-grid">
<div class="uncovered-list" id="unc-list"><div class="loading">Cliquer "Détails" pour charger</div></div>
</div>
</div>
</div>
<script>
async function loadData(withDetail) {
try {
const url = '/api/wtp-udock-coverage.php' + (withDetail ? '?detail=1' : '');
const r = await fetch(url, {credentials:'same-origin'});
const ct = r.headers.get('content-type')||'';
if (!r.ok || ct.indexOf('html')>=0) throw new Error('API HTML or error');
const d = await r.json();
document.getElementById('meta').textContent = 'Mis à jour · ' + new Date(d.ts).toLocaleString('fr-FR') + ' · source: ' + d.source;
document.getElementById('cov-num').textContent = d.coverage_pct + '%';
document.getElementById('progress-fill').style.width = d.coverage_pct + '%';
document.getElementById('stat-covered').textContent = d.covered;
document.getElementById('stat-uncovered').textContent = d.uncovered;
document.getElementById('stat-total').textContent = d.total_pages;
document.getElementById('stat-imm').textContent = d.immutable_blocked;
document.getElementById('stat-goal').textContent = d.target_100pct_remaining;
document.getElementById('pat-udock').textContent = d.by_pattern['wtp-unified-dock.js'];
document.getElementById('pat-xlinks').textContent = d.by_pattern['opus-xlinks'];
document.getElementById('pat-sidebar').textContent = d.by_pattern['wtp-sidebar'];
document.getElementById('pat-xnav').textContent = d.by_pattern['v130-xnav'];
document.getElementById('live-val').textContent = d.covered + ' / ' + d.total_pages + ' (' + d.coverage_pct + '%)';
document.getElementById('live-bar').style.width = d.coverage_pct + '%';
if (withDetail && d.uncovered_top30) {
const list = document.getElementById('unc-list');
list.innerHTML = '';
d.uncovered_top30.forEach(u => {
const div = document.createElement('div');
div.className = 'unc-item' + (u.immutable ? ' unc-imm' : '');
div.innerHTML = '<span class="name">' + u.name + '</span><span class="size">' + u.size_human + '</span>';
list.appendChild(div);
});
document.getElementById('detail-section').style.display = 'block';
}
} catch (e) {
document.getElementById('meta').textContent = '⚠️ Erreur fetch: ' + e.message;
document.getElementById('cov-num').textContent = '?';
}
}
loadData();
setInterval(loadData, 60000); // refresh 1min
</script>
<!-- WTP_UDOCK_V1 (self) --><script src="/wtp-unified-dock.js" defer></script>
<script src="/opus-antioverlap-doctrine.js?v=1776776094" defer></script>
</body>
</html>