1089 lines
50 KiB
PHP
Executable File
1089 lines
50 KiB
PHP
Executable File
<?php
|
|
/**
|
|
* HAMID ULTRA MAX - Dashboard Central
|
|
* Toutes les fonctionnalités en un seul endroit
|
|
*/
|
|
?>
|
|
<!DOCTYPE html>
|
|
<html data-theme="dark" lang="fr">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>HAMID ULTRA MAX - Dashboard</title>
|
|
<style>
|
|
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
body {
|
|
font-family: 'Segoe UI', system-ui, sans-serif;
|
|
background: linear-gradient(135deg, #0a0a1a 0%, #1a1a3e 50%, #0d0d2b 100%);
|
|
min-height: 100vh;
|
|
color: #fff;
|
|
}
|
|
.header {
|
|
background: rgba(0,212,255,0.1);
|
|
border-bottom: 1px solid #00d4ff;
|
|
padding: 20px;
|
|
text-align: center;
|
|
}
|
|
.header h1 {
|
|
font-size: 2.5em;
|
|
background: linear-gradient(90deg, #00d4ff, #9333ea, #00d4ff);
|
|
-webkit-background-clip: text;
|
|
-webkit-text-fill-color: transparent;
|
|
animation: glow 3s ease-in-out infinite;
|
|
}
|
|
@keyframes glow {
|
|
0%, 100% { filter: brightness(1); }
|
|
50% { filter: brightness(1.3); }
|
|
}
|
|
.header p { color: #888; margin-top: 10px; }
|
|
.back-link {
|
|
position: absolute;
|
|
left: 20px;
|
|
top: 20px;
|
|
color: #00d4ff;
|
|
text-decoration: none;
|
|
font-size: 1.2em;
|
|
}
|
|
.back-link:hover { text-decoration: underline; }
|
|
|
|
.container {
|
|
max-width: 1400px;
|
|
margin: 0 auto;
|
|
padding: 30px;
|
|
}
|
|
|
|
.section {
|
|
margin-bottom: 40px;
|
|
}
|
|
.section h2 {
|
|
color: #00d4ff;
|
|
margin-bottom: 20px;
|
|
padding-bottom: 10px;
|
|
border-bottom: 1px solid #333;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 10px;
|
|
}
|
|
|
|
.cards {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
|
gap: 20px;
|
|
}
|
|
|
|
.card {
|
|
background: rgba(255,255,255,0.05);
|
|
border: 1px solid #333;
|
|
border-radius: 15px;
|
|
padding: 25px;
|
|
transition: all 0.3s ease;
|
|
cursor: pointer;
|
|
}
|
|
.card:hover {
|
|
transform: translateY(-5px);
|
|
border-color: #00d4ff;
|
|
box-shadow: 0 10px 40px rgba(0,212,255,0.2);
|
|
}
|
|
.card.purple:hover { border-color: #9333ea; box-shadow: 0 10px 40px rgba(147,51,234,0.2); }
|
|
.card.green:hover { border-color: #22c55e; box-shadow: 0 10px 40px rgba(34,197,94,0.2); }
|
|
.card.orange:hover { border-color: #f59e0b; box-shadow: 0 10px 40px rgba(245,158,11,0.2); }
|
|
.card.red:hover { border-color: #ef4444; box-shadow: 0 10px 40px rgba(239,68,68,0.2); }
|
|
|
|
.card-icon {
|
|
font-size: 3em;
|
|
margin-bottom: 15px;
|
|
}
|
|
.card h3 {
|
|
font-size: 1.3em;
|
|
margin-bottom: 10px;
|
|
}
|
|
.card p {
|
|
color: #888;
|
|
font-size: 0.9em;
|
|
line-height: 1.5;
|
|
}
|
|
.card .status {
|
|
margin-top: 15px;
|
|
padding: 5px 12px;
|
|
border-radius: 20px;
|
|
font-size: 0.8em;
|
|
display: inline-block;
|
|
}
|
|
.status.active { background: rgba(34,197,94,0.2); color: #22c55e; }
|
|
.status.ready { background: rgba(245,158,11,0.2); color: #f59e0b; }
|
|
.status.beta { background: rgba(147,51,234,0.2); color: #9333ea; }
|
|
|
|
/* Modal */
|
|
.modal {
|
|
display: none;
|
|
position: fixed;
|
|
top: 0; left: 0;
|
|
width: 100%; height: 100%;
|
|
background: rgba(0,0,0,0.8);
|
|
z-index: 1000;
|
|
justify-content: center;
|
|
align-items: center;
|
|
}
|
|
.modal.active { display: flex; }
|
|
.modal-content {
|
|
background: #1a1a3e;
|
|
border: 1px solid #00d4ff;
|
|
border-radius: 15px;
|
|
padding: 30px;
|
|
max-width: 600px;
|
|
width: 90%;
|
|
max-height: 80vh;
|
|
overflow-y: auto;
|
|
}
|
|
.modal h3 {
|
|
margin-bottom: 20px;
|
|
color: #00d4ff;
|
|
}
|
|
.modal input, .modal textarea, .modal select {
|
|
width: 100%;
|
|
padding: 12px;
|
|
margin-bottom: 15px;
|
|
border: 1px solid #333;
|
|
border-radius: 8px;
|
|
background: #0a0a1a;
|
|
color: #fff;
|
|
font-size: 1em;
|
|
}
|
|
.modal textarea { min-height: 100px; resize: vertical; }
|
|
.modal button {
|
|
padding: 12px 25px;
|
|
border: none;
|
|
border-radius: 8px;
|
|
cursor: pointer;
|
|
font-size: 1em;
|
|
margin-right: 10px;
|
|
}
|
|
.modal .btn-primary { background: #00d4ff; color: #000; }
|
|
.modal .btn-secondary { background: #333; color: #fff; }
|
|
.modal .btn-primary:hover { background: #00b8e6; }
|
|
|
|
.result-box {
|
|
background: #0a0a1a;
|
|
border: 1px solid #333;
|
|
border-radius: 8px;
|
|
padding: 15px;
|
|
margin-top: 15px;
|
|
max-height: 300px;
|
|
overflow-y: auto;
|
|
white-space: pre-wrap;
|
|
font-family: monospace;
|
|
font-size: 0.9em;
|
|
}
|
|
.result-box img {
|
|
max-width: 100%;
|
|
border-radius: 8px;
|
|
margin-top: 10px;
|
|
}
|
|
|
|
/* Stats */
|
|
.stats {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
|
|
gap: 15px;
|
|
margin-bottom: 30px;
|
|
}
|
|
.stat {
|
|
background: rgba(0,212,255,0.1);
|
|
border: 1px solid #00d4ff;
|
|
border-radius: 10px;
|
|
padding: 20px;
|
|
text-align: center;
|
|
}
|
|
.stat-value {
|
|
font-size: 2.5em;
|
|
font-weight: bold;
|
|
color: #00d4ff;
|
|
}
|
|
.stat-label {
|
|
color: #888;
|
|
font-size: 0.9em;
|
|
margin-top: 5px;
|
|
}
|
|
|
|
.loading {
|
|
display: inline-block;
|
|
width: 20px;
|
|
height: 20px;
|
|
border: 2px solid #333;
|
|
border-top-color: #00d4ff;
|
|
border-radius: 50%;
|
|
animation: spin 1s linear infinite;
|
|
}
|
|
@keyframes spin { to { transform: rotate(360deg); } }
|
|
</style>
|
|
<link href="https://fonts.googleapis.com/css2?family=DM+Sans:wght@400;500;600;700
|
|
</head>family=JetBrains+Mono:wght@400;500;700</head>display=swap" rel="stylesheet">
|
|
</head>
|
|
<body>
|
|
<div class="header">
|
|
<a href="hamid-fullscreen.php" class="back-link">← Retour au Chat</a>
|
|
<h1>🧠 HAMID ULTRA MAX</h1>
|
|
<p>Dashboard Central - Toutes les fonctionnalités IA avancées</p>
|
|
</div>
|
|
|
|
<div class="container">
|
|
<!-- Stats -->
|
|
<div class="stats" id="stats">
|
|
<div class="stat">
|
|
<div class="stat-value" id="stat-providers">11</div>
|
|
<div class="stat-label">Providers IA</div>
|
|
</div>
|
|
<div class="stat">
|
|
<div class="stat-value" id="stat-memories">-</div>
|
|
<div class="stat-label">Mémoires</div>
|
|
</div>
|
|
<div class="stat">
|
|
<div class="stat-value" id="stat-kb">-</div>
|
|
<div class="stat-label">KB Articles</div>
|
|
</div>
|
|
<div class="stat">
|
|
<div class="stat-value">5</div>
|
|
<div class="stat-label">Voix TTS</div>
|
|
</div>
|
|
<div class="stat">
|
|
<div class="stat-value">57</div>
|
|
<div class="stat-label">Services</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Chat IA -->
|
|
<div class="section">
|
|
<h2>💬 Chat & Intelligence</h2>
|
|
<div class="cards">
|
|
<div class="card" onclick="window.location='hamid-fullscreen.php'">
|
|
<div class="card-icon">🧠</div>
|
|
<h3>Chat HAMID</h3>
|
|
<p>Interface de chat principal avec intelligence ULTRA (10 techniques cognitives), multi-providers, TTS/STT</p>
|
|
<span class="status active">✓ Actif</span>
|
|
</div>
|
|
<div class="card" onclick="openModal('agent')">
|
|
<div class="card-icon">🤖</div>
|
|
<h3>Agent Autonome</h3>
|
|
<p>Lance des tâches complexes multi-étapes. L'agent planifie et exécute automatiquement.</p>
|
|
<span class="status active">✓ Actif</span>
|
|
</div>
|
|
<div class="card" onclick="openModal('summarize')">
|
|
<div class="card-icon">📝</div>
|
|
<h3>Résumé Automatique</h3>
|
|
<p>Résume n'importe quel texte en version courte, moyenne ou longue.</p>
|
|
<span class="status active">✓ Actif</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Multimodal -->
|
|
<div class="section">
|
|
<h2>🎨 Multimodal</h2>
|
|
<div class="cards">
|
|
<div class="card purple" onclick="openModal('vision')">
|
|
<div class="card-icon">👁️</div>
|
|
<h3>Vision / Analyse Image</h3>
|
|
<p>Upload une image et pose des questions dessus. Analyse avec Gemini Vision.</p>
|
|
<span class="status active">✓ Actif</span>
|
|
</div>
|
|
<div class="card purple" onclick="openModal('imagegen')">
|
|
<div class="card-icon">🎨</div>
|
|
<h3>Génération d'Images</h3>
|
|
<p>Crée des images IA à partir d'un prompt. Utilise Stable Diffusion via Pollinations.</p>
|
|
<span class="status active">✓ Actif</span>
|
|
</div>
|
|
<div class="card purple" onclick="openModal('tts')">
|
|
<div class="card-icon">🔊</div>
|
|
<h3>Text-to-Speech</h3>
|
|
<p>Convertis du texte en audio avec 5 voix naturelles Microsoft Edge.</p>
|
|
<span class="status active">✓ Actif</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Documents -->
|
|
<div class="section">
|
|
<h2>📄 Documents & Fichiers</h2>
|
|
<div class="cards">
|
|
<div class="card green" onclick="openModal('files')">
|
|
<div class="card-icon">📎</div>
|
|
<h3>Analyse de Fichiers</h3>
|
|
<p>Upload PDF, Word, Excel, CSV, JSON, TXT. Extrait et analyse le contenu.</p>
|
|
<span class="status active">✓ Actif</span>
|
|
</div>
|
|
<div class="card green" onclick="openModal('translate')">
|
|
<div class="card-icon">🌍</div>
|
|
<h3>Traduction</h3>
|
|
<p>Traduis du texte dans n'importe quelle langue (EN, FR, ES, DE, IT, PT, etc.)</p>
|
|
<span class="status active">✓ Actif</span>
|
|
</div>
|
|
<div class="card green" onclick="openModal('charts')">
|
|
<div class="card-icon">📊</div>
|
|
<h3>Graphiques</h3>
|
|
<p>Génère des graphiques (barres, lignes, camembert) à partir de données.</p>
|
|
<span class="status active">✓ Actif</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Code & Dev -->
|
|
<div class="section">
|
|
<h2>💻 Code & Développement</h2>
|
|
<div class="cards">
|
|
<div class="card orange" onclick="openModal('code')">
|
|
<div class="card-icon">⚡</div>
|
|
<h3>Exécution de Code</h3>
|
|
<p>Exécute du code Python, PHP ou Bash en temps réel. Comme Jupyter mais intégré.</p>
|
|
<span class="status active">✓ Actif</span>
|
|
</div>
|
|
<div class="card orange" onclick="openModal('websearch')">
|
|
<div class="card-icon">🔍</div>
|
|
<h3>Web Search</h3>
|
|
<p>Recherche sur le web en temps réel via DuckDuckGo + Wikipedia.</p>
|
|
<span class="status active">✓ Actif</span>
|
|
</div>
|
|
<div class="card orange" onclick="openModal('webhooks')">
|
|
<div class="card-icon">🔗</div>
|
|
<h3>Webhooks</h3>
|
|
<p>Configure des webhooks pour N8N, Slack, Make, ou tout autre service.</p>
|
|
<span class="status active">✓ Actif</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Mémoire & KB -->
|
|
<div class="section">
|
|
<h2>🧠 Mémoire & Knowledge Base</h2>
|
|
<div class="cards">
|
|
<div class="card red" onclick="openModal('memory')">
|
|
<div class="card-icon">💾</div>
|
|
<h3>Mémoire Long-Terme</h3>
|
|
<p>Gère les mémoires persistantes de HAMID. Ajoute des faits, préférences, contextes.</p>
|
|
<span class="status active">✓ Actif</span>
|
|
</div>
|
|
<div class="card red" onclick="openModal('rag')">
|
|
<div class="card-icon">🔮</div>
|
|
<h3>RAG Search</h3>
|
|
<p>Recherche sémantique dans la KB et la mémoire. Embeddings vectoriels 384D.</p>
|
|
<span class="status active">✓ Actif</span>
|
|
</div>
|
|
<div class="card red" onclick="window.location='hamid-kb.php'">
|
|
<div class="card-icon">📚</div>
|
|
<h3>Knowledge Base</h3>
|
|
<p>Accède à la base de connaissances complète. Ajoute, modifie, supprime des articles.</p>
|
|
<span class="status active">✓ Actif</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<!-- Nouvelles Fonctionnalités ULTRA MAX++ -->
|
|
<div class="section">
|
|
<h2>🆕 Outils Avancés</h2>
|
|
<div class="cards">
|
|
<div class="card" onclick="openModal('ocr')">
|
|
<div class="card-icon">📜</div>
|
|
<h3>OCR</h3>
|
|
<p>Extraire le texte d'une image (capture écran, photo document)</p>
|
|
<span class="status active">✓ Actif</span>
|
|
</div>
|
|
<div class="card purple" onclick="openModal('youtube')">
|
|
<div class="card-icon">▶️</div>
|
|
<h3>YouTube Transcript</h3>
|
|
<p>Extraire les sous-titres d'une vidéo YouTube</p>
|
|
<span class="status active">✓ Actif</span>
|
|
</div>
|
|
<div class="card green" onclick="openModal('email')">
|
|
<div class="card-icon">📧</div>
|
|
<h3>Email SMTP</h3>
|
|
<p>Envoyer des emails via SMTP</p>
|
|
<span class="status active">✓ Actif</span>
|
|
</div>
|
|
<div class="card orange" onclick="openModal('calendar')">
|
|
<div class="card-icon">📅</div>
|
|
<h3>Calendrier</h3>
|
|
<p>Gérer événements, rendez-vous et rappels</p>
|
|
<span class="status active">✓ Actif</span>
|
|
</div>
|
|
<div class="card red" onclick="openModal('scrape')">
|
|
<div class="card-icon">🕷️</div>
|
|
<h3>Web Scraping</h3>
|
|
<p>Extraire données de n'importe quel site web</p>
|
|
<span class="status active">✓ Actif</span>
|
|
</div>
|
|
<div class="card" onclick="openModal('history')">
|
|
<div class="card-icon">💬</div>
|
|
<h3>Historique</h3>
|
|
<p>Consulter l'historique des conversations</p>
|
|
<span class="status active">✓ Actif</span>
|
|
</div>
|
|
<div class="card purple" onclick="openModal('plugins')">
|
|
<div class="card-icon">🔌</div>
|
|
<h3>Plugins</h3>
|
|
<p>Gérer les extensions et plugins</p>
|
|
<span class="status active">✓ Actif</span>
|
|
</div>
|
|
<div class="card green" onclick="window.open('hamid-api-public.php?endpoint=docs')">
|
|
<div class="card-icon">🔑</div>
|
|
<h3>API Publique</h3>
|
|
<p>Documentation API REST</p>
|
|
<span class="status active">✓ Actif</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Outils Développeur -->
|
|
<div class="section">
|
|
<h2>🛠️ Outils Développeur</h2>
|
|
<div class="cards">
|
|
<div class="card" onclick="window.open('hamid-code-ui.php')">
|
|
<div class="card-icon">💻</div>
|
|
<h3>Code IDE</h3>
|
|
<p>IDE complet avec exécution code et IA intégrée</p>
|
|
<span class="status active">✓ Actif</span>
|
|
</div>
|
|
<div class="card purple" onclick="window.open('hamid-cli.php?command=help')">
|
|
<div class="card-icon">⌨️</div>
|
|
<h3>CLI API</h3>
|
|
<p>Interface ligne de commande</p>
|
|
<span class="status active">✓ Actif</span>
|
|
</div>
|
|
<div class="card green" onclick="window.open('hamid-bitvise.php?action=status')">
|
|
<div class="card-icon">🖥️</div>
|
|
<h3>Bitvise/SSH</h3>
|
|
<p>API pour connexions SSH/Terminal</p>
|
|
<span class="status active">✓ Actif</span>
|
|
</div>
|
|
<div class="card orange" onclick="window.open('hamid-status.php')">
|
|
<div class="card-icon">📊</div>
|
|
<h3>Status</h3>
|
|
<p>État du système et des services</p>
|
|
<span class="status active">✓ Actif</span>
|
|
</div>
|
|
<div class="card red" onclick="window.open('hamid-monitor.php')">
|
|
<div class="card-icon">📈</div>
|
|
<h3>Monitoring</h3>
|
|
<p>Surveillance en temps réel</p>
|
|
<span class="status active">✓ Actif</span>
|
|
</div>
|
|
<div class="card" onclick="window.open('hamid-brain-monitor.php')">
|
|
<div class="card-icon">🧠</div>
|
|
<h3>Brain Monitor</h3>
|
|
<p>Surveillance du cerveau IA</p>
|
|
<span class="status active">✓ Actif</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Modals -->
|
|
<div class="modal" id="modal">
|
|
<div class="modal-content" id="modal-content">
|
|
<!-- Contenu dynamique -->
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
// Charger stats
|
|
async function loadStats() {
|
|
try {
|
|
const mem = await fetch('/hamid-learn.php?action=stats').then(r => r.json());
|
|
document.getElementById('stat-memories').textContent = mem.total || 0;
|
|
|
|
const rag = await fetch('/hamid-rag.php?query=test').then(r => r.json());
|
|
document.getElementById('stat-kb').textContent = rag.kb?.length || 0;
|
|
} catch(e) {}
|
|
}
|
|
loadStats();
|
|
|
|
function openModal(type) {
|
|
const modal = document.getElementById('modal');
|
|
const content = document.getElementById('modal-content');
|
|
|
|
const templates = {
|
|
|
|
ocr: `
|
|
<h3>📜 OCR - Extraction de Texte</h3>
|
|
<input type="file" id="ocr-file" accept="image/*">
|
|
<select id="ocr-lang">
|
|
<option value="fra+eng">Français + Anglais</option>
|
|
<option value="fra">Français</option>
|
|
<option value="eng">Anglais</option>
|
|
</select>
|
|
<button class="btn-primary" onclick="runOCR()">Extraire</button>
|
|
<button class="btn-secondary" onclick="closeModal()">Fermer</button>
|
|
<div class="result-box" id="ocr-result" style="display:none"></div>
|
|
`,
|
|
youtube: `
|
|
<h3>▶️ YouTube Transcript</h3>
|
|
<input type="text" id="youtube-url" placeholder="URL YouTube (https://youtube.com/watch?v=...)">
|
|
<button class="btn-primary" onclick="runYouTube()">Extraire</button>
|
|
<button class="btn-secondary" onclick="closeModal()">Fermer</button>
|
|
<div class="result-box" id="youtube-result" style="display:none"></div>
|
|
`,
|
|
email: `
|
|
<h3>📧 Envoyer un Email</h3>
|
|
<input type="email" id="email-to" placeholder="Destinataire (email)">
|
|
<input type="text" id="email-subject" placeholder="Sujet">
|
|
<textarea id="email-body" placeholder="Contenu de l'email..."></textarea>
|
|
<button class="btn-primary" onclick="sendEmail()">Envoyer</button>
|
|
<button class="btn-secondary" onclick="closeModal()">Fermer</button>
|
|
<div class="result-box" id="email-result" style="display:none"></div>
|
|
`,
|
|
calendar: `
|
|
<h3>📅 Calendrier</h3>
|
|
<input type="text" id="cal-title" placeholder="Titre de l'événement">
|
|
<input type="datetime-local" id="cal-start">
|
|
<input type="datetime-local" id="cal-end">
|
|
<input type="text" id="cal-location" placeholder="Lieu (optionnel)">
|
|
<button class="btn-primary" onclick="addEvent()">Ajouter</button>
|
|
<button class="btn-secondary" onclick="listEvents()">Voir événements</button>
|
|
<button class="btn-secondary" onclick="closeModal()">Fermer</button>
|
|
<div class="result-box" id="calendar-result" style="display:none"></div>
|
|
`,
|
|
scrape: `
|
|
<h3>🕷️ Web Scraping</h3>
|
|
<input type="text" id="scrape-url" placeholder="URL à scraper">
|
|
<input type="text" id="scrape-selector" placeholder="Sélecteur CSS (optionnel)">
|
|
<select id="scrape-mode">
|
|
<option value="text">Texte</option>
|
|
<option value="links">Liens</option>
|
|
<option value="images">Images</option>
|
|
</select>
|
|
<button class="btn-primary" onclick="runScrape()">Scraper</button>
|
|
<button class="btn-secondary" onclick="closeModal()">Fermer</button>
|
|
<div class="result-box" id="scrape-result" style="display:none"></div>
|
|
`,
|
|
history: `
|
|
<h3>💬 Historique des Conversations</h3>
|
|
<input type="text" id="history-search" placeholder="Rechercher...">
|
|
<button class="btn-primary" onclick="loadHistory()">Charger</button>
|
|
<button class="btn-secondary" onclick="searchHistory()">Rechercher</button>
|
|
<button class="btn-secondary" onclick="closeModal()">Fermer</button>
|
|
<div class="result-box" id="history-result" style="display:none"></div>
|
|
`,
|
|
plugins: `
|
|
<h3>🔌 Plugins</h3>
|
|
<button class="btn-primary" onclick="listPlugins()">Liste des plugins</button>
|
|
<button class="btn-secondary" onclick="closeModal()">Fermer</button>
|
|
<div class="result-box" id="plugins-result" style="display:none"></div>
|
|
`,
|
|
agent: `
|
|
<h3>🤖 Agent Autonome</h3>
|
|
<input type="text" id="agent-task" placeholder="Décris la tâche à exécuter...">
|
|
<button class="btn-primary" onclick="runAgent()">Lancer l'Agent</button>
|
|
<button class="btn-secondary" onclick="closeModal()">Fermer</button>
|
|
<div class="result-box" id="agent-result" style="display:none"></div>
|
|
`,
|
|
vision: `
|
|
<h3>👁️ Analyse d'Image</h3>
|
|
<input type="file" id="vision-file" accept="image/*">
|
|
<input type="text" id="vision-prompt" placeholder="Question sur l'image..." value="Décris cette image en détail">
|
|
<button class="btn-primary" onclick="runVision()">Analyser</button>
|
|
<button class="btn-secondary" onclick="closeModal()">Fermer</button>
|
|
<div class="result-box" id="vision-result" style="display:none"></div>
|
|
`,
|
|
imagegen: `
|
|
<h3>🎨 Génération d'Image</h3>
|
|
<input type="text" id="imagegen-prompt" placeholder="Décris l'image à générer...">
|
|
<button class="btn-primary" onclick="runImageGen()">Générer</button>
|
|
<button class="btn-secondary" onclick="closeModal()">Fermer</button>
|
|
<div class="result-box" id="imagegen-result" style="display:none"></div>
|
|
`,
|
|
tts: `
|
|
<h3>🔊 Text-to-Speech</h3>
|
|
<textarea id="tts-text" placeholder="Texte à convertir en audio..."></textarea>
|
|
<select id="tts-voice">
|
|
<option value="fr-FR-DeniseNeural">Denise (Femme douce)</option>
|
|
<option value="fr-FR-HenriNeural">Henri (Homme)</option>
|
|
<option value="fr-FR-EloiseNeural">Eloise (Femme)</option>
|
|
<option value="fr-FR-VivienneMultilingualNeural">Vivienne (Multilingue)</option>
|
|
<option value="fr-FR-RemyMultilingualNeural">Remy (Multilingue)</option>
|
|
</select>
|
|
<button class="btn-primary" onclick="runTTS()">Écouter</button>
|
|
<button class="btn-secondary" onclick="closeModal()">Fermer</button>
|
|
<div class="result-box" id="tts-result" style="display:none"></div>
|
|
`,
|
|
files: `
|
|
<h3>📎 Analyse de Fichiers</h3>
|
|
<input type="file" id="file-upload" accept=".pdf,.docx,.xlsx,.csv,.txt,.json,.md">
|
|
<button class="btn-primary" onclick="runFileAnalysis()">Analyser</button>
|
|
<button class="btn-secondary" onclick="closeModal()">Fermer</button>
|
|
<div class="result-box" id="file-result" style="display:none"></div>
|
|
`,
|
|
translate: `
|
|
<h3>🌍 Traduction</h3>
|
|
<textarea id="translate-text" placeholder="Texte à traduire..."></textarea>
|
|
<select id="translate-source">
|
|
<option value="en">Anglais</option>
|
|
<option value="fr">Français</option>
|
|
<option value="es">Espagnol</option>
|
|
<option value="de">Allemand</option>
|
|
<option value="it">Italien</option>
|
|
<option value="pt">Portugais</option>
|
|
</select>
|
|
→
|
|
<select id="translate-target">
|
|
<option value="fr">Français</option>
|
|
<option value="en">Anglais</option>
|
|
<option value="es">Espagnol</option>
|
|
<option value="de">Allemand</option>
|
|
<option value="it">Italien</option>
|
|
<option value="pt">Portugais</option>
|
|
</select>
|
|
<button class="btn-primary" onclick="runTranslate()">Traduire</button>
|
|
<button class="btn-secondary" onclick="closeModal()">Fermer</button>
|
|
<div class="result-box" id="translate-result" style="display:none"></div>
|
|
`,
|
|
code: `
|
|
<h3>⚡ Exécution de Code</h3>
|
|
<select id="code-lang">
|
|
<option value="python">Python</option>
|
|
<option value="php">PHP</option>
|
|
<option value="bash">Bash</option>
|
|
</select>
|
|
<textarea id="code-input" placeholder="print('Hello World')" style="font-family:monospace"></textarea>
|
|
<button class="btn-primary" onclick="runCode()">Exécuter</button>
|
|
<button class="btn-secondary" onclick="closeModal()">Fermer</button>
|
|
<div class="result-box" id="code-result" style="display:none"></div>
|
|
`,
|
|
websearch: `
|
|
<h3>🔍 Web Search</h3>
|
|
<input type="text" id="search-query" placeholder="Rechercher sur le web...">
|
|
<button class="btn-primary" onclick="runWebSearch()">Rechercher</button>
|
|
<button class="btn-secondary" onclick="closeModal()">Fermer</button>
|
|
<div class="result-box" id="search-result" style="display:none"></div>
|
|
`,
|
|
charts: `
|
|
<h3>📊 Génération de Graphiques</h3>
|
|
<select id="chart-type">
|
|
<option value="bar">Barres</option>
|
|
<option value="line">Ligne</option>
|
|
<option value="pie">Camembert</option>
|
|
<option value="doughnut">Donut</option>
|
|
</select>
|
|
<input type="text" id="chart-labels" placeholder="Labels (séparés par virgule): Jan,Fév,Mar">
|
|
<input type="text" id="chart-data" placeholder="Données (séparées par virgule): 10,20,30">
|
|
<input type="text" id="chart-title" placeholder="Titre du graphique">
|
|
<button class="btn-primary" onclick="runChart()">Générer</button>
|
|
<button class="btn-secondary" onclick="closeModal()">Fermer</button>
|
|
<div class="result-box" id="chart-result" style="display:none"></div>
|
|
`,
|
|
memory: `
|
|
<h3>💾 Mémoire Long-Terme</h3>
|
|
<select id="memory-type">
|
|
<option value="fact">Fait</option>
|
|
<option value="preference">Préférence</option>
|
|
<option value="context">Contexte</option>
|
|
<option value="skill">Compétence</option>
|
|
</select>
|
|
<textarea id="memory-content" placeholder="Contenu de la mémoire..."></textarea>
|
|
<input type="number" id="memory-importance" placeholder="Importance (1-10)" value="5" min="1" max="10">
|
|
<button class="btn-primary" onclick="addMemory()">Ajouter</button>
|
|
<button class="btn-secondary" onclick="closeModal()">Fermer</button>
|
|
<div class="result-box" id="memory-result" style="display:none"></div>
|
|
`,
|
|
rag: `
|
|
<h3>🔮 RAG Search</h3>
|
|
<input type="text" id="rag-query" placeholder="Recherche sémantique...">
|
|
<button class="btn-primary" onclick="runRAG()">Rechercher</button>
|
|
<button class="btn-secondary" onclick="closeModal()">Fermer</button>
|
|
<div class="result-box" id="rag-result" style="display:none"></div>
|
|
`,
|
|
webhooks: `
|
|
<h3>🔗 Webhooks</h3>
|
|
<input type="text" id="webhook-name" placeholder="Nom du webhook">
|
|
<input type="text" id="webhook-url" placeholder="URL (https://...)">
|
|
<select id="webhook-event">
|
|
<option value="message">Message</option>
|
|
<option value="alert">Alerte</option>
|
|
<option value="report">Rapport</option>
|
|
</select>
|
|
<button class="btn-primary" onclick="registerWebhook()">Enregistrer</button>
|
|
<button class="btn-secondary" onclick="listWebhooks()">Liste</button>
|
|
<button class="btn-secondary" onclick="closeModal()">Fermer</button>
|
|
<div class="result-box" id="webhook-result" style="display:none"></div>
|
|
`,
|
|
summarize: `
|
|
<h3>📝 Résumé Automatique</h3>
|
|
<textarea id="summarize-text" placeholder="Texte à résumer..."></textarea>
|
|
<select id="summarize-length">
|
|
<option value="short">Court (50 mots)</option>
|
|
<option value="medium" selected>Moyen (150 mots)</option>
|
|
<option value="long">Long (300 mots)</option>
|
|
</select>
|
|
<button class="btn-primary" onclick="runSummarize()">Résumer</button>
|
|
<button class="btn-secondary" onclick="closeModal()">Fermer</button>
|
|
<div class="result-box" id="summarize-result" style="display:none"></div>
|
|
`
|
|
};
|
|
|
|
content.innerHTML = templates[type] || '<p>Non disponible</p>';
|
|
modal.classList.add('active');
|
|
}
|
|
|
|
function closeModal() {
|
|
document.getElementById('modal').classList.remove('active');
|
|
}
|
|
|
|
// Fonctions d'exécution
|
|
async function runAgent() {
|
|
const task = document.getElementById('agent-task').value;
|
|
const result = document.getElementById('agent-result');
|
|
result.style.display = 'block';
|
|
result.innerHTML = '<span class="loading"></span> Agent en cours...';
|
|
|
|
const data = await fetch('/hamid-agent.php', {
|
|
method: 'POST',
|
|
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
|
|
body: 'task=' + encodeURIComponent(task)
|
|
}).then(r => r.json());
|
|
|
|
result.innerHTML = data.result || JSON.stringify(data, null, 2);
|
|
}
|
|
|
|
async function runVision() {
|
|
const file = document.getElementById('vision-file').files[0];
|
|
const prompt = document.getElementById('vision-prompt').value;
|
|
const result = document.getElementById('vision-result');
|
|
|
|
if (!file) { alert('Sélectionne une image'); return; }
|
|
|
|
result.style.display = 'block';
|
|
result.innerHTML = '<span class="loading"></span> Analyse en cours...';
|
|
|
|
const reader = new FileReader();
|
|
reader.onload = async function(e) {
|
|
const base64 = e.target.result.split(',')[1];
|
|
const data = await fetch('/hamid-vision.php', {
|
|
method: 'POST',
|
|
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
|
|
body: 'image=' + encodeURIComponent(base64) + '&prompt=' + encodeURIComponent(prompt)
|
|
}).then(r => r.json());
|
|
|
|
result.innerHTML = data.description || data.error || 'Erreur';
|
|
};
|
|
reader.readAsDataURL(file);
|
|
}
|
|
|
|
async function runImageGen() {
|
|
const prompt = document.getElementById('imagegen-prompt').value;
|
|
const result = document.getElementById('imagegen-result');
|
|
result.style.display = 'block';
|
|
result.innerHTML = '<span class="loading"></span> Génération en cours (10-30 sec)...';
|
|
|
|
const data = await fetch('/hamid-image-gen.php?prompt=' + encodeURIComponent(prompt)).then(r => r.json());
|
|
|
|
if (data.image_url) {
|
|
result.innerHTML = '<img src="' + data.image_url + '" alt="Generated">';
|
|
} else {
|
|
result.innerHTML = 'Erreur: ' + (data.error || 'Unknown');
|
|
}
|
|
}
|
|
|
|
async function runTTS() {
|
|
const text = document.getElementById('tts-text').value;
|
|
const voice = document.getElementById('tts-voice').value;
|
|
const result = document.getElementById('tts-result');
|
|
result.style.display = 'block';
|
|
result.innerHTML = '<span class="loading"></span> Génération audio...';
|
|
|
|
const audio = new Audio('/hamid-tts.php?text=' + encodeURIComponent(text) + '&voice=' + voice);
|
|
audio.play();
|
|
result.innerHTML = '🔊 Lecture en cours...';
|
|
}
|
|
|
|
async function runFileAnalysis() {
|
|
const file = document.getElementById('file-upload').files[0];
|
|
const result = document.getElementById('file-result');
|
|
|
|
if (!file) { alert('Sélectionne un fichier'); return; }
|
|
|
|
result.style.display = 'block';
|
|
result.innerHTML = '<span class="loading"></span> Analyse en cours...';
|
|
|
|
const formData = new FormData();
|
|
formData.append('file', file);
|
|
|
|
const data = await fetch('/hamid-files.php', {method: 'POST', body: formData}).then(r => r.json());
|
|
|
|
result.innerHTML = '<b>' + data.filename + '</b> (' + data.chars + ' chars)\n\n' + (data.content || 'Erreur').substring(0, 2000);
|
|
}
|
|
|
|
async function runTranslate() {
|
|
const text = document.getElementById('translate-text').value;
|
|
const source = document.getElementById('translate-source').value;
|
|
const target = document.getElementById('translate-target').value;
|
|
const result = document.getElementById('translate-result');
|
|
result.style.display = 'block';
|
|
result.innerHTML = '<span class="loading"></span> Traduction...';
|
|
|
|
const data = await fetch('/hamid-translate.php', {
|
|
method: 'POST',
|
|
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
|
|
body: 'text=' + encodeURIComponent(text) + '&source=' + source + '&target=' + target
|
|
}).then(r => r.json());
|
|
|
|
result.innerHTML = data.translated || data.error || 'Erreur';
|
|
}
|
|
|
|
async function runCode() {
|
|
const code = document.getElementById('code-input').value;
|
|
const lang = document.getElementById('code-lang').value;
|
|
const result = document.getElementById('code-result');
|
|
result.style.display = 'block';
|
|
result.innerHTML = '<span class="loading"></span> Exécution...';
|
|
|
|
const data = await fetch('/hamid-code.php', {
|
|
method: 'POST',
|
|
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
|
|
body: 'code=' + encodeURIComponent(code) + '&language=' + lang
|
|
}).then(r => r.json());
|
|
|
|
result.innerHTML = data.output || data.error || 'Pas de sortie';
|
|
}
|
|
|
|
async function runWebSearch() {
|
|
const query = document.getElementById('search-query').value;
|
|
const result = document.getElementById('search-result');
|
|
result.style.display = 'block';
|
|
result.innerHTML = '<span class="loading"></span> Recherche...';
|
|
|
|
const data = await fetch('/hamid-websearch.php?query=' + encodeURIComponent(query)).then(r => r.json());
|
|
|
|
let html = '<b>Résultats:</b>\n\n';
|
|
if (data.instant_answer) html += data.instant_answer + '\n\n';
|
|
if (data.wikipedia?.extract) html += '<b>Wikipedia:</b> ' + data.wikipedia.extract;
|
|
result.innerHTML = html || 'Pas de résultats';
|
|
}
|
|
|
|
async function runChart() {
|
|
const type = document.getElementById('chart-type').value;
|
|
const labels = document.getElementById('chart-labels').value.split(',');
|
|
const dataValues = document.getElementById('chart-data').value.split(',').map(Number);
|
|
const title = document.getElementById('chart-title').value;
|
|
const result = document.getElementById('chart-result');
|
|
result.style.display = 'block';
|
|
result.innerHTML = '<span class="loading"></span> Génération...';
|
|
|
|
const chartData = {
|
|
labels: labels,
|
|
datasets: [{label: title, data: dataValues, backgroundColor: ['#00d4ff','#9333ea','#22c55e','#f59e0b','#ef4444']}]
|
|
};
|
|
|
|
const data = await fetch('/hamid-charts.php', {
|
|
method: 'POST',
|
|
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
|
|
body: 'type=' + type + '&data=' + encodeURIComponent(JSON.stringify(chartData)) + '&title=' + encodeURIComponent(title)
|
|
}).then(r => r.json());
|
|
|
|
result.innerHTML = '<img src="' + data.chart_url + '">';
|
|
}
|
|
|
|
async function addMemory() {
|
|
const type = document.getElementById('memory-type').value;
|
|
const content = document.getElementById('memory-content').value;
|
|
const importance = document.getElementById('memory-importance').value;
|
|
const result = document.getElementById('memory-result');
|
|
result.style.display = 'block';
|
|
|
|
const data = await fetch('/hamid-learn.php', {
|
|
method: 'POST',
|
|
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
|
|
body: 'action=add&type=' + type + '&content=' + encodeURIComponent(content) + '&importance=' + importance
|
|
}).then(r => r.json());
|
|
|
|
result.innerHTML = data.success ? '✅ Mémoire ajoutée!' : '❌ Erreur';
|
|
loadStats();
|
|
}
|
|
|
|
async function runRAG() {
|
|
const query = document.getElementById('rag-query').value;
|
|
const result = document.getElementById('rag-result');
|
|
result.style.display = 'block';
|
|
result.innerHTML = '<span class="loading"></span> Recherche...';
|
|
|
|
const data = await fetch('/hamid-rag.php?query=' + encodeURIComponent(query)).then(r => r.json());
|
|
|
|
let html = '<b>Mémoires (' + (data.memory?.length || 0) + '):</b>\n';
|
|
(data.memory || []).forEach(m => html += '• [' + m.memory_type + '] ' + m.content + '\n');
|
|
html += '\n<b>KB (' + (data.kb?.length || 0) + '):</b>\n';
|
|
(data.kb || []).forEach(k => html += '• ' + k.title + '\n');
|
|
|
|
result.innerHTML = html;
|
|
}
|
|
|
|
async function registerWebhook() {
|
|
const name = document.getElementById('webhook-name').value;
|
|
const url = document.getElementById('webhook-url').value;
|
|
const event = document.getElementById('webhook-event').value;
|
|
const result = document.getElementById('webhook-result');
|
|
result.style.display = 'block';
|
|
|
|
const data = await fetch('/hamid-webhook.php', {
|
|
method: 'POST',
|
|
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
|
|
body: 'action=register&name=' + encodeURIComponent(name) + '&url=' + encodeURIComponent(url) + '&event_type=' + event
|
|
}).then(r => r.json());
|
|
|
|
result.innerHTML = data.success ? '✅ Webhook enregistré (ID: ' + data.id + ')' : '❌ Erreur';
|
|
}
|
|
|
|
async function listWebhooks() {
|
|
const result = document.getElementById('webhook-result');
|
|
result.style.display = 'block';
|
|
|
|
const data = await fetch('/hamid-webhook.php?action=list').then(r => r.json());
|
|
|
|
let html = '<b>Webhooks:</b>\n';
|
|
(data.webhooks || []).forEach(w => html += '• ' + w.name + ' → ' + w.url + ' [' + w.event_type + ']\n');
|
|
result.innerHTML = html || 'Aucun webhook';
|
|
}
|
|
|
|
async function runSummarize() {
|
|
const text = document.getElementById('summarize-text').value;
|
|
const length = document.getElementById('summarize-length').value;
|
|
const result = document.getElementById('summarize-result');
|
|
result.style.display = 'block';
|
|
result.innerHTML = '<span class="loading"></span> Résumé en cours...';
|
|
|
|
const data = await fetch('/hamid-summarize.php', {
|
|
method: 'POST',
|
|
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
|
|
body: 'text=' + encodeURIComponent(text) + '&length=' + length
|
|
}).then(r => r.json());
|
|
|
|
result.innerHTML = data.summary || data.error || 'Erreur';
|
|
}
|
|
|
|
|
|
// === NOUVELLES FONCTIONS ULTRA MAX++ ===
|
|
|
|
async function runOCR() {
|
|
const file = document.getElementById("ocr-file").files[0];
|
|
const lang = document.getElementById("ocr-lang").value;
|
|
const result = document.getElementById("ocr-result");
|
|
if (!file) { alert("Sélectionne une image"); return; }
|
|
result.style.display = "block";
|
|
result.innerHTML = "<span class=\"loading\"></span> Extraction en cours...";
|
|
const reader = new FileReader();
|
|
reader.onload = async function(e) {
|
|
const base64 = e.target.result.split(",")[1];
|
|
const data = await fetch("/hamid-ocr.php", {
|
|
method: "POST",
|
|
headers: {"Content-Type": "application/x-www-form-urlencoded"},
|
|
body: "image=" + encodeURIComponent(base64) + "&lang=" + lang
|
|
}).then(r => r.json());
|
|
result.innerHTML = data.text || data.error || "Pas de texte trouvé";
|
|
};
|
|
reader.readAsDataURL(file);
|
|
}
|
|
|
|
async function runYouTube() {
|
|
const url = document.getElementById("youtube-url").value;
|
|
const result = document.getElementById("youtube-result");
|
|
result.style.display = "block";
|
|
result.innerHTML = "<span class=\"loading\"></span> Extraction...";
|
|
const data = await fetch("/hamid-youtube.php?url=" + encodeURIComponent(url)).then(r => r.json());
|
|
result.innerHTML = data.transcript ? data.transcript.substring(0, 3000) : (data.error || "Erreur");
|
|
}
|
|
|
|
async function sendEmail() {
|
|
const to = document.getElementById("email-to").value;
|
|
const subject = document.getElementById("email-subject").value;
|
|
const body = document.getElementById("email-body").value;
|
|
const result = document.getElementById("email-result");
|
|
result.style.display = "block";
|
|
const data = await fetch("/hamid-email.php", {
|
|
method: "POST",
|
|
headers: {"Content-Type": "application/x-www-form-urlencoded"},
|
|
body: "action=send&to=" + encodeURIComponent(to) + "&subject=" + encodeURIComponent(subject) + "&body=" + encodeURIComponent(body)
|
|
}).then(r => r.json());
|
|
result.innerHTML = data.success ? "✅ Email envoyé à " + to : "❌ " + (data.error || "Erreur envoi");
|
|
}
|
|
|
|
async function addEvent() {
|
|
const title = document.getElementById("cal-title").value;
|
|
const start = document.getElementById("cal-start").value;
|
|
const end = document.getElementById("cal-end").value || start;
|
|
const location = document.getElementById("cal-location").value;
|
|
const result = document.getElementById("calendar-result");
|
|
result.style.display = "block";
|
|
const data = await fetch("/hamid-calendar.php", {
|
|
method: "POST",
|
|
headers: {"Content-Type": "application/x-www-form-urlencoded"},
|
|
body: "action=add&title=" + encodeURIComponent(title) + "&start_date=" + start + "&end_date=" + end + "&location=" + encodeURIComponent(location)
|
|
}).then(r => r.json());
|
|
result.innerHTML = data.success ? "✅ Événement ajouté!" : "❌ Erreur";
|
|
}
|
|
|
|
async function listEvents() {
|
|
const result = document.getElementById("calendar-result");
|
|
result.style.display = "block";
|
|
result.innerHTML = "<span class=\"loading\"></span> Chargement...";
|
|
const data = await fetch("/hamid-calendar.php?action=upcoming").then(r => r.json());
|
|
let html = "<b>Événements à venir:</b><br><br>";
|
|
(data.events || []).forEach(e => html += "• <b>" + e.title + "</b> - " + e.start_date + "<br>");
|
|
result.innerHTML = html || "Aucun événement";
|
|
}
|
|
|
|
async function runScrape() {
|
|
const url = document.getElementById("scrape-url").value;
|
|
const selector = document.getElementById("scrape-selector").value;
|
|
const mode = document.getElementById("scrape-mode").value;
|
|
const result = document.getElementById("scrape-result");
|
|
result.style.display = "block";
|
|
result.innerHTML = "<span class=\"loading\"></span> Scraping...";
|
|
const data = await fetch("/hamid-scrape.php", {
|
|
method: "POST",
|
|
headers: {"Content-Type": "application/x-www-form-urlencoded"},
|
|
body: "url=" + encodeURIComponent(url) + "&selector=" + encodeURIComponent(selector) + "&mode=" + mode
|
|
}).then(r => r.json());
|
|
if (data.text) result.innerHTML = "<b>" + data.title + "</b><br><br>" + data.text.substring(0, 2000);
|
|
else if (data.links) result.innerHTML = data.links.map(l => "• <a href=\"" + l.href + "\" target=\"_blank\">" + l.text + "</a>").join("<br>");
|
|
else result.innerHTML = JSON.stringify(data, null, 2);
|
|
}
|
|
|
|
async function loadHistory() {
|
|
const result = document.getElementById("history-result");
|
|
result.style.display = "block";
|
|
result.innerHTML = "<span class=\"loading\"></span> Chargement...";
|
|
const data = await fetch("/hamid-history.php?action=list_conversations").then(r => r.json());
|
|
let html = "<b>Conversations:</b><br><br>";
|
|
(data.conversations || []).forEach(c => html += "• " + c.title + " (" + (c.message_count || 0) + " msgs)<br>");
|
|
result.innerHTML = html || "Aucune conversation";
|
|
}
|
|
|
|
async function searchHistory() {
|
|
const query = document.getElementById("history-search").value || prompt("Rechercher:");
|
|
if (!query) return;
|
|
const result = document.getElementById("history-result");
|
|
result.style.display = "block";
|
|
result.innerHTML = "<span class=\"loading\"></span> Recherche...";
|
|
const data = await fetch("/hamid-history.php?action=search&q=" + encodeURIComponent(query)).then(r => r.json());
|
|
let html = "<b>Résultats pour \"" + query + "\":</b><br><br>";
|
|
(data.results || []).forEach(r => html += "• " + r.content.substring(0, 100) + "...<br>");
|
|
result.innerHTML = html || "Aucun résultat";
|
|
}
|
|
|
|
async function listPlugins() {
|
|
const result = document.getElementById("plugins-result");
|
|
result.style.display = "block";
|
|
result.innerHTML = "<span class=\"loading\"></span> Chargement...";
|
|
const data = await fetch("/hamid-plugins.php?action=list").then(r => r.json());
|
|
let html = "<b>Plugins installés:</b><br><br>";
|
|
(data.plugins || []).forEach(p => html += "• " + p.name + " v" + p.version + " [" + (p.enabled ? "✓ Actif" : "✗ Inactif") + "]<br>");
|
|
result.innerHTML = html || "Aucun plugin";
|
|
}
|
|
|
|
// Fermer modal sur clic extérieur
|
|
document.getElementById('modal').addEventListener('click', function(e) {
|
|
if (e.target === this) closeModal();
|
|
});
|
|
</script>
|
|
|
|
|
|
|
|
</body>
|
|
</html>
|