New changes.

main
nataly 9 months ago
parent b2616e5ebf
commit bfae98835f

@ -272,56 +272,6 @@ def add_invoice_pdf(request, order_id):
def add_payment_pdf(request, order_id):
order = get_object_or_404(Order, id=order_id)
payments = OrderPayment.objects.filter(order = order)
paid_amount = OrderPayment.objects.filter(order=order, date_paid__isnull=False).aggregate(total_paid=Sum('amount'))['total_paid'] or 0
cart_total = order.get_cart_total
remaining_amount = cart_total - paid_amount
invoice = order.invoice
# Render both invoice and payment details templates to HTML
invoice_template = get_template('details_templates/invoice-details.html')
payment_template = get_template('details_templates/payment-details.html')
invoice_html = invoice_template.render({'order': order})
payment_html = payment_template.render({'order': order, 'payments':payments, 'remaining_amount':remaining_amount,})
# Combine the HTML content of both templates
combined_html = f"{invoice_html}<div style='page-break-before: always;'></div>{payment_html}"
# Define CSS
css_string = '''
@font-face {
font-family: 'Poppins';
src: url('path_to_poppins_font_file.ttf') format('truetype'); /* Update the path to the font file */
}
body {
font-family: 'Poppins', sans-serif; /* Use Poppins font for the entire document */
}
/* Your existing CSS styles */
/* Add or modify styles as needed */
'''
# Generate PDF
pdf = HTML(string=combined_html).write_pdf(
stylesheets=[
CSS(string=css_string),
CSS(string='@page { margin: 30px; }')
],
presentational_hints=True
)
# Return PDF
response = HttpResponse(pdf, content_type='application/pdf')
response['Content-Disposition'] = 'attachment; filename="my_pdf.pdf"'
return response

Binary file not shown.

@ -2,7 +2,13 @@ from osichat.models import *
from rest_framework import serializers
class ChatRoomGuestSerializer(serializers.ModelSerializer):
class Meta:
model = ChatRoomGuest
fields = '__all__'
class ChatRoomSerializer(serializers.ModelSerializer):
chatroomguest = ChatRoomGuestSerializer()
class Meta:
model = ChatRoom
fields = '__all__'

@ -5,6 +5,8 @@ from django.template.loader import render_to_string
from asgiref.sync import async_to_sync
from django.shortcuts import get_object_or_404
import requests
from django.forms.models import model_to_dict
from django.core.serializers.json import DjangoJSONEncoder
class OsitcomVisitor(WebsocketConsumer):
@ -67,12 +69,7 @@ class OsitcomChatRoom(WebsocketConsumer):
if event_type == 'load_chat':
self.client_type = text_data_json.get('client_type')
event = {
'type': 'load_chat_handler',
}
async_to_sync(self.channel_layer.group_send)(
self.session_id, event
)
self.load_chat_handler()
if event_type == 'start_conversation':
chat_room = ChatRoom.objects.create(
@ -115,7 +112,7 @@ class OsitcomChatRoom(WebsocketConsumer):
def load_chat_handler(self, event):
def load_chat_handler(self):
if self.chat_room:
chat_room = self.chat_room
chat_room_messages = ChatMessage.objects.filter(room=chat_room).order_by('date_sent')
@ -127,9 +124,18 @@ class OsitcomChatRoom(WebsocketConsumer):
'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',
'context': context,
'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)
self.send(text_data=json.dumps({
'event_type': 'load_chat',
'html': html,
}))
else:
html = render_to_string("chat-widget.html", context=context)
@ -163,9 +169,16 @@ class OsitcomChatRoom(WebsocketConsumer):
'chat_message': chat_message,
}
if self.client_type == 'mobile_admin':
chat_message_data = model_to_dict(chat_message)
self.send(text_data=json.dumps({
'event_type': 'send_message',
'context': context,
'chat_message_data': chat_message_data,
},cls=DjangoJSONEncoder))
elif self.client_type == 'website_admin':
html = render_to_string("chat_templates/message.html", context=context)
self.send(text_data=json.dumps({
'event_type': 'send_message',
'html': html,
}))
else:
html = render_to_string("partials/message.html", context=context)

@ -94,7 +94,7 @@
{% else %}
{% if message.chatmessageattachment.is_image %}
<div class="'w-fit p-4 rounded-l-3xl rounded-tr-3xl text-white shadow-md text-sm leading-6 bg-opacity-70 bg-osiblue">
<img src="http://192.168.1.111:8000/{{message.chatmessageattachment.attachment}}">
<img src="http://192.168.1.102:8000/{{message.chatmessageattachment.attachment}}">
</div>
{% else %}
<div class="w-full p-4 rounded-l-3xl rounded-tr-3xl text-white shadow-md text-sm leading-6 bg-opacity-70 bg-osiblue">
@ -138,7 +138,7 @@
<form class="px-5 pb-5 bg-transparent relative" id="sendMessage">
{% csrf_token %}
<div class="w-full bg-white h-fit rounded-md border border-gray-200 flex items-center justify-between">
<textarea name="message" id="dynamicTextarea" onkeyup="adjustTextHeight(this);"
<textarea name="message" id="dynamicTextarea"
placeholder="Write your message..."
class="w-full outline-none p-3 resize-none h-[50px] max-h-[200px] duration-500"></textarea>

@ -7,7 +7,7 @@
<img class="w-full h-full rounded-full"
src="http://192.168.0.100:8000{{chat_message.member.staffprofile.image.url}}">
{% else %}
<p>nn</p>
<p>{{chat_message.member.first_name.0}}{{chat_message.member.last_name.0}}</p>
{% endif %}
</div>
</div>

@ -1,10 +1,12 @@
{% load static %}
<p id="sessionid" class="hidden">{{guest_session_id}}</p>
<p id="chatRoomId" class="hidden">{{chat_room.id}}</p>
<div class="w-full h-full flex flex-col justify-between">
<p id="sessionid" class="hidden">{{guest_session_id}}</p>
<!-- HEADER -->
<div
class="w-full flex items-center gap-1 py-3 px-3 border-b border-gray-100 text-[17px] text-secondosiblue">
<div
class="w-[30px] h-[30px] rounded-full shadow-md text-white flex justify-center items-center bg-osiblue">
<div class="w-full flex items-center gap-1 py-3 px-3 border-b border-gray-100 text-[17px] text-secondosiblue">
<div class="w-[30px] h-[30px] rounded-full shadow-md text-white flex justify-center items-center bg-osiblue">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5"
stroke="currentColor" class="w-5">
<path stroke-linecap="round" stroke-linejoin="round"
@ -15,83 +17,79 @@
<p>{{chat_room.chatroomguest.name}}</p>
</div>
<!-- CONVERSATION -->
<div class="w-full h-full flex-l flex flex-col gap-3 overflow-y-auto p-3">
<!-- MESSAGES -->
<div class="w-full h-full overflow-y-auto flex-l flex flex-col justify-end gap-3 p-3 relative" style="overflow-y: auto !important;">
{% for message in chat_messages %}
{% if message.member == request.user %}
<div class="w-full flex items-end justify-end gap-2">
<div
class="w-fit px-3 py-2 rounded-l-3xl rounded-tr-3xl text-white shadow-md text-sm leading-6 bg-opacity-70 bg-osiblue ">
<p class="break-all">{{message.content}}</p>
</div>
<div
class="w-[30px] h-[30px] rounded-full shadow-md text-white flex justify-center items-center bg-osiblue uppercase text-xs">
<p>nn</p>
</div>
</div>
{% else %}
<div class="w-full flex items-end justify-start gap-2">
<div
class="w-[30px] h-[30px] rounded-full shadow-md text-white flex justify-center items-center bg-osiblue">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5"
stroke="currentColor" class="w-5">
<path stroke-linecap="round" stroke-linejoin="round"
d="M15.75 6a3.75 3.75 0 1 1-7.5 0 3.75 3.75 0 0 1 7.5 0ZM4.501 20.118a7.5 7.5 0 0 1 14.998 0A17.933 17.933 0 0 1 12 21.75c-2.676 0-5.216-.584-7.499-1.632Z" />
</svg>
</div>
<div
class="w-fit bg-gray-50 px-3 py-2 rounded-r-3xl rounded-tl-3xl text-secondosiblue text-sm leading-7 bg-opacity-50 shadow-md border border-gray-100">
<p class="break-all">{{message.content}}</p>
</div>
{% if message.member == request.user %}
<div class="w-full flex items-end justify-end gap-2">
<div
class="w-fit px-3 py-2 rounded-l-3xl rounded-tr-3xl text-white shadow-md text-sm leading-6 bg-opacity-70 bg-osiblue">
<p class="break-all">{{message.content}}</p>
</div>
{% endif %}
{% endfor %}
</div>
<!-- INPUT FORM -->
<form class="px-5 pb-5 bg-transparent relative" id="sendMessage">
<input name="user_id" hidden value="{{request.user.id}}">
<!-- INCLUDE TYPING HERE -->
<div class="mb-2 flex justify-start items-center gap-2 absolute -top-11 ">
<div
class="w-[30px] h-[30px] rounded-full shadow-md text-white flex justify-center items-center bg-osiblue uppercase text-xs">
<p>nn</p>
</div>
</div>
{% else %}
<div class="w-full flex items-end justify-start gap-2">
<div
class="w-fit rounded-r-3xl rounded-tl-3xl px-2 py-2 bg-gray-50 border border-gray-100 shadow-md flex space-x-1 justify-start items-center">
<div class="h-2 w-2 bg-secondosiblue rounded-full animate-typing"></div>
<div class="h-2 w-2 bg-osiblue rounded-full animate-typing" style="animation-delay: 0.2s;">
</div>
<div class="h-2 w-2 bg-fifthosiblue rounded-full animate-typing"
style="animation-delay: 0.4s;"></div>
class="w-[30px] h-[30px] rounded-full shadow-md text-white flex justify-center items-center bg-osiblue">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5"
stroke="currentColor" class="w-5">
<path stroke-linecap="round" stroke-linejoin="round"
d="M15.75 6a3.75 3.75 0 1 1-7.5 0 3.75 3.75 0 0 1 7.5 0ZM4.501 20.118a7.5 7.5 0 0 1 14.998 0A17.933 17.933 0 0 1 12 21.75c-2.676 0-5.216-.584-7.499-1.632Z" />
</svg>
</div>
<div
class="w-fit bg-gray-50 px-3 py-2 rounded-r-3xl rounded-tl-3xl text-secondosiblue text-sm leading-7 bg-opacity-50 shadow-md border border-gray-100">
<p class="break-all">{{message.content}}</p>
</div>
</div>
<!-- END TYPING -->
{% endif %}
{% endfor %}
<!-- INCLUDE TYPING HERE -->
<!-- <div class="mb-2 flex justify-start items-center gap-2">
<div
class="w-[30px] h-[30px] rounded-full shadow-md text-white flex justify-center items-center bg-osiblue uppercase text-xs">
<p>nn</p>
</div>
<div
class="w-full bg-white h-fit rounded-md border border-gray-200 flex items-center justify-between">
<textarea name="message" id="dynamicTextarea" onkeyup="adjustTextHeight(this);"
placeholder="Write your message..."
class="w-fit rounded-r-3xl rounded-tl-3xl px-2 py-2 bg-gray-50 border border-gray-100 shadow-md flex space-x-1 justify-start items-center">
<div class="h-2 w-2 bg-secondosiblue rounded-full animate-typing"></div>
<div class="h-2 w-2 bg-osiblue rounded-full animate-typing" style="animation-delay: 0.2s;"></div>
<div class="h-2 w-2 bg-fifthosiblue rounded-full animate-typing" style="animation-delay: 0.4s;">
</div>
</div>
</div> -->
<!-- END TYPING -->
</div>
<!-- INPUT FORM -->
<form class="px-5 pb-5 bg-transparent relative" id="sendMessage">
{% csrf_token %}
<div class="w-full bg-white h-fit rounded-md border border-gray-200 flex items-center justify-between">
<textarea name="message" id="dynamicTextarea" placeholder="Write your message..."
class="w-full outline-none p-3 resize-none h-[50px] max-h-[200px] duration-500"></textarea>
<input type="text" value="{{request.user.id}}" name="user_id" class="hidden">
<div class="h-full right-0 top-0 px-3 flex items-center gap-2 text-osiblue">
<div>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"
stroke-width="1.5" stroke="currentColor" class="w-5 notFilledSvg">
<div class="relative">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5"
stroke="currentColor" class="w-5 notFilledSvg cursor-pointer" id="svgFileUpload">
<path stroke-linecap="round" stroke-linejoin="round"
d="m18.375 12.739-7.693 7.693a4.5 4.5 0 0 1-6.364-6.364l10.94-10.94A3 3 0 1 1 19.5 7.372L8.552 18.32m.009-.01-.01.01m5.699-9.941-7.81 7.81a1.5 1.5 0 0 0 2.112 2.13" />
</svg>
<input type="file" id="fileupload" name="" placeholder="Select file" multiple class="hidden">
<select id="filePathInput" name="filePath" multiple hidden></select>
</div>
<button type="submit" class="hidden">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"
stroke-width="1.5" stroke="currentColor" class="w-5 notFilledSvg">
<button type="submit" id="submitMessageButton" class="hidden">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5"
stroke="currentColor" class="w-5 notFilledSvg">
<path stroke-linecap="round" stroke-linejoin="round"
d="M6 12 3.269 3.125A59.769 59.769 0 0 1 21.485 12 59.768 59.768 0 0 1 3.27 20.875L5.999 12Zm0 0h7.5" />
</svg>

@ -2,100 +2,47 @@
<div id="chatWidget" class="hidden fixed bg-black bg-opacity-50 inset-0 z-50 h-[100vh]">
<div
class="w-[950px] min-h-[500px] h-[80%] bg-white rounded-md border border-gray-200 shadow-xl z-20 right-9 bottom-24 grid grid-cols-3 fixed">
<!-- LEFT SIDE - CHATS -->
<div id="osichat-conversations">
<div id="osichat-conversations" class="h-full overflow-y-auto border-r border-gray-200 bg-gray-50">
<!-- HEADER -->
<div class="grid grid-cols-2 sticky top-0 z-10">
<div
class="w-full flex items-center justify-center gap-1 py-3 px-3 border-b border-gray-100 bg-white rounded-md shadow-md cursor-pointer text-secondosiblue">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5"
stroke="currentColor" class="w-5">
<path stroke-linecap="round" stroke-linejoin="round"
d="M7.5 8.25h9m-9 3H12m-9.75 1.51c0 1.6 1.123 2.994 2.707 3.227 1.129.166 2.27.293 3.423.379.35.026.67.21.865.501L12 21l2.755-4.133a1.14 1.14 0 0 1 .865-.501 48.172 48.172 0 0 0 3.423-.379c1.584-.233 2.707-1.626 2.707-3.228V6.741c0-1.602-1.123-2.995-2.707-3.228A48.394 48.394 0 0 0 12 3c-2.392 0-4.744.175-7.043.513C3.373 3.746 2.25 5.14 2.25 6.741v6.018Z" />
</svg>
<p>Chats</p>
</div>
<div
class="w-full flex items-center justify-center gap-1 py-3 px-3 border-b border-gray-100 bg-gray-100 text-gray-400 cursor-pointer">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" class="w-5" fill="none">
<path
d="M2.5 8.18677C2.60406 6.08705 2.91537 4.77792 3.84664 3.84664C4.77792 2.91537 6.08705 2.60406 8.18677 2.5M21.5 8.18677C21.3959 6.08705 21.0846 4.77792 20.1534 3.84664C19.2221 2.91537 17.9129 2.60406 15.8132 2.5M15.8132 21.5C17.9129 21.3959 19.2221 21.0846 20.1534 20.1534C21.0846 19.2221 21.3959 17.9129 21.5 15.8132M8.18676 21.5C6.08705 21.3959 4.77792 21.0846 3.84664 20.1534C2.91537 19.2221 2.60406 17.9129 2.5 15.8132"
stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
<path
d="M19.6352 11.3178C19.8784 11.6224 20 11.7746 20 12C20 12.2254 19.8784 12.3776 19.6352 12.6822C18.5423 14.0504 15.7514 17 12 17C8.24862 17 5.45768 14.0504 4.36483 12.6822C4.12161 12.3776 4 12.2254 4 12C4 11.7746 4.12161 11.6224 4.36483 11.3178C5.45768 9.9496 8.24862 7 12 7C15.7514 7 18.5423 9.9496 19.6352 11.3178Z"
stroke="currentColor" stroke-width="1.5" />
<path
d="M14 12C14 10.8954 13.1046 10 12 10C10.8954 10 10 10.8954 10 12C10 13.1046 10.8954 14 12 14C13.1046 14 14 13.1046 14 12Z"
stroke="currentColor" stroke-width="1.5" />
</svg>
<p>Visitors</p>
</div>
</div>
<!-- CONVERSATIONS -->
{% include 'chat_templates/conversations.html' %}
</div>
<!-- RIGHT SIDE - CONVERSATION -->
<div class="col-span-2 h-full" id="inner-conversation">
<!-- INCLUDE VISITORS TABLE -->
<div class="overflow-x-auto border border-gray-100 tableContainer">
<table class="min-w-full divide-y">
<!-- TABLE HEADER -->
<thead class="bg-gray-50">
<tr>
<th scope="col"
class="px-6 py-3 text-sm text-gray-500 uppercase border-r border-gray-100 whitespace-nowrap">
User ID
</th>
<th scope="col"
class="px-6 py-3 text-sm text-gray-500 uppercase border-r border-gray-100 whitespace-nowrap">
Location
</th>
<th scope="col"
class="px-6 py-3 text-sm text-gray-500 uppercase border-r border-gray-100 whitespace-nowrap">
Country
</th>
<th scope="col"
class="px-6 py-3 text-sm text-gray-500 uppercase border-r border-gray-100 whitespace-nowrap">
Referrer
</th>
<th scope="col"
class="px-6 py-3 text-sm text-gray-500 uppercase whitespace-nowrap">
Duration
</th>
</tr>
</thead>
<!-- TABLE BODY -->
<tbody class="bg-white divide-y divide-gray-200">
<tr>
<td class="px-6 py-4 text-center text-sm border-r border-gray-100">
<p class="text-secondosiblue">12</p>
</td>
<td class="px-6 py-4 text-center text-sm border-r border-gray-100">
<p class="text-secondosiblue">Jounieh</p>
</td>
<td class="px-6 py-4 text-center text-sm border-r border-gray-100">
<p class="text-secondosiblue">Lebanon</p>
</td>
<td class="px-6 py-4 text-center text-sm border-r border-gray-100">
<p class="text-secondosiblue">3232</p>
</td>
<td class="px-6 py-4 text-center text-sm">
<p class="text-secondosiblue">2
</p>
</td>
</tr>
<tr>
<td class="px-6 py-4 text-center text-sm border-r border-gray-100">
<p class="text-secondosiblue">12</p>
</td>
<td class="px-6 py-4 text-center text-sm border-r border-gray-100">
<p class="text-secondosiblue">Jounieh</p>
</td>
<td class="px-6 py-4 text-center text-sm border-r border-gray-100">
<p class="text-secondosiblue">Lebanon</p>
</td>
<td class="px-6 py-4 text-center text-sm border-r border-gray-100">
<p class="text-secondosiblue">3232</p>
</td>
<td class="px-6 py-4 text-center text-sm">
<p class="text-secondosiblue">2
</p>
</td>
</tr>
</tbody>
</table>
</div>
<!-- END -->
<!-- the messages are here -->
</div>
</div>
<div class="w-[60px] h-[60px] rounded-full shadow-md flex justify-center items-center bg-osiblue fixed bottom-5 right-9 z-30 text-white text-sm border-4 border-white hidden hover:shadow-2xl duration-500 cursor-pointer"
@ -121,4 +68,7 @@
<p>Osichat</p>
</div>
<script type="text/javascript" src='{% static "js/osichat-admin/conversation.js" %}'></script>
<!---------------------- JS SCRIPTS -------------------->
<script type="text/javascript" src='{% static "js/osichat-admin/conversation.js" %}'></script>
<script type="text/javascript" src='{% static "js/osichat-admin/chat-toggle.js" %}'></script>

@ -1,35 +1,8 @@
<div class="h-full border-r border-gray-200 bg-gray-50 flex flex-col text-secondosiblue">
<!-- HEADER -->
<div class="grid grid-cols-2">
<div class="w-full flex items-center justify-center gap-1 py-3 px-3 border-b border-gray-100 bg-white rounded-md shadow-md cursor-pointer">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5"
stroke="currentColor" class="w-5">
<path stroke-linecap="round" stroke-linejoin="round"
d="M7.5 8.25h9m-9 3H12m-9.75 1.51c0 1.6 1.123 2.994 2.707 3.227 1.129.166 2.27.293 3.423.379.35.026.67.21.865.501L12 21l2.755-4.133a1.14 1.14 0 0 1 .865-.501 48.172 48.172 0 0 0 3.423-.379c1.584-.233 2.707-1.626 2.707-3.228V6.741c0-1.602-1.123-2.995-2.707-3.228A48.394 48.394 0 0 0 12 3c-2.392 0-4.744.175-7.043.513C3.373 3.746 2.25 5.14 2.25 6.741v6.018Z" />
</svg>
<p>Chats</p>
<!-- <div class="w-[20px] h-[20px] border border-secondosiblue rounded-full flex justify-center items-center text-secondosiblue text-[10px]">
<p>2</p>
</div> -->
</div>
<div class="w-full flex items-center justify-center gap-1 py-3 px-3 border-b border-gray-100 bg-gray-100 text-gray-400 cursor-pointer">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" class="w-5" fill="none">
<path d="M2.5 8.18677C2.60406 6.08705 2.91537 4.77792 3.84664 3.84664C4.77792 2.91537 6.08705 2.60406 8.18677 2.5M21.5 8.18677C21.3959 6.08705 21.0846 4.77792 20.1534 3.84664C19.2221 2.91537 17.9129 2.60406 15.8132 2.5M15.8132 21.5C17.9129 21.3959 19.2221 21.0846 20.1534 20.1534C21.0846 19.2221 21.3959 17.9129 21.5 15.8132M8.18676 21.5C6.08705 21.3959 4.77792 21.0846 3.84664 20.1534C2.91537 19.2221 2.60406 17.9129 2.5 15.8132" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
<path d="M19.6352 11.3178C19.8784 11.6224 20 11.7746 20 12C20 12.2254 19.8784 12.3776 19.6352 12.6822C18.5423 14.0504 15.7514 17 12 17C8.24862 17 5.45768 14.0504 4.36483 12.6822C4.12161 12.3776 4 12.2254 4 12C4 11.7746 4.12161 11.6224 4.36483 11.3178C5.45768 9.9496 8.24862 7 12 7C15.7514 7 18.5423 9.9496 19.6352 11.3178Z" stroke="currentColor" stroke-width="1.5" />
<path d="M14 12C14 10.8954 13.1046 10 12 10C10.8954 10 10 10.8954 10 12C10 13.1046 10.8954 14 12 14C13.1046 14 14 13.1046 14 12Z" stroke="currentColor" stroke-width="1.5" />
</svg>
<p>Visitors</p>
</div>
</div>
<div class="h-full flex flex-col text-secondosiblue">
<!-- CHATS -->
{% for chat in latest_chat_rooms %}
<div class="w-full flex flex-col gap-1 py-3 px-3 border-b border-gray-100 text-sm cursor-pointer" data-id="{{chat.id}}" onclick="openConversation({{chat.id}})">
<div class="w-full flex flex-col gap-1 py-3 px-3 border-b border-gray-100 text-sm cursor-pointer"
data-id="{{chat.id}}" onclick="openConversation({{chat.id}})">
<div class="w-full flex justify-between items-center">
<p class="text-secondosiblue font-poppinsBold">{{chat.chatroomguest.name}}</p>

@ -0,0 +1,36 @@
{% if chat_message.member %}
<div class="w-full flex justify-start items-end gap-2 fade-in-up">
<div>
<div
class="w-[30px] h-[30px] rounded-full shadow-md text-white flex justify-center items-center bg-osiblue uppercase text-xs">
{% if chat_message.member.staffprofile.image %}
<img class="w-full h-full rounded-full"
src="http://192.168.0.100:8000{{chat_message.member.staffprofile.image.url}}">
{% else %}
<p>{{chat_message.member.first_name.0}}{{chat_message.member.last_name.0}}</p>
{% endif %}
</div>
</div>
<div
class="w-fit bg-gray-50 px-3 py-2 rounded-r-3xl rounded-tl-3xl text-secondosiblue text-sm leading-6 bg-opacity-50 shadow-md border border-gray-100">
<p class="break-all">{{chat_message.content}}</p>
</div>
</div>
{% else %}
<div class="w-full flex justify-end">
<div
class="w-fit px-3 py-2 rounded-l-3xl rounded-tr-3xl text-white shadow-md text-sm leading-6 bg-opacity-70 bg-osiblue fade-in-up">
<p class="break-all">{{chat_message.content}}</p>
</div>
</div>
{% endif %}
<style>
@keyframes fadeInAndUp {
from { opacity: 0; transform: translateY(12px); }
to { opacity: 1; transform: translateY(0px); }
}
.fade-in-up {
animation: fadeInAndUp 0.6s ease;
}
</style>

@ -1254,10 +1254,6 @@
<!-- MODULES DROP DOWN ON MOBILE -->
<script type="text/javascript" src='{% static "js/accessibilities-dropdown.js" %}'></script>
<script type="text/javascript" src='{% static "js/osichat/textarea.js" %}'></script>
<script type="text/javascript" src='{% static "js/osichat-admin/chat-toggle.js" %}'></script>
</body>
</html>

@ -656,6 +656,10 @@ video {
position: relative;
}
.sticky {
position: sticky;
}
.inset-0 {
inset: 0px;
}
@ -1095,14 +1099,14 @@ video {
height: 60px;
}
.h-\[700px\] {
height: 700px;
}
.h-\[70px\] {
height: 70px;
}
.h-\[80\%\] {
height: 80%;
}
.h-\[80px\] {
height: 80px;
}
@ -1128,26 +1132,6 @@ video {
height: 100vh;
}
.h-\[600px\] {
height: 600px;
}
.h-\[100\%\] {
height: 100%;
}
.h-\[80\%\] {
height: 80%;
}
.h-\[70\%\] {
height: 70%;
}
.h-\[3020pxpx\] {
height: 3020pxpx;
}
.max-h-\[200px\] {
max-height: 200px;
}
@ -1352,10 +1336,6 @@ video {
width: 80%;
}
.w-\[800px\] {
width: 800px;
}
.w-\[80px\] {
width: 80px;
}
@ -1372,6 +1352,10 @@ video {
width: 95%;
}
.w-\[950px\] {
width: 950px;
}
.w-fit {
width: -moz-fit-content;
width: fit-content;
@ -1381,14 +1365,6 @@ video {
width: 100%;
}
.w-\[900px\] {
width: 900px;
}
.w-\[950px\] {
width: 950px;
}
.min-w-full {
min-width: 100%;
}
@ -1409,6 +1385,10 @@ video {
flex-grow: 1;
}
.flex-grow-0 {
flex-grow: 0;
}
.border-collapse {
border-collapse: collapse;
}
@ -1555,6 +1535,10 @@ video {
flex-direction: column;
}
.flex-col-reverse {
flex-direction: column-reverse;
}
.flex-wrap {
flex-wrap: wrap;
}
@ -1645,6 +1629,10 @@ video {
border-color: rgb(229 231 235 / var(--tw-divide-opacity));
}
.overflow-auto {
overflow: auto;
}
.overflow-hidden {
overflow: hidden;
}
@ -1661,6 +1649,10 @@ video {
overflow-y: auto;
}
.overflow-y-hidden {
overflow-y: hidden;
}
.truncate {
overflow: hidden;
text-overflow: ellipsis;
@ -1882,6 +1874,11 @@ video {
background-color: rgb(191 219 254 / var(--tw-bg-opacity));
}
.bg-blue-400 {
--tw-bg-opacity: 1;
background-color: rgb(96 165 250 / var(--tw-bg-opacity));
}
.bg-blue-500 {
--tw-bg-opacity: 1;
background-color: rgb(59 130 246 / var(--tw-bg-opacity));
@ -1937,6 +1934,11 @@ video {
background-color: rgb(187 247 208 / var(--tw-bg-opacity));
}
.bg-green-400 {
--tw-bg-opacity: 1;
background-color: rgb(74 222 128 / var(--tw-bg-opacity));
}
.bg-green-500 {
--tw-bg-opacity: 1;
background-color: rgb(34 197 94 / var(--tw-bg-opacity));
@ -2129,6 +2131,10 @@ video {
padding: 0.75rem;
}
.p-4 {
padding: 1rem;
}
.p-5 {
padding: 1.25rem;
}
@ -2428,11 +2434,21 @@ video {
color: rgb(146 156 183 / var(--tw-text-opacity));
}
.text-gray-100 {
--tw-text-opacity: 1;
color: rgb(243 244 246 / var(--tw-text-opacity));
}
.text-gray-200 {
--tw-text-opacity: 1;
color: rgb(229 231 235 / var(--tw-text-opacity));
}
.text-gray-300 {
--tw-text-opacity: 1;
color: rgb(209 213 219 / var(--tw-text-opacity));
}
.text-gray-400 {
--tw-text-opacity: 1;
color: rgb(156 163 175 / var(--tw-text-opacity));
@ -2498,16 +2514,6 @@ video {
color: rgb(234 179 8 / var(--tw-text-opacity));
}
.text-gray-100 {
--tw-text-opacity: 1;
color: rgb(243 244 246 / var(--tw-text-opacity));
}
.text-gray-300 {
--tw-text-opacity: 1;
color: rgb(209 213 219 / var(--tw-text-opacity));
}
.underline {
text-decoration-line: underline;
}
@ -3397,8 +3403,8 @@ video {
display: none;
}
.md\:h-\[550px\] {
height: 550px;
.md\:h-\[500px\] {
height: 500px;
}
.md\:h-fit {
@ -3406,26 +3412,6 @@ video {
height: fit-content;
}
.md\:h-full {
height: 100%;
}
.md\:h-\[80\] {
height: 80;
}
.md\:h-\[80\%\] {
height: 80%;
}
.md\:h-\[100\%\] {
height: 100%;
}
.md\:h-\[500px\] {
height: 500px;
}
.md\:w-\[250px\] {
width: 250px;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 937 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

@ -1,9 +1,6 @@
const openChatButton = document.getElementById('openChatContainer');
const chatWidget = document.getElementById('chatWidget');
const closeChatButton = document.getElementById('closeChatContainer');
const conversation = document.getElementById('conversation');
function scrollToBottom() {
@ -20,11 +17,7 @@ openChatButton.addEventListener('click', function () {
function closeChat() {
chatWidget.classList.add('hidden');
openChatButton.classList.remove('hidden');
if (closeChatButton) {
closeChatButton.classList.add('hidden');
} else if (closeMobileChatButton) {
closeMobileChatButton.classList.add('hidden');
}
closeChatButton.classList.add('hidden');
}
@ -32,5 +25,3 @@ closeChatButton.addEventListener('click', closeChat);
closeMobileChatButton.addEventListener('click', closeChat);

@ -1,13 +1,16 @@
const admin_chat_ws_scheme = window.location.protocol === "https:" ? "wss" : "ws";
const admin_chat_domain = "192.168.1.111:8000";
const admin_chat_domain = "192.168.1.102:8000";
let chatWebSocket = null;
function openConversation(chatId) {
fetch(`/chat-rooms/${chatId}/`)
.then(response => response.text())
.then(html => {
document.getElementById('inner-conversation').innerHTML = html;
const conversationContainer = document.getElementById('inner-conversation')
conversationContainer.innerHTML = html;
const guestSessionId = document.getElementById('sessionid').textContent;
const chatRoomId = document.getElementById('chatRoomId').textContent.trim();
// Close the previous WebSocket connection if it exists
if (chatWebSocket) {
chatWebSocket.close();
@ -15,38 +18,49 @@ function openConversation(chatId) {
chatWebSocket = new WebSocket(`${admin_chat_ws_scheme}://${admin_chat_domain}/ws/osichat/${guestSessionId}/`);
chatWebSocket.onopen = function() {
chatWebSocket.onopen = function () {
console.log('WebSocket connection to osichat established');
chatWebSocket.send(JSON.stringify({ 'event_type': 'load_chat', 'client_type': 'website_admin' }));
};
const sendMessageForm = document.querySelector('#sendMessage');
sendMessageForm.addEventListener('submit', function (event) {
event.preventDefault();
const message = event.target.elements.message.value;
const user_id = event.target.elements.user_id.value;
sendMessage.addEventListener('submit', function (event) {
event.preventDefault();
const message = event.target.elements.message.value;
const user_id = event.target.elements.user_id.value;
const eventMessage = {
'event_type': 'send_message',
'message': message,
'user_id': user_id
};
const eventMessage = {
'event_type': 'send_message',
'message': message,
'user_id': user_id
};
chatWebSocket.send(JSON.stringify(eventMessage));
chatWebSocket.send(JSON.stringify(eventMessage));
event.target.reset();
event.target.reset();
});
chatWebSocket.onclose = function() {
chatWebSocket.onclose = function () {
console.log('WebSocket connection to osichat closed');
};
chatWebSocket.onerror = function(error) {
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="http://' + domain + '/static/js/osichat-admin/textarea.js"]')) {
const textareaScript = document.createElement('script');
textareaScript.type = 'text/javascript';
textareaScript.src = `http://${domain}/static/js/osichat-admin/textarea.js`;
conversationContainer.appendChild(textareaScript);
}
}

@ -0,0 +1,37 @@
(function() {
// FUNCTION TO ADJUST TEXTAREA HEIGHT AND SUBMIT BUTTON VISIBILITY
function adjustTextAreaAndButton(textarea, submitButton) {
if (textarea.value.trim() === '') {
textarea.style.height = '50px';
} else {
textarea.style.height = textarea.scrollHeight + 'px';
}
if (textarea.value.trim() === '') {
submitButton.classList.add('hidden');
} else {
submitButton.classList.remove('hidden');
}
}
// INITIALIZE ELEMENTS
const chatRoomId = document.getElementById('chatRoomId').textContent.trim();
const form = document.querySelector('#sendMessage');
const textarea = document.querySelector('#dynamicTextarea');
const conversationContainer = document.getElementById('conversation');
const submitButton = document.getElementById('submitMessageButton');
// EVENT LISTENERS
textarea.addEventListener('input', () => adjustTextAreaAndButton(textarea, submitButton));
form.addEventListener('submit', (event) => {
textarea.style.height = '50px';
submitButton.classList.add('hidden');
setTimeout(() => {
conversationContainer.scrollTop = conversationContainer.scrollHeight;
}, 100);
});
console.log('hi from textarea script');
})();

@ -1,12 +1,12 @@
const chat_ws_scheme = window.location.protocol === "https:" ? "wss" : "ws";
const domain = "192.168.1.111:8000";
const domain = "192.168.1.102:8000";
// FUNCTION TO FETCH THE SESSION ID
async function fetchSessionID() {
let session_id = 'Unknown';
while (session_id === 'Unknown') {
try {
const response = await fetch('http://192.168.1.111:3000/get-client-session/');
const response = await fetch('http://192.168.1.102:3000/get-client-session/');
const data = await response.json();
if (data.session_id) {
session_id = data.session_id;

@ -22,6 +22,7 @@ const textarea = document.querySelector('#dynamicTextarea');
const conversationContainer = document.getElementById('conversation');
const submitButton = document.getElementById('submitMessageButton');
// EVENT LISTENERS
textarea.addEventListener('input', () => adjustTextAreaAndButton(textarea, submitButton));

@ -1,4 +1,4 @@
const imageDomain = "http://192.168.1.111:8000/";
const imageDomain = "http://192.168.1.102:8000/";
// TO TRIGGER TEH FILE UPLOADER WHEN CLICKING ON THE UPLOAD FILE SVG
document.getElementById('svgFileUpload').addEventListener('click', function() {

Loading…
Cancel
Save