338 lines
10 KiB
JavaScript
338 lines
10 KiB
JavaScript
/**
|
||
* JavaScript pour la gestion des clés API du chatbot
|
||
*/
|
||
|
||
// État global
|
||
let currentProvider = null;
|
||
let editMode = false;
|
||
|
||
// Helper URLs
|
||
const API_HELP_URLS = {
|
||
'gemini': 'https://aistudio.google.com/apikey',
|
||
'mistral': 'https://console.mistral.ai/api-keys/',
|
||
'openai': 'https://platform.openai.com/api-keys'
|
||
};
|
||
|
||
// ========== Modal Management ==========
|
||
|
||
function openAddKeyModal(provider = null) {
|
||
const modal = document.getElementById('keyModal');
|
||
const title = document.getElementById('modalTitle');
|
||
const form = document.getElementById('keyForm');
|
||
const providerSelect = document.getElementById('provider');
|
||
const testResult = document.getElementById('testResult');
|
||
|
||
// Reset form
|
||
form.reset();
|
||
testResult.style.display = 'none';
|
||
document.getElementById('keyAction').value = 'add';
|
||
editMode = false;
|
||
|
||
// Pre-select provider if provided
|
||
if (provider) {
|
||
providerSelect.value = provider;
|
||
updateModelsList();
|
||
providerSelect.disabled = false;
|
||
} else {
|
||
providerSelect.disabled = false;
|
||
}
|
||
|
||
title.textContent = 'Ajouter une clé API';
|
||
modal.classList.add('show');
|
||
}
|
||
|
||
function editKey(provider) {
|
||
currentProvider = provider;
|
||
editMode = true;
|
||
|
||
// Récupérer les infos de la clé
|
||
fetch(`chatbot_api_ajax.php?action=get&provider=${provider}`)
|
||
.then(response => response.json())
|
||
.then(data => {
|
||
if (data.success) {
|
||
const modal = document.getElementById('keyModal');
|
||
const title = document.getElementById('modalTitle');
|
||
const form = document.getElementById('keyForm');
|
||
const providerSelect = document.getElementById('provider');
|
||
const modelSelect = document.getElementById('model_default');
|
||
const testResult = document.getElementById('testResult');
|
||
|
||
testResult.style.display = 'none';
|
||
document.getElementById('keyAction').value = 'edit';
|
||
|
||
// Remplir le formulaire
|
||
providerSelect.value = provider;
|
||
providerSelect.disabled = true;
|
||
updateModelsList();
|
||
|
||
// Attendre que la liste des modèles soit chargée
|
||
setTimeout(() => {
|
||
modelSelect.value = data.data.model_default;
|
||
|
||
if (data.data.quota_max) {
|
||
document.getElementById('set_quota').checked = true;
|
||
document.getElementById('quota_max').value = data.data.quota_max;
|
||
toggleQuotaInput();
|
||
}
|
||
}, 100);
|
||
|
||
title.textContent = `Modifier la clé ${provider}`;
|
||
modal.classList.add('show');
|
||
} else {
|
||
showToast(data.error || 'Erreur lors du chargement', 'error');
|
||
}
|
||
})
|
||
.catch(error => {
|
||
console.error('Error:', error);
|
||
showToast('Erreur de connexion', 'error');
|
||
});
|
||
}
|
||
|
||
function closeKeyModal() {
|
||
const modal = document.getElementById('keyModal');
|
||
modal.classList.remove('show');
|
||
currentProvider = null;
|
||
editMode = false;
|
||
}
|
||
|
||
// ========== Form Handling ==========
|
||
|
||
function updateModelsList() {
|
||
const provider = document.getElementById('provider').value;
|
||
const modelSelect = document.getElementById('model_default');
|
||
const keyHelp = document.getElementById('keyHelp');
|
||
|
||
// Clear current options
|
||
modelSelect.innerHTML = '<option value="">-- Sélectionner un modèle --</option>';
|
||
|
||
if (!provider) {
|
||
keyHelp.innerHTML = '';
|
||
return;
|
||
}
|
||
|
||
// Populate models for selected provider
|
||
if (models[provider]) {
|
||
models[provider].forEach(model => {
|
||
const option = document.createElement('option');
|
||
option.value = model.model_id;
|
||
option.textContent = model.display_name;
|
||
if (model.recommended) {
|
||
option.textContent += ' ⭐';
|
||
}
|
||
modelSelect.appendChild(option);
|
||
});
|
||
|
||
// Auto-select first recommended model
|
||
const recommended = models[provider].find(m => m.recommended);
|
||
if (recommended) {
|
||
modelSelect.value = recommended.model_id;
|
||
}
|
||
}
|
||
|
||
// Update help text
|
||
if (API_HELP_URLS[provider]) {
|
||
keyHelp.innerHTML = `💡 Obtenir une clé : <a href="${API_HELP_URLS[provider]}" target="_blank">${API_HELP_URLS[provider]}</a>`;
|
||
} else {
|
||
keyHelp.innerHTML = '';
|
||
}
|
||
}
|
||
|
||
function toggleQuotaInput() {
|
||
const checkbox = document.getElementById('set_quota');
|
||
const quotaGroup = document.getElementById('quotaGroup');
|
||
quotaGroup.style.display = checkbox.checked ? 'block' : 'none';
|
||
}
|
||
|
||
function toggleKeyVisibility() {
|
||
const input = document.getElementById('api_key');
|
||
const button = event.target;
|
||
|
||
if (input.type === 'password') {
|
||
input.type = 'text';
|
||
button.textContent = '🙈';
|
||
} else {
|
||
input.type = 'password';
|
||
button.textContent = '👁️';
|
||
}
|
||
}
|
||
|
||
// ========== Form Submission ==========
|
||
|
||
document.getElementById('keyForm').addEventListener('submit', function(e) {
|
||
e.preventDefault();
|
||
|
||
const formData = new FormData(this);
|
||
formData.append('action', 'save');
|
||
|
||
// Show loading
|
||
const submitBtn = this.querySelector('button[type="submit"]');
|
||
const originalText = submitBtn.innerHTML;
|
||
submitBtn.innerHTML = '⏳ Enregistrement...';
|
||
submitBtn.disabled = true;
|
||
|
||
fetch('chatbot_api_ajax.php', {
|
||
method: 'POST',
|
||
body: formData
|
||
})
|
||
.then(response => response.json())
|
||
.then(data => {
|
||
if (data.success) {
|
||
showToast(data.message || 'Clé enregistrée avec succès', 'success');
|
||
closeKeyModal();
|
||
|
||
// Reload page to show updated keys
|
||
setTimeout(() => {
|
||
window.location.reload();
|
||
}, 1000);
|
||
} else {
|
||
showToast(data.error || 'Erreur lors de l\'enregistrement', 'error');
|
||
}
|
||
})
|
||
.catch(error => {
|
||
console.error('Error:', error);
|
||
showToast('Erreur de connexion', 'error');
|
||
})
|
||
.finally(() => {
|
||
submitBtn.innerHTML = originalText;
|
||
submitBtn.disabled = false;
|
||
});
|
||
});
|
||
|
||
// ========== Test Connection ==========
|
||
|
||
function testKeyBeforeSave() {
|
||
const provider = document.getElementById('provider').value;
|
||
const apiKey = document.getElementById('api_key').value;
|
||
const model = document.getElementById('model_default').value;
|
||
|
||
if (!provider || !apiKey || !model) {
|
||
showToast('Veuillez remplir tous les champs obligatoires', 'error');
|
||
return;
|
||
}
|
||
|
||
testConnectionWithParams(provider, apiKey, model);
|
||
}
|
||
|
||
function testConnection(provider) {
|
||
testConnectionWithParams(provider, null, null);
|
||
}
|
||
|
||
function testConnectionWithParams(provider, apiKey = null, model = null) {
|
||
const testResult = document.getElementById('testResult');
|
||
testResult.style.display = 'block';
|
||
testResult.className = 'test-result';
|
||
testResult.innerHTML = '🔄 Test en cours...';
|
||
|
||
const formData = new FormData();
|
||
formData.append('action', 'test');
|
||
formData.append('provider', provider);
|
||
if (apiKey) formData.append('api_key', apiKey);
|
||
if (model) formData.append('model', model);
|
||
|
||
fetch('chatbot_api_ajax.php', {
|
||
method: 'POST',
|
||
body: formData
|
||
})
|
||
.then(response => response.json())
|
||
.then(data => {
|
||
if (data.success) {
|
||
testResult.className = 'test-result success';
|
||
testResult.innerHTML = `✅ ${data.message}<br><small>Latence: ${data.latency_ms}ms</small>`;
|
||
} else {
|
||
testResult.className = 'test-result error';
|
||
testResult.innerHTML = `❌ ${data.message}`;
|
||
}
|
||
})
|
||
.catch(error => {
|
||
console.error('Error:', error);
|
||
testResult.className = 'test-result error';
|
||
testResult.innerHTML = '❌ Erreur de connexion au serveur';
|
||
});
|
||
}
|
||
|
||
// ========== Delete Key ==========
|
||
|
||
function deleteKey(provider) {
|
||
if (!confirm(`Êtes-vous sûr de vouloir supprimer la clé ${provider} ?\n\nCette action est irréversible.`)) {
|
||
return;
|
||
}
|
||
|
||
const formData = new FormData();
|
||
formData.append('action', 'delete');
|
||
formData.append('provider', provider);
|
||
|
||
fetch('chatbot_api_ajax.php', {
|
||
method: 'POST',
|
||
body: formData
|
||
})
|
||
.then(response => response.json())
|
||
.then(data => {
|
||
if (data.success) {
|
||
showToast('Clé supprimée avec succès', 'success');
|
||
setTimeout(() => {
|
||
window.location.reload();
|
||
}, 1000);
|
||
} else {
|
||
showToast(data.error || 'Erreur lors de la suppression', 'error');
|
||
}
|
||
})
|
||
.catch(error => {
|
||
console.error('Error:', error);
|
||
showToast('Erreur de connexion', 'error');
|
||
});
|
||
}
|
||
|
||
// ========== Toast Notifications ==========
|
||
|
||
function showToast(message, type = 'info') {
|
||
const container = document.getElementById('toast-container');
|
||
const toast = document.createElement('div');
|
||
toast.className = `toast ${type}`;
|
||
|
||
const icons = {
|
||
'success': '✅',
|
||
'error': '❌',
|
||
'warning': '⚠️',
|
||
'info': 'ℹ️'
|
||
};
|
||
|
||
toast.innerHTML = `
|
||
<span class="toast-icon">${icons[type] || icons.info}</span>
|
||
<span class="toast-message">${message}</span>
|
||
`;
|
||
|
||
container.appendChild(toast);
|
||
|
||
// Auto-remove after 4 seconds
|
||
setTimeout(() => {
|
||
toast.style.opacity = '0';
|
||
toast.style.transform = 'translateX(100%)';
|
||
setTimeout(() => toast.remove(), 300);
|
||
}, 4000);
|
||
}
|
||
|
||
// ========== Close modal on outside click ==========
|
||
|
||
document.getElementById('keyModal').addEventListener('click', function(e) {
|
||
if (e.target === this) {
|
||
closeKeyModal();
|
||
}
|
||
});
|
||
|
||
// ========== Keyboard shortcuts ==========
|
||
|
||
document.addEventListener('keydown', function(e) {
|
||
// ESC to close modal
|
||
if (e.key === 'Escape') {
|
||
const modal = document.getElementById('keyModal');
|
||
if (modal.classList.contains('show')) {
|
||
closeKeyModal();
|
||
}
|
||
}
|
||
});
|
||
|
||
// ========== Initialize ==========
|
||
|
||
console.log('✅ Chatbot Settings JS loaded');
|
||
console.log('Available models:', models);
|