Chatbotma / templates /index.html
Docfile's picture
Update templates/index.html
49603e8 verified
raw
history blame
12.3 kB
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Mariam AI</title>
<script src="https://cdn.tailwindcss.com"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet">
<link href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/github.min.css" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
<style>
.message-transition {
transition: all 0.3s ease-in-out;
}
.gradient-background {
background: linear-gradient(120deg, #84fab0 0%, #8fd3f4 100%);
}
.message-content pre {
background-color: #f6f8fa;
border-radius: 6px;
padding: 16px;
overflow-x: auto;
margin: 8px 0;
}
.message-content code {
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
font-size: 0.9em;
}
.message-content p {
margin-bottom: 0.5rem;
}
.message-content ul, .message-content ol {
margin-left: 1.5rem;
margin-bottom: 0.5rem;
}
.message-content ul {
list-style-type: disc;
}
.message-content ol {
list-style-type: decimal;
}
.message-content a {
color: #2563eb;
text-decoration: underline;
}
.message-content table {
border-collapse: collapse;
margin: 8px 0;
width: 100%;
}
.message-content th, .message-content td {
border: 1px solid #e5e7eb;
padding: 8px;
text-align: left;
}
.message-content th {
background-color: #f9fafb;
}
</style>
</head>
<body class="bg-gray-50 min-h-screen">
<div class="container mx-auto px-4 py-8 max-w-4xl">
<!-- Header -->
<div class="text-center mb-8">
<h1 class="text-4xl font-bold text-gray-800 mb-2">Mariam AI</h1>
<p class="text-gray-600">Votre assistant intelligent personnel</p>
</div>
<!-- Settings Panel -->
<div class="mb-6 p-4 bg-white rounded-lg shadow-md">
<div class="flex items-center justify-between">
<div class="flex items-center space-x-4">
<label class="flex items-center space-x-2 cursor-pointer">
<input type="checkbox" id="webSearchToggle" class="form-checkbox h-5 w-5 text-blue-600">
<span class="text-gray-700">Activer la recherche web</span>
</label>
</div>
<div class="flex space-x-4">
<button onclick="clearHistory()" class="bg-red-500 hover:bg-red-600 text-white px-4 py-2 rounded-lg transition duration-200">
<i class="fas fa-trash mr-2"></i>Effacer l'historique
</button>
<div class="relative">
<input type="file" id="fileInput" class="hidden" accept="image/*,.pdf,.txt">
<button onclick="document.getElementById('fileInput').click()" class="bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded-lg transition duration-200">
<i class="fas fa-upload mr-2"></i>Télécharger un fichier
</button>
</div>
</div>
</div>
</div>
<!-- Chat Container -->
<div class="bg-white rounded-lg shadow-md h-[600px] flex flex-col">
<!-- Messages Area -->
<div id="chatMessages" class="flex-1 overflow-y-auto p-4 space-y-4">
<!-- Existing chat history -->
{% for message in chat_history %}
<div class="flex {{ 'justify-end' if message.role == 'user' else 'justify-start' }} message-transition">
<div class="max-w-[70%] p-3 rounded-lg {{ 'bg-blue-500 text-white rounded-br-none' if message.role == 'user' else 'bg-gray-100 text-gray-800 rounded-bl-none' }}">
{% if message.role == 'user' %}
{{ message.content }}
{% else %}
<div class="message-content prose">
{{ message.content_html | safe }}
</div>
{% endif %}
</div>
</div>
{% endfor %}
</div>
<!-- Input Area -->
<div class="border-t p-4">
<form id="chatForm" class="flex space-x-2">
<input type="text" id="messageInput" class="flex-1 border rounded-lg px-4 py-2 focus:outline-none focus:border-blue-500" placeholder="Posez votre question...">
<button type="submit" class="bg-blue-500 hover:bg-blue-600 text-white px-6 py-2 rounded-lg transition duration-200">
<i class="fas fa-paper-plane"></i>
</button>
</form>
</div>
</div>
</div>
<script>
let currentFile = null;
// Initialize highlight.js
document.addEventListener('DOMContentLoaded', (event) => {
document.querySelectorAll('pre code').forEach((el) => {
hljs.highlightElement(el);
});
});
// Function to highlight code in new messages
function highlightCode() {
document.querySelectorAll('pre code').forEach((el) => {
hljs.highlightElement(el);
});
}
document.getElementById('fileInput').addEventListener('change', async (e) => {
const file = e.target.files[0];
if (!file) return;
const formData = new FormData();
formData.append('file', file);
try {
const response = await fetch('/upload', {
method: 'POST',
body: formData
});
const data = await response.json();
if (data.success) {
currentFile = data.filename;
alert('Fichier téléchargé avec succès !');
} else {
alert('Erreur lors du téléchargement du fichier');
}
} catch (error) {
console.error('Error:', error);
alert('Erreur lors du téléchargement du fichier');
}
});
async function clearHistory() {
try {
const response = await fetch('/clear', {
method: 'POST'
});
const data = await response.json();
if (data.success) {
document.getElementById('chatMessages').innerHTML = '';
}
} catch (error) {
console.error('Error:', error);
alert('Erreur lors de la suppression de l\'historique');
}
}
document.getElementById('chatForm').addEventListener('submit', async (e) => {
e.preventDefault();
const messageInput = document.getElementById('messageInput');
const message = messageInput.value.trim();
if (!message) return;
// Add user message to chat
addMessage('user', message);
messageInput.value = '';
// Show typing indicator
addTypingIndicator();
try {
const response = await fetch('/chat', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
message: message,
web_search: document.getElementById('webSearchToggle').checked,
file: currentFile
}),
});
const data = await response.json();
// Remove typing indicator
removeTypingIndicator();
if (data.error) {
addMessage('assistant', `Erreur: ${data.error}`);
} else {
addMessage('assistant', data.response, data.response_html);
highlightCode();
}
// Reset current file
currentFile = null;
} catch (error) {
removeTypingIndicator();
addMessage('assistant', 'Désolé, une erreur est survenue.');
}
});
function addMessage(role, content, contentHtml = null) {
const messagesContainer = document.getElementById('chatMessages');
const messageDiv = document.createElement('div');
messageDiv.className = `flex ${role === 'user' ? 'justify-end' : 'justify-start'} message-transition`;
const messageBubble = document.createElement('div');
messageBubble.className = `max-w-[70%] p-3 rounded-lg ${
role === 'user'
? 'bg-blue-500 text-white rounded-br-none'
: 'bg-gray-100 text-gray-800 rounded-bl-none'
}`;
if (role === 'user' || !contentHtml) {
messageBubble.textContent = content;
} else {
const contentWrapper = document.createElement('div');
contentWrapper.className = 'message-content prose';
contentWrapper.innerHTML = contentHtml;
messageBubble.appendChild(contentWrapper);
}
messageDiv.appendChild(messageBubble);
messagesContainer.appendChild(messageDiv);
scrollToBottom();
}
function addTypingIndicator() {
const messagesContainer = document.getElementById('chatMessages');
const indicatorDiv = document.createElement('div');
indicatorDiv.id = 'typingIndicator';
indicatorDiv.className = 'flex justify-start message-transition';
indicatorDiv.innerHTML = `
<div class="bg-gray-100 p-3 rounded-lg rounded-bl-none">
<div class="flex space-x-2">
<div class="w-2 h-2 bg-gray-400 rounded-full animate-bounce"></div>
<div class="w-2 h-2 bg-gray-400 rounded-full animate-bounce" style="animation-delay: 0.2s"></div>
<div class="w-2 h-2 bg-gray-400 rounded-full animate-bounce" style="animation-delay: 0.4s"></div>
</div>
</div>
`;
messagesContainer.appendChild(indicatorDiv);
scrollToBottom();
}
function removeTypingIndicator() {
const indicator = document.getElementById('typingIndicator');
if (indicator) {
indicator.remove();
}
}
function scrollToBottom() {
const messagesContainer = document.getElementById('chatMessages');
messagesContainer.scrollTop = messagesContainer.scrollHeight;
}
// Handle keyboard shortcuts
document.addEventListener('keydown', (e) => {
// Ctrl/Cmd + Enter to submit
if ((e.ctrlKey || e.metaKey) && e.key === 'Enter') {
document.getElementById('chatForm').dispatchEvent(new Event('submit'));
}
});
// Auto-resize input field
const messageInput = document.getElementById('messageInput');
messageInput.addEventListener('input', function() {
this.style.height = 'auto';
this.style.height = (this.scrollHeight) + 'px';
});
// Initialize scroll position
scrollToBottom();
</script>
</body>
</html>