Dashboard Masticationpedia: differenze tra le versioni
Nessun oggetto della modifica Etichetta: Annullato |
Nessun oggetto della modifica Etichetta: Annullato |
||
| Riga 1: | Riga 1: | ||
<!-- ========= Masticationpedia AI (minimo, pronto all'uso) ========= --> | |||
< | <!-- Bottone di apertura --> | ||
< | <button id="btn-open-mpai" style="padding:.55rem .9rem;border:1px solid #d0d7de;border-radius:8px;cursor:pointer"> | ||
🤖 Masticationpedia AI | |||
</button> | |||
<!-- | <!-- Pannello AI --> | ||
< | <div id="mpai" class="mpai-root" style="display:none; margin-top:12px;"> | ||
<div class="mpai-header"> | <div class="mpai-header"> | ||
<div class="mpai-title">🤖 Masticationpedia <b>AI</b></div> | <div class="mpai-title">🤖 Masticationpedia <b>AI</b></div> | ||
<div class="mpai-actions"> | |||
<label class="mpai-field">Modello | |||
<select id="mpai-model"> | |||
<option value="gpt-4o-2024-05-13" selected>gpt-4o-2024-05-13</option> | |||
<option value="gpt-4-turbo-2024-04-09">gpt-4-turbo-2024-04-09</option> | |||
</select> | |||
</label> | |||
</div> | |||
</div> | </div> | ||
<div id="mpai-chat" class="mpai-chat" | |||
< | <div id="mpai-chat" class="mpai-chat"></div> | ||
<div class="mpai-composer"> | |||
<textarea id="mpai-input" rows="3" placeholder="Scrivi qui la tua domanda... (Ctrl/⌘+Invio per inviare)"></textarea> | |||
<button id="mpai-send" class="mpai-btn primary">Invia</button> | |||
</div> | </div> | ||
<div class="mpai- | |||
< | <div class="mpai-hint"> | ||
Le chiavi API restano lato server. Questo box chiama <code>/dashboard/api/openai_project_gpt.php</code>. | |||
</div> | </div> | ||
</div> | </div> | ||
<!-- Stili minimi --> | |||
<style> | <style> | ||
.mpai- | .mpai-root{ | ||
.mpai-msg.user { background:#eff6ff; border: | --line:#e5e7eb; --card:#fff; --text:#111827; --muted:#6b7280; --primary:#0a7cff; | ||
.mpai-msg.assistant { background:#f0fdf4; border:1px solid # | font-family:system-ui,-apple-system,Segoe UI,Roboto,Arial,sans-serif; color:var(--text); | ||
border:1px solid var(--line); border-radius:12px; background:var(--card); padding:12px; | |||
} | |||
.mpai-header{display:flex;justify-content:space-between;align-items:center;gap:10px;margin-bottom:8px} | |||
.mpai-title{font-size:18px;font-weight:700} | |||
.mpai-field{display:flex;align-items:center;gap:6px} | |||
.mpai-field select{border:1px solid var(--line);border-radius:8px;padding:.35rem .5rem} | |||
.mpai-chat{display:flex;flex-direction:column;gap:10px;max-height:50vh;overflow:auto; | |||
border:1px solid var(--line);border-radius:12px;background:#fff;padding:10px} | |||
.mpai-msg{border:1px solid var(--line);border-radius:12px;background:#fff;padding:10px} | |||
.mpai-msg .role{font-weight:600;margin-bottom:4px} | |||
.mpai-msg.user{background:#eff6ff;border-color:#bee3f8} | |||
.mpai-msg.assistant{background:#f0fdf4;border-color:#d1fae5} | |||
.mpai-composer{display:flex;gap:8px;align-items:flex-end;margin-top:10px} | |||
.mpai-composer textarea{flex:1 1 auto;min-height:90px;border:1px solid var(--line);border-radius:12px;padding:10px} | |||
.mpai-btn{border:1px solid var(--line);background:#fff;padding:.45rem .8rem;border-radius:8px;cursor:pointer} | |||
.mpai-btn.primary{background:var(--primary);border-color:var(--primary);color:#fff} | |||
.mpai-hint{margin-top:8px;color:var(--muted);font-size:12px} | |||
</style> | </style> | ||
<!-- JavaScript (tutto qui) --> | |||
<script> | <script> | ||
document.addEventListener( | document.addEventListener('DOMContentLoaded', function(){ | ||
const panel = document.getElementById( | |||
const chatEl = document.getElementById( | // --- riferimenti UI --- | ||
const inputEl = document.getElementById( | const API_URL = '/dashboard/api/openai_project_gpt.php'; | ||
const | const btnOpen = document.getElementById('btn-open-mpai'); | ||
const | const panel = document.getElementById('mpai'); | ||
const chatEl = document.getElementById('mpai-chat'); | |||
const inputEl = document.getElementById('mpai-input'); | |||
const sendBtn = document.getElementById('mpai-send'); | |||
const modelSel = document.getElementById('mpai-model'); | |||
// | // apri pannello | ||
btnOpen. | btnOpen.addEventListener('click', () => { panel.style.display = 'block'; inputEl?.focus(); }); | ||
// | // utilità: aggiunge un messaggio in chat | ||
function | function addMsg(role, text, returnNode=false){ | ||
const | const wrap = document.createElement('div'); | ||
wrap.className = 'mpai-msg ' + (role==='user' ? 'user' : 'assistant'); | |||
wrap.innerHTML = '<div class="role">'+(role==='user'?'Tu':'GPT')+'</div><div class="text"></div>'; | |||
chatEl.appendChild( | wrap.querySelector('.text').textContent = text; | ||
chatEl.appendChild(wrap); | |||
chatEl.scrollTop = chatEl.scrollHeight; | chatEl.scrollTop = chatEl.scrollHeight; | ||
return returnNode ? wrap : undefined; | |||
} | |||
// invio alla tua API | |||
async function askOpenAI(prompt){ | |||
const model = (modelSel?.value || 'gpt-4o-2024-05-13').trim(); | |||
const pending = addMsg('assistant','…elaboro…', true); | |||
try{ | |||
const res = await fetch(API_URL, { | |||
method:'POST', | |||
headers:{ 'Content-Type':'application/json' }, | |||
credentials:'include', // se usi Basic Auth/sessioni | |||
body: JSON.stringify({ model, prompt }) | |||
}); | |||
const raw = await res.text(); | |||
let j; | |||
try { j = JSON.parse(raw); } catch(e) { j = { status:'error', error:'Risposta non JSON', raw }; } | |||
pending.remove(); | |||
if (j.status === 'ok' && j.result){ | |||
addMsg('assistant', j.result); | |||
} else { | |||
addMsg('assistant', '⚠️ Errore API: ' + (j.error || 'sconosciuto') + (j.raw ? '\n\nRAW:\n'+j.raw : '')); | |||
} | |||
} catch(err){ | |||
pending.remove(); | |||
addMsg('assistant', '❌ ' + err.message); | |||
} | |||
} | |||
// invio messaggio | |||
function sendNow(){ | |||
const text = (inputEl.value || '').trim(); | |||
if (!text) { inputEl.focus(); return; } | |||
addMsg('user', text); | |||
inputEl.value = ''; | |||
askOpenAI(text); | |||
} | } | ||
sendBtn.addEventListener('click', sendNow); | |||
inputEl.addEventListener('keydown', (e)=>{ | |||
if ((e.metaKey || e.ctrlKey) && e.key === 'Enter'){ e.preventDefault(); sendNow(); } | |||
if( | }); | ||
}; | |||
}); | }); | ||
</script> | </script> | ||
Versione delle 07:41, 28 set 2025
<button id="btn-open-mpai" style="padding:.55rem .9rem;border:1px solid #d0d7de;border-radius:8px;cursor:pointer">
🤖 Masticationpedia AI
</button>
<style>
.mpai-root{
--line:#e5e7eb; --card:#fff; --text:#111827; --muted:#6b7280; --primary:#0a7cff;
font-family:system-ui,-apple-system,Segoe UI,Roboto,Arial,sans-serif; color:var(--text);
border:1px solid var(--line); border-radius:12px; background:var(--card); padding:12px;
}
.mpai-header{display:flex;justify-content:space-between;align-items:center;gap:10px;margin-bottom:8px}
.mpai-title{font-size:18px;font-weight:700}
.mpai-field{display:flex;align-items:center;gap:6px}
.mpai-field select{border:1px solid var(--line);border-radius:8px;padding:.35rem .5rem}
.mpai-chat{display:flex;flex-direction:column;gap:10px;max-height:50vh;overflow:auto;
border:1px solid var(--line);border-radius:12px;background:#fff;padding:10px}
.mpai-msg{border:1px solid var(--line);border-radius:12px;background:#fff;padding:10px}
.mpai-msg .role{font-weight:600;margin-bottom:4px}
.mpai-msg.user{background:#eff6ff;border-color:#bee3f8}
.mpai-msg.assistant{background:#f0fdf4;border-color:#d1fae5}
.mpai-composer{display:flex;gap:8px;align-items:flex-end;margin-top:10px}
.mpai-composer textarea{flex:1 1 auto;min-height:90px;border:1px solid var(--line);border-radius:12px;padding:10px}
.mpai-btn{border:1px solid var(--line);background:#fff;padding:.45rem .8rem;border-radius:8px;cursor:pointer}
.mpai-btn.primary{background:var(--primary);border-color:var(--primary);color:#fff}
.mpai-hint{margin-top:8px;color:var(--muted);font-size:12px}
</style>
<script> document.addEventListener('DOMContentLoaded', function(){
// --- riferimenti UI ---
const API_URL = '/dashboard/api/openai_project_gpt.php';
const btnOpen = document.getElementById('btn-open-mpai');
const panel = document.getElementById('mpai');
const chatEl = document.getElementById('mpai-chat');
const inputEl = document.getElementById('mpai-input');
const sendBtn = document.getElementById('mpai-send');
const modelSel = document.getElementById('mpai-model');
// apri pannello
btnOpen.addEventListener('click', () => { panel.style.display = 'block'; inputEl?.focus(); });
// utilità: aggiunge un messaggio in chat
function addMsg(role, text, returnNode=false){
const wrap = document.createElement('div');
wrap.className = 'mpai-msg ' + (role==='user' ? 'user' : 'assistant');
wrap.innerHTML = '
'+(role==='user'?'Tu':'GPT')+'
';
wrap.querySelector('.text').textContent = text;
chatEl.appendChild(wrap);
chatEl.scrollTop = chatEl.scrollHeight;
return returnNode ? wrap : undefined;
}
// invio alla tua API
async function askOpenAI(prompt){
const model = (modelSel?.value || 'gpt-4o-2024-05-13').trim();
const pending = addMsg('assistant','…elaboro…', true);
try{
const res = await fetch(API_URL, {
method:'POST',
headers:{ 'Content-Type':'application/json' },
credentials:'include', // se usi Basic Auth/sessioni
body: JSON.stringify({ model, prompt })
});
const raw = await res.text();
let j;
try { j = JSON.parse(raw); } catch(e) { j = { status:'error', error:'Risposta non JSON', raw }; }
pending.remove();
if (j.status === 'ok' && j.result){
addMsg('assistant', j.result);
} else {
addMsg('assistant', '⚠️ Errore API: ' + (j.error || 'sconosciuto') + (j.raw ? '\n\nRAW:\n'+j.raw : ));
}
} catch(err){
pending.remove();
addMsg('assistant', '❌ ' + err.message);
}
}
// invio messaggio
function sendNow(){
const text = (inputEl.value || ).trim();
if (!text) { inputEl.focus(); return; }
addMsg('user', text);
inputEl.value = ;
askOpenAI(text);
}
sendBtn.addEventListener('click', sendNow);
inputEl.addEventListener('keydown', (e)=>{
if ((e.metaKey || e.ctrlKey) && e.key === 'Enter'){ e.preventDefault(); sendNow(); }
});
}); </script>