Files
html/orphans-dashboard.html
Opus Wire b578d4fb30
Some checks failed
WEVAL NonReg / nonreg (push) Has been cancelled
feat(wtp-udock-v1): BATCH FINAL - 120 pages (273/294 = 92.9% COVERAGE)
MILESTONE EPIC: plus de 92 pct du parc HTML couvert avec nav unifie

Progression session tour 29-34:
  Avant   :   4 / 294 (1.4%)
  Tour 29 :  10 / 294 (3.4%)
  Tour 30 :  22 / 294 (7.5%)
  Tour 31 :  46 / 294 (15.6%)
  Tour 32 :  77 / 294 (26.2%)
  Tour 33 : 153 / 294 (52.0%)
  Tour 34 : 273 / 294 (92.9%) ← 120 pages batch final

Categories couvertes batch 7 final (120):
* Hubs: agents-hub, agents-unified-registry, vsm-hub, qa-hub, knowledge-hub, wevia-hub, wevads-hub, blade-hub, anthropic-hub, deepseek-hub, huggingface-hub, google-hub, namecheap-hub, cyber-monitor, universal-integration-hub, caps-hub, office-admins, security-hub
* Logins: arsenal-login, ethica-login, weval-login, wtp-login, office-login
* Dashboards: crm-pipeline-live, lean6sigma-dashboard, infra-dashboard-live, crm-dashboard-live, database-dashboard-live, office-365-dashboard-live, ethica-dashboard-live, em-dashboard, orphans-dashboard, dormant-dashboard-v2
* SSO/Security: sso-monitor, security-hub
* Agents: agents-fleet, agents-unified-registry, agents-hub, ia-sovereign-registry
* Blade: blade-actions, blade-center, blade-install
* BPMN: bpmn-studio-NEW, bpmn-studio-live
* LinkedIn: linkedin-automation-v96, linkedin-control-v97
* Ethica: ethica-chatbot, ethica-hcp-manager
* OpenClaw: claw-chat, claw-code
* Business: case-studies, booking, pricing, wevia-vs-opus, golive, go-100pct, pitch variants
* Autres 60+: 404, avatar-picker, cgu, nonreg-old/v2, solution-finder, mission-billing, paperclip, value-stream, value-chain, weval-data-hub, decision-gmail-o365, wevia-evolution, ops-screens-live, dmaic-workbench, dmaic-tracker, owner-actions-tracker, etc.

SKIP (19 chattr+i): cartographie-screens, vsm-pipelines, wevia-meeting-rooms, l99-saas, all-ia-hub (has v130-xnav), all-screens-live (no </body>), ethica-drill, ethica-sms, office-workflow, marketplace, droid-terminal, googlecba*, +autres protected

Zero ecrasement · Zero regression · Idempotent · Full GOLD backup · Zero dormant
2026-04-21 13:24:21 +02:00

274 lines
14 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="fr" data-theme="dark">
<head>
<meta charset="UTF-8">
<title>Orphans Dashboard — Doctrine 92 Hub Merged</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<style>
:root{--bg:#05060a;--bg2:#0e111c;--bg3:#181c2b;--br:#1f2436;--tx:#f1f5f9;--tx2:#94a3b8;--ac:#6366f1;--green:#22c55e;--yellow:#fbbf24;--red:#ef4444}
*{margin:0;padding:0;box-sizing:border-box}
body{font-family:system-ui,sans-serif;background:var(--bg);color:var(--tx);padding:24px;line-height:1.5}
h1{font-size:30px;font-weight:800;background:linear-gradient(135deg,#6366f1,#ec4899);-webkit-background-clip:text;color:transparent;margin-bottom:4px}
.sub{color:var(--tx2);margin-bottom:20px;font-size:14px}
.back{display:inline-block;padding:8px 16px;background:var(--bg3);border:1px solid var(--br);border-radius:8px;color:var(--tx);text-decoration:none;margin-bottom:20px;transition:.2s}
.back:hover{border-color:var(--ac);transform:translateX(-2px)}
.stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:14px;margin-bottom:24px}
.stat{background:var(--bg2);border:1px solid var(--br);border-radius:12px;padding:16px;transition:.2s}
.stat:hover{border-color:var(--ac);transform:translateY(-2px)}
.stat.active{border-color:var(--green)}
.stat.dormant{border-color:var(--yellow)}
.stat.archive{border-color:var(--tx2)}
.stat .n{font-size:28px;font-weight:800;color:var(--ac);margin-bottom:4px}
.stat.active .n{color:var(--green)}
.stat.dormant .n{color:var(--yellow)}
.stat.archive .n{color:var(--tx2)}
.stat .l{font-size:11px;color:var(--tx2);text-transform:uppercase;letter-spacing:.5px}
.tabs{display:flex;gap:8px;margin-bottom:20px;border-bottom:1px solid var(--br)}
.tab{padding:10px 20px;background:none;border:none;color:var(--tx2);cursor:pointer;font-weight:600;font-size:14px;border-bottom:2px solid transparent;transition:.2s}
.tab.active{color:var(--ac);border-bottom-color:var(--ac)}
.tab:hover{color:var(--tx)}
.tab .count{display:inline-block;background:var(--bg3);padding:2px 8px;border-radius:10px;font-size:11px;margin-left:6px}
.filter{margin-bottom:16px;display:flex;gap:10px;align-items:center;flex-wrap:wrap}
.filter input{background:var(--bg2);border:1px solid var(--br);border-radius:8px;padding:10px 14px;color:var(--tx);font-size:14px;min-width:240px}
.filter input:focus{outline:none;border-color:var(--ac)}
.filter select{background:var(--bg2);border:1px solid var(--br);border-radius:8px;padding:10px 14px;color:var(--tx);font-size:14px;cursor:pointer}
.pages{display:grid;grid-template-columns:repeat(auto-fill,minmax(320px,1fr));gap:10px}
.page{display:block;padding:12px 14px;background:var(--bg2);border:1px solid var(--br);border-radius:10px;color:var(--tx);text-decoration:none;transition:.2s;position:relative}
.page:hover{border-color:var(--ac);transform:translateY(-1px);box-shadow:0 4px 12px rgba(99,102,241,0.2)}
.page-header{display:flex;justify-content:space-between;align-items:flex-start;gap:8px;margin-bottom:6px}
.pn{font-family:'SF Mono',Menlo,monospace;font-size:12px;color:var(--ac);font-weight:600;word-break:break-all}
.page.active .pn{color:var(--green)}
.page.dormant .pn{color:var(--yellow)}
.page.archive .pn{color:var(--tx2)}
.pt{font-size:13px;color:var(--tx);margin-bottom:4px;font-weight:500}
.pm{font-size:11px;color:var(--tx2);display:flex;gap:10px;flex-wrap:wrap}
.badge{display:inline-block;padding:2px 8px;border-radius:10px;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.3px}
.badge.active{background:rgba(34,197,94,0.2);color:var(--green);border:1px solid var(--green)}
.badge.dormant{background:rgba(251,191,36,0.2);color:var(--yellow);border:1px solid var(--yellow)}
.badge.archive{background:rgba(148,163,184,0.2);color:var(--tx2);border:1px solid var(--tx2)}
.badge.suite{background:var(--bg3);color:var(--tx2);border:1px solid var(--br)}
.empty{text-align:center;padding:40px;color:var(--tx2)}
.loading{text-align:center;padding:40px;color:var(--ac)}
.snippet-btn{display:inline-block;margin-top:10px;padding:10px 16px;background:linear-gradient(135deg,#6366f1,#ec4899);color:#fff;border-radius:8px;font-size:13px;font-weight:600;cursor:pointer;border:none}
.snippet-btn:hover{transform:translateY(-1px);box-shadow:0 4px 12px rgba(99,102,241,0.4)}
#snippet-modal{display:none;position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.8);z-index:100;padding:40px;overflow:auto}
#snippet-modal.show{display:block}
.modal-content{background:var(--bg2);border:1px solid var(--br);border-radius:12px;padding:24px;max-width:900px;margin:0 auto}
.modal-content pre{background:#000;border:1px solid var(--br);border-radius:8px;padding:14px;overflow:auto;font-size:12px;color:var(--green);max-height:500px}
.modal-close{float:right;background:none;border:none;color:var(--tx);font-size:24px;cursor:pointer}
/* === OPUS RESPONSIVE FIX v2 19avr — append-only, doctrine #14 === */
@media(max-width: 480px) {
html, body { overflow-x: hidden !important; max-width: 100vw; }
body, main, section, article { word-break: break-word; overflow-wrap: anywhere; }
img, video, iframe, canvas, svg, table, pre, code { max-width: 100% !important; }
pre, code { white-space: pre-wrap; word-break: break-all; }
table { display: block; overflow-x: auto; }
.container, [class*="container"], [class*="wrapper"] { max-width: 100vw !important; padding-left: 12px !important; padding-right: 12px !important; }
[class*="grid"], [class*="-grid"] { grid-template-columns: 1fr !important; gap: 10px !important; }
[class*="kpi"], [class*="stats"], [class*="-cards"] { grid-template-columns: 1fr !important; }
header, nav, footer { flex-wrap: wrap !important; }
header > *, nav > *, footer > * { max-width: 100%; }
h1 { font-size: 22px !important; word-break: break-word; }
h2 { font-size: 18px !important; }
.pitch, [class*="pitch"], [class*="hero"] { word-break: break-word; overflow-wrap: anywhere; }
}
/* === OPUS RESPONSIVE FIX v2 END === */
</style></head>
<body>
<a href="/weval-technology-platform.html" class="back">← WTP</a>
<h1>Orphans Dashboard</h1>
<div class="sub">Doctrine 92 · Hub Merged · V82 suites métier + D91 classifier</div>
<div class="stats" id="stats"></div>
<div class="tabs">
<button class="tab active" data-filter="all">Tous <span class="count" id="c-all">·</span></button>
<button class="tab" data-filter="ACTIVE">Actifs à rebrancher <span class="count" id="c-active">·</span></button>
<button class="tab" data-filter="DORMANT">Dormant <span class="count" id="c-dormant">·</span></button>
<button class="tab" data-filter="ARCHIVE">Archive <span class="count" id="c-archive">·</span></button>
</div>
<div class="filter">
<input type="text" id="search" placeholder="Rechercher page, titre ou suite métier…">
<select id="suite-filter"><option value="">Toutes suites</option></select>
<button class="snippet-btn" onclick="showSnippet()">📋 Voir snippet HTML WTP-ready</button>
</div>
<div id="pages" class="pages"><div class="loading">Chargement…</div></div>
<div id="snippet-modal">
<div class="modal-content">
<button class="modal-close" onclick="hideSnippet()">×</button>
<h2>Snippet HTML prêt à injecter dans WTP</h2>
<p class="sub">Additive pur · avant &lt;/body&gt; · pattern V80 · GOLD backup obligatoire</p>
<pre id="snippet-code">Chargement…</pre>
<button class="snippet-btn" onclick="copySnippet()">Copier</button>
</div>
</div>
<script>
let DATA = null;
let CURRENT_FILTER = 'all';
let CURRENT_SUITE = '';
let SEARCH_TERM = '';
async function load() {
try {
const r = await fetch('/api/opus5-orphans-hub.php');
DATA = await r.json();
renderStats();
renderSuiteFilter();
render();
} catch (e) {
document.getElementById('pages').innerHTML = '<div class="empty">Erreur chargement : ' + e.message + '</div>';
}
}
function renderStats() {
const s = DATA.stats;
document.getElementById('stats').innerHTML = `
<div class="stat"><div class="n">${s.total_orphans}</div><div class="l">Total orphelins</div></div>
<div class="stat active"><div class="n">${s.active_to_link}</div><div class="l">Actifs à rebrancher</div></div>
<div class="stat dormant"><div class="n">${s.dormant_candidate}</div><div class="l">Dormant (user decide)</div></div>
<div class="stat archive"><div class="n">${s.archive_legit}</div><div class="l">Archive légitime</div></div>
<div class="stat"><div class="n">${s.suites_v82}</div><div class="l">Suites métier V82</div></div>
<div class="stat"><div class="n">${s.sync_ok ? '✓' : '≠'}</div><div class="l">V82↔D91 sync</div></div>
`;
document.getElementById('c-all').textContent = s.total_orphans;
document.getElementById('c-active').textContent = s.active_to_link;
document.getElementById('c-dormant').textContent = s.dormant_candidate;
document.getElementById('c-archive').textContent = s.archive_legit;
}
function renderSuiteFilter() {
const suites = [...new Set(DATA.merged.map(m => m.suite_v82))].sort();
const sel = document.getElementById('suite-filter');
suites.forEach(s => sel.innerHTML += `<option value="${s}">${s}</option>`);
}
function render() {
let filtered = DATA.merged;
if (CURRENT_FILTER !== 'all') filtered = filtered.filter(m => m.classif_d91 === CURRENT_FILTER);
if (CURRENT_SUITE) filtered = filtered.filter(m => m.suite_v82 === CURRENT_SUITE);
if (SEARCH_TERM) {
const q = SEARCH_TERM.toLowerCase();
filtered = filtered.filter(m =>
m.page.toLowerCase().includes(q) ||
(m.title||'').toLowerCase().includes(q) ||
(m.suite_v82||'').toLowerCase().includes(q)
);
}
const container = document.getElementById('pages');
if (filtered.length === 0) {
container.innerHTML = '<div class="empty">Aucun orphelin pour ce filtre</div>';
return;
}
container.innerHTML = filtered.map(m => {
const cls = m.classif_d91.toLowerCase();
return `
<a href="${m.url}" class="page ${cls}" target="_blank">
<div class="page-header">
<div class="pn">${m.page}</div>
<span class="badge ${cls}">${m.classif_d91}</span>
</div>
<div class="pt">${m.title || '(sans titre)'}</div>
<div class="pm">
<span class="badge suite">${m.suite_v82}</span>
<span>${m.size_kb} KB</span>
<span>${m.class}</span>
${m.reason ? '<span>· '+m.reason+'</span>' : ''}
</div>
</a>
`;
}).join('');
}
document.querySelectorAll('.tab').forEach(t => t.onclick = () => {
document.querySelectorAll('.tab').forEach(x => x.classList.remove('active'));
t.classList.add('active');
CURRENT_FILTER = t.dataset.filter;
render();
});
document.getElementById('search').oninput = e => { SEARCH_TERM = e.target.value; render(); };
document.getElementById('suite-filter').onchange = e => { CURRENT_SUITE = e.target.value; render(); };
function showSnippet() {
document.getElementById('snippet-modal').classList.add('show');
document.getElementById('snippet-code').textContent = DATA.snippet_html || '(empty)';
}
function hideSnippet() { document.getElementById('snippet-modal').classList.remove('show'); }
function copySnippet() {
navigator.clipboard.writeText(DATA.snippet_html);
alert('Snippet copié — paste avant
<!-- === 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 t34final) --><script src="/wtp-unified-dock.js" defer></script>
</body> dans WTP');
}
load();
</script>
<script src="/api/archi-meta-badge.js" defer></script>
</body></html>