@@ -1,5 +1,5 @@
|
||||
{
|
||||
"generated_at": "2026-04-20T14:30:02.246896",
|
||||
"generated_at": "2026-04-20T14:35:01.654450",
|
||||
"stats": {
|
||||
"total": 26,
|
||||
"pending": 20,
|
||||
|
||||
@@ -0,0 +1,281 @@
|
||||
{
|
||||
"ts": "2026-04-20T12:35:01+00:00",
|
||||
"server": "s204",
|
||||
"s204": {
|
||||
"load": 2.16,
|
||||
"uptime": "2026-04-14 11:51:24",
|
||||
"ram_total_mb": 31335,
|
||||
"ram_used_mb": 12356,
|
||||
"ram_free_mb": 18978,
|
||||
"disk_total": "150G",
|
||||
"disk_used": "112G",
|
||||
"disk_free": "33G",
|
||||
"disk_pct": "78%",
|
||||
"fpm_workers": 110,
|
||||
"docker_containers": 19,
|
||||
"cpu_cores": 8
|
||||
},
|
||||
"s95": {
|
||||
"load": 0.68,
|
||||
"disk_pct": "82%",
|
||||
"status": "UP",
|
||||
"ram_total_mb": 15610,
|
||||
"ram_free_mb": 11199
|
||||
},
|
||||
"pmta": [
|
||||
{
|
||||
"name": "SER6",
|
||||
"ip": "110.239.84.121",
|
||||
"status": "DOWN"
|
||||
},
|
||||
{
|
||||
"name": "SER7",
|
||||
"ip": "110.239.65.64",
|
||||
"status": "DOWN"
|
||||
},
|
||||
{
|
||||
"name": "SER8",
|
||||
"ip": "182.160.55.107",
|
||||
"status": "DOWN"
|
||||
},
|
||||
{
|
||||
"name": "SER9",
|
||||
"ip": "110.239.86.68",
|
||||
"status": "DOWN"
|
||||
}
|
||||
],
|
||||
"assets": {
|
||||
"html_pages": 285,
|
||||
"php_apis": 746,
|
||||
"wiki_entries": 1798,
|
||||
"vault_doctrines": 58,
|
||||
"vault_sessions": 87,
|
||||
"vault_decisions": 12
|
||||
},
|
||||
"tools": {
|
||||
"total": 626,
|
||||
"registry_version": "?"
|
||||
},
|
||||
"sovereign": {
|
||||
"status": "UP",
|
||||
"providers": [
|
||||
"Cerebras-fast",
|
||||
"Cerebras-think",
|
||||
"Groq",
|
||||
"Cloudflare-AI",
|
||||
"Gemini",
|
||||
"SambaNova",
|
||||
"NVIDIA-NIM",
|
||||
"Mistral",
|
||||
"Groq-OSS",
|
||||
"HF-Space",
|
||||
"HF-Router",
|
||||
"OpenRouter",
|
||||
"GitHub-Models"
|
||||
],
|
||||
"active": 13,
|
||||
"total": 13,
|
||||
"primary": "Cerebras-fast",
|
||||
"cost": "0€"
|
||||
},
|
||||
"ethica": {
|
||||
"total_hcps": 161730,
|
||||
"with_email": 110437,
|
||||
"with_phone": 155145,
|
||||
"gap_email": 51293,
|
||||
"pct_email": 68.3,
|
||||
"pct_phone": 95.9,
|
||||
"by_country": [
|
||||
{
|
||||
"country": "DZ",
|
||||
"hcps": 122337,
|
||||
"with_email": 78354,
|
||||
"with_tel": 119394,
|
||||
"pct_email": 64,
|
||||
"pct_tel": 97.6
|
||||
},
|
||||
{
|
||||
"country": "MA",
|
||||
"hcps": 19720,
|
||||
"with_email": 15066,
|
||||
"with_tel": 18733,
|
||||
"pct_email": 76.4,
|
||||
"pct_tel": 95
|
||||
},
|
||||
{
|
||||
"country": "TN",
|
||||
"hcps": 17794,
|
||||
"with_email": 15138,
|
||||
"with_tel": 17018,
|
||||
"pct_email": 85.1,
|
||||
"pct_tel": 95.6
|
||||
},
|
||||
{
|
||||
"country": "INTL",
|
||||
"hcps": 1879,
|
||||
"with_email": 1879,
|
||||
"with_tel": 0,
|
||||
"pct_email": 100,
|
||||
"pct_tel": 0
|
||||
}
|
||||
]
|
||||
},
|
||||
"docker": [
|
||||
{
|
||||
"name": "loki",
|
||||
"status": "Up 4 days",
|
||||
"ports": ""
|
||||
},
|
||||
{
|
||||
"name": "listmonk",
|
||||
"status": "Up 4 days",
|
||||
"ports": ""
|
||||
},
|
||||
{
|
||||
"name": "plausible-plausible-1",
|
||||
"status": "Up 2 days",
|
||||
"ports": ""
|
||||
},
|
||||
{
|
||||
"name": "plausible-plausible-db-1",
|
||||
"status": "Up 2 days",
|
||||
"ports": ""
|
||||
},
|
||||
{
|
||||
"name": "plausible-plausible-events-db-1",
|
||||
"status": "Up 2 days",
|
||||
"ports": ""
|
||||
},
|
||||
{
|
||||
"name": "n8n-docker-n8n-1",
|
||||
"status": "Up 4 days",
|
||||
"ports": ""
|
||||
},
|
||||
{
|
||||
"name": "mattermost-docker-mm-db-1",
|
||||
"status": "Up 4 days",
|
||||
"ports": ""
|
||||
},
|
||||
{
|
||||
"name": "mattermost-docker-mattermost-1",
|
||||
"status": "Up 4 days (healthy)",
|
||||
"ports": ""
|
||||
},
|
||||
{
|
||||
"name": "twenty",
|
||||
"status": "Up 4 days",
|
||||
"ports": ""
|
||||
},
|
||||
{
|
||||
"name": "twenty-redis",
|
||||
"status": "Up 4 days",
|
||||
"ports": ""
|
||||
},
|
||||
{
|
||||
"name": "langfuse",
|
||||
"status": "Up 4 days",
|
||||
"ports": ""
|
||||
},
|
||||
{
|
||||
"name": "redis-weval",
|
||||
"status": "Up 5 days",
|
||||
"ports": ""
|
||||
},
|
||||
{
|
||||
"name": "gitea",
|
||||
"status": "Up 5 days",
|
||||
"ports": ""
|
||||
},
|
||||
{
|
||||
"name": "node-exporter",
|
||||
"status": "Up 5 days",
|
||||
"ports": ""
|
||||
},
|
||||
{
|
||||
"name": "prometheus",
|
||||
"status": "Up 5 days",
|
||||
"ports": ""
|
||||
},
|
||||
{
|
||||
"name": "searxng",
|
||||
"status": "Up 5 days",
|
||||
"ports": ""
|
||||
},
|
||||
{
|
||||
"name": "uptime-kuma",
|
||||
"status": "Up 12 hours (healthy)",
|
||||
"ports": ""
|
||||
},
|
||||
{
|
||||
"name": "vaultwarden",
|
||||
"status": "Up 5 days (healthy)",
|
||||
"ports": ""
|
||||
},
|
||||
{
|
||||
"name": "qdrant",
|
||||
"status": "Up 5 days",
|
||||
"ports": ""
|
||||
}
|
||||
],
|
||||
"crons": {
|
||||
"active": 35
|
||||
},
|
||||
"git": {
|
||||
"head": "d475e1213 auto-sync-1435",
|
||||
"dirty": 2,
|
||||
"status": "DIRTY"
|
||||
},
|
||||
"nonreg": {
|
||||
"total": 153,
|
||||
"passed": 153,
|
||||
"score": "100%"
|
||||
},
|
||||
"services": [
|
||||
{
|
||||
"name": "DeerFlow",
|
||||
"port": 3002,
|
||||
"status": "UP"
|
||||
},
|
||||
{
|
||||
"name": "DeerFlow API",
|
||||
"port": 8001,
|
||||
"status": "UP"
|
||||
},
|
||||
{
|
||||
"name": "Qdrant",
|
||||
"port": 6333,
|
||||
"status": "UP"
|
||||
},
|
||||
{
|
||||
"name": "Ollama",
|
||||
"port": 11434,
|
||||
"status": "UP"
|
||||
},
|
||||
{
|
||||
"name": "Redis",
|
||||
"port": 6379,
|
||||
"status": "UP"
|
||||
},
|
||||
{
|
||||
"name": "Sovereign",
|
||||
"port": 4000,
|
||||
"status": "UP"
|
||||
},
|
||||
{
|
||||
"name": "SearXNG",
|
||||
"port": 8080,
|
||||
"status": "UP"
|
||||
}
|
||||
],
|
||||
"whisper": {
|
||||
"binary": "COMPILED",
|
||||
"model": "142MB"
|
||||
},
|
||||
"grand_total": 3532,
|
||||
"health": {
|
||||
"score": 5,
|
||||
"max": 6,
|
||||
"pct": 83
|
||||
},
|
||||
"elapsed_ms": 10641
|
||||
}
|
||||
@@ -206,7 +206,7 @@ if ($action === "intents_wired" || $action === "intents_list") {
|
||||
if (strpos($f, ".gold") !== false || strpos($f, ".GOLD") !== false) continue;
|
||||
$content = @file_get_contents($f);
|
||||
$trigs = [];
|
||||
if (preg_match_all('/preg_match\(['"]([^'"]+)['"]/', $content, $mm)) {
|
||||
if (preg_match_all('/preg_match\([\'"]([^\'"]+)[\'"]/', $content, $mm)) {
|
||||
$trigs = array_slice($mm[1], 0, 3);
|
||||
}
|
||||
$intents[] = [
|
||||
@@ -222,15 +222,13 @@ if ($action === "intents_wired" || $action === "intents_list") {
|
||||
|
||||
|
||||
// ============================================================================
|
||||
// V34 — WORKFLOW ACTIONS (rapatrié depuis /office-workflow.php stale)
|
||||
// Pointe S95 source of truth (10.1.0.3) via $pdo existant
|
||||
// V34 WORKFLOW ACTIONS - rapatrie depuis office-workflow.php stale, pointe S95
|
||||
// ============================================================================
|
||||
|
||||
$STEP_NAMES = ['Register', 'Verify Email', 'DNS Setup', 'Domain Verify', 'Exchange Config', 'AntiSpam', 'Warmup', 'Live', 'Done'];
|
||||
$STEP_NAMES = ["Register", "Verify Email", "DNS Setup", "Domain Verify", "Exchange Config", "AntiSpam", "Warmup", "Live", "Done"];
|
||||
|
||||
if ($action === "workflow_overview") {
|
||||
$by_step = $pdo->query("
|
||||
SELECT current_step, COUNT(*) AS total,
|
||||
$q = "SELECT current_step, COUNT(*) AS total,
|
||||
COUNT(*) FILTER (WHERE LOWER(status)='active') AS active,
|
||||
COUNT(*) FILTER (WHERE LOWER(status)='warming') AS warming,
|
||||
COUNT(*) FILTER (WHERE LOWER(status)='suspended') AS suspended,
|
||||
@@ -238,16 +236,13 @@ if ($action === "workflow_overview") {
|
||||
COUNT(*) FILTER (WHERE LOWER(status)='pending' OR status IS NULL) AS pending
|
||||
FROM admin.office_accounts
|
||||
WHERE current_step IS NOT NULL
|
||||
GROUP BY current_step ORDER BY current_step
|
||||
")->fetchAll(PDO::FETCH_ASSOC);
|
||||
GROUP BY current_step ORDER BY current_step";
|
||||
$by_step = $pdo->query($q)->fetchAll(PDO::FETCH_ASSOC);
|
||||
foreach ($by_step as &$row) {
|
||||
$idx = (int)$row["current_step"];
|
||||
$row["step_name"] = $STEP_NAMES[$idx] ?? ("step $idx");
|
||||
$row["step_name"] = $STEP_NAMES[$idx] ?? ("step " . $idx);
|
||||
}
|
||||
$by_status = $pdo->query("
|
||||
SELECT COALESCE(LOWER(status), 'null') AS status, COUNT(*) AS n
|
||||
FROM admin.office_accounts GROUP BY 1 ORDER BY 2 DESC
|
||||
")->fetchAll(PDO::FETCH_ASSOC);
|
||||
$by_status = $pdo->query("SELECT COALESCE(LOWER(status), 'null') AS status, COUNT(*) AS n FROM admin.office_accounts GROUP BY 1 ORDER BY 2 DESC")->fetchAll(PDO::FETCH_ASSOC);
|
||||
$total = (int)$pdo->query("SELECT COUNT(*) FROM admin.office_accounts")->fetchColumn();
|
||||
echo json_encode([
|
||||
"ok" => true,
|
||||
@@ -318,24 +313,10 @@ if ($action === "workflow_setstatus" && $_SERVER["REQUEST_METHOD"] === "POST") {
|
||||
}
|
||||
|
||||
if ($action === "workflow_steps_stats") {
|
||||
// Workflow steps table state
|
||||
$ws_count = (int)$pdo->query("SELECT COUNT(*) FROM admin.office_workflow_steps")->fetchColumn();
|
||||
$ws_accounts = (int)$pdo->query("SELECT COUNT(DISTINCT account_id) FROM admin.office_workflow_steps")->fetchColumn();
|
||||
$steps = $ws_count > 0 ? $pdo->query("
|
||||
SELECT step_name, COUNT(*) AS total,
|
||||
COUNT(*) FILTER (WHERE status IN ('Complete','complete','Completed')) AS done,
|
||||
COUNT(*) FILTER (WHERE status='Pending') AS pending,
|
||||
COUNT(*) FILTER (WHERE status IN ('Failed','Error')) AS failed
|
||||
FROM admin.office_workflow_steps GROUP BY step_name ORDER BY 2 DESC
|
||||
")->fetchAll(PDO::FETCH_ASSOC) : [];
|
||||
echo json_encode([
|
||||
"ok" => true,
|
||||
"workflow_steps_table" => [
|
||||
"total_steps" => $ws_count,
|
||||
"unique_accounts" => $ws_accounts,
|
||||
"by_step_name" => $steps
|
||||
]
|
||||
]);
|
||||
$steps = $ws_count > 0 ? $pdo->query("SELECT step_name, COUNT(*) AS total FROM admin.office_workflow_steps GROUP BY step_name ORDER BY 2 DESC")->fetchAll(PDO::FETCH_ASSOC) : [];
|
||||
echo json_encode(["ok" => true, "workflow_steps_table" => ["total_steps" => $ws_count, "unique_accounts" => $ws_accounts, "by_step_name" => $steps]]);
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"ok": true,
|
||||
"version": "V83-business-kpi",
|
||||
"ts": "2026-04-20T12:35:00+00:00",
|
||||
"ts": "2026-04-20T12:35:44+00:00",
|
||||
"summary": {
|
||||
"total_categories": 7,
|
||||
"total_kpis": 56,
|
||||
|
||||
@@ -3,7 +3,7 @@ return array (
|
||||
'name' => 'wevia_contact_sales',
|
||||
'triggers' =>
|
||||
array (
|
||||
0 => 'contact',
|
||||
0 => 'contact weval',
|
||||
1 => 'commercial',
|
||||
2 => 'sales contact',
|
||||
3 => 'demo request',
|
||||
@@ -15,4 +15,5 @@ return array (
|
||||
'status' => 'EXECUTED',
|
||||
'created_at' => '2026-04-19T17:23:52+00:00',
|
||||
'source' => 'opus4-autowire-early-v2',
|
||||
'fix' => 'trigger contact → contact weval (doctrine #13 cause racine - 20avr)',
|
||||
);
|
||||
|
||||
160
office-app.html
@@ -365,6 +365,7 @@
|
||||
<button class="tab" data-tab="actions">ACTIONS</button>
|
||||
<button class="tab" data-tab="scripts">SCRIPTS & APIs</button>
|
||||
<button class="tab" data-tab="intents">INTENTS CHAT</button>
|
||||
<button class="tab" data-tab="workflow">WORKFLOW</button>
|
||||
<button class="tab" data-tab="console">CONSOLE</button>
|
||||
</div>
|
||||
|
||||
@@ -487,6 +488,69 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- WORKFLOW PANEL V34 -->
|
||||
<div class="panel" id="panel-workflow">
|
||||
<div class="action-bar">
|
||||
<button class="btn primary" onclick="loadWorkflow()">▶ Load workflow</button>
|
||||
<button class="btn" onclick="loadWorkflow()">↻ Refresh</button>
|
||||
</div>
|
||||
<div class="stats" id="wf-stats" style="margin-bottom:18px">
|
||||
<div class="stat-card"><div class="lbl">Total</div><div class="val" id="wf-total">—</div><div class="sub">loading</div></div>
|
||||
<div class="stat-card ok"><div class="lbl">Active</div><div class="val" id="wf-active">—</div><div class="sub">status active</div></div>
|
||||
<div class="stat-card warn"><div class="lbl">Warming</div><div class="val" id="wf-warming">—</div><div class="sub">warmup</div></div>
|
||||
<div class="stat-card"><div class="lbl">Pending</div><div class="val" id="wf-pending">—</div><div class="sub">pending</div></div>
|
||||
<div class="stat-card fail"><div class="lbl">Blocked</div><div class="val" id="wf-blocked">—</div><div class="sub">blocked</div></div>
|
||||
</div>
|
||||
<div class="tbl-wrap" style="margin-bottom:18px">
|
||||
<div class="tbl-head">
|
||||
<h3>WORKFLOW STEPS — 8 steps Register → Live</h3>
|
||||
<span class="info" id="wf-info">—</span>
|
||||
</div>
|
||||
<table id="wf-steps-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>STEP #</th>
|
||||
<th>NAME</th>
|
||||
<th class="td-center">TOTAL</th>
|
||||
<th class="td-center">ACTIVE</th>
|
||||
<th class="td-center">WARMING</th>
|
||||
<th class="td-center">PENDING</th>
|
||||
<th class="td-center">BLOCKED</th>
|
||||
<th class="td-center">%</th>
|
||||
<th>ACTIONS</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="wf-steps-body">
|
||||
<tr><td colspan="9" class="loading">Click Load workflow</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="tbl-wrap">
|
||||
<div class="tbl-head">
|
||||
<h3>ACCOUNTS (drill-down par step)</h3>
|
||||
<span class="info" id="wf-accounts-info">Click un step pour voir accounts</span>
|
||||
</div>
|
||||
<table id="wf-accounts-table" style="display:none">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#ID</th>
|
||||
<th>TENANT DOMAIN</th>
|
||||
<th>ADMIN EMAIL</th>
|
||||
<th>STEP</th>
|
||||
<th>STATUS</th>
|
||||
<th class="td-center">LICENSE</th>
|
||||
<th class="td-center">MFA</th>
|
||||
<th>ACTIONS</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="wf-accounts-body"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /WORKFLOW PANEL V34 -->
|
||||
|
||||
|
||||
<!-- CONSOLE PANEL -->
|
||||
<div class="panel" id="panel-console">
|
||||
<div class="tbl-head" style="background:var(--bg-2);border:1px solid var(--border);border-radius:10px 10px 0 0;margin-bottom:0">
|
||||
@@ -709,9 +773,105 @@ function switchTab(name) {
|
||||
document.querySelectorAll('.panel').forEach(p => p.classList.toggle('active', p.id === 'panel-' + name));
|
||||
if (name === 'intents' && !document.getElementById('intents-body').children.length) loadIntents();
|
||||
if (name === 'scripts' && !document.getElementById('scripts-apis').children.length) loadApis();
|
||||
if (name === 'workflow' && !document.getElementById('wf-steps-body').children.length) loadWorkflow();
|
||||
if (name === 'workflow' && document.getElementById('wf-steps-body').children.length === 1) loadWorkflow();
|
||||
|
||||
}
|
||||
document.querySelectorAll('.tab').forEach(t => t.addEventListener('click', () => switchTab(t.dataset.tab)));
|
||||
|
||||
|
||||
// V34 — WORKFLOW ACTIONS
|
||||
async function loadWorkflow() {
|
||||
try {
|
||||
const r = await fetch(API + '?action=workflow_overview');
|
||||
const d = await r.json();
|
||||
if (!d.ok) throw new Error(d.error || 'fail');
|
||||
|
||||
// Aggregate status totals
|
||||
const bs = {};
|
||||
(d.by_status || []).forEach(s => bs[s.status] = parseInt(s.n));
|
||||
document.getElementById('wf-total').textContent = d.total_accounts;
|
||||
document.getElementById('wf-active').textContent = bs.active || 0;
|
||||
document.getElementById('wf-warming').textContent = bs.warming || 0;
|
||||
document.getElementById('wf-pending').textContent = bs.pending || 0;
|
||||
document.getElementById('wf-blocked').textContent = bs.blocked || 0;
|
||||
|
||||
const body = document.getElementById('wf-steps-body');
|
||||
document.getElementById('wf-info').textContent = (d.by_step||[]).length + ' steps';
|
||||
body.innerHTML = (d.by_step || []).map(s => {
|
||||
const pct = d.total_accounts ? ((s.total / d.total_accounts) * 100).toFixed(1) : 0;
|
||||
return `<tr>
|
||||
<td style="color:var(--accent-2)"><strong>${s.current_step}</strong></td>
|
||||
<td>${s.step_name}</td>
|
||||
<td class="td-center">${s.total}</td>
|
||||
<td class="td-center"><span class="pill ok">${s.active}</span></td>
|
||||
<td class="td-center">${s.warming || 0}</td>
|
||||
<td class="td-center">${s.pending || 0}</td>
|
||||
<td class="td-center">${s.blocked > 0 ? '<span class="pill warn">' + s.blocked + '</span>' : 0}</td>
|
||||
<td class="td-center">${pct}%</td>
|
||||
<td><button class="btn sm" onclick="loadWfAccounts(${s.current_step})">drill</button></td>
|
||||
</tr>`;
|
||||
}).join('');
|
||||
log('workflow loaded: ' + d.total_accounts + ' accounts', 'ok');
|
||||
} catch (e) {
|
||||
log('workflow FAIL: ' + e.message, 'fail');
|
||||
}
|
||||
}
|
||||
|
||||
async function loadWfAccounts(step) {
|
||||
log('drill step=' + step + '...');
|
||||
try {
|
||||
const r = await fetch(API + '?action=workflow_accounts&step=' + step + '&limit=100');
|
||||
const d = await r.json();
|
||||
if (!d.ok) throw new Error(d.error);
|
||||
document.getElementById('wf-accounts-info').textContent = 'step=' + step + ' · ' + d.count + ' accounts';
|
||||
document.getElementById('wf-accounts-table').style.display = '';
|
||||
const body = document.getElementById('wf-accounts-body');
|
||||
body.innerHTML = (d.accounts || []).map(a => {
|
||||
const stPill = a.status === 'active' ? 'ok' : (a.status === 'pending' ? 'no' : (a.status === 'blocked' ? 'warn' : 'no'));
|
||||
return `<tr data-aid="${a.id}">
|
||||
<td>${a.id}</td>
|
||||
<td style="color:var(--accent-2)">${a.tenant_domain || ''}</td>
|
||||
<td>${a.admin_email || '<span style=color:var(--ink-faint)>—</span>'}</td>
|
||||
<td>${a.current_step} ${a.step_name}</td>
|
||||
<td><span class="pill ${stPill}">${a.status || 'null'}</span></td>
|
||||
<td class="td-center">${a.has_license ? '✓' : '—'}</td>
|
||||
<td class="td-center">${a.has_mfa ? '✓' : '—'}</td>
|
||||
<td>
|
||||
<button class="btn sm" onclick="wfAdv(${a.id})" title="advance step">▶</button>
|
||||
<button class="btn sm" onclick="wfRet(${a.id})" title="retreat step">◀</button>
|
||||
</td>
|
||||
</tr>`;
|
||||
}).join('');
|
||||
log(' ' + d.count + ' accounts for step ' + step, 'ok');
|
||||
} catch (e) {
|
||||
log('drill FAIL: ' + e.message, 'fail');
|
||||
}
|
||||
}
|
||||
|
||||
async function wfAdv(aid) {
|
||||
try {
|
||||
const fd = new FormData();
|
||||
fd.append('aid', aid);
|
||||
const r = await fetch(API + '?action=workflow_advance', { method: 'POST', body: fd });
|
||||
const d = await r.json();
|
||||
if (d.ok) log('advance #' + aid + ': step ' + d.from_step + ' -> ' + d.to_step + ' (' + d.new_step_name + ')', 'ok');
|
||||
else log('advance #' + aid + ' FAIL: ' + d.error, 'fail');
|
||||
} catch (e) { log('advance ERR: ' + e.message, 'fail'); }
|
||||
}
|
||||
|
||||
async function wfRet(aid) {
|
||||
try {
|
||||
const fd = new FormData();
|
||||
fd.append('aid', aid);
|
||||
const r = await fetch(API + '?action=workflow_retreat', { method: 'POST', body: fd });
|
||||
const d = await r.json();
|
||||
if (d.ok) log('retreat #' + aid + ': step ' + d.from_step + ' -> ' + d.to_step + ' (' + d.new_step_name + ')', 'ok');
|
||||
else log('retreat #' + aid + ' FAIL: ' + d.error, 'fail');
|
||||
} catch (e) { log('retreat ERR: ' + e.message, 'fail'); }
|
||||
}
|
||||
|
||||
|
||||
// init
|
||||
loadOverview();
|
||||
loadTenants();
|
||||
|
||||
|
Before Width: | Height: | Size: 98 KiB After Width: | Height: | Size: 98 KiB |
|
Before Width: | Height: | Size: 88 KiB After Width: | Height: | Size: 88 KiB |
|
Before Width: | Height: | Size: 43 KiB After Width: | Height: | Size: 43 KiB |
|
Before Width: | Height: | Size: 43 KiB After Width: | Height: | Size: 43 KiB |
|
Before Width: | Height: | Size: 91 KiB After Width: | Height: | Size: 91 KiB |
|
Before Width: | Height: | Size: 317 KiB After Width: | Height: | Size: 202 KiB |
|
Before Width: | Height: | Size: 194 KiB After Width: | Height: | Size: 194 KiB |
|
Before Width: | Height: | Size: 133 KiB After Width: | Height: | Size: 133 KiB |
|
Before Width: | Height: | Size: 137 KiB After Width: | Height: | Size: 138 KiB |
|
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 45 KiB |
|
Before Width: | Height: | Size: 228 KiB After Width: | Height: | Size: 227 KiB |
|
Before Width: | Height: | Size: 151 KiB After Width: | Height: | Size: 152 KiB |
@@ -24,7 +24,7 @@ body{font-family:-apple-system,sans-serif;background:#0a0e27;color:#e2e8f0;paddi
|
||||
<body>
|
||||
<div class="header">
|
||||
<h1>🎬 V90 Selenium Business Scenarios</h1>
|
||||
<div class="meta">Generated: 2026-04-20T14:33:11 · Duration: 39.48s · Chrome headless</div>
|
||||
<div class="meta">Generated: 2026-04-20T14:35:24 · Duration: 38.11s · Chrome headless</div>
|
||||
</div>
|
||||
<div class="stats">
|
||||
<div class="stat"><div class="val pass">6</div><div class="label">PASS</div></div>
|
||||
@@ -34,23 +34,23 @@ body{font-family:-apple-system,sans-serif;background:#0a0e27;color:#e2e8f0;paddi
|
||||
</div>
|
||||
<div class="scenario pass">
|
||||
<h3><span class="pass">[PASS]</span> wtp_main_with_auth</h3>
|
||||
<div class="meta">URL: https://weval-consulting.com/weval-technology-platform.html · Load: 1.08s · Steps: 2</div>
|
||||
<div class="meta">URL: https://weval-consulting.com/weval-technology-platform.html · Load: 1.17s · Steps: 2</div>
|
||||
<div class="meta">Title: WEVAL — Connexion</div>
|
||||
<div class="checks"><span class="check-pass">✓ text_in_body: "weval"</span><br></div><div class="screenshots"><a href="/test-results/v90/wtp_main_with_auth_01_top.png" target="_blank"><img src="/test-results/v90/wtp_main_with_auth_01_top.png" alt="01_top" title="01_top"></a><a href="/test-results/v90/wtp_main_with_auth_02_bottom.png" target="_blank"><img src="/test-results/v90/wtp_main_with_auth_02_bottom.png" alt="02_bottom" title="02_bottom"></a></div></div><div class="scenario warn">
|
||||
<h3><span class="warn">[WARN]</span> login_ux</h3>
|
||||
<div class="meta">URL: https://weval-consulting.com/login.html · Load: 0.12s · Steps: 2</div>
|
||||
<div class="meta">URL: https://weval-consulting.com/login.html · Load: 0.13s · Steps: 2</div>
|
||||
<div class="meta">Title: WEVAL — Connexion</div>
|
||||
<div class="checks"><span class="check-pass">✓ element_exists: "#pass"</span><br><span class="check-fail">✗ text_in_body: "Mot de passe"</span><br></div><div class="screenshots"><a href="/test-results/v90/login_ux_01_top.png" target="_blank"><img src="/test-results/v90/login_ux_01_top.png" alt="01_top" title="01_top"></a><a href="/test-results/v90/login_ux_02_bottom.png" target="_blank"><img src="/test-results/v90/login_ux_02_bottom.png" alt="02_bottom" title="02_bottom"></a></div></div><div class="scenario pass">
|
||||
<h3><span class="pass">[PASS]</span> main_site_public</h3>
|
||||
<div class="meta">URL: https://weval-consulting.com/ · Load: 1.08s · Steps: 2</div>
|
||||
<div class="meta">URL: https://weval-consulting.com/ · Load: 1.19s · Steps: 2</div>
|
||||
<div class="meta">Title: WEVAL Consulting — Enterprise Digital Transformation | ERP · Cloud · IA · Cybers</div>
|
||||
<div class="checks"><span class="check-pass">✓ text_in_title: "WEVAL"</span><br><span class="check-pass">✓ text_in_body: "weval"</span><br></div><div class="screenshots"><a href="/test-results/v90/main_site_public_01_top.png" target="_blank"><img src="/test-results/v90/main_site_public_01_top.png" alt="01_top" title="01_top"></a><a href="/test-results/v90/main_site_public_02_bottom.png" target="_blank"><img src="/test-results/v90/main_site_public_02_bottom.png" alt="02_bottom" title="02_bottom"></a></div></div><div class="scenario pass">
|
||||
<h3><span class="pass">[PASS]</span> business_kpi_dashboard</h3>
|
||||
<div class="meta">URL: https://weval-consulting.com/business-kpi-dashboard.php · Load: 2.28s · Steps: 2</div>
|
||||
<div class="meta">URL: https://weval-consulting.com/business-kpi-dashboard.php · Load: 2.35s · Steps: 2</div>
|
||||
<div class="meta">Title: V83 Business KPI Dashboard — SaaS Ready</div>
|
||||
<div class="checks"><span class="check-pass">✓ text_in_body: "kpi"</span><br></div><div class="screenshots"><a href="/test-results/v90/business_kpi_dashboard_01_top.png" target="_blank"><img src="/test-results/v90/business_kpi_dashboard_01_top.png" alt="01_top" title="01_top"></a><a href="/test-results/v90/business_kpi_dashboard_02_bottom.png" target="_blank"><img src="/test-results/v90/business_kpi_dashboard_02_bottom.png" alt="02_bottom" title="02_bottom"></a></div></div><div class="scenario warn">
|
||||
<h3><span class="warn">[WARN]</span> depts_kpi_page</h3>
|
||||
<div class="meta">URL: https://weval-consulting.com/v64-15depts.html · Load: 0.93s · Steps: 2</div>
|
||||
<div class="meta">URL: https://weval-consulting.com/v64-15depts.html · Load: 0.88s · Steps: 2</div>
|
||||
<div class="meta">Title: WEVAL Consulting — Enterprise Digital Transformation | ERP · Cloud · IA · Cybers</div>
|
||||
<div class="checks"><span class="check-fail">✗ text_in_body: "depart"</span><br></div><div class="screenshots"><a href="/test-results/v90/depts_kpi_page_01_top.png" target="_blank"><img src="/test-results/v90/depts_kpi_page_01_top.png" alt="01_top" title="01_top"></a><a href="/test-results/v90/depts_kpi_page_02_bottom.png" target="_blank"><img src="/test-results/v90/depts_kpi_page_02_bottom.png" alt="02_bottom" title="02_bottom"></a></div></div><div class="scenario pass">
|
||||
<h3><span class="pass">[PASS]</span> api_manifest</h3>
|
||||
@@ -58,10 +58,10 @@ body{font-family:-apple-system,sans-serif;background:#0a0e27;color:#e2e8f0;paddi
|
||||
<div class="meta">Title: </div>
|
||||
<div class="checks"><span class="check-pass">✓ text_in_body: "weval"</span><br><span class="check-pass">✓ text_in_body: "health"</span><br></div><div class="screenshots"><a href="/test-results/v90/api_manifest_01_top.png" target="_blank"><img src="/test-results/v90/api_manifest_01_top.png" alt="01_top" title="01_top"></a><a href="/test-results/v90/api_manifest_02_bottom.png" target="_blank"><img src="/test-results/v90/api_manifest_02_bottom.png" alt="02_bottom" title="02_bottom"></a></div></div><div class="scenario pass">
|
||||
<h3><span class="pass">[PASS]</span> api_l99_honest</h3>
|
||||
<div class="meta">URL: https://weval-consulting.com/api/l99-honest.php · Load: 0.11s · Steps: 2</div>
|
||||
<div class="meta">URL: https://weval-consulting.com/api/l99-honest.php · Load: 0.12s · Steps: 2</div>
|
||||
<div class="meta">Title: </div>
|
||||
<div class="checks"><span class="check-pass">✓ text_in_body: "6sigma"</span><br><span class="check-pass">✓ text_in_body: "201"</span><br></div><div class="screenshots"><a href="/test-results/v90/api_l99_honest_01_top.png" target="_blank"><img src="/test-results/v90/api_l99_honest_01_top.png" alt="01_top" title="01_top"></a><a href="/test-results/v90/api_l99_honest_02_bottom.png" target="_blank"><img src="/test-results/v90/api_l99_honest_02_bottom.png" alt="02_bottom" title="02_bottom"></a></div></div><div class="scenario pass">
|
||||
<h3><span class="pass">[PASS]</span> api_business_kpi_full</h3>
|
||||
<div class="meta">URL: https://weval-consulting.com/api/wevia-v83-business-kpi.php?action=full · Load: 1.1s · Steps: 2</div>
|
||||
<div class="meta">URL: https://weval-consulting.com/api/wevia-v83-business-kpi.php?action=full · Load: 1.06s · Steps: 2</div>
|
||||
<div class="meta">Title: </div>
|
||||
<div class="checks"><span class="check-pass">✓ text_in_body: "revenue"</span><br><span class="check-pass">✓ text_in_body: "catalog"</span><br></div><div class="screenshots"><a href="/test-results/v90/api_business_kpi_full_01_top.png" target="_blank"><img src="/test-results/v90/api_business_kpi_full_01_top.png" alt="01_top" title="01_top"></a><a href="/test-results/v90/api_business_kpi_full_02_bottom.png" target="_blank"><img src="/test-results/v90/api_business_kpi_full_02_bottom.png" alt="02_bottom" title="02_bottom"></a></div></div></body></html>
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"ts": "2026-04-20T14:33:11",
|
||||
"ts": "2026-04-20T14:35:24",
|
||||
"version": "V90",
|
||||
"scenarios": [
|
||||
{
|
||||
@@ -18,7 +18,7 @@
|
||||
"level": "SEVERE",
|
||||
"message": "https://weval-consulting.com/api/auth-check.php - Failed to load resource: the server responded with a status of 401 ()",
|
||||
"source": "network",
|
||||
"timestamp": 1776688393249
|
||||
"timestamp": 1776688525621
|
||||
}
|
||||
],
|
||||
"network_errors": [],
|
||||
@@ -30,15 +30,15 @@
|
||||
{
|
||||
"step": "01_top",
|
||||
"path": "/var/www/html/test-results/v90/wtp_main_with_auth_01_top.png",
|
||||
"size": 46491
|
||||
"size": 46458
|
||||
},
|
||||
{
|
||||
"step": "02_bottom",
|
||||
"path": "/var/www/html/test-results/v90/wtp_main_with_auth_02_bottom.png",
|
||||
"size": 46469
|
||||
"size": 46410
|
||||
}
|
||||
],
|
||||
"load_time_s": 1.08,
|
||||
"load_time_s": 1.17,
|
||||
"title": "WEVAL \u2014 Connexion",
|
||||
"body_text_len": 219,
|
||||
"body_preview": "WEVAL Consulting\nEspace s\u00e9curis\u00e9 \u2014 Authentification requise\nRedirection SSO Authentik...\nConnexion SSO (Authentik)\nOU\nConnexion manuelle\nConnexion chiffr\u00e9e \u00b7 Session s\u00e9curis\u00e9e\nRetour au site\nWEVAL Con"
|
||||
@@ -69,15 +69,15 @@
|
||||
{
|
||||
"step": "01_top",
|
||||
"path": "/var/www/html/test-results/v90/login_ux_01_top.png",
|
||||
"size": 46429
|
||||
"size": 46414
|
||||
},
|
||||
{
|
||||
"step": "02_bottom",
|
||||
"path": "/var/www/html/test-results/v90/login_ux_02_bottom.png",
|
||||
"size": 46400
|
||||
"size": 46455
|
||||
}
|
||||
],
|
||||
"load_time_s": 0.12,
|
||||
"load_time_s": 0.13,
|
||||
"title": "WEVAL \u2014 Connexion",
|
||||
"body_text_len": 219,
|
||||
"body_preview": "WEVAL Consulting\nEspace s\u00e9curis\u00e9 \u2014 Authentification requise\nRedirection SSO Authentik...\nConnexion SSO (Authentik)\nOU\nConnexion manuelle\nConnexion chiffr\u00e9e \u00b7 Session s\u00e9curis\u00e9e\nRetour au site\nWEVAL Con"
|
||||
@@ -108,18 +108,18 @@
|
||||
{
|
||||
"step": "01_top",
|
||||
"path": "/var/www/html/test-results/v90/main_site_public_01_top.png",
|
||||
"size": 300884
|
||||
"size": 232880
|
||||
},
|
||||
{
|
||||
"step": "02_bottom",
|
||||
"path": "/var/www/html/test-results/v90/main_site_public_02_bottom.png",
|
||||
"size": 153289
|
||||
"size": 155492
|
||||
}
|
||||
],
|
||||
"load_time_s": 1.08,
|
||||
"load_time_s": 1.19,
|
||||
"title": "WEVAL Consulting \u2014 Enterprise Digital Transformation | ERP \u00b7 Cloud \u00b7 IA \u00b7 Cybers\u00e9curit\u00e9",
|
||||
"body_text_len": 12388,
|
||||
"body_preview": "FLAGSHIP\nWEVIA EM \u2014 L\u2019IA souveraine qui orchestre votre value chain de bout en bout.\nD\u00e9couvrir \u2192\n\u2715\nAccueil\nServices\nSolutions\nMarketplace\nActualit\u00e9s\nBlog\nProducts\n\ud83e\udde0 WEVIA\n\ud83c\udf93 IA Academy\nTech Radar\nTrouv"
|
||||
"body_text_len": 12558,
|
||||
"body_preview": "FLAGSHIP\nWEVIA EM \u2014 L\u2019IA souveraine qui orchestre votre value chain de bout en bout.\nD\u00e9couvrir \u2192\n\u2715\nAccueil\nServices\nSolutions\nMarketplace\nActualit\u00e9s\nBlog\nProducts\n\ud83e\udde0 WEVIA\n\ud83c\udf93 IA Academy\nEN\nTech Radar\nTr"
|
||||
},
|
||||
{
|
||||
"name": "business_kpi_dashboard",
|
||||
@@ -142,18 +142,18 @@
|
||||
{
|
||||
"step": "01_top",
|
||||
"path": "/var/www/html/test-results/v90/business_kpi_dashboard_01_top.png",
|
||||
"size": 324435
|
||||
"size": 206695
|
||||
},
|
||||
{
|
||||
"step": "02_bottom",
|
||||
"path": "/var/www/html/test-results/v90/business_kpi_dashboard_02_bottom.png",
|
||||
"size": 199059
|
||||
"size": 198821
|
||||
}
|
||||
],
|
||||
"load_time_s": 2.28,
|
||||
"load_time_s": 2.35,
|
||||
"title": "V83 Business KPI Dashboard \u2014 SaaS Ready",
|
||||
"body_text_len": 5523,
|
||||
"body_preview": "V83 Business KPI Dashboard \u2014 SaaS Ready\n56 KPIs across 7 categories \u2014 orienter le business (vous + clients) \u00b7 Updated: 12:33:29\n\u2190 ERP Portal\n56\nTOTAL KPIS\n7\nCATEGORIES\n29\nLIVE (ON TARGET)\n22\nBELOW TAR"
|
||||
"body_text_len": 5148,
|
||||
"body_preview": "V83 Business KPI Dashboard \u2014 SaaS Ready\n56 KPIs across 7 categories \u2014 orienter le business (vous + clients) \u00b7 Updated: 12:35:41\n\u2190 ERP Portal\n56\nTOTAL KPIS\n7\nCATEGORIES\n29\nLIVE (ON TARGET)\n22\nBELOW TAR"
|
||||
},
|
||||
{
|
||||
"name": "depts_kpi_page",
|
||||
@@ -176,15 +176,15 @@
|
||||
{
|
||||
"step": "01_top",
|
||||
"path": "/var/www/html/test-results/v90/depts_kpi_page_01_top.png",
|
||||
"size": 136590
|
||||
"size": 136358
|
||||
},
|
||||
{
|
||||
"step": "02_bottom",
|
||||
"path": "/var/www/html/test-results/v90/depts_kpi_page_02_bottom.png",
|
||||
"size": 140669
|
||||
"size": 140922
|
||||
}
|
||||
],
|
||||
"load_time_s": 0.93,
|
||||
"load_time_s": 0.88,
|
||||
"title": "WEVAL Consulting \u2014 Enterprise Digital Transformation | ERP \u00b7 Cloud \u00b7 IA \u00b7 Cybers\u00e9curit\u00e9",
|
||||
"body_text_len": 1111,
|
||||
"body_preview": "Accueil\nServices\nSolutions\nMarketplace\nActualit\u00e9s\nBlog\nProducts\n\ud83e\udde0 WEVIA\n\ud83c\udf93 IA Academy\nTech Radar\nTrouver ma solution\nContact\nFR\nAccueil\nServices\nMarketplace\nSolutions\nActualit\u00e9s\n\ud83e\udde0 WEVIA\nWeval\nWeval, l\u2019"
|
||||
@@ -215,7 +215,7 @@
|
||||
{
|
||||
"step": "01_top",
|
||||
"path": "/var/www/html/test-results/v90/api_manifest_01_top.png",
|
||||
"size": 93585
|
||||
"size": 93329
|
||||
},
|
||||
{
|
||||
"step": "02_bottom",
|
||||
@@ -254,15 +254,15 @@
|
||||
{
|
||||
"step": "01_top",
|
||||
"path": "/var/www/html/test-results/v90/api_l99_honest_01_top.png",
|
||||
"size": 44017
|
||||
"size": 44034
|
||||
},
|
||||
{
|
||||
"step": "02_bottom",
|
||||
"path": "/var/www/html/test-results/v90/api_l99_honest_02_bottom.png",
|
||||
"size": 44017
|
||||
"size": 44034
|
||||
}
|
||||
],
|
||||
"load_time_s": 0.11,
|
||||
"load_time_s": 0.12,
|
||||
"title": "",
|
||||
"body_text_len": 684,
|
||||
"body_preview": "{\n \"ok\": true,\n \"v\": \"V5.3-l99-honest-opus-19avr\",\n \"ts\": \"2026-04-20T14:28:18+02:00\",\n \"doctrine_4_honest\": \"TRUE - no hardcode, real exec of 2 nonreg files\",\n \"master\": {\n \"fil"
|
||||
@@ -293,22 +293,22 @@
|
||||
{
|
||||
"step": "01_top",
|
||||
"path": "/var/www/html/test-results/v90/api_business_kpi_full_01_top.png",
|
||||
"size": 100275
|
||||
"size": 100309
|
||||
},
|
||||
{
|
||||
"step": "02_bottom",
|
||||
"path": "/var/www/html/test-results/v90/api_business_kpi_full_02_bottom.png",
|
||||
"size": 89793
|
||||
"size": 89825
|
||||
}
|
||||
],
|
||||
"load_time_s": 1.1,
|
||||
"load_time_s": 1.06,
|
||||
"title": "",
|
||||
"body_text_len": 25280,
|
||||
"body_preview": "{\n \"ok\": true,\n \"version\": \"V83-business-kpi\",\n \"ts\": \"2026-04-20T12:33:47+00:00\",\n \"catalog\": {\n \"revenue\": {\n \"title\": \"\\ud83d\\udcb0 Revenue & Business Growth\",\n "
|
||||
"body_preview": "{\n \"ok\": true,\n \"version\": \"V83-business-kpi\",\n \"ts\": \"2026-04-20T12:35:59+00:00\",\n \"catalog\": {\n \"revenue\": {\n \"title\": \"\\ud83d\\udcb0 Revenue & Business Growth\",\n "
|
||||
}
|
||||
],
|
||||
"pass": 6,
|
||||
"fail": 0,
|
||||
"warn": 2,
|
||||
"total_duration_s": 39.48
|
||||
"total_duration_s": 38.11
|
||||
}
|
||||
|
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 45 KiB |
|
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 45 KiB |