diff --git a/osinaweb/db.sqlite3 b/osinaweb/db.sqlite3 index aadcd747..22f14596 100644 Binary files a/osinaweb/db.sqlite3 and b/osinaweb/db.sqlite3 differ diff --git a/osinaweb/osichat/__pycache__/consumers.cpython-310.pyc b/osinaweb/osichat/__pycache__/consumers.cpython-310.pyc index 632fb0c8..05c5bf67 100644 Binary files a/osinaweb/osichat/__pycache__/consumers.cpython-310.pyc and b/osinaweb/osichat/__pycache__/consumers.cpython-310.pyc differ diff --git a/osinaweb/osichat/__pycache__/models.cpython-310.pyc b/osinaweb/osichat/__pycache__/models.cpython-310.pyc index 6b63d8db..c4ee32e3 100644 Binary files a/osinaweb/osichat/__pycache__/models.cpython-310.pyc and b/osinaweb/osichat/__pycache__/models.cpython-310.pyc differ diff --git a/osinaweb/osichat/__pycache__/routing.cpython-310.pyc b/osinaweb/osichat/__pycache__/routing.cpython-310.pyc index 1e97130d..2f3edad4 100644 Binary files a/osinaweb/osichat/__pycache__/routing.cpython-310.pyc and b/osinaweb/osichat/__pycache__/routing.cpython-310.pyc differ diff --git a/osinaweb/osichat/consumers.py b/osinaweb/osichat/consumers.py index 0a418d31..95f0544c 100644 --- a/osinaweb/osichat/consumers.py +++ b/osinaweb/osichat/consumers.py @@ -52,23 +52,34 @@ class OsitcomVisitor(WebsocketConsumer): class OsitcomChatRoom(WebsocketConsumer): def connect(self): - self.session_id = self.scope['url_route']['kwargs']['session_id'] self.domain = 'https://osina.ositcom.com' + self.session_id = self.scope['url_route']['kwargs']['session_id'] + self.visitor = Visitor.objects.filter(session_id=self.session_id).last() + + if self.scope['url_route']['kwargs'].get('chat_id'): #Case where admin is accessing a specific conversation between the conversations of this visior + self.chat_room = get_object_or_404(ChatRoom, id=self.scope['url_route']['kwargs'].get('chat_id')) + else: + chat_room_guest = ChatRoomGuest.objects.filter(visitor=self.visitor).last() #Case where the visitor will always acesss his last conversation + if chat_room_guest: + self.chat_room = chat_room_guest.room + else: + self.chat_room = None + + + if self.chat_room: + self.group = f"{self.session_id}_{self.chat_room.id}" + else: + self.group = self.session_id + async_to_sync(self.channel_layer.group_add)( - self.session_id, self.channel_name + self.group, self.channel_name ) self.accept() - self.visitor = Visitor.objects.filter(session_id=self.session_id).last() - chat_room_guest = ChatRoomGuest.objects.filter(visitor=self.visitor).last() - if chat_room_guest: - chat_room = chat_room_guest.room - self.chat_room = chat_room - else: - self.chat_room = None - + + def disconnect(self, close_code): async_to_sync(self.channel_layer.group_discard)( - self.session_id, self.channel_name + self.group, self.channel_name ) @@ -100,12 +111,19 @@ class OsitcomChatRoom(WebsocketConsumer): visitor=self.visitor ) self.chat_room = chat_room + self.group = f"{self.session_id}_{self.chat_room.id}" event = { 'type': 'start_conversation_handler', 'chat_room_id': chat_room.id } + async_to_sync(self.channel_layer.group_discard)( + self.group, self.channel_name + ) + async_to_sync(self.channel_layer.group_add)( + self.group, self.channel_name + ) async_to_sync(self.channel_layer.group_send)( - self.session_id, event + self.group, event ) if event_type == 'typing': @@ -115,7 +133,7 @@ class OsitcomChatRoom(WebsocketConsumer): 'typing_status': text_data_json.get('typing_status') } async_to_sync(self.channel_layer.group_send)( - self.session_id, event + self.group, event ) if event_type == 'send_message': @@ -134,7 +152,7 @@ class OsitcomChatRoom(WebsocketConsumer): 'chat_message_id': chat_message.id } async_to_sync(self.channel_layer.group_send)( - self.session_id, event + self.group, event ) if event_type == 'uploaded_file': @@ -158,7 +176,7 @@ class OsitcomChatRoom(WebsocketConsumer): 'file_name': text_data_json.get('file_name'), } async_to_sync(self.channel_layer.group_send)( - self.session_id, event + self.group, event ) if event_type == 'update_read_messages' and self.chat_room: @@ -222,7 +240,7 @@ class OsitcomChatRoom(WebsocketConsumer): 'user_id': text_data_json.get('user_id') } async_to_sync(self.channel_layer.group_send)( - self.session_id, event + self.group, event ) if event_type == 'submit_review': @@ -244,7 +262,7 @@ class OsitcomChatRoom(WebsocketConsumer): 'review_id': review.id } async_to_sync(self.channel_layer.group_send)( - self.session_id, event + self.group, event ) @@ -295,7 +313,7 @@ class OsitcomChatRoom(WebsocketConsumer): }, cls=DjangoJSONEncoder)) elif self.client_type == 'website_admin': - html = render_to_string("chat_templates/chat-widget.html", context=context) + html = render_to_string("chat_templates/chat-room.html", context=context) self.send(text_data=json.dumps({ 'event_type': 'load_chat', 'html': html, @@ -370,7 +388,7 @@ class OsitcomChatRoom(WebsocketConsumer): 'chat_message_data': chat_message_data, },cls=DjangoJSONEncoder)) elif self.client_type == 'website_admin': - html = render_to_string("chat_templates/message.html", context=context) + html = render_to_string("chat_templates/partials/message.html", context=context) self.send(text_data=json.dumps({ 'event_type': 'send_message', 'html': html, diff --git a/osinaweb/osichat/models.py b/osinaweb/osichat/models.py index ec523149..50e673d3 100644 --- a/osinaweb/osichat/models.py +++ b/osinaweb/osichat/models.py @@ -2,6 +2,7 @@ from django.db import models from osinacore.models import * import mimetypes import os +import pycountry # Create your models here. class Visitor(models.Model): @@ -11,6 +12,11 @@ class Visitor(models.Model): name = models.CharField(max_length=200, blank=True, null=True) mobile_number = models.CharField(max_length=10, null=True, blank=True) email = models.CharField(max_length=100, null=True, blank=True) + @property + def flag_image_url(self): + flag_url = f"https://flagcdn.com/w320/{self.country.lower()}.webp" + return flag_url + class VisitorLog(models.Model): diff --git a/osinaweb/osichat/routing.py b/osinaweb/osichat/routing.py index 5439cef6..2a833e40 100644 --- a/osinaweb/osichat/routing.py +++ b/osinaweb/osichat/routing.py @@ -4,5 +4,6 @@ from .consumers import * websocket_urlpatterns = [ path("ws/osichat/visitors/", OsitcomVisitor.as_asgi()), path("ws/osichat//", OsitcomChatRoom.as_asgi()), + path("ws/osichat-admin///", OsitcomChatRoom.as_asgi()), ] \ No newline at end of file diff --git a/osinaweb/osinacore/__pycache__/custom_context.cpython-310.pyc b/osinaweb/osinacore/__pycache__/custom_context.cpython-310.pyc index 283e1124..89064394 100644 Binary files a/osinaweb/osinacore/__pycache__/custom_context.cpython-310.pyc and b/osinaweb/osinacore/__pycache__/custom_context.cpython-310.pyc differ diff --git a/osinaweb/osinacore/templates/chat_templates/chat-room.html b/osinaweb/osinacore/templates/chat_templates/chat-room.html index c17fd45e..2173e094 100644 --- a/osinaweb/osinacore/templates/chat_templates/chat-room.html +++ b/osinaweb/osinacore/templates/chat_templates/chat-room.html @@ -1,55 +1,94 @@ {% load static %} - - - -
-
- - - +
+
-

{{chat_room.chatroomguest.name}}

+

{{chat_room.chatroomguest.visitor.name}}

- {% for message in chat_messages %} - {% if message.member == request.user %} -
-
-

{{message.content}}

-
- -
-

nn

-
-
- {% else %} -
-
- - - -
-
-

{{message.content}}

-
-
- {% endif %} + {% for message in chat_room_messages %} + {% if message.member %} + {% if not message.chatmessageattachment %} +
+
+

{{message.content}}

+
+
+ {% else %} + {% if message.chatmessageattachment.is_image %} +
+
+ +
+
+ {% else %} +
+
+
+
+ + + + + +
+
+ {{message.chatmessageattachment.file_name}} +
+
+
+
+ {% endif %} + {% endif %} + {% else %} +
+
+
+ +
+
+ {% if not message.chatmessageattachment %} +
+

{{message.content}}

+
+ {% else %} + {% if message.chatmessageattachment.is_image %} +
+ +
+ {% else %} +
+
+
+ + + + + +
+
+ {{message.chatmessageattachment.file_name}} +
+
+
+ {% endif %} + {% endif %} +
+ {% endif %} {% endfor %} + + {% for chat in latest_chat_rooms %} -
+
-

{{chat.chatroomguest.name}}

+

{{chat.chatroomguest.visitor.session_id}}

diff --git a/osinaweb/osinacore/templates/chat_templates/message.html b/osinaweb/osinacore/templates/chat_templates/message.html deleted file mode 100644 index 31005e3f..00000000 --- a/osinaweb/osinacore/templates/chat_templates/message.html +++ /dev/null @@ -1,36 +0,0 @@ -{% if chat_message.member %} -
-
-
- {% if chat_message.member.staffprofile.image %} - - {% else %} -

{{chat_message.member.first_name.0}}{{chat_message.member.last_name.0}}

- {% endif %} -
-
-
-

{{chat_message.content}}

-
-
-{% else %} -
-
-

{{chat_message.content}}

-
-
-{% endif %} - - diff --git a/osinaweb/osinacore/templates/chat_templates/partials/message.html b/osinaweb/osinacore/templates/chat_templates/partials/message.html new file mode 100644 index 00000000..c2eb22da --- /dev/null +++ b/osinaweb/osinacore/templates/chat_templates/partials/message.html @@ -0,0 +1,73 @@ +{% if chat_message.member %} + {% if not chat_message.chatmessageattachment %} +
+
+

{{chat_message.content}}

+
+
+ {% else %} + {% if chat_message.chatmessageattachment.is_image %} +
+
+ +
+
+ {% else %} +
+
+
+
+ + + + + +
+
+ {{chat_message.chatmessageattachment.file_name}} +
+
+
+
+ {% endif %} + {% endif %} +{% else %} +
+
+
+ +
+
+ {% if not chat_message.chatmessageattachment %} +
+

{{chat_message.content}}

+
+ {% else %} + {% if chat_message.chatmessageattachment.is_image %} +
+ +
+ {% else %} +
+
+
+ + + + + +
+
+ {{chat_message.chatmessageattachment.file_name}} +
+
+
+ {% endif %} + {% endif %} +
+{% endif %} \ No newline at end of file diff --git a/osinaweb/osinaweb/__pycache__/settings.cpython-310.pyc b/osinaweb/osinaweb/__pycache__/settings.cpython-310.pyc index 46c01c3f..d3062be3 100644 Binary files a/osinaweb/osinaweb/__pycache__/settings.cpython-310.pyc and b/osinaweb/osinaweb/__pycache__/settings.cpython-310.pyc differ diff --git a/osinaweb/static/images/uploaded_chat_files/Artboard 2 (2).png b/osinaweb/static/images/uploaded_chat_files/Artboard 2 (2).png new file mode 100644 index 00000000..a90b2c6f Binary files /dev/null and b/osinaweb/static/images/uploaded_chat_files/Artboard 2 (2).png differ diff --git a/osinaweb/static/js/osichat-admin/conversation.js b/osinaweb/static/js/osichat-admin/conversation.js index 222b7a22..6cf4ed4c 100644 --- a/osinaweb/static/js/osichat-admin/conversation.js +++ b/osinaweb/static/js/osichat-admin/conversation.js @@ -1,34 +1,52 @@ const admin_chat_ws_scheme = window.location.protocol === "https:" ? "wss" : "ws"; +const protocol = window.location.protocol === "https:" ? "https" : "http"; const admin_chat_domain = "osina.ositcom.com"; -let chatWebSocket = null; +let chatWebSocket; +const userId = document.getElementById('userId').textContent.trim(); -function openConversation(chatId) { - fetch(`/chat-rooms/${chatId}/`) - .then(response => response.text()) - .then(html => { - const conversationContainer = document.getElementById('inner-conversation') - conversationContainer.innerHTML = html; - const guestSessionId = document.getElementById('sessionid').textContent.trim(); - const userId = document.getElementById('userId').textContent.trim(); - // Close the previous WebSocket connection if it exists - if (chatWebSocket) { - chatWebSocket.close(); - } +function handleChatRoomClick(event) { + const sessionId = event.currentTarget.getAttribute('data-session'); + const chatId = event.currentTarget.getAttribute('data-chatid'); + if (sessionId && chatId) { + openConversation(sessionId, chatId); + } else { + console.error('Session ID not found for this chat room.'); + } +} - chatWebSocket = new WebSocket(`${admin_chat_ws_scheme}://${admin_chat_domain}/ws/osichat/${guestSessionId}/`); +document.querySelectorAll('.chat-room').forEach(div => { + div.addEventListener('click', handleChatRoomClick); +}); + +function appendTextAreaScript(domain, conversationContainer) { + if (!document.querySelector(`script[src="${protocol}://${admin_chat_domain}/static/js/osichat-admin/textarea.js"]`)) { + const textareaScript = document.createElement('script'); + textareaScript.type = 'text/javascript'; + textareaScript.src = `${protocol}://${admin_chat_domain}/static/js/osichat-admin/textarea.js`; + conversationContainer.appendChild(textareaScript); + } +} - chatWebSocket.onopen = function () { - console.log('WebSocket connection to osichat established'); - chatWebSocket.send(JSON.stringify({ 'event_type': 'load_chat', 'client_type': 'website_admin' })); - }; + +function openConversation(sessionid, chatid) { + if (chatWebSocket && chatWebSocket.readyState !== WebSocket.CLOSED) { //Close previous sockets + chatWebSocket.close(); + } + chatWebSocket = new WebSocket(`${admin_chat_ws_scheme}://${admin_chat_domain}/ws/osichat-admin/${sessionid}/${chatid}/`); + chatWebSocket.onopen = function () { + console.log('WebSocket connection to osichat established'); + chatWebSocket.send(JSON.stringify({ 'event_type': 'load_chat', 'client_type': 'website_admin' })); + }; + function handleLoadChatEvent(data, chatWebSocket) { + let chatDiv = document.getElementById('inner-conversation'); + chatDiv.innerHTML = data.html; + appendTextAreaScript(admin_chat_domain, chatDiv); const sendMessageForm = document.querySelector('#sendMessage'); sendMessageForm.addEventListener('submit', function (event) { event.preventDefault(); - const message = event.target.elements.message.value; - const eventMessage = { 'event_type': 'send_message', 'message': message, @@ -36,32 +54,34 @@ function openConversation(chatId) { }; chatWebSocket.send(JSON.stringify(eventMessage)); - event.target.reset(); }); + } + + chatWebSocket.onmessage = function (e) { + const data = JSON.parse(e.data); + switch (data.event_type) { + case 'load_chat': + handleLoadChatEvent(data, chatWebSocket); + break; + case 'send_message': + const messagesDiv = document.getElementById('messages_container'); + messagesDiv.insertAdjacentHTML('beforeend', data.html); + if (!data.user) { // If it is sent by a guest play a notification sound for the guest + const notificationSound = document.getElementById('notification-sound'); + notificationSound.play(); + } + break; + default: + console.log('Unknown event type:', data.event_type); + } + }; + chatWebSocket.onclose = function () { + console.log('WebSocket connection to osichat closed'); + }; - - chatWebSocket.onclose = function () { - console.log('WebSocket connection to osichat closed'); - }; - - chatWebSocket.onerror = function (error) { - console.error('WebSocket error:', error); - }; - - appendTextAreaScript(admin_chat_domain, conversationContainer); - }) - .catch(error => console.error('Error loading conversation details:', error)); -} - - -function appendTextAreaScript(domain, conversationContainer) { - // Check if the script is already appended - if (!document.querySelector('script[src="https://' + domain + '/static/js/osichat-admin/textarea.js"]')) { - const textareaScript = document.createElement('script'); - textareaScript.type = 'text/javascript'; - textareaScript.src = `https://${domain}/static/js/osichat-admin/textarea.js`; - conversationContainer.appendChild(textareaScript); - } + chatWebSocket.onerror = function (error) { + console.error('WebSocket error:', error); + }; } diff --git a/osinaweb/static/js/osichat/conversation.js b/osinaweb/static/js/osichat/conversation.js index 47aa76dd..0703787b 100644 --- a/osinaweb/static/js/osichat/conversation.js +++ b/osinaweb/static/js/osichat/conversation.js @@ -1,5 +1,6 @@ const chat_ws_scheme = window.location.protocol === "https:" ? "wss" : "ws"; -const domain = "osina.ositcom.com"; +const protocol = window.location.protocol === "https:" ? "https" : "http"; +const domain = "osina.ositcom"; let osichatSocket; let isOpen = false; let chatLoaded = false; @@ -49,7 +50,7 @@ function hideLoader() { function appendTextAreaScript(domain, chatDiv) { const textareaScript = document.createElement('script'); textareaScript.type = 'text/javascript'; - textareaScript.src = `https://${domain}/static/js/osichat/textarea.js`; + textareaScript.src = `${protocol}://${domain}/static/js/osichat/textarea.js`; chatDiv.appendChild(textareaScript); } @@ -91,10 +92,10 @@ function handleLoadChatEvent(data, osichatSocket) { } - if (!document.querySelector('script[src="https://' + domain + '/static/js/osichat/chat-toggle.js"]')) { + if (!document.querySelector(`script[src="${protocol}://${domain}/static/js/osichat/chat-toggle.js"]`)) { const script = document.createElement('script'); script.type = 'text/javascript'; - script.src = `https://${domain}/static/js/osichat/chat-toggle.js`; + script.src = `${protocol}://${domain}/static/js/osichat/chat-toggle.js`; chatDiv.appendChild(script); } @@ -110,12 +111,12 @@ function handleLoadChatEvent(data, osichatSocket) { const uploadScript = document.createElement('script'); uploadScript.type = 'text/javascript'; - uploadScript.src = `https://${domain}/static/js/osichat/upload-file.js`; + uploadScript.src = `${protocol}://${domain}/static/js/osichat/upload-file.js`; chatDiv.appendChild(uploadScript); const endChatScript = document.createElement('script'); endChatScript.type = 'text/javascript'; - endChatScript.src = `https://${domain}/static/js/osichat/end-chat.js`; + endChatScript.src = `${protocol}://${domain}/static/js/osichat/end-chat.js`; chatDiv.appendChild(endChatScript); const endChatButton = document.getElementById('endChat'); @@ -126,7 +127,7 @@ function handleLoadChatEvent(data, osichatSocket) { if (sendReviewContainer) { const sendReviewScript = document.createElement('script'); sendReviewScript.type = 'text/javascript'; - sendReviewScript.src = `https://${domain}/static/js/osichat/send-review.js`; + sendReviewScript.src = `${protocol}://${domain}/static/js/osichat/send-review.js`; chatDiv.appendChild(sendReviewScript); } } @@ -202,7 +203,7 @@ async function initializeChatWebSocket() { unreadMessages.classList.remove('hidden'); unreadMessages.innerHTML = data.html; const script = document.createElement('script'); - script.src = `https://${domain}/static/js/osichat/chat-toggle.js`; + script.src = `${protocol}://${domain}/static/js/osichat/chat-toggle.js`; document.body.appendChild(script); } else { unreadMessages.classList.add('hidden'); @@ -218,7 +219,7 @@ async function initializeChatWebSocket() { document.getElementById(`endChat`).classList.add('hidden'); const sendReviewScript = document.createElement('script'); sendReviewScript.type = 'text/javascript'; - sendReviewScript.src = `https://${domain}/static/js/osichat/send-review.js`; + sendReviewScript.src = `${protocol}://${domain}/static/js/osichat/send-review.js`; currentChat.appendChild(sendReviewScript); break; case 'submit_review': @@ -228,7 +229,7 @@ async function initializeChatWebSocket() { } const reviewScript = document.createElement('script'); reviewScript.type = 'text/javascript'; - reviewScript.src = `https://${domain}/static/js/osichat/send-review.js`; + reviewScript.src = `${protocol}://${domain}/static/js/osichat/send-review.js`; submitReview.appendChild(reviewScript); break; default: @@ -237,7 +238,6 @@ async function initializeChatWebSocket() { }; osichatSocket.onclose = () => { - console.log('WebSocket connection to osichat closed'); showLoader(); setTimeout(() => { console.log('Attempting to reconnect to WebSocket...');