|
|
| (58 versioni intermedie di uno stesso utente non sono mostrate) |
| Riga 1: |
Riga 1: |
| <html> | | <html> |
| <h2>🔧 Dashboard Operativa – Masticationpedia</h2> | | <h2>🔧 Dashboard Operativa – Masticationpedia</h2> |
| <p><em>Centro di comando per progetti, API, file e backup</em></p> | | <p><em>Centro di comando per progetti, API, file e backup</em></p> |
|
| |
|
| <!-- 🔘 Pulsanti di navigazione -->
| | <a href="/dashboard/api/log_view.php" target="_blank">🧾 Apri Log Dashboard</a> |
| <div style="margin: 2rem 0; display: flex; flex-wrap: wrap; gap: 1rem;">
| | <button onclick="clearServerLog()">🧹 Svuota Log</button> |
| <button class="dashboard-toggle" onclick="toggleDashboardBox('api-settings')">⚙️ Connessione API</button> | |
| <button class="dashboard-toggle" onclick="toggleDashboardBox('project-status')">📊 Stato Progetti</button>
| |
| <button class="dashboard-toggle"
| |
| onclick="toggleDashboardBox('chatgpt-plus')">🤖 ChatGPT plus</button>
| |
| <button class="dashboard-toggle" onclick="toggleDashboardBox('test-tools')">🧪 Strumenti di Test</button>
| |
| <button class="dashboard-toggle" onclick="toggleDashboardBox('activity-log')">📘 Registro Attività</button>
| |
| <button class="dashboard-toggle" onclick="uploadToOpenAI()">📄 Carica in OpenAI</button> | |
| </div>
| |
|
| |
|
| | <div style="margin: 2rem 0; display: flex; flex-wrap: wrap; gap: 1rem;"> |
| | <button class="dashboard-toggle" onclick="toggleDashboardBox('api-settings')">⚙️ Connessione API</button> |
|
| |
|
| | | <button class="dashboard-toggle" |
| <!-- 📦 Connessione API (via server, nessuna key lato client) --> | | onclick="(window.showMpAI ? showMpAI() : (function(){var el=document.getElementById('mpAI'); if(el){ el.style.display='block'; el.scrollIntoView({behavior:'smooth'});} else { alert('#mpAI non trovato'); } })())"> |
| <div id="api-settings" style="display:none; padding:1rem; border:1px solid #ccc; border-radius:8px; background:#f9f9f9;">
| | 🤖 Masticationpedia AI |
| <strong>Connessione API (protetta dal server)</strong><br><br>
| | </button> |
| | |
| <label>Modello</label>
| |
| <select id="model-select" style="width:100%; margin-bottom:0.5rem;">
| |
| <option value="gpt-4o-2024-05-13" selected>gpt-4o-2024-05-13</option>
| |
| <option value="gpt-4o-mini">gpt-4o-mini</option>
| |
| <option value="gpt-4-turbo-2024-04-09">gpt-4-turbo-2024-04-09</option>
| |
| </select>
| |
| | |
| <label>Prompt di test</label>
| |
| <textarea id="test-prompt" rows="3" style="width:100%; margin-bottom:0.5rem;">Dimmi una curiosità sulla mandibola</textarea><br>
| |
| | |
| <button onclick="testAPIConnection()">▶️ Esegui</button>
| |
| <pre id="api-result" style="background:#f0f0f0; padding:1rem; border:1px solid #ccc; margin-top:1rem; white-space:pre-wrap;"></pre>
| |
| </div>
| |
| | |
| | |
| | |
| <!-- 📊 Stato Progetti -->
| |
| <div id="project-status" style="display:none; padding:1rem; border:1px solid #ccc; border-radius:8px; background:#f9f9f9;">
| |
| <strong>Stato Progetti:</strong><br><br>
| |
| <button onclick="openProjectDialog()" style="margin-bottom:1rem; background:#007bff; color:white; border:none; padding:0.5rem 1rem; border-radius:5px; font-weight:bold;">➕ Nuovo Progetto</button>
| |
| | |
| <div id="newProjectDialog" style="display:none; padding:1rem; border:1px solid #ccc; margin-top:1rem;">
| |
| <h4>➕ Crea Nuovo Progetto</h4>
| |
| <input id="newProjectTitle" placeholder="Titolo progetto" style="width:100%; margin-bottom:0.5rem;" />
| |
| <input id="newProjectNotes" placeholder="Note (opzionale)" style="width:100%; margin-bottom:0.5rem;" />
| |
| <button onclick="addNewProject()">📅 Salva</button>
| |
| <button onclick="closeProjectDialog()">❌ Chiudi</button> | |
| </div> | | </div> |
|
| |
|
| <table id="projectTable" style="width:100%; border-collapse: collapse; font-size: 0.95rem;"> | | <!-- ============== MASTICATIONPEDIA AI ============== --> |
| <thead> | | <div id="mpAI" class="mpai-root" style="display:none"> |
| <tr style="background:#eaeaea;"> | | <div class="mpai-header"> |
| <th>🧱 Modulo</th><th>📊 Stato</th><th>🗓️ Data</th><th>🔍 Note</th><th>🗑️</th>
| | <div class="mpai-title">🤖 Masticationpedia <b>AI</b></div> |
| </tr> | | <div class="mpai-actions"> |
| </thead>
| | <button id="mpai-new-chat" class="mpai-btn ghost">Nuova chat</button> |
| <tbody id="projectRows">
| | <button id="mpai-clear" class="mpai-btn danger">Pulisci conversazione</button> |
| <tr>
| | <button id="mpai-save-as-project" class="mpai-btn">💾 Salva come progetto</button> |
| <td>Connessione API</td>
| | </div> |
| <td style="color:green; font-weight:bold;">✅ Completato</td> | | </div> |
| <td>6 apr 2025</td> | |
| <td>Setup funzionante</td>
| |
| </tr> | |
| </tbody> | |
| </table>
| |
|
| |
|
| <div style="margin-top: 1rem;">
| | <div class="mpai-grid"> |
| <label for="response"><strong>🧠 Risposta GPT – Analisi progetto:</strong></label><br>
| | <aside class="mpai-col mpai-left"> |
| <textarea id="response" rows="8" style="width: 100%; margin-top: 6px; margin-bottom: 15px; padding: 8px; font-family: monospace; background-color: #f5f5f5; border: 1px solid #ccc; border-radius: 6px;" placeholder="Qui apparirà la risposta generata da GPT sull’analisi del progetto..."></textarea>
| | <h4>📂 Progetti</h4> |
| </div>
| | <div id="mpai-project-list" class="mpai-projects"> |
| </div> | | <em class="muted">Carico progetti…</em> |
| | </div> |
| | <div class="mpai-new-project"> |
| | <input id="mpai-project-name" type="text" placeholder="Nuovo progetto (A-Z 0-9 _ -)" /> |
| | <button id="mpai-project-create" class="mpai-btn">Crea</button> |
| | </div> |
| | <div class="mpai-help muted"> |
| | Ogni progetto mantiene la sua cronologia locale (browser). |
| | </div> |
| | </aside> |
|
| |
|
| <!-- 🤖 ChatGPT plus (unico contenitore) --> | | <main class="mpai-col mpai-center"> |
| <div id="chatgpt-plus" style="display:none; padding:1rem; border:1px solid #ccc; border-radius:8px; background:#fcfcfc;"> | | <div id="mpai-uploads" class="mpai-uploads" data-state="idle"> |
| <strong>ChatGPT plus – Generazione capitoli</strong><br><br>
| | <div class="mpai-dropzone" id="mpai-dropzone"> |
| | <div> |
| | <div class="muted" style="margin-bottom:6px;">Trascina qui file <b>sanificati</b> oppure</div> |
| | <label class="mpai-file-label"> |
| | <input id="mpai-file-input" type="file" multiple style="display:none;"> |
| | <span class="mpai-btn">📂 Aggiungi file</span> |
| | </label> |
| | </div> |
| | </div> |
| | <div id="mpai-file-list" class="mpai-filelist"></div> |
| | </div> |
|
| |
|
| <!-- Barra superiore -->
| | <div id="mpai-chat" class="mpai-chat"> |
| <div style="display:flex; gap:12px; flex-wrap:wrap; margin-bottom:10px;">
| | <div class="mpai-msg mpai-hint"> |
| <label>📁 Progetto:
| | Benvenuto. Seleziona un progetto a sinistra, oppure scrivi subito: se non c’è un progetto creo una conversazione locale. Le risposte appariranno qui sotto in ordine, come in ChatGPT. |
| <select id="mpChatProject">
| | </div> |
| <option value="Generazione_capitoli" selected>Generazione capitoli</option>
| | </div> |
| </select>
| |
| </label>
| |
| <label>⚙️ Modalità:
| |
| <select id="mpChatMode">
| |
| <option value="analysis">Analisi</option>
| |
| <option value="rewrite">Riscrittura</option> | |
| <option value="generate">Genera capitolo</option>
| |
| <option value="biblio">Bibliografia</option>
| |
| </select>
| |
| </label>
| |
| </div>
| |
|
| |
|
| <!-- Allegati -->
| | <div class="mpai-composer"> |
| <div style="display:flex; gap:8px; align-items:center; flex-wrap:wrap; margin-bottom:8px;">
| | <textarea id="mpai-input" rows="3" placeholder="Scrivi qui la tua domanda..."></textarea> |
| <input id="mpChatFile" type="file" multiple />
| |
| <span id="mpChatDrop" style="border:1px dashed #bbb; padding:6px 10px; border-radius:8px; cursor:pointer; user-select:none;">
| |
| Trascina qui file (solo elenco, non inviati)
| |
| </span>
| |
| </div>
| |
| <div id="mpChatFiles" style="display:flex; gap:8px; flex-wrap:wrap; margin-bottom:8px;"></div>
| |
|
| |
|
| <!-- Input domanda -->
| | <div class="mpai-composer-right"> |
| <label><b>Domanda</b> (breve, come in ChatGPT):</label>
| | <label class="mpai-check" style="margin:0 0 6px 0;"> |
| <div style="display:flex; gap:8px; align-items:flex-start; margin-bottom:8px;">
| | <input id="mpai-drop-urls" type="checkbox"> |
| <textarea id="mpChatPrompt" rows="3" style="flex:1 1 auto; width:100%;"></textarea>
| | Ignora/Cancella URL e allegati per questo invio |
| <button id="mpChatSend">Invia</button>
| | </label> |
| </div>
| | <button id="mpai-send" class="mpai-btn primary">Invia</button> |
| | </div> |
| | </div> |
| | </main> |
|
| |
|
| <!-- Output risposta -->
| | <aside class="mpai-col mpai-right"> |
| <label><b>Risposta</b> (box grande):</label>
| | <h4>⚙️ Impostazioni</h4> |
| <div id="mpChatAnswer" style="min-height:220px; border:1px solid #ddd; background:#fff; border-radius:8px; padding:10px; white-space:pre-wrap;"></div>
| | <label class="mpai-field">Modello |
| | | <select id="mpai-model"> |
| <!-- Explorer semplice dei file salvati --> | | <option value="gpt-4o-2024-05-13" selected>gpt-4o-2024-05-13</option> |
| <div style="margin-top:10px; border-top:1px dashed #ddd; padding-top:10px;"> | | <option value="gpt-4-turbo-2024-04-09">gpt-4-turbo-2024-04-09</option> |
| <div style="display:flex; align-items:center; gap:8px; margin-bottom:6px;">
| | </select> |
| <strong>🗂️ File salvati (output/)</strong>
| | </label> |
| <button id="mpChatRefresh" title="Aggiorna elenco">Aggiorna</button>
| | <label class="mpai-field">Temperatura |
| | <input id="mpai-temp" type="number" min="0" max="1" step="0.1" value="0.7"> |
| | </label> |
| | <label class="mpai-check"> |
| | <input id="mpai-sanitized-only" type="checkbox" checked> |
| | Usa solo file <b>sanificati</b> come contesto |
| | </label> |
| | <div class="mpai-help muted"> |
| | Le API key restano lato server (file sicuro). Il browser non vede mai le chiavi. |
| | </div> |
| | </aside> |
| | </div> |
| </div> | | </div> |
| <div id="mpSavedList" style="max-height:180px; overflow:auto; border:1px solid #eee; background:#fff; border-radius:8px; padding:6px; font-family:monospace; font-size:12px;">
| |
| <em style="color:#777;">Nessun file elencato. Clicca “Aggiorna”.</em>
| |
| </div>
| |
| </div>
| |
|
| |
|
| |
|
| |
| <!-- Azioni -->
| |
| <div style="margin-top:8px; display:flex; gap:8px; justify-content:flex-end;">
| |
| <button id="mpChatClear">Pulisci</button>
| |
| <button id="mpChatCopy">Copia risposta</button>
| |
| <button id="mpChatSave">📥 Salva risposta</button>
| |
| </div>
| |
| </div>
| |
|
| |
|
| |
|
| <!-- 📁 Importa file dal server (semplificata) --> | | <!-- ============ STILI (CSS) ============ --> |
| <div id="serverFileSimpleImportContainer"> | | <style> |
| <div class="dashboard-box" style="margin-top:1rem;">
| | .mpai-root{--bg:#f7f8fa;--card:#fff;--muted:#6b7280;--line:#e5e7eb;--text:#111827;--primary:#0a7cff;--danger:#e74c3c;--accent:#eef2ff;font-family:system-ui,-apple-system,Segoe UI,Roboto,Arial,sans-serif;color:var(--text)} |
| <h4>📁 Importa file dal server (semplificata)</h4> | | .mpai-header{display:flex;align-items:center;justify-content:space-between;margin:8px 0 12px} |
| <label for="sourcePathInput"><b>📂 Percorso Assoluto del file sorgente:</b></label><br> | | .mpai-title{font-size:20px;font-weight:700} |
| <input type="text" id="sourcePathInput" placeholder="/percorso/assoluto/file.php" style="width:100%; margin-bottom:0.5rem;"><br> | | .mpai-actions{display:flex;gap:8px} |
| <label for="projectNameInput"><b>📁 Cartella di destinazione nel progetto:</b></label><br> | | .mpai-btn{border:1px solid var(--line);background:#fff;padding:.45rem .8rem;border-radius:8px;cursor:pointer} |
| <input type="text" id="projectNameInput" placeholder="nome_progetto/"> | | .mpai-btn:hover{background:#f3f4f6} |
| </div>
| | .mpai-btn.primary{background:var(--primary);border-color:var(--primary);color:#fff} |
| </div>
| | .mpai-btn.danger{background:var(--danger);border-color:var(--danger);color:#fff} |
| | .mpai-btn.ghost{background:transparent} |
| | .muted{color:var(--muted)} |
| | .mpai-grid{display:grid;grid-template-columns:260px minmax(0,1fr) 260px;gap:12px} |
| | .mpai-col{background:#fff;border:1px solid var(--line);border-radius:12px;padding:12px} |
| | .mpai-left,.mpai-right{max-height:75vh;overflow:auto} |
| | .mpai-projects{display:flex;flex-direction:column;gap:6px;margin:8px 0} |
| | .mpai-projects .row{display:flex;align-items:center;gap:6px;justify-content:space-between;border:1px solid var(--line);border-radius:8px;padding:6px 8px} |
| | .mpai-projects .row .title{font-family:monospace;font-size:12px} |
| | .mpai-new-project{display:flex;gap:6px;margin-top:8px} |
| | .mpai-new-project input{flex:1 1 auto;padding:.45rem .6rem;border:1px solid var(--line);border-radius:8px} |
| | .mpai-field{display:flex;flex-direction:column;gap:4px;margin:8px 0} |
| | .mpai-field input,.mpai-field select{padding:.45rem .6rem;border:1px solid var(--line);border-radius:8px} |
| | .mpai-check{display:flex;align-items:center;gap:8px;margin:8px 0} |
| | .mpai-center{display:flex;flex-direction:column;gap:10px} |
| | .mpai-uploads{border:1px dashed var(--line);border-radius:12px;padding:10px;background:#fafafa} |
| | .mpai-dropzone{display:flex;align-items:center;justify-content:center;border-radius:10px;padding:12px;background:var(--accent);text-align:center} |
| | .mpai-filelist{display:flex;flex-wrap:wrap;gap:6px;margin-top:8px} |
| | .mpai-filepill{display:flex;align-items:center;gap:6px;border:1px solid var(--line);border-radius:999px;padding:4px 8px;background:#fff;font-size:12px} |
| | .mpai-filepill button{border:none;background:transparent;cursor:pointer;color:#c00} |
| | .mpai-chat{display:flex;flex-direction:column;gap:10px;max-height:50vh;overflow:auto;border:1px solid var(--line);border-radius:12px;padding:10px;background:#fff} |
| | .mpai-msg{border:1px solid var(--line);border-radius:12px;padding:10px;background:#fff} |
| | .mpai-msg.user{border-color:#bee3f8;background:#eff6ff} |
| | .mpai-msg.assistant{border-color:#d1fae5;background:#f0fdf4} |
| | .mpai-msg.error{border-color:#fecaca;background:#fff1f2} |
| | .mpai-msg .role{font-weight:600;margin-bottom:4px} |
| | .mpai-hint{border-style:dashed;color:var(--muted)} |
| | .mpai-composer{display:flex;gap:8px;align-items:flex-end} |
| | .mpai-composer textarea{flex:1 1 auto;min-height:90px;border:1px solid var(--line);border-radius:12px;padding:10px} |
| | .mpai-composer-right{display:flex;flex-direction:column;gap:6px} |
|
| |
|
| | /* --- Blocchi codice nelle risposte + copia --- */ |
| | .mp-code{border:1px solid #e5e7eb;border-radius:10px;overflow:hidden;margin:.5rem 0;background:#fff} |
| | .mp-code__hdr{display:flex;justify-content:space-between;align-items:center;padding:.5rem .75rem;border-bottom:1px solid #e5e7eb;background:#f8fafc} |
| | .mp-code__lang{font-family:ui-monospace, Menlo, Consolas, monospace;color:#334155} |
| | .mp-copy{border:1px solid #e5e7eb;background:#fff;border-radius:8px;padding:.25rem .5rem;cursor:pointer} |
| | .mp-copy:hover{background:#f1f5f9} |
| | .mp-code pre{margin:0;padding:.75rem 1rem;overflow:auto;font-family:ui-monospace, Menlo, Consolas, monospace;font-size:13px} |
| | @media (max-width:1100px){.mpai-grid{grid-template-columns:1fr}.mpai-left,.mpai-right{max-height:none}} |
| | </style> |
|
| |
|
| <!-- | | <!-- ========= SEZIONI LEGACY (nascoste) ========= --> |
| 📄 Prompt + Risposta GPT + Salvataggio
| | <div id="api-settings" style="display:none; padding:1rem; border:1px solid #ccc; border-radius:8px; background:#f9f9f9;"> |
| <div style="margin-top:2rem;">
| | <strong>Connessione API (protetta dal server)</strong><br><br> |
| <h3>📄 Prompt attuale:</h3> | |
| <textarea id="promptArea" style="width:100%; height:200px; font-family:monospace;"></textarea><br>
| |
| <button onclick="loadPrompt()">📂 Carica prompt.txt</button>
| |
| <button onclick="savePrompt()">📅 Salva prompt.txt</button>
| |
| </div>
| |
|
| |
|
| <div style="margin-top:2rem;"> | | <label>Modello</label> |
| <h3>📥 Risposta GPT da salvare:</h3>
| | <select id="model-select" style="width:100%; margin-bottom:0.5rem;"> |
| <textarea id="gpt-response-area" rows="8" style="width:100%; margin-bottom:0.5rem;" placeholder="Inserisci qui la risposta generata da GPT"></textarea><br>
| | <option value="gpt-4o-2024-05-13" selected>gpt-4o-2024-05-13</option> |
| <input type="text" id="gpt-filename" placeholder="Nome file (es: login.php)" style="width:60%;">
| | <option value="gpt-4-turbo-2024-04-09">gpt-4-turbo-2024-04-09</option> |
| <select id="gpt-subfolder">
| | </select> |
| <option value="php">php</option>
| |
| <option value="docs">docs</option>
| |
| <option value="json">json</option> | |
| </select>
| |
| <input type="text" id="newProjectTitle" value="SSO_LinkedIn" placeholder="Project">
| |
| <button onclick="salvaFileDaTextarea()" style="background:#28a745; color:white; border:none; padding:0.4rem 1rem; border-radius:5px; font-weight:bold;">📅 Salva nel progetto</button>
| |
| </div>
| |
| -->
| |
|
| |
|
| | <label>Prompt di test</label> |
| | <textarea id="test_prompt" rows="3" style="width:100%; margin-bottom:0.5rem;">Dimmi una curiosità sulla mandibola</textarea> |
|
| |
|
| <!-- 📁 Caricamento File GPT --> | | <label style="display:inline-flex; gap:.4rem; align-items:center; margin:.25rem 0 .75rem;"> |
| <div style="margin-top:2rem;">
| | <input id="test_drop_urls" type="checkbox"> |
| <h3>📁 Carica File GPT</h3>
| | Ignora/Cancella URL e allegati per questo invio |
| <label>📁 Project: <input type="text" id="gpt-load-project" value="SSO_LinkedIn" /></label>
| | </label><br> |
| <label>📂 Subfolder: <input type="text" id="gpt-load-subfolder" value="php" /></label>
| |
| <label>📄 Filename: <input type="text" id="gpt-load-filename" placeholder="es: testGPT.php" /></label>
| |
| <button onclick="caricaFileGPT()">📁 Carica file</button>
| |
| </div> | |
|
| |
|
| <!-- 🧪 Console JS --> | | <button id="test_run">Esegui</button> |
| <div id="test-tools" style="display:none; padding:1rem; border:1px solid #ccc; border-radius:8px; background:#f9f9f9;">
| |
| <strong>Console JS:</strong><br>
| |
| <textarea id="codeArea" placeholder="Scrivi codice JS da testare..." style="width:100%; height:100px;"></textarea><br>
| |
| <button onclick="runTestCode()">▶️ Esegui</button>
| |
| <pre id="consoleOutput" style="background:#000; color:#0f0; padding:1rem; border-radius:8px; font-family:monospace;"></pre>
| |
| </div>
| |
|
| |
|
| <!-- 📘 Registro Attività --> | | <pre id="api-result" style="background:#f0f0f0; padding:1rem; border:1px solid #ccc; margin-top:1rem; white-space:pre-wrap;"></pre> |
| <div id="activity-log" style="display:none; padding:1rem; border:1px solid #ccc; border-radius:8px; background:#fdfdfd;">
| |
| <strong>📘 Registro attività:</strong>
| |
| <button onclick="clearActivityLog()" style="float:right; background:#e74c3c; color:white; border:none; padding:0.4rem 1rem; border-radius:6px; font-weight:bold;">🧹 Svuota</button>
| |
| <div id="activityLogContent" style="margin-top:1rem; max-height:250px; overflow-y:auto; background:#f0f0f0; padding:1rem; border:1px solid #ccc; border-radius:6px; font-family:monospace; font-size:0.85rem;">
| |
| <em><span style="color:#888;">Registro avviato...</span></em>
| |
| </div> | | </div> |
| </div> | | <script> |
| | // JS minimo temporaneo per sbloccare la pagina |
| | // (serve solo a NON avere errori di sintassi) |
| | </script> |
|
| |
|
| <!-- ✅ Carica il file JS che gestisce tutto
| | |
| <script src="/w/index.php?title=MediaWiki:CommonDashboard.js&action=raw&ctype=text/javascript"></script>
| |
| </html> | | </html> |
| -->
| |
|
| |
|
| |
| <script>
| |
| // === ChatGPT plus esteso (UI + Salva + Explorer) — INLINE ===
| |
| (function(){
| |
| const $ = s => document.querySelector(s);
| |
| const panel = $('#chatgpt-plus');
| |
| if (!panel) return;
| |
|
| |
| const projectSel = $('#mpChatProject');
| |
| const modeSel = $('#mpChatMode');
| |
| const fileInput = $('#mpChatFile');
| |
| const drop = $('#mpChatDrop');
| |
| const filesBox = $('#mpChatFiles');
| |
| const promptEl = $('#mpChatPrompt');
| |
| const sendBtn = $('#mpChatSend');
| |
| const ansBox = $('#mpChatAnswer');
| |
| const clearBtn = $('#mpChatClear');
| |
| const copyBtn = $('#mpChatCopy');
| |
| const saveBtn = $('#mpChatSave');
| |
|
| |
| // Explorer
| |
| const refreshBtn = $('#mpChatRefresh');
| |
| const savedList = $('#mpSavedList');
| |
|
| |
| let attached = [];
| |
|
| |
| function renderFiles(){
| |
| if (!filesBox) return;
| |
| filesBox.innerHTML = attached.map(n =>
| |
| `<span style="border:1px solid #eee; border-radius:6px; padding:4px 6px; background:#fafafa; font-size:12px;">${n}</span>`
| |
| ).join('');
| |
| }
| |
| function addFiles(list){ for (const f of list) attached.push(f.name); renderFiles(); }
| |
|
| |
| fileInput?.addEventListener('change', () => {
| |
| if (fileInput.files?.length) addFiles(fileInput.files);
| |
| fileInput.value = '';
| |
| });
| |
| ['dragenter','dragover','dragleave','drop'].forEach(evt=>{
| |
| drop?.addEventListener(evt, e => { e.preventDefault(); e.stopPropagation(); });
| |
| });
| |
| drop?.addEventListener('drop', e => {
| |
| const dt = e.dataTransfer;
| |
| if (dt?.files?.length) addFiles(dt.files);
| |
| });
| |
|
| |
| sendBtn?.addEventListener('click', () => {
| |
| const q = (promptEl.value||'').trim();
| |
| const project = projectSel?.value || 'Generazione_capitoli';
| |
| const mode = modeSel?.value || 'analysis';
| |
| if (!q) { ansBox.textContent = 'Scrivi la domanda nel box sopra.'; return; }
| |
| ansBox.textContent =
| |
| `✅ Pannello pronto\n\n` +
| |
| `• Progetto: ${project}\n` +
| |
| `• Modalità: ${mode}\n` +
| |
| `• Domanda:\n${q}\n\n` +
| |
| `• Allegati (solo elenco, non inviati):\n` +
| |
| (attached.length ? ('- ' + attached.join('\n- ')) : '(nessuno)');
| |
| });
| |
|
| |
| clearBtn?.addEventListener('click', () => { ansBox.textContent = ''; });
| |
| copyBtn?.addEventListener('click', async () => {
| |
| const txt = ansBox.textContent || '';
| |
| if (!txt.trim()) return;
| |
| try { await navigator.clipboard.writeText(txt); copyBtn.textContent='Copiato!'; setTimeout(()=>copyBtn.textContent='Copia risposta',1200); }
| |
| catch { alert('Impossibile copiare negli appunti.'); }
| |
| });
| |
|
| |
| saveBtn?.addEventListener('click', async () => {
| |
| const project = projectSel?.value || 'Generazione_capitoli';
| |
| const content = ansBox.textContent || '';
| |
| if (!content.trim()){ alert('Nessuna risposta da salvare.'); return; }
| |
| try {
| |
| const r = await fetch('/dashboard/api/save_output.php', {
| |
| method:'POST',
| |
| headers:{'Content-Type':'application/json'},
| |
| body: JSON.stringify({ project, content })
| |
| });
| |
| const j = await r.json();
| |
| if (!j.ok) throw new Error(j.error||'Errore salvataggio');
| |
| alert('Risposta salvata: ' + j.file);
| |
| await refreshList(); // aggiorna elenco dopo salvataggio
| |
| } catch (e){
| |
| alert('Salvataggio non ancora configurato (manca save_output.php).');
| |
| }
| |
| });
| |
|
| |
| async function refreshList(){
| |
| const project = projectSel?.value || 'Generazione_capitoli';
| |
| if (!savedList) return;
| |
| savedList.innerHTML = '<em style="color:#777;">Aggiorno…</em>';
| |
| try {
| |
| const r = await fetch('/dashboard/api/list_saved_output.php?project=' + encodeURIComponent(project) + '&sub=output');
| |
| const j = await r.json();
| |
| if (!j.ok) throw new Error(j.error||'Errore lista');
| |
| if (!j.files.length){
| |
| savedList.innerHTML = '<em style="color:#777;">Nessun file salvato.</em>';
| |
| return;
| |
| }
| |
| savedList.innerHTML = j.files.map(f=>{
| |
| const d = new Date(f.mtime*1000).toLocaleString();
| |
| return `<div class="mp-saved-item" data-name="${f.name}" style="display:flex; gap:8px; align-items:center; justify-content:space-between; border-bottom:1px dashed #eee; padding:4px 0;">
| |
| <span><a href="#" class="open" data-name="${f.name}">${f.name}</a> <span style="color:#888;">(${f.size} B, ${d})</span></span>
| |
| <button class="open" data-name="${f.name}" title="Apri nel box Risposta">Apri</button>
| |
| </div>`;
| |
| }).join('');
| |
| savedList.querySelectorAll('.open').forEach(el=>{
| |
| el.addEventListener('click', async (ev)=>{
| |
| ev.preventDefault();
| |
| await openFile(el.getAttribute('data-name'));
| |
| });
| |
| });
| |
| } catch(e){
| |
| savedList.innerHTML = '<span style="color:#c00;">Errore: '+e.message+'</span>';
| |
| }
| |
| }
| |
| async function openFile(name){
| |
| const project = projectSel?.value || 'Generazione_capitoli';
| |
| try{
| |
| const r = await fetch('/dashboard/api/read_saved_output.php', {
| |
| method:'POST',
| |
| headers:{'Content-Type':'application/json'},
| |
| body: JSON.stringify({ project, file: name })
| |
| });
| |
| const j = await r.json();
| |
| if (!j.ok) throw new Error(j.error||'Errore lettura');
| |
| ansBox.textContent = j.content || '';
| |
| } catch(e){
| |
| alert('Errore apertura file: ' + e.message);
| |
| }
| |
| }
| |
|
| |
| // Aggiorna quando apri il pannello (se usi toggleDashboardBox)
| |
| const toggle = window.toggleDashboardBox;
| |
| if (typeof toggle === 'function'){
| |
| window.toggleDashboardBox = function(id){
| |
| const res = toggle.apply(this, arguments);
| |
| if (id === 'chatgpt-plus' && panel.style.display !== 'none'){
| |
| refreshList();
| |
| }
| |
| return res;
| |
| };
| |
| }
| |
|
| |
| // Bottone Aggiorna
| |
| refreshBtn?.addEventListener('click', refreshList);
| |
|
| |
| // Primo popolamento
| |
| document.addEventListener('DOMContentLoaded', refreshList);
| |
| })();
| |
| </script>
| |