Some checks failed
WEVAL NonReg / nonreg (push) Has been cancelled
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
190 lines
10 KiB
HTML
190 lines
10 KiB
HTML
<!DOCTYPE html><html lang="fr"><head><meta charset="UTF-8"><title>DMAIC Workbench</title>
|
|
<style>
|
|
body{font-family:system-ui;background:#0a0e1a;color:#e2e8f0;margin:0;padding:20px}
|
|
h1{color:#a5b4fc;font-size:1.4rem}
|
|
.cycle-list{background:#151e33;border-radius:8px;padding:16px;margin-bottom:20px}
|
|
.cycle{padding:10px;border-bottom:1px solid #1e293b;cursor:pointer;display:flex;justify-content:space-between;align-items:center}
|
|
.cycle:hover{background:#1e293b}
|
|
.phase-badge{padding:3px 10px;border-radius:4px;font-size:.7rem;font-weight:600;text-transform:uppercase}
|
|
.phase-define{background:#fbbf24;color:#000}
|
|
.phase-measure{background:#3b82f6;color:#fff}
|
|
.phase-analyze{background:#a855f7;color:#fff}
|
|
.phase-improve{background:#22c55e;color:#fff}
|
|
.phase-control{background:#14b8a6;color:#fff}
|
|
.progress{display:flex;align-items:center;gap:8px}
|
|
.progress-bar{width:120px;height:6px;background:#1e293b;border-radius:3px;overflow:hidden}
|
|
.progress-fill{height:100%;background:linear-gradient(90deg,#6366f1,#a855f7)}
|
|
.tabs{display:flex;gap:2px;margin-bottom:14px;background:#151e33;padding:4px;border-radius:8px}
|
|
.tab{flex:1;padding:10px;text-align:center;cursor:pointer;border-radius:6px;font-weight:500;color:#94a3b8}
|
|
.tab.active{background:#6366f1;color:#fff}
|
|
.tab-content{background:#151e33;border-radius:8px;padding:20px;display:none;min-height:200px}
|
|
.tab-content.active{display:block}
|
|
.breadcrumb{color:#64748b;font-size:.8rem;margin-bottom:10px}
|
|
.breadcrumb a{color:#a5b4fc;text-decoration:none}
|
|
.btn{padding:8px 16px;background:#6366f1;color:#fff;border:none;border-radius:6px;cursor:pointer;font-weight:500}
|
|
.btn:hover{background:#4f46e5}
|
|
</style></head>
|
|
<body>
|
|
<div class="breadcrumb"><a href="/vsm-hub.html">VSM Hub</a> / DMAIC Workbench</div>
|
|
<h1>🔬 DMAIC Workbench — <span id="tenant-name">weval</span></h1>
|
|
|
|
<div id="cycle-list" class="cycle-list"><h3>Cycles DMAIC actifs</h3><div>Loading...</div></div>
|
|
|
|
<div id="detail" style="display:none">
|
|
<div class="tabs">
|
|
<div class="tab active" data-tab="define">📋 Define</div>
|
|
<div class="tab" data-tab="measure">📏 Measure</div>
|
|
<div class="tab" data-tab="analyze">🔍 Analyze</div>
|
|
<div class="tab" data-tab="improve">🚀 Improve</div>
|
|
<div class="tab" data-tab="control">🎯 Control</div>
|
|
</div>
|
|
<div id="tab-define" class="tab-content active"><h3>Define — Charter & scope</h3><p id="define-data">Loading...</p></div>
|
|
<div id="tab-measure" class="tab-content"><h3>Measure — Baseline KPIs</h3><p id="measure-data">Loading...</p></div>
|
|
<div id="tab-analyze" class="tab-content"><h3>Analyze — Root causes (Ishikawa 5Why)</h3><p id="analyze-data">Loading...</p></div>
|
|
<div id="tab-improve" class="tab-content"><h3>Improve — Actions & tests</h3><p id="improve-data">Loading...</p></div>
|
|
<div id="tab-control" class="tab-content"><h3>Control — SPC & sustain</h3><p id="control-data">Loading...</p></div>
|
|
<button class="btn" onclick="advance()">Avancer phase</button>
|
|
</div>
|
|
|
|
<script>
|
|
const q = new URLSearchParams(location.search);
|
|
const TENANT = q.get('tenant') || 'weval';
|
|
const VS = q.get('vs_id') || null;
|
|
document.getElementById('tenant-name').textContent = TENANT;
|
|
|
|
fetch(`/api/em/dmaic?tenant=${TENANT}`).then(r=>r.json()).then(d=>{
|
|
const list = document.getElementById('cycle-list');
|
|
list.innerHTML = '<h3>Cycles DMAIC actifs</h3>' + (d.cycles||[]).map(c=>`
|
|
<div class="cycle" onclick="location='?tenant=${TENANT}&vs_id=${c.vs_id}'">
|
|
<div><strong>${c.name}</strong><div style="color:#64748b;font-size:.75rem">${c.vs_id}</div></div>
|
|
<div class="progress">
|
|
<span class="phase-badge phase-${c.phase}">${c.phase}</span>
|
|
<div class="progress-bar"><div class="progress-fill" style="width:${c.progress}%"></div></div>
|
|
<span style="color:#64748b">${c.progress}%</span>
|
|
</div>
|
|
</div>`).join('');
|
|
if (VS) loadDetail(VS);
|
|
});
|
|
|
|
function loadDetail(vsId){
|
|
document.getElementById('detail').style.display='block';
|
|
fetch(`/api/em/dmaic/${TENANT}/${vsId}`).then(r=>r.json()).then(d=>{
|
|
['define','measure','analyze','improve','control'].forEach(ph=>{
|
|
const data = d[`${ph}_data`];
|
|
document.getElementById(`${ph}-data`).textContent = data && Object.keys(data).length ? JSON.stringify(data,null,2) : '(vide — à compléter)';
|
|
});
|
|
});
|
|
}
|
|
|
|
document.querySelectorAll('.tab').forEach(t=>t.onclick=function(){
|
|
document.querySelectorAll('.tab').forEach(x=>x.classList.remove('active'));
|
|
document.querySelectorAll('.tab-content').forEach(x=>x.classList.remove('active'));
|
|
this.classList.add('active');
|
|
document.getElementById('tab-'+this.dataset.tab).classList.add('active');
|
|
});
|
|
|
|
function advance(){
|
|
if (!VS) return;
|
|
const phases = ['define','measure','analyze','improve','control'];
|
|
const current = document.querySelector('.phase-badge')?.textContent || 'define';
|
|
const next = phases[Math.min(phases.indexOf(current)+1, 4)];
|
|
fetch(`/api/em/dmaic?action=advance&tenant=${TENANT}&vs_id=${VS}`, {method:'POST',body:`phase=${next}&progress=${(phases.indexOf(next)+1)*20}`,headers:{'Content-Type':'application/x-www-form-urlencoded'}})
|
|
.then(r=>r.json()).then(d=>{alert('Phase: '+d.phase);location.reload()});
|
|
}
|
|
</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) {
|
|
// Clone card content + show close btn + increase font-size
|
|
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 a more-specific drill is already active (e.g. pp-card custom), let it handle
|
|
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);} });
|
|
}
|
|
}
|
|
|
|
// Initial + mutation observer
|
|
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>
|
|
|
|
<script>
|
|
/* HTMLGUARD_V1_DMAIC - Auto-redirect session expire + error surface */
|
|
(function(){
|
|
if (window._safeJsonGuard) return;
|
|
window._safeJsonGuard = async function(r) {
|
|
const t = (await r.text()).trim();
|
|
if (t.startsWith('<!DOCTYPE') || t.startsWith('<html')) {
|
|
if ((t.indexOf('Login') > -1 || t.indexOf('login') > -1) && !window._sessionExpiredWarned) {
|
|
window._sessionExpiredWarned = true;
|
|
console.warn('[HTMLGUARD_V1_DMAIC] Session expired');
|
|
const banner = document.createElement('div');
|
|
banner.style.cssText = 'position:fixed;top:0;left:0;right:0;z-index:99999;background:#f59e0b;color:#000;padding:10px 20px;text-align:center;font-family:system-ui,sans-serif;font-size:14px;font-weight:600;box-shadow:0 2px 8px rgba(0,0,0,.3)';
|
|
banner.innerHTML = '⚠ Session expirée · <a href="'+window.location.pathname+'" style="color:#7c2d12;text-decoration:underline;margin-left:8px">Se reconnecter</a>';
|
|
document.body.appendChild(banner);
|
|
}
|
|
return {error: 'html_response', isHtmlError: true, status: r.status};
|
|
}
|
|
try { return JSON.parse(t); }
|
|
catch(e) { return {error: 'json_parse: ' + e.message, raw: t.substring(0, 200)}; }
|
|
};
|
|
|
|
// Intercept global fetch to auto-apply guard on .json() calls
|
|
const _origJson = Response.prototype.json;
|
|
// Safer: don't monkey-patch — just expose helper. Existing code works, new code uses _safeJsonGuard.
|
|
})();
|
|
</script>
|
|
<!-- WTP_UDOCK_V1 (Opus 21-avr t34final) --><script src="/wtp-unified-dock.js" defer></script>
|
|
</body></html>
|