Files
docupulse/static/js/conversation.js
2025-05-28 14:06:36 +02:00

210 lines
8.2 KiB
JavaScript

// Initialize chat when document is ready
$(document).ready(function() {
const conversationId = window.conversationId; // Set this in the template
const currentUserId = window.currentUserId; // Set this in the template
const chat = ChatManager.getInstance(conversationId);
const state = chat.state;
console.log('[Conversation] Initializing chat for conversation:', conversationId);
// Keep track of messages we've already displayed
const displayedMessageIds = new Set();
// Function to append a new message to the chat
function appendMessage(message) {
console.log('[Conversation] Attempting to append message:', {
messageId: message.id,
content: message.content,
senderId: message.sender_id,
currentUserId: currentUserId
});
// Check if we've already displayed this message
if (displayedMessageIds.has(message.id)) {
return;
}
displayedMessageIds.add(message.id);
const isCurrentUser = message.sender_id === currentUserId;
const messageHtml = `
<div class="message ${isCurrentUser ? 'sent' : 'received'}" data-message-id="${message.id}">
${!isCurrentUser ? `
<img src="${message.sender_avatar}"
alt="${message.sender_name}"
class="rounded-circle me-2"
style="width: 40px; height: 40px; object-fit: cover;">
` : ''}
<div class="message-content">
<div class="message-info">
<span class="fw-medium">${message.sender_name}</span>
<span class="text-muted ms-2">${message.created_at}</span>
</div>
${message.content}
${message.attachments && message.attachments.length > 0 ? `
<div class="attachments mt-2">
${message.attachments.map((attachment, index) => `
<div class="attachment mb-1">
<a href="${attachment.url}" class="btn btn-sm">
<i class="fas fa-paperclip me-1"></i>
${attachment.name}
<small class="ms-1">(${Math.round(attachment.size / 1024)} KB)</small>
</a>
</div>
`).join('')}
</div>
` : ''}
</div>
${isCurrentUser ? `
<img src="${message.sender_avatar}"
alt="${message.sender_name}"
class="rounded-circle ms-2"
style="width: 40px; height: 40px; object-fit: cover;">
` : ''}
</div>
`;
// Remove the "no messages" placeholder if it exists
$('.text-center.text-muted').remove();
$('#chatMessages').append(messageHtml);
console.log('[Conversation] Message appended to chat:', message.id);
scrollToBottom();
}
// Initialize displayedMessageIds with existing messages
$('.message').each(function() {
const messageId = $(this).data('message-id');
if (messageId) {
displayedMessageIds.add(messageId);
}
});
// Scroll to bottom of chat messages
function scrollToBottom() {
const chatMessages = document.getElementById('chatMessages');
chatMessages.scrollTop = chatMessages.scrollHeight;
}
scrollToBottom();
// Listen for new messages
$(document).on('new_message', function(event, message) {
console.log('[Conversation] Received new_message event:', {
messageId: message.id,
eventType: event.type,
timestamp: new Date().toISOString()
});
appendMessage(message);
});
// Handle file selection
$('#fileInput').on('change', function() {
const files = Array.from(this.files);
if (files.length > 0) {
const fileNames = files.map(file => file.name).join(', ');
$('#selectedFiles').text(files.length > 1 ? `${files.length} files selected: ${fileNames}` : fileNames);
} else {
$('#selectedFiles').text('');
}
});
// Handle message form submission
let isSubmitting = false;
$('#messageForm').off('submit').on('submit', function(e) {
e.preventDefault();
e.stopPropagation();
if (isSubmitting) {
console.log('[Conversation] Message submission already in progress');
return false;
}
const messageInput = $('#messageInput');
const submitButton = $('#messageForm button[type="submit"]');
const submitIcon = submitButton.find('.fa-paper-plane');
const spinner = submitButton.find('.fa-circle-notch');
const message = messageInput.val().trim();
const fileInput = $('#fileInput')[0];
const files = Array.from(fileInput.files);
if (!message && files.length === 0) {
console.log('[Conversation] Empty message submission attempted');
return false;
}
console.log('[Conversation] Submitting message:', {
hasText: !!message,
fileCount: files.length,
timestamp: new Date().toISOString()
});
isSubmitting = true;
messageInput.prop('disabled', true);
submitButton.prop('disabled', true);
submitIcon.addClass('d-none');
spinner.removeClass('d-none');
const formData = new FormData();
formData.append('message', message);
formData.append('csrf_token', $('input[name="csrf_token"]').val());
formData.append('file_count', files.length);
files.forEach((file, index) => {
formData.append(`file_${index}`, file);
});
$.ajax({
url: window.sendMessageUrl,
method: 'POST',
data: formData,
processData: false,
contentType: false,
success: function(response) {
console.log('[Conversation] Message sent successfully:', {
response: response,
timestamp: new Date().toISOString()
});
if (response.success) {
messageInput.val('');
fileInput.value = '';
$('#selectedFiles').text('');
// Append the message directly since we sent it
if (response.message) {
console.log('[Conversation] Appending sent message directly:', response.message.id);
// Update the ChatManager's lastMessageId
chat.state.connectionState.lastMessageId = response.message.id;
appendMessage(response.message);
}
} else {
console.error('[Conversation] Message send failed:', response);
alert('Failed to send message. Please try again.');
}
},
error: function(xhr, status, error) {
console.error('[Conversation] Failed to send message:', {
status: status,
error: error,
response: xhr.responseText,
timestamp: new Date().toISOString()
});
alert('Failed to send message. Please try again.');
},
complete: function() {
messageInput.prop('disabled', false);
submitButton.prop('disabled', false);
submitIcon.removeClass('d-none');
spinner.addClass('d-none');
isSubmitting = false;
console.log('[Conversation] Message submission completed');
}
});
return false;
});
// Clean up on page unload
$(window).on('beforeunload', function() {
console.log('[Conversation] Cleaning up on page unload');
chat.cleanup();
});
});