Some checks failed
WEVAL NonReg / nonreg (push) Has been cancelled
19 pages PRIO4 business enrichies: - gws-setup v63-send-queue l99-fullscreen v78-real-wire weval-portal - ethica-country crm-audit infra-tour infra-tour-2s-5c-blade - partners-emails onboarding-em arsenal-offline ultimate-quality - wevia-demo-autonomous linkedin-automation-v96 blade-install - solutions oss-catalog wtp Cumul session: - 146 pages UX doctrine 60 (127 + 19) - 32 tags Opus - 29 doctrines vault (146-184) Handler robuste 75+ pages consecutives ZERO regression. NR 153/153 invariant.
231 lines
9.9 KiB
HTML
231 lines
9.9 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="fr"><head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<title>LinkedIn Automation - V96 WEVAL</title>
|
|
<style>
|
|
:root{--bg:#0a0e1a;--bg2:#141b2d;--bg3:#1e2740;--fg:#e8ecf4;--t2:#9aa5c0;--t3:#5f6b85;--brd:rgba(255,255,255,.08);--gold:#d4af37;--em:#10b981;--cy:#06b6d4;--am:#f59e0b;--co:#ef4444;--vi:#8b5cf6;--sa:#3b82f6;}
|
|
*{box-sizing:border-box;margin:0;padding:0}
|
|
body{background:var(--bg);color:var(--fg);font-family:'SF Pro Display',system-ui,sans-serif;min-height:100vh;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:22px;font-weight:700}
|
|
.hdr h1 span{color:var(--gold)}
|
|
.sub{color:var(--t2);font-size:12px;margin-top:2px}
|
|
.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:12px;margin-bottom:24px}
|
|
.mc{background:var(--bg2);border:1px solid var(--brd);border-left:3px solid var(--gold);padding:14px;border-radius:8px}
|
|
.mc-l{font-size:10px;color:var(--t2);text-transform:uppercase;letter-spacing:1px}
|
|
.mc-v{font-size:26px;font-weight:700;margin:6px 0;color:var(--fg)}
|
|
.mc-s{font-size:11px;color:var(--em)}
|
|
.mc.v{border-left-color:var(--vi)}
|
|
.mc.c{border-left-color:var(--cy)}
|
|
.mc.e{border-left-color:var(--em)}
|
|
.mc.a{border-left-color:var(--am)}
|
|
.mc.s{border-left-color:var(--sa)}
|
|
.sec{margin-bottom:24px}
|
|
.sec h2{font-size:14px;font-weight:600;color:var(--t2);text-transform:uppercase;letter-spacing:1.5px;margin-bottom:12px;display:flex;align-items:center;gap:8px}
|
|
.sec h2::before{content:'';width:6px;height:6px;background:var(--gold);border-radius:50%;box-shadow:0 0 8px var(--gold)}
|
|
.btns{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:14px}
|
|
.btn{padding:9px 16px;background:var(--bg3);border:1px solid var(--brd);border-radius:6px;color:var(--fg);cursor:pointer;font-size:12px;font-weight:500;transition:all .15s}
|
|
.btn:hover{background:var(--gold);color:#000;border-color:var(--gold)}
|
|
.btn.primary{background:var(--gold);color:#000}
|
|
.qc{display:flex;flex-direction:column;gap:10px;max-height:520px;overflow-y:auto}
|
|
.q{background:var(--bg2);border:1px solid var(--brd);border-radius:8px;padding:14px;position:relative}
|
|
.q-h{display:flex;justify-content:space-between;align-items:center;margin-bottom:10px}
|
|
.q-t{color:var(--cy);font-size:11px;font-weight:600;text-transform:uppercase}
|
|
.q-m{display:flex;gap:10px;font-size:10px;color:var(--t3)}
|
|
.q-c{color:var(--fg);font-size:12px;line-height:1.6;white-space:pre-wrap;background:var(--bg3);padding:12px;border-radius:6px;max-height:200px;overflow-y:auto}
|
|
.q-a{display:flex;gap:6px;margin-top:10px}
|
|
.q-a button{padding:5px 11px;background:var(--bg3);border:1px solid var(--brd);border-radius:4px;color:var(--t2);font-size:11px;cursor:pointer}
|
|
.q-a button:hover{background:var(--em);color:#fff;border-color:var(--em)}
|
|
.spnr{display:inline-block;width:12px;height:12px;border:2px solid var(--gold);border-top:2px solid transparent;border-radius:50%;animation:sp 1s linear infinite;vertical-align:middle}
|
|
@keyframes sp{to{transform:rotate(360deg)}}
|
|
.loading{text-align:center;color:var(--t2);padding:30px;font-size:13px}
|
|
</style><!-- DOCTRINE-60-UX-ENRICH direct-inject-20260424-142737 -->
|
|
<style id="doctrine60-ux-direct">
|
|
|
|
/* DOCTRINE-60-UX-ENRICH injected-direct */
|
|
body::before {
|
|
content: '';
|
|
position: fixed;
|
|
top: 0; left: 0; width: 100vw; height: 100vh;
|
|
background: radial-gradient(circle at 50% 50%, rgba(100,180,255,0.08), transparent 60%);
|
|
pointer-events: none;
|
|
z-index: -1;
|
|
}
|
|
.card, .kpi, .panel, .btn {
|
|
transition: all 0.3s cubic-bezier(0.2,0,0.1,1);
|
|
}
|
|
.card:hover, .kpi:hover, .panel:hover {
|
|
box-shadow: 0 4px 20px rgba(100,180,255,0.2);
|
|
border-color: rgba(100,180,255,0.5);
|
|
}
|
|
@keyframes pulseD60 {
|
|
0%,100% { opacity: 1; transform: scale(1); }
|
|
50% { opacity: 0.7; transform: scale(1.05); }
|
|
}
|
|
.pulse, .live-indicator, .active, .online {
|
|
animation: pulseD60 3s ease-in-out infinite;
|
|
}
|
|
.modal, .chat, .speech, .overlay {
|
|
backdrop-filter: blur(12px);
|
|
-webkit-backdrop-filter: blur(12px);
|
|
}
|
|
.enter-stagger {
|
|
animation: enterStagD60 0.5s cubic-bezier(0.2,0,0.1,1) forwards;
|
|
}
|
|
@keyframes enterStagD60 {
|
|
from { opacity: 0; transform: translateY(20px); }
|
|
to { opacity: 1; transform: translateY(0); }
|
|
}
|
|
|
|
</style>
|
|
</head><body>
|
|
|
|
<div class="hdr">
|
|
<div>
|
|
<h1>LinkedIn <span>Automation Hub</span> <span style="font-size:13px;color:var(--t3)">V96</span></h1>
|
|
<div class="sub">Sovereign AI posts generation + queue + stats · piloted by WEVIA Master</div>
|
|
</div>
|
|
<div>
|
|
<a href="/weval-technology-platform.html" class="btn">← WTP</a>
|
|
<a href="/wevia-master.html" class="btn primary">WEVIA Chat</a>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="sec">
|
|
<h2>Page Stats (Weval · 921 followers)</h2>
|
|
<div class="grid" id="stats"></div>
|
|
</div>
|
|
|
|
<div class="sec">
|
|
<h2>Actions Sovereign IA (0€ cost)</h2>
|
|
<div class="btns">
|
|
<button class="btn primary" onclick="gen('wevia_sovereign_ai')">🤖 Generate WEVIA AI post</button>
|
|
<button class="btn primary" onclick="gen('ethica_hcp')">💊 Generate Ethica HCP post</button>
|
|
<button class="btn primary" onclick="gen('vistex_sap')">🏢 Generate Vistex SAP post</button>
|
|
<button class="btn primary" onclick="gen('case_study')">📊 Generate Case Study</button>
|
|
<button class="btn" onclick="loadQueue()">🔄 Refresh Queue</button>
|
|
<button class="btn" onclick="clearQueue()" style="color:var(--co)">🗑 Clear Queue</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="sec">
|
|
<h2>Generated Posts Queue</h2>
|
|
<div class="qc" id="queue"><div class="loading"><span class="spnr"></span> Loading...</div></div>
|
|
</div>
|
|
|
|
<script>
|
|
const API='/api/v96-linkedin-automation.php';
|
|
|
|
async function loadStats(){
|
|
try{
|
|
const r=await fetch(API+'?action=overview');
|
|
const d=await r.json();
|
|
const s=d.page_stats||{};
|
|
const kpi=d.kpis_to_push_score_10||{};
|
|
document.getElementById('stats').innerHTML = [
|
|
['Followers','v',s.followers||0,'+'+(s.last_7d_new_followers||0)+' 7d ('+s.pct_growth_followers+'%)'],
|
|
['Search Appearances','c',s.last_7d_search_appearances||0,'+'+(s.pct_growth_search||0)+'% 7d'],
|
|
['Post Impressions','e',s.last_7d_post_impressions||0,'+'+(s.pct_growth_impressions||0)+'% 7d'],
|
|
['Page Visitors','a',s.last_7d_page_visitors||0,'+'+(s.pct_growth_visitors||0)+'% 7d'],
|
|
['Queue Pending','s',d.queue_pending||0,'AI drafts ready'],
|
|
['Published','','0','manual or API'],
|
|
['Pixel Hits','c',d.pixel_hits_month||0,'LinkedIn ref: '+(d.pixel_linkedin_referrer||0)],
|
|
].map(([l,c,v,sub])=>`<div class="mc ${c}"><div class="mc-l">${l}</div><div class="mc-v">${v}</div><div class="mc-s">${sub}</div></div>`).join('');
|
|
}catch(e){document.getElementById('stats').innerHTML='<div class="loading" style="color:var(--co)">Error: '+e.message+'</div>';}
|
|
}
|
|
|
|
async function loadQueue(){
|
|
document.getElementById('queue').innerHTML='<div class="loading"><span class="spnr"></span> Loading queue...</div>';
|
|
try{
|
|
const r=await fetch(API+'?action=queue');
|
|
const d=await r.json();
|
|
if(!d.queue||d.queue.length===0){
|
|
document.getElementById('queue').innerHTML='<div class="loading">No posts generated yet. Click a theme button above to generate.</div>';
|
|
return;
|
|
}
|
|
document.getElementById('queue').innerHTML = d.queue.slice().reverse().map(q=>`
|
|
<div class="q">
|
|
<div class="q-h">
|
|
<div class="q-t">${q.theme}</div>
|
|
<div class="q-m">
|
|
<span>📏 ${q.chars}c</span>
|
|
<span>🔢 ${q.metrics_count}m</span>
|
|
<span>#️⃣ ${q.hashtags_count}h</span>
|
|
<span>⏱ ${q.latency_ms}ms</span>
|
|
<span>💰 0€</span>
|
|
</div>
|
|
</div>
|
|
<div class="q-c">${(q.post||'').replace(/</g,'<').replace(/\\n/g,'\n')}</div>
|
|
<div class="q-a">
|
|
<button onclick="cpy(this,\`${q.id}\`)">📋 Copy to clipboard</button>
|
|
<button onclick="openLinkedIn()">🔗 Open LinkedIn</button>
|
|
<span style="color:var(--t3);font-size:10px;padding:5px 0">${q.provider}</span>
|
|
</div>
|
|
</div>
|
|
`).join('');
|
|
}catch(e){document.getElementById('queue').innerHTML='<div class="loading" style="color:var(--co)">Error: '+e.message+'</div>';}
|
|
}
|
|
|
|
async function gen(theme){
|
|
const b=event.target;
|
|
const orig=b.innerHTML;
|
|
b.innerHTML='<span class="spnr"></span> Generating via sovereign Ollama...';
|
|
b.disabled=true;
|
|
try{
|
|
const r=await fetch(API+'?action=generate_post&theme='+theme);
|
|
await r.json();
|
|
await loadQueue();
|
|
await loadStats();
|
|
}catch(e){alert('Error: '+e.message);}
|
|
b.innerHTML=orig;
|
|
b.disabled=false;
|
|
}
|
|
|
|
async function clearQueue(){
|
|
if(!confirm('Clear entire queue?'))return;
|
|
await fetch(API+'?action=clear_queue');
|
|
loadQueue();
|
|
loadStats();
|
|
}
|
|
|
|
function cpy(btn,id){
|
|
const q=[...document.querySelectorAll('.q')].find(e=>e.textContent.includes(id));
|
|
const txt=q?.querySelector('.q-c')?.textContent||'';
|
|
navigator.clipboard.writeText(txt).then(()=>{
|
|
btn.textContent='✅ Copied!';
|
|
setTimeout(()=>btn.textContent='📋 Copy to clipboard',2000);
|
|
});
|
|
}
|
|
|
|
function openLinkedIn(){
|
|
window.open('https://www.linkedin.com/company/69533182/admin/page-posts/published/','_blank');
|
|
}
|
|
|
|
loadStats();
|
|
loadQueue();
|
|
setInterval(loadStats,30000);
|
|
</script>
|
|
|
|
<script src="/api/a11y-auto-enhancer.js" defer></script>
|
|
<!-- WTP_UDOCK_V1 (Opus 21-avr t34final) --><script src="/wtp-unified-dock.js" defer></script>
|
|
<script src="/opus-antioverlap-doctrine.js?v=1776776094" defer></script>
|
|
<!-- DOCTRINE-60-UX-JS --><script id="doctrine60-ux-js-direct">
|
|
|
|
// DOCTRINE-60-UX-JS staggered entrance
|
|
(function(){
|
|
if (!('IntersectionObserver' in window)) return;
|
|
const obs = new IntersectionObserver((entries) => {
|
|
entries.forEach((e, i) => {
|
|
if (e.isIntersecting) {
|
|
setTimeout(() => e.target.classList.add('enter-stagger'), i * 80);
|
|
obs.unobserve(e.target);
|
|
}
|
|
});
|
|
});
|
|
document.querySelectorAll('.card, .kpi, .panel').forEach(el => obs.observe(el));
|
|
})();
|
|
|
|
</script>
|
|
</body></html>
|