diff --git a/.DS_Store b/.DS_Store index ae27df9e..c2a6a0cb 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/osinaweb/.DS_Store b/osinaweb/.DS_Store index d39507ca..87b62318 100644 Binary files a/osinaweb/.DS_Store and b/osinaweb/.DS_Store differ diff --git a/osinaweb/db.sqlite3 b/osinaweb/db.sqlite3 index 95194055..fa8120b5 100644 Binary files a/osinaweb/db.sqlite3 and b/osinaweb/db.sqlite3 differ diff --git a/osinaweb/input.css b/osinaweb/input.css index c7d86d94..36b451d1 100644 --- a/osinaweb/input.css +++ b/osinaweb/input.css @@ -20,13 +20,22 @@ width: 0px !important; } +#conversation::-webkit-scrollbar { + width: 3px !important; + } + +#conversation::-webkit-scrollbar-thumb { + background: #c0c2c58b !important; +} + + + @media screen and (max-width: 798px) { #closeChatContainer { display: none !important; } } - .rtl { direction: rtl; } diff --git a/osinaweb/osichat/__pycache__/admin.cpython-310.pyc b/osinaweb/osichat/__pycache__/admin.cpython-310.pyc index 01a6452c..7306fde1 100644 Binary files a/osinaweb/osichat/__pycache__/admin.cpython-310.pyc and b/osinaweb/osichat/__pycache__/admin.cpython-310.pyc differ diff --git a/osinaweb/osichat/__pycache__/consumers.cpython-310.pyc b/osinaweb/osichat/__pycache__/consumers.cpython-310.pyc index 56ea9268..24fe4200 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 0a006e4c..5c8ded38 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/admin.py b/osinaweb/osichat/admin.py index 50a8a297..7f28068c 100644 --- a/osinaweb/osichat/admin.py +++ b/osinaweb/osichat/admin.py @@ -2,6 +2,7 @@ from django.contrib import admin from .models import * # Register your models here. admin.site.register(Visitor) +admin.site.register(VisitorLog) admin.site.register(ChatRoom) admin.site.register(ChatRoomGuest) admin.site.register(ChatMember) diff --git a/osinaweb/osichat/api/__pycache__/serializers.cpython-310.pyc b/osinaweb/osichat/api/__pycache__/serializers.cpython-310.pyc index f8fd8d40..6c2b519f 100644 Binary files a/osinaweb/osichat/api/__pycache__/serializers.cpython-310.pyc and b/osinaweb/osichat/api/__pycache__/serializers.cpython-310.pyc differ diff --git a/osinaweb/osichat/api/serializers.py b/osinaweb/osichat/api/serializers.py index b55694fd..1655e754 100644 --- a/osinaweb/osichat/api/serializers.py +++ b/osinaweb/osichat/api/serializers.py @@ -7,6 +7,13 @@ class ChatRoomGuestSerializer(serializers.ModelSerializer): model = ChatRoomGuest fields = '__all__' + +class ChatMessageAttachement(serializers.ModelSerializer): + class Meta: + model = ChatMessageAttachment + fields = '__all__' + + class ChatRoomSerializer(serializers.ModelSerializer): chatroomguest = ChatRoomGuestSerializer() class Meta: diff --git a/osinaweb/osichat/consumers.py b/osinaweb/osichat/consumers.py index 81a37092..7103c6a1 100644 --- a/osinaweb/osichat/consumers.py +++ b/osinaweb/osichat/consumers.py @@ -19,23 +19,32 @@ class OsitcomVisitor(WebsocketConsumer): def disconnect(self, close_code): if self.visitor: - self.visitor.left_date = datetime.now() - self.visitor.save() + self.current_log.left_date = datetime.now() + self.current_log.save() async_to_sync(self.channel_layer.group_discard)( 'ositcom_visitors', self.channel_name ) def receive(self, text_data): text_data_json = json.loads(text_data) event_type = text_data_json.get('event_type') - if event_type == 'new_visitor': - self.visitor = Visitor.objects.create( - session_id = text_data_json.get('session_id'), - ip_address = text_data_json.get('client_ip'), + if event_type == 'visitor_ping': + session_id = text_data_json.get('session_id') + if Visitor.objects.filter(session_id=session_id).last(): + self.visitor = Visitor.objects.filter(session_id=session_id).last() + else: + self.visitor = Visitor.objects.create( + session_id = session_id, + ip_address = text_data_json.get('client_ip'), + country = text_data_json.get('country'), + ) + + self.current_log = VisitorLog.objects.create( + visitor = self.visitor, referrer = text_data_json.get('referrer'), - country = text_data_json.get('client_country'), url = text_data_json.get('url'), visit_date = datetime.now() - ) + ) + @@ -48,14 +57,14 @@ class OsitcomChatRoom(WebsocketConsumer): self.session_id, self.channel_name ) self.accept() - chat_room_guest = ChatRoomGuest.objects.filter(session_id=self.session_id).last() + 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 @@ -79,11 +88,15 @@ class OsitcomChatRoom(WebsocketConsumer): name=f"Support: {self.session_id}", date_created = datetime.now() ) + if text_data_json.get('guest_name'): + self.visitor.name = text_data_json.get('guest_name') + self.visitor.save() + if text_data_json.get('guest_mobile_number'): + self.visitor.mobile_number = text_data_json.get('guest_mobile_number') + self.visitor.save() chat_room_guest = ChatRoomGuest.objects.create( room=chat_room, - name= text_data_json.get('guest_name'), - mobile_number= text_data_json.get('guest_mobile_number'), - session_id=self.session_id + visitor=self.visitor ) self.chat_room = chat_room event = { @@ -193,7 +206,7 @@ class OsitcomChatRoom(WebsocketConsumer): else: number_of_unread = ChatMessage.objects.filter(room=self.chat_room, member__isnull=False).exclude(chatmessageseen__guest=guest).count() - latest_unread_message = ChatMessage.objects.filter(room=self.chat_room).exclude(chatmessageseen__guest=guest).last() + latest_unread_message = ChatMessage.objects.filter(room=self.chat_room, member__isnull=False).exclude(chatmessageseen__guest=guest).last() event = { 'type': 'update_read_messages_handler', @@ -220,21 +233,39 @@ class OsitcomChatRoom(WebsocketConsumer): if self.chat_room: chat_room = self.chat_room chat_room_messages = ChatMessage.objects.filter(room=chat_room).order_by('date_sent') + else: chat_room = None chat_room_messages = None + context = { 'chat_room': chat_room, 'chat_room_messages': chat_room_messages, } + if self.client_type == 'mobile_admin': - chat_room_data = model_to_dict(chat_room) - chat_room_messages_data = [model_to_dict(message) for message in chat_room_messages] - self.send(text_data=json.dumps({ - 'event_type': 'load_chat', - 'chat_room_data': chat_room_data, - 'chat_room_messages_data': chat_room_messages_data - },cls=DjangoJSONEncoder)) + chat_room_data = model_to_dict(chat_room) + chat_room_messages_data = [] + + for message in chat_room_messages: + message_data = model_to_dict(message) + attachment = getattr(message, 'chatmessageattachment', None) + if attachment: + message_data['attachment'] = { + 'attachment': attachment.attachment, + 'is_image': attachment.is_image(), + 'file_name': attachment.file_name, + } + else: + message_data['attachment'] = None + + chat_room_messages_data.append(message_data) + + self.send(text_data=json.dumps({ + 'event_type': 'load_chat', + 'chat_room_data': chat_room_data, + 'chat_room_messages_data': chat_room_messages_data, + }, cls=DjangoJSONEncoder)) elif self.client_type == 'website_admin': html = render_to_string("chat_templates/chat-widget.html", context=context) @@ -328,12 +359,22 @@ class OsitcomChatRoom(WebsocketConsumer): 'message_attachment': message_attachment, 'file_type': event['file_type'] } - html = render_to_string("partials/message-attachment.html", context=context) - self.send(text_data=json.dumps({ - 'event_type': 'uploaded_file', - 'file_name': event['file_name'], - 'html': html, - })) + if self.client_type == 'mobile_admin': + message_attachment_data = model_to_dict(message_attachment) + self.send(text_data=json.dumps({ + 'event_type': 'uploaded_file', + 'message_attachment_data': message_attachment_data, + 'user': message_attachment.message.member.id if message_attachment.message.member else None, + 'file_type': event['file_type'] + },cls=DjangoJSONEncoder)) + else: + html = render_to_string("partials/message-attachment.html", context=context) + self.send(text_data=json.dumps({ + 'event_type': 'uploaded_file', + 'file_name': event['file_name'], + 'user': message_attachment.message.member.id if message_attachment.message.member else None, + 'html': html, + })) def update_read_messages_handler(self, event): latest_unread_message_id = event.get('latest_unread_message_id') @@ -351,19 +392,6 @@ class OsitcomChatRoom(WebsocketConsumer): else: latest_unread_message = None - def uploaded_file_handler(self, event): - message_attachment = get_object_or_404(ChatMessageAttachment, id=event['message_attachment_id']) - context = { - 'message_attachment': message_attachment, - 'file_type': event['file_type'] - } - html = render_to_string("partials/message-attachment.html", context=context) - self.send(text_data=json.dumps({ - 'event_type': 'uploaded_file', - 'file_name': event['file_name'], - 'html': html, - })) - def end_chat_handler(self, event): if event['user_id']: member = get_object_or_404(User, id=event['user_id']) diff --git a/osinaweb/osichat/migrations/0018_visitorlog_remove_chatroomguest_mobile_number_and_more.py b/osinaweb/osichat/migrations/0018_visitorlog_remove_chatroomguest_mobile_number_and_more.py new file mode 100644 index 00000000..1682ddf3 --- /dev/null +++ b/osinaweb/osichat/migrations/0018_visitorlog_remove_chatroomguest_mobile_number_and_more.py @@ -0,0 +1,72 @@ +# Generated by Django 4.2.5 on 2024-08-02 19:36 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('osichat', '0017_chatroom_date_terminated_chatroom_terminated_by'), + ] + + operations = [ + migrations.CreateModel( + name='VisitorLog', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('url', models.URLField()), + ('referrer', models.URLField(blank=True, null=True)), + ('visit_date', models.DateTimeField(null=True)), + ('left_date', models.DateTimeField(null=True)), + ], + ), + migrations.RemoveField( + model_name='chatroomguest', + name='mobile_number', + ), + migrations.RemoveField( + model_name='chatroomguest', + name='name', + ), + migrations.RemoveField( + model_name='chatroomguest', + name='session_id', + ), + migrations.RemoveField( + model_name='visitor', + name='left_date', + ), + migrations.RemoveField( + model_name='visitor', + name='referrer', + ), + migrations.RemoveField( + model_name='visitor', + name='url', + ), + migrations.RemoveField( + model_name='visitor', + name='visit_date', + ), + migrations.AddField( + model_name='chatroomguest', + name='visitor', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='osichat.visitor'), + ), + migrations.AddField( + model_name='visitor', + name='email', + field=models.CharField(blank=True, max_length=100, null=True), + ), + migrations.AddField( + model_name='visitor', + name='mobile_number', + field=models.CharField(blank=True, max_length=10, null=True), + ), + migrations.AddField( + model_name='visitor', + name='name', + field=models.CharField(blank=True, max_length=200, null=True), + ), + ] diff --git a/osinaweb/osichat/migrations/0019_visitorlog_visitor.py b/osinaweb/osichat/migrations/0019_visitorlog_visitor.py new file mode 100644 index 00000000..a5beeaf0 --- /dev/null +++ b/osinaweb/osichat/migrations/0019_visitorlog_visitor.py @@ -0,0 +1,19 @@ +# Generated by Django 4.2.5 on 2024-08-02 20:01 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('osichat', '0018_visitorlog_remove_chatroomguest_mobile_number_and_more'), + ] + + operations = [ + migrations.AddField( + model_name='visitorlog', + name='visitor', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='osichat.visitor'), + ), + ] diff --git a/osinaweb/osichat/migrations/__pycache__/0018_visitorlog_remove_chatroomguest_mobile_number_and_more.cpython-310.pyc b/osinaweb/osichat/migrations/__pycache__/0018_visitorlog_remove_chatroomguest_mobile_number_and_more.cpython-310.pyc new file mode 100644 index 00000000..e70f87d4 Binary files /dev/null and b/osinaweb/osichat/migrations/__pycache__/0018_visitorlog_remove_chatroomguest_mobile_number_and_more.cpython-310.pyc differ diff --git a/osinaweb/osichat/migrations/__pycache__/0019_visitorlog_visitor.cpython-310.pyc b/osinaweb/osichat/migrations/__pycache__/0019_visitorlog_visitor.cpython-310.pyc new file mode 100644 index 00000000..a4dc8754 Binary files /dev/null and b/osinaweb/osichat/migrations/__pycache__/0019_visitorlog_visitor.cpython-310.pyc differ diff --git a/osinaweb/osichat/models.py b/osinaweb/osichat/models.py index 35eaa056..55c4b464 100644 --- a/osinaweb/osichat/models.py +++ b/osinaweb/osichat/models.py @@ -8,11 +8,19 @@ class Visitor(models.Model): session_id = models.CharField(max_length=300) ip_address = models.CharField(max_length=300) country = models.CharField(max_length=15, null=True) + 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) + + +class VisitorLog(models.Model): + visitor = models.ForeignKey(Visitor, on_delete=models.CASCADE, null=True) url = models.URLField() referrer = models.URLField(null=True, blank=True) visit_date = models.DateTimeField(null=True) left_date = models.DateTimeField(null=True) + class ChatRoom(models.Model): name = models.CharField(max_length=300) created_by = models.ForeignKey(User, null=True, on_delete=models.SET_NULL, blank=True) @@ -36,11 +44,7 @@ class ChatRoom(models.Model): class ChatRoomGuest(models.Model): room = models.OneToOneField(ChatRoom, on_delete=models.CASCADE, null=True) - name = models.CharField(max_length=300) - mobile_number = models.CharField(max_length=100) - session_id = models.CharField(max_length=300) - - + visitor = models.ForeignKey(Visitor, null=True, on_delete=models.CASCADE) class ChatMember(models.Model): member = models.ForeignKey(User, on_delete=models.CASCADE) diff --git a/osinaweb/osichat/templates/chat-room.html b/osinaweb/osichat/templates/chat-room.html index f63ce930..406a1706 100644 --- a/osinaweb/osichat/templates/chat-room.html +++ b/osinaweb/osichat/templates/chat-room.html @@ -1,5 +1,6 @@ {%load static%} +
@@ -32,14 +33,13 @@
-

{% if chat_room.chatroomguest.name %}Hello {{chat_room.chatroomguest.name}},{% else %}Hello,{% endif %} thank you for contacting us. Please bear with us while we +

{% if chat_room.chatroomguest.visitor.name %}Hello {{chat_room.chatroomguest.visitor.name}},{% else %}Hello,{% endif %} thank you for contacting us. Please bear with us while we connect you with the next available agent as soon as possible.

- {% for message in chat_room_messages %} {% if message.member %} @@ -64,7 +64,7 @@ {% if message.chatmessageattachment.is_image %}
- +
{% else %}
- - -
+ {% csrf_token %}
+ class="w-full outline-none p-3 resize-none h-[50px] max-h-[200px] duration-500 border-none rounded-md">
@@ -159,12 +157,13 @@
+
-
- + +
+ -

Osichat 2.0 by Ositcom

-
- -
\ No newline at end of file +

Osichat 2.0 by Ositcom

+ + \ No newline at end of file diff --git a/osinaweb/osichat/templates/chat-widget.html b/osinaweb/osichat/templates/chat-widget.html index 952cf388..e9ad768e 100644 --- a/osinaweb/osichat/templates/chat-widget.html +++ b/osinaweb/osichat/templates/chat-widget.html @@ -3,11 +3,19 @@