Some checks failed
WEVAL NonReg / nonreg (push) Has been cancelled
Couverture dock nav: - Tour 29: 10 pages - Tour 30 batch 2: +12 (22 total) - Tour 31 batch 3: +24 (46 total) Pages injectees batch 3 (+92 bytes chacune, additif idempotent): * Dashboards: api-key-hub, tasks-live, nonreg, monitoring, trust-center * Pages hub: methodologie, playbook-3-phases, integrations-marketplace, automation-hub * Navigation: pages-index, weval-sitemap * Business: candidates-pool, contacts-segmentation-dashboard, kaouther-compose * Landings: landing-industrie, landing-ocp, landing-banque, landing-retail, ecosysteme-ia-maroc * Controls: linkedin-control-v98, blade-control, world-map-live, vsm-15depts-NEW, nl-autowire-status SKIP: vsm-pipelines.html (chattr+i) GOLD: /opt/wevads/vault/gold_*_t31_*.html Doctrine: ERP Global single source nav · Zero ecrasement · Zero regression · Idempotent
249 lines
14 KiB
HTML
249 lines
14 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="fr">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>WEVAL Sitemap · Toutes pages · Source unique</title>
|
||
<style>
|
||
*{margin:0;padding:0;box-sizing:border-box}
|
||
:root{
|
||
--bg:#09090b; --surface:#13131a; --surface2:#1a1a24; --border:#2a2a35;
|
||
--text:#fafafa; --muted:#94a3b8; --accent:#6366f1; --accent2:#a855f7;
|
||
--green:#22c55e; --amber:#f59e0b; --red:#ef4444; --cyan:#22d3ee;
|
||
--grad:linear-gradient(135deg,#6366f1 0%,#a855f7 50%,#ec4899 100%);
|
||
}
|
||
body{font-family:-apple-system,Inter,Segoe UI,sans-serif;background:var(--bg);color:var(--text);min-height:100vh;line-height:1.5}
|
||
.topbar{background:var(--surface);border-bottom:1px solid var(--border);padding:14px 28px;display:flex;justify-content:space-between;align-items:center;position:sticky;top:0;z-index:100;backdrop-filter:blur(20px)}
|
||
.topbar h1{font-size:1.15rem;font-weight:700;background:var(--grad);-webkit-background-clip:text;-webkit-text-fill-color:transparent;letter-spacing:-0.02em}
|
||
.topbar .meta{display:flex;gap:14px;align-items:center;font-size:.78rem;color:var(--muted)}
|
||
.topbar .live{display:inline-flex;align-items:center;gap:6px;color:var(--green);font-weight:600}
|
||
.topbar .live::before{content:'';width:8px;height:8px;background:var(--green);border-radius:99px;box-shadow:0 0 12px var(--green);animation:pulse 1.5s infinite}
|
||
@keyframes pulse{0%,100%{opacity:1}50%{opacity:.4}}
|
||
.bread{padding:14px 28px;background:var(--surface);font-size:.78rem;color:var(--muted);border-bottom:1px solid var(--border)}
|
||
.bread a{color:var(--accent);text-decoration:none;margin-right:6px}
|
||
main{padding:28px;max-width:1700px;margin:0 auto}
|
||
.hero{background:linear-gradient(135deg,rgba(99,102,241,.1),rgba(168,85,247,.05));border:1px solid rgba(99,102,241,.2);border-radius:16px;padding:24px 28px;margin-bottom:24px;position:relative;overflow:hidden}
|
||
.hero::before{content:'';position:absolute;top:-50%;right:-10%;width:300px;height:300px;background:radial-gradient(circle,rgba(99,102,241,.15),transparent 70%);pointer-events:none}
|
||
.hero h2{font-size:1.4rem;margin-bottom:6px;background:var(--grad);-webkit-background-clip:text;-webkit-text-fill-color:transparent}
|
||
.hero p{color:var(--muted);font-size:.85rem;line-height:1.6}
|
||
.kpi-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:14px;margin-bottom:18px}
|
||
.kpi{background:var(--surface);border:1px solid var(--border);border-radius:14px;padding:16px;position:relative;overflow:hidden}
|
||
.kpi::before{content:'';position:absolute;top:0;left:0;right:0;height:3px;background:var(--grad);opacity:.6}
|
||
.kpi .lbl{font-size:.7rem;color:var(--muted);text-transform:uppercase;letter-spacing:1px;font-weight:600;margin-bottom:4px}
|
||
.kpi .val{font-size:1.6rem;font-weight:700;background:linear-gradient(180deg,var(--text),var(--muted));-webkit-background-clip:text;-webkit-text-fill-color:transparent;line-height:1.1}
|
||
.kpi .sub{font-size:.7rem;color:var(--muted);margin-top:4px}
|
||
.controls{display:flex;gap:10px;margin-bottom:18px;flex-wrap:wrap;align-items:center}
|
||
.search{flex:1;min-width:280px;padding:10px 14px;background:var(--surface);border:1px solid var(--border);border-radius:10px;color:var(--text);font-size:.88rem;outline:none}
|
||
.search:focus{border-color:var(--accent)}
|
||
.filter-btn{padding:7px 13px;background:var(--surface);border:1px solid var(--border);border-radius:99px;color:var(--muted);font-size:.75rem;cursor:pointer;transition:.2s;font-weight:600}
|
||
.filter-btn:hover{border-color:var(--accent);color:var(--text)}
|
||
.filter-btn.active{background:var(--accent);color:#fff;border-color:var(--accent)}
|
||
.cat-section{background:var(--surface);border:1px solid var(--border);border-radius:14px;padding:16px;margin-bottom:14px}
|
||
.cat-title{font-size:.95rem;font-weight:700;color:var(--text);display:flex;align-items:center;gap:10px;margin-bottom:12px}
|
||
.cat-title .badge{background:var(--surface2);color:var(--cyan);padding:3px 9px;border-radius:99px;font-size:.7rem;font-weight:600;font-variant-numeric:tabular-nums}
|
||
.page-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(240px,1fr));gap:8px}
|
||
.page-card{background:var(--surface2);border:1px solid var(--border);border-radius:8px;padding:10px 12px;display:flex;flex-direction:column;gap:4px;transition:.2s;text-decoration:none;color:var(--text);cursor:pointer}
|
||
.page-card:hover{border-color:var(--accent);background:rgba(99,102,241,.08);transform:translateY(-1px);box-shadow:0 8px 20px rgba(99,102,241,.1)}
|
||
.page-card .name{font-size:.78rem;font-weight:600;color:var(--text);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
||
.page-card .meta{font-size:.65rem;color:var(--muted);display:flex;justify-content:space-between;align-items:center;gap:6px}
|
||
.page-card .badge-orphan{background:rgba(245,158,11,.15);color:var(--amber);padding:1px 6px;border-radius:4px;font-size:.6rem;font-weight:600}
|
||
.page-card .badge-linked{background:rgba(34,197,94,.15);color:var(--green);padding:1px 6px;border-radius:4px;font-size:.6rem;font-weight:600}
|
||
.empty{text-align:center;color:var(--muted);padding:40px;font-size:.85rem;font-style:italic}
|
||
footer{padding:32px 28px;text-align:center;color:var(--muted);font-size:.75rem;border-top:1px solid var(--border);margin-top:32px}
|
||
footer a{color:var(--accent);text-decoration:none;margin:0 8px}
|
||
.refresh{padding:5px 12px;background:var(--surface2);border:1px solid var(--border);border-radius:99px;color:var(--muted);font-size:.7rem;cursor:pointer}
|
||
.refresh:hover{border-color:var(--accent);color:var(--text)}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
|
||
<div class="topbar">
|
||
<h1>🗺 WEVAL Sitemap · Toutes pages</h1>
|
||
<div class="meta">
|
||
<span>Source: <a href="/api/weval-sitemap-api.php" style="color:var(--cyan)">sitemap-api</a></span>
|
||
<span>Refresh: <span id="ts">—</span></span>
|
||
<button class="refresh" onclick="loadAll()">↻</button>
|
||
<span class="live">LIVE</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="bread">
|
||
<a href="/">Home</a> /
|
||
<a href="/wevia-erp-v2.html">ERP V2</a> /
|
||
<a href="/architecture.html">Architecture</a> /
|
||
<span style="color:var(--text)">Sitemap exhaustif</span>
|
||
</div>
|
||
|
||
<main>
|
||
|
||
<div class="hero">
|
||
<h2>🗺 Sitemap exhaustif · Source unique fichiers</h2>
|
||
<p>Référentiel complet de toutes les pages HTML déployées · Live filesystem scan · Catégorisation automatique · Détection orphelins · Last modified · Recherche + filtres · <b>Aucune page perdue</b> · <b>Zero orphan</b> · Auto-refresh 60s</p>
|
||
</div>
|
||
|
||
<div class="kpi-grid">
|
||
<div class="kpi"><div class="lbl">Total pages</div><div class="val" id="k-total">—</div><div class="sub">HTML déployées</div></div>
|
||
<div class="kpi"><div class="lbl">Catégories</div><div class="val" id="k-cats">—</div><div class="sub">groupées par fonction</div></div>
|
||
<div class="kpi"><div class="lbl">Orphan pages</div><div class="val" id="k-orphan">—</div><div class="sub">non linkées encore</div></div>
|
||
<div class="kpi"><div class="lbl">Last update</div><div class="val" id="k-last" style="font-size:1rem">—</div><div class="sub">scan timestamp</div></div>
|
||
</div>
|
||
|
||
<div class="controls">
|
||
<input type="text" class="search" id="search" placeholder="🔍 Rechercher par nom (ex: agent, hub, dashboard, ethica)..." oninput="render()">
|
||
<button class="filter-btn active" onclick="setFilter('all',this)">Toutes</button>
|
||
<button class="filter-btn" onclick="setFilter('orphan',this)">⚠ Orphelines</button>
|
||
<button class="filter-btn" onclick="setFilter('linked',this)">✓ Liées</button>
|
||
</div>
|
||
|
||
<div id="cat-list"></div>
|
||
|
||
</main>
|
||
|
||
<footer>
|
||
WEVAL Sitemap · scan exhaustif filesystem · v1.0 ·
|
||
<a href="/wevia-master.html">WEVIA Master</a> ·
|
||
<a href="/wevia-erp-v2.html">ERP V2</a> ·
|
||
<a href="/wevia-erp-unified.html">ERP V1</a> ·
|
||
<a href="/architecture.html">Architecture</a> ·
|
||
<a href="/api/weval-sitemap-api.php">API JSON</a>
|
||
</footer>
|
||
|
||
<script>
|
||
let DATA = null;
|
||
let FILTER = 'all';
|
||
|
||
function fmt(n){return (n||0).toLocaleString('fr-FR')}
|
||
|
||
async function loadAll() {
|
||
document.getElementById('ts').textContent = new Date().toLocaleTimeString('fr-FR');
|
||
try {
|
||
DATA = await fetch('/api/weval-sitemap-api.php').then(r => r.json());
|
||
if (!DATA.ok) throw new Error('api error');
|
||
document.getElementById('k-total').textContent = fmt(DATA.stats.total_pages);
|
||
document.getElementById('k-cats').textContent = fmt(DATA.stats.total_categories);
|
||
document.getElementById('k-orphan').textContent = fmt(DATA.stats.orphan_count);
|
||
document.getElementById('k-last').textContent = new Date(DATA.ts).toLocaleString('fr-FR');
|
||
render();
|
||
} catch (e) {
|
||
document.getElementById('cat-list').innerHTML = '<div class="empty">Erreur API: ' + e.message + '</div>';
|
||
}
|
||
}
|
||
|
||
function setFilter(f, btn) {
|
||
FILTER = f;
|
||
document.querySelectorAll('.filter-btn').forEach(b => b.classList.remove('active'));
|
||
btn.classList.add('active');
|
||
render();
|
||
}
|
||
|
||
function render() {
|
||
if (!DATA) return;
|
||
const search = document.getElementById('search').value.toLowerCase().trim();
|
||
const out = [];
|
||
|
||
const cats = Object.keys(DATA.by_category).sort((a,b) =>
|
||
DATA.by_category[b].length - DATA.by_category[a].length
|
||
);
|
||
|
||
for (const cat of cats) {
|
||
let pages = DATA.by_category[cat];
|
||
if (FILTER === 'orphan') pages = pages.filter(p => p.is_orphan);
|
||
if (FILTER === 'linked') pages = pages.filter(p => !p.is_orphan);
|
||
if (search) pages = pages.filter(p => p.name.toLowerCase().includes(search));
|
||
if (pages.length === 0) continue;
|
||
|
||
const cards = pages.map(p => {
|
||
const orphanBadge = p.is_orphan
|
||
? `<span class="badge-orphan">orphan</span>`
|
||
: `<span class="badge-linked">${p.ref_count}×</span>`;
|
||
return `
|
||
<a class="page-card" href="${p.url}" target="_blank">
|
||
<div class="name" title="${p.name}">${p.name}</div>
|
||
<div class="meta">
|
||
<span>${p.size_kb} KB · ${p.mtime_human}</span>
|
||
${orphanBadge}
|
||
</div>
|
||
</a>`;
|
||
}).join('');
|
||
|
||
out.push(`
|
||
<div class="cat-section">
|
||
<div class="cat-title">${cat} <span class="badge">${pages.length}</span></div>
|
||
<div class="page-grid">${cards}</div>
|
||
</div>`);
|
||
}
|
||
|
||
document.getElementById('cat-list').innerHTML = out.length
|
||
? out.join('')
|
||
: '<div class="empty">Aucun résultat pour ces filtres</div>';
|
||
}
|
||
|
||
loadAll();
|
||
setInterval(loadAll, 60000);
|
||
</script>
|
||
|
||
<script src="/api/ux-drill-enricher.php"></script>
|
||
<!-- === OPUS UNIVERSAL DRILL-DOWN v1 19avr — append-only, doctrine #14 === -->
|
||
<script>
|
||
(function(){
|
||
if (window.__opusUniversalDrill) return; window.__opusUniversalDrill = true;
|
||
var d = document;
|
||
var m = d.createElement('div');
|
||
m.id = 'opus-udrill';
|
||
m.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.82);backdrop-filter:blur(6px);display:none;align-items:center;justify-content:center;z-index:99995;padding:20px;cursor:pointer';
|
||
var inner = d.createElement('div');
|
||
inner.id = 'opus-udrill-in';
|
||
inner.style.cssText = 'max-width:900px;width:100%;max-height:90vh;overflow:auto;background:#0b0d15;border:1px solid rgba(99,102,241,0.35);border-radius:14px;padding:28px;cursor:default;box-shadow:0 20px 60px rgba(0,0,0,0.6);color:#e2e8f0;font:14px/1.55 Inter,system-ui,sans-serif';
|
||
inner.addEventListener('click', function(e){ e.stopPropagation(); });
|
||
m.appendChild(inner);
|
||
m.addEventListener('click', function(){ m.style.display='none'; });
|
||
d.addEventListener('keydown', function(e){ if(e.key==='Escape') m.style.display='none'; });
|
||
(d.body || d.documentElement).appendChild(m);
|
||
function openCard(card) {
|
||
var html = '<div style="display:flex;justify-content:flex-end;margin-bottom:14px"><button id="opus-udrill-close" style="padding:6px 14px;background:#171b2a;border:1px solid rgba(99,102,241,0.25);color:#e2e8f0;border-radius:8px;cursor:pointer;font-size:12px">✕ Fermer (Esc)</button></div>';
|
||
html += '<div style="transform-origin:top left;font-size:1.05em">' + card.outerHTML + '</div>';
|
||
inner.innerHTML = html;
|
||
d.getElementById('opus-udrill-close').onclick = function(){ m.style.display='none'; };
|
||
m.style.display = 'flex';
|
||
}
|
||
function wire(root) {
|
||
var sels = '.card,[class*="card"],.kpi,[class*="kpi"],.stat,[class*="stat"],.tile,[class*="tile"],.metric,[class*="metric"],.widget,[class*="widget"]';
|
||
var cards = root.querySelectorAll(sels);
|
||
for (var i = 0; i < cards.length; i++) {
|
||
var c = cards[i];
|
||
if (c.__opusWired) continue;
|
||
if (c.closest('button, a, input, select, textarea, #opus-udrill')) continue;
|
||
var r = c.getBoundingClientRect();
|
||
if (r.width < 60 || r.height < 40) continue;
|
||
c.__opusWired = true;
|
||
c.style.cursor = 'pointer';
|
||
c.setAttribute('role','button');
|
||
c.setAttribute('tabindex','0');
|
||
c.addEventListener('click', function(ev){
|
||
if (ev.target.closest('[data-pp-id]') && window.__opusDrillInit) return;
|
||
if (ev.target.closest('a,button,input,select')) return;
|
||
ev.preventDefault(); ev.stopPropagation();
|
||
openCard(this);
|
||
});
|
||
c.addEventListener('keydown', function(ev){ if(ev.key==='Enter'||ev.key===' '){ev.preventDefault();openCard(this);} });
|
||
}
|
||
}
|
||
var initRun = function(){ wire(d.body || d.documentElement); };
|
||
if (d.readyState === 'loading') d.addEventListener('DOMContentLoaded', initRun);
|
||
else initRun();
|
||
var mo = new MutationObserver(function(muts){
|
||
var newCard = false;
|
||
for (var i=0;i<muts.length;i++) if (muts[i].addedNodes.length) { newCard = true; break; }
|
||
if (newCard) initRun();
|
||
});
|
||
mo.observe(d.body || d.documentElement, {childList:true, subtree:true});
|
||
})();
|
||
</script>
|
||
<!-- === OPUS UNIVERSAL DRILL-DOWN END === -->
|
||
|
||
|
||
<script src="/api/a11y-auto-enhancer.js" defer></script>
|
||
<!-- WTP_UDOCK_V1 (Opus 21-avr t31b3) --><script src="/wtp-unified-dock.js" defer></script>
|
||
</body>
|
||
</html>
|