200 lines
8.6 KiB
HTML
200 lines
8.6 KiB
HTML
{% extends "base.html" %}
|
||
{% block title %}Paramètres - Administration{% endblock %}
|
||
|
||
{% block content %}
|
||
<div class="container-fluid">
|
||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||
<div>
|
||
<h1><i class="bi bi-gear"></i> Paramètres de l'application</h1>
|
||
<p class="text-muted">Configuration des intégrations et services</p>
|
||
</div>
|
||
<a href="{{ url_for('admin.index') }}" class="btn btn-outline-secondary">
|
||
<i class="bi bi-arrow-left"></i> Retour
|
||
</a>
|
||
</div>
|
||
|
||
<div class="row">
|
||
<div class="col-lg-6 mb-4">
|
||
<div class="card h-100"><div class="card-header"><h5 class="mb-0"><i class="bi bi-shield-lock"></i> API REST GMAO</h5></div><div class="card-body">
|
||
<p class="text-muted small">La clé donne un accès en lecture à l’API. Elle n’est jamais conservée en clair et ne sera affichée qu’une fois.</p>
|
||
<form method="post" action="{{ url_for('admin.generate_api_key') }}" class="d-inline"><button class="btn btn-primary" type="submit"><i class="bi bi-arrow-repeat"></i> Générer ou renouveler</button></form>
|
||
<form method="post" action="{{ url_for('admin.revoke_api_key') }}" class="d-inline"><button class="btn btn-outline-danger" type="submit"><i class="bi bi-x-circle"></i> Révoquer</button></form>
|
||
</div></div>
|
||
</div>
|
||
<!-- Section OpenRouter -->
|
||
<div class="col-lg-6 mb-4">
|
||
<div class="card">
|
||
<div class="card-header">
|
||
<h5 class="mb-0">
|
||
<i class="bi bi-key"></i> OpenRouter API
|
||
</h5>
|
||
</div>
|
||
<div class="card-body">
|
||
<p class="text-muted small mb-3">
|
||
La clé API OpenRouter est utilisée pour l'interprétation des emails par l'IA.
|
||
Obtenez votre clé sur <a href="https://openrouter.ai/keys" target="_blank">openrouter.ai/keys</a>
|
||
</p>
|
||
|
||
<form id="openrouter-form">
|
||
<div class="mb-3">
|
||
<label for="openrouter-key" class="form-label">Clé API OpenRouter</label>
|
||
<div class="input-group">
|
||
<input type="password" class="form-control" id="openrouter-key"
|
||
placeholder="sk-or-v1-..."
|
||
value="{{ openrouter_key or '' }}">
|
||
<button class="btn btn-outline-secondary" type="button" onclick="toggleKeyVisibility()">
|
||
<i class="bi bi-eye" id="eye-icon"></i>
|
||
</button>
|
||
</div>
|
||
<div class="form-text">
|
||
{% if openrouter_key %}
|
||
<span class="text-success"><i class="bi bi-check-circle"></i> Clé configurée ({{ openrouter_key[:10] }}...{{ openrouter_key[-4:] }})</span>
|
||
{% else %}
|
||
<span class="text-warning"><i class="bi bi-exclamation-triangle"></i> Aucune clé configurée</span>
|
||
{% endif %}
|
||
</div>
|
||
</div>
|
||
|
||
<button type="submit" class="btn btn-primary">
|
||
<i class="bi bi-save"></i> Sauvegarder
|
||
</button>
|
||
|
||
<button type="button" class="btn btn-outline-secondary ms-2" onclick="testApiKey()">
|
||
<i class="bi bi-play"></i> Tester
|
||
</button>
|
||
</form>
|
||
|
||
<div id="test-result" class="mt-3" style="display:none;"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Section Modèle IA -->
|
||
<div class="col-lg-6 mb-4">
|
||
<div class="card">
|
||
<div class="card-header">
|
||
<h5 class="mb-0">
|
||
<i class="bi bi-cpu"></i> Modèle IA
|
||
</h5>
|
||
</div>
|
||
<div class="card-body">
|
||
<p class="text-muted small mb-3">
|
||
Modèle utilisé pour l'interprétation des emails GMAO.
|
||
</p>
|
||
|
||
<div class="mb-3">
|
||
<label class="form-label">Modèle actuel</label>
|
||
<input type="text" class="form-control" value="poolside/laguna-m.1:free" readonly>
|
||
<div class="form-text">
|
||
<span class="text-success"><i class="bi bi-check-circle"></i> Modèle gratuit et rapide</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="alert alert-info small">
|
||
<i class="bi bi-info-circle"></i>
|
||
<strong>Modèles recommandés:</strong>
|
||
<ul class="mb-0 mt-1">
|
||
<li><code>poolside/laguna-m.1:free</code> - Gratuit, rapide</li>
|
||
<li><code>openrouter/optimus-alpha</code> - Plus puissant</li>
|
||
<li><code>anthropic/claude-3-haiku</code> - Haute qualité</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Section Contexte GMAO -->
|
||
<div class="card mb-4">
|
||
<div class="card-header">
|
||
<h5 class="mb-0">
|
||
<i class="bi bi-building"></i> Contexte GMAO
|
||
</h5>
|
||
</div>
|
||
<div class="card-body">
|
||
<p class="text-muted">
|
||
Le contexte GMAO est utilisé par l'IA pour mieux interpréter les emails.
|
||
Il contient des informations sur votre établissement, équipements, procédures, etc.
|
||
</p>
|
||
<a href="{{ url_for('outlook_dashboard.context_config') }}" class="btn btn-primary">
|
||
<i class="bi bi-pencil"></i> Configurer le contexte GMAO
|
||
</a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
function toggleKeyVisibility() {
|
||
const input = document.getElementById('openrouter-key');
|
||
const icon = document.getElementById('eye-icon');
|
||
|
||
if (input.type === 'password') {
|
||
input.type = 'text';
|
||
icon.classList.remove('bi-eye');
|
||
icon.classList.add('bi-eye-slash');
|
||
} else {
|
||
input.type = 'password';
|
||
icon.classList.remove('bi-eye-slash');
|
||
icon.classList.add('bi-eye');
|
||
}
|
||
}
|
||
|
||
document.getElementById('openrouter-form').addEventListener('submit', function(e) {
|
||
e.preventDefault();
|
||
|
||
const key = document.getElementById('openrouter-key').value;
|
||
const btn = e.target.querySelector('button[type="submit"]');
|
||
const originalText = btn.innerHTML;
|
||
|
||
btn.disabled = true;
|
||
btn.innerHTML = '<span class="spinner-border spinner-border-sm"></span> Sauvegarde...';
|
||
|
||
fetch('/admin/settings/openrouter', {
|
||
method: 'POST',
|
||
headers: {'Content-Type': 'application/json'},
|
||
body: JSON.stringify({api_key: key})
|
||
})
|
||
.then(response => response.json())
|
||
.then(data => {
|
||
if (data.success) {
|
||
location.reload();
|
||
} else {
|
||
alert('Erreur: ' + data.error);
|
||
}
|
||
})
|
||
.catch(error => {
|
||
alert('Erreur: ' + error.message);
|
||
})
|
||
.finally(() => {
|
||
btn.disabled = false;
|
||
btn.innerHTML = originalText;
|
||
});
|
||
});
|
||
|
||
function testApiKey() {
|
||
const key = document.getElementById('openrouter-key').value;
|
||
if (!key) {
|
||
alert('Entrez une clé API');
|
||
return;
|
||
}
|
||
|
||
const resultDiv = document.getElementById('test-result');
|
||
resultDiv.style.display = 'block';
|
||
resultDiv.innerHTML = '<div class="alert alert-info"><i class="bi bi-hourglass-split"></i> Test en cours...</div>';
|
||
|
||
fetch('https://openrouter.ai/api/v1/models', {
|
||
headers: {'Authorization': 'Bearer ' + key}
|
||
})
|
||
.then(response => {
|
||
if (response.ok) {
|
||
resultDiv.innerHTML = '<div class="alert alert-success"><i class="bi bi-check-circle"></i> Clé API valide !</div>';
|
||
} else {
|
||
resultDiv.innerHTML = '<div class="alert alert-danger"><i class="bi bi-x-circle"></i> Clé API invalide</div>';
|
||
}
|
||
})
|
||
.catch(error => {
|
||
resultDiv.innerHTML = '<div class="alert alert-danger"><i class="bi bi-x-circle"></i> Erreur: ' + error.message + '</div>';
|
||
});
|
||
}
|
||
</script>
|
||
{% endblock %}
|