emile 10 months ago
parent 909b7bdb39
commit 5b27f5284f

Binary file not shown.

@ -60,13 +60,19 @@ class OsitcomVisitor(WebsocketConsumer):
'visitors': visitors, 'visitors': visitors,
} }
if self.client_type == 'mobile_admin': if self.client_type == 'mobile_admin':
visitor_data = [] visitors_data = []
for visitor in visitors: for visitor in visitors:
visitor_data = model_to_dict(visitor) visitor_dict = model_to_dict(visitor)
visitor_logs = VisitorLog.objects.filter(visitor=visitor)
visitor_logs_data = [model_to_dict(log) for log in visitor_logs]
visitor_dict['visitor_logs'] = visitor_logs_data
visitors_data.append(visitor_dict)
self.send(text_data=json.dumps({ self.send(text_data=json.dumps({
'event_type': 'get_visitors', 'event_type': 'get_visitors',
'visitor_data': visitor_data, 'visitors_data': visitors_data,
}, cls=DjangoJSONEncoder)) }, cls=DjangoJSONEncoder))
@ -147,6 +153,7 @@ class OsitcomChatRooms(WebsocketConsumer):
chat_room = get_object_or_404(ChatRoom, id=event['chatroom_id']) chat_room = get_object_or_404(ChatRoom, id=event['chatroom_id'])
user = get_object_or_404(User, id=self.user_id) user = get_object_or_404(User, id=self.user_id)
number_of_unread = ChatMessage.objects.filter(room=chat_room).exclude(member=user).exclude(chatmessageseen__member=user).count() number_of_unread = ChatMessage.objects.filter(room=chat_room).exclude(member=user).exclude(chatmessageseen__member=user).count()
last_message = ChatMessage.objects.filter(room=chat_room).last()
context = { context = {
'chat_room': chat_room, 'chat_room': chat_room,
@ -163,6 +170,7 @@ class OsitcomChatRooms(WebsocketConsumer):
self.send(text_data=json.dumps({ self.send(text_data=json.dumps({
'event_type': 'new_update', 'event_type': 'new_update',
'chatroom_id': chat_room.id, 'chatroom_id': chat_room.id,
'user': last_message.member.id if last_message and last_message.member else None,
'html': html, 'html': html,
})) }))
@ -237,10 +245,6 @@ class OsitcomChatRoom(WebsocketConsumer):
) )
self.chat_room = chat_room self.chat_room = chat_room
self.group = f"{self.session_id}_{self.chat_room.id}" 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)( async_to_sync(self.channel_layer.group_discard)(
self.group, self.channel_name self.group, self.channel_name
) )
@ -251,6 +255,11 @@ class OsitcomChatRoom(WebsocketConsumer):
self.group, event self.group, event
) )
event = {
'type': 'start_conversation_handler',
'chat_room_id': chat_room.id
}
if event_type == 'typing': if event_type == 'typing':
event = { event = {
'type': 'typing_handler', 'type': 'typing_handler',

@ -1,5 +1,19 @@
{% load static %} {% load static %}
<div class="w-full h-full flex flex-col justify-end"> <!-- RECONNECTING LOADER -->
<div id="roomLoader" class="w-full h-full absolute flex justify-center items-center bg-black bg-opacity-60 z-20 inset-0 rounded-r-md hidden">
<div class="flex flex-col justify-center items-center gap-2">
<p class="text-white">Reconneting</p>
<div class="w-fit flex gap-1 justify-start items-center">
<div class="h-2 w-2 bg-white rounded-full animate-typing shadow-md"></div>
<div class="h-2 w-2 bg-white rounded-full animate-typing shadow-md" style="animation-delay: 0.2s;"></div>
<div class="h-2 w-2 bg-white rounded-full animate-typing shadow-md" style="animation-delay: 0.4s;">
</div>
</div>
</div>
</div>
<div class="w-full h-full flex flex-col justify-between">
<!-- HEADER --> <!-- 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-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 uppercase text-xs"> <div class="w-[30px] h-[30px] rounded-full shadow-md text-white flex justify-center items-center bg-osiblue uppercase text-xs">
@ -9,8 +23,9 @@
<p>{{chat_room.chatroomguest.visitor.name}}</p> <p>{{chat_room.chatroomguest.visitor.name}}</p>
</div> </div>
<div class="overflow-y-auto flex flex-col justify-end">
<!-- MESSAGES --> <!-- MESSAGES -->
<div class="flex-1 overflow-y-auto p-3 flex flex-col gap-4" id="messages_container"> <div class="overflow-y-auto p-3 flex flex-col gap-4" id="messages_container">
{% for message in chat_room_messages %} {% for message in chat_room_messages %}
{% if message.member %} {% if message.member %}
{% if not message.chatmessageattachment %} {% if not message.chatmessageattachment %}
@ -87,8 +102,6 @@
{% endif %} {% endif %}
{% endfor %} {% endfor %}
<audio id="notification-sound" src="{{domain}}/static/notifications/osichat-notification.mp3" preload="auto"></audio>
</div> </div>
@ -118,4 +131,5 @@
</div> </div>
</div> </div>
</form> </form>
</div>
</div> </div>

@ -4,11 +4,11 @@
<div <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"> 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 --> <!-- LEFT SIDE - CHATS -->
<div id="widgetLeftSide" class="h-full overflow-y-auto border-r border-gray-200 bg-gray-50"> <div id="widgetLeftSide" class="h-full overflow-y-auto border-r border-gray-200 bg-gray-50 relative rounded-l-md">
</div> </div>
<!-- RIGHT SIDE --> <!-- RIGHT SIDE -->
<div class="col-span-2 overflow-hidden" id="widgetRightSide"> <div class="col-span-2 overflow-hidden relative" id="widgetRightSide">
</div> </div>
</div> </div>

@ -2,8 +2,8 @@
<div class="w-full flex justify-between items-center"> <div class="w-full flex justify-between items-center">
<p class="text-secondosiblue font-poppinsBold">{{chat_room.chatroomguest.visitor.ip_address}}</p> <p class="text-secondosiblue font-poppinsBold">{{chat_room.chatroomguest.visitor.ip_address}}</p>
<div <div data-roomid={{chat_room.id}}
class="w-[20px] h-[20px] bg-osiblue rounded-full shadow-md flex justify-center items-center text-white text-[10px]"> class="unread w-[20px] h-[20px] bg-osiblue rounded-full shadow-md flex justify-center items-center text-white text-[10px] {% if chat_room.number_of_unread == 0 %} hidden {% endif %}">
<p>{{number_of_unread}}</p> <p>{{number_of_unread}}</p>
</div> </div>
</div> </div>

@ -1,9 +1,22 @@
<!-- HEADER --> <!-- RECONNECTING LOADER -->
<div class="grid grid-cols-2 sticky top-0 z-10"> <div id="roomsLoader" class="w-full h-full absolute flex justify-center items-center bg-black bg-opacity-60 z-20 inset-0 rounded-l-md hidden">
<div class="flex flex-col justify-center items-center gap-2">
<p class="text-white">Reconneting</p>
<div class="w-fit flex gap-1 justify-start items-center">
<div class="h-2 w-2 bg-white rounded-full animate-typing shadow-md"></div>
<div class="h-2 w-2 bg-white rounded-full animate-typing shadow-md" style="animation-delay: 0.2s;"></div>
<div class="h-2 w-2 bg-white rounded-full animate-typing shadow-md" style="animation-delay: 0.4s;">
</div>
</div>
</div>
</div>
<!-- HEADER -->
<div class="grid grid-cols-2 sticky top-0 z-10 rounded-l-md">
<div <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"> 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" <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"
stroke="currentColor" class="w-5"> class="w-5">
<path stroke-linecap="round" stroke-linejoin="round" <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" /> 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> </svg>
@ -26,17 +39,18 @@
</svg> </svg>
<p>Visitors</p> <p>Visitors</p>
</div> </div>
</div> </div>
<div class="h-full flex flex-col text-secondosiblue" id="chatrooms"> <div class="h-full flex flex-col text-secondosiblue" id="chatrooms">
<!-- CHATS --> <!-- CHATS -->
{% for chat_room in chat_rooms %} {% for chat_room in chat_rooms %}
<div data-roomid = {{chat_room.id}} data-session="{{chat_room.chatroomguest.visitor.session_id}}" class="chat-room w-full flex flex-col gap-1 py-3 px-3 border-b border-gray-100 text-sm cursor-pointer"> <div data-roomid={{chat_room.id}} data-session="{{chat_room.chatroomguest.visitor.session_id}}"
class="chat-room w-full flex flex-col gap-1 py-3 px-3 border-b border-gray-100 text-sm cursor-pointer">
<div class="w-full flex justify-between items-center"> <div class="w-full flex justify-between items-center">
<p class="text-secondosiblue font-poppinsBold">{{chat_room.chatroomguest.visitor.ip_address}}</p> <p class="text-secondosiblue font-poppinsBold">{{chat_room.chatroomguest.visitor.ip_address}}</p>
<div <div data-roomid={{chat_room.id}}
class="w-[20px] h-[20px] bg-osiblue rounded-full shadow-md flex justify-center items-center text-white text-[10px]"> class="unread w-[20px] h-[20px] bg-osiblue rounded-full shadow-md flex justify-center items-center text-white text-[10px] {% if chat_room.number_of_unread == 0 %} hidden {% endif %}">
<p>{{chat_room.number_of_unread}}</p> <p>{{chat_room.number_of_unread}}</p>
</div> </div>
</div> </div>
@ -46,4 +60,6 @@
<p class="text-gray-500 opacity-70 text-xs">{{chat_room.last_updated}}</p> <p class="text-gray-500 opacity-70 text-xs">{{chat_room.last_updated}}</p>
</div> </div>
{% endfor %} {% endfor %}
</div> </div>
<audio id="notification-sound" src="{{domain}}/static/notifications/osichat-notification.mp3" preload="auto"></audio>

@ -714,6 +714,10 @@ video {
bottom: 4rem; bottom: 4rem;
} }
.bottom-2 {
bottom: 0.5rem;
}
.bottom-20 { .bottom-20 {
bottom: 5rem; bottom: 5rem;
} }
@ -722,10 +726,18 @@ video {
bottom: 6rem; bottom: 6rem;
} }
.bottom-28 {
bottom: 7rem;
}
.bottom-3 { .bottom-3 {
bottom: 0.75rem; bottom: 0.75rem;
} }
.bottom-32 {
bottom: 8rem;
}
.bottom-5 { .bottom-5 {
bottom: 1.25rem; bottom: 1.25rem;
} }
@ -842,18 +854,6 @@ video {
top: 14px; top: 14px;
} }
.bottom-2 {
bottom: 0.5rem;
}
.bottom-28 {
bottom: 7rem;
}
.bottom-32 {
bottom: 8rem;
}
.z-10 { .z-10 {
z-index: 10; z-index: 10;
} }
@ -1103,6 +1103,10 @@ video {
height: 210px; height: 210px;
} }
.h-\[22px\] {
height: 22px;
}
.h-\[250px\] { .h-\[250px\] {
height: 250px; height: 250px;
} }
@ -1200,10 +1204,6 @@ video {
height: 100vh; height: 100vh;
} }
.h-\[22px\] {
height: 22px;
}
.max-h-\[200px\] { .max-h-\[200px\] {
max-height: 200px; max-height: 200px;
} }
@ -1332,6 +1332,10 @@ video {
width: 220px; width: 220px;
} }
.w-\[22px\] {
width: 22px;
}
.w-\[240px\] { .w-\[240px\] {
width: 240px; width: 240px;
} }
@ -1449,10 +1453,6 @@ video {
width: 100%; width: 100%;
} }
.w-\[22px\] {
width: 22px;
}
.min-w-full { .min-w-full {
min-width: 100%; min-width: 100%;
} }
@ -1843,6 +1843,11 @@ video {
border-top-right-radius: 0px; border-top-right-radius: 0px;
} }
.rounded-l {
border-top-left-radius: 0.25rem;
border-bottom-left-radius: 0.25rem;
}
.rounded-bl-md { .rounded-bl-md {
border-bottom-left-radius: 0.375rem; border-bottom-left-radius: 0.375rem;
} }
@ -2196,6 +2201,10 @@ video {
--tw-bg-opacity: 0.8; --tw-bg-opacity: 0.8;
} }
.bg-opacity-60 {
--tw-bg-opacity: 0.6;
}
.bg-gradient-to-b { .bg-gradient-to-b {
background-image: linear-gradient(to bottom, var(--tw-gradient-stops)); background-image: linear-gradient(to bottom, var(--tw-gradient-stops));
} }
@ -3190,6 +3199,10 @@ video {
} }
} */ } */
.hover\:pointer-events-none:hover {
pointer-events: none;
}
.hover\:scale-105:hover { .hover\:scale-105:hover {
--tw-scale-x: 1.05; --tw-scale-x: 1.05;
--tw-scale-y: 1.05; --tw-scale-y: 1.05;
@ -3202,6 +3215,10 @@ video {
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
} }
.hover\:overflow-hidden:hover {
overflow: hidden;
}
.hover\:bg-gray-100:hover { .hover\:bg-gray-100:hover {
--tw-bg-opacity: 1; --tw-bg-opacity: 1;
background-color: rgb(243 244 246 / var(--tw-bg-opacity)); background-color: rgb(243 244 246 / var(--tw-bg-opacity));

@ -2,42 +2,85 @@
function handleChatRoomClick(event) { function handleChatRoomClick(event) {
const sessionId = event.currentTarget.getAttribute('data-session'); const sessionId = event.currentTarget.getAttribute('data-session');
const chatId = event.currentTarget.getAttribute('data-roomid'); const chatId = event.currentTarget.getAttribute('data-roomid');
if (sessionId && chatId) { if (sessionId && chatId && chatId !== currentChatId) {
showLoader();
openConversation(sessionId, chatId); openConversation(sessionId, chatId);
} else { currentChatId = chatId;
console.error('Session ID not found for this chat room.');
} }
} }
document.querySelectorAll('.chat-room').forEach(div => { document.querySelectorAll('.chat-room').forEach(div => {
div.addEventListener('click', handleChatRoomClick); div.addEventListener('click', handleChatRoomClick);
}); });
function appendTextAreaScript(domain, conversationContainer) {
if (!document.querySelector(`script[src="${protocol}://${admin_chat_domain}/static/js/osichat-admin/textarea.js"]`)) { function markCurrentChatRead(chatid) {
const unreadElement = document.querySelector(`.unread[data-roomid='${chatid}']`);
if (unreadElement) {
unreadElement.classList.add('hidden');
}
}
// FUNCTIONS TO SHOW & HIDE THE LOADER
function showLoader() {
const roomLoader = document.getElementById('roomLoader');
if (roomLoader) {
roomLoader.classList.remove('hidden');
}
const widgetLeftSide = document.getElementById('widgetLeftSide');
widgetLeftSide.classList.remove('overflow-y-auto');
widgetLeftSide.classList.add('overflow-hidden');
}
function hideLoader() {
const roomLoader = document.getElementById('roomLoader');
if (roomLoader) {
roomLoader.classList.add('hidden');
}
const widgetLeftSide = document.getElementById('widgetLeftSide');
widgetLeftSide.classList.remove('overflow-hidden');
widgetLeftSide.classList.add('overflow-y-auto');
}
function appendTextAreaScript(conversationContainer) {
const textareaScript = document.createElement('script'); const textareaScript = document.createElement('script');
textareaScript.type = 'text/javascript'; textareaScript.type = 'text/javascript';
textareaScript.src = `${protocol}://${admin_chat_domain}/static/js/osichat-admin/textarea.js`; textareaScript.src = `${protocol}://${admin_chat_domain}/static/js/osichat-admin/textarea.js`;
conversationContainer.appendChild(textareaScript); conversationContainer.appendChild(textareaScript);
} }
}
function scrollBottom() {
const conversationContainer = document.getElementById('messages_container');
if (conversationContainer) {
conversationContainer.scrollTo({
top: conversationContainer.scrollHeight,
behavior: 'smooth'
});
}
}
function openConversation(sessionid, chatid) { function openConversation(sessionId, chatId) {
if (osichatadminroomSocket && osichatadminroomSocket.readyState !== WebSocket.CLOSED) { //Close previous sockets if (osichatadminroomSocket) {
osichatadminroomSocket.close(); osichatadminroomSocket.close();
} }
osichatadminroomSocket = new WebSocket(`${admin_chat_ws_scheme}://${admin_chat_domain}/ws/osichat-admin/${sessionid}/${chatid}/`);
osichatadminroomSocket = new WebSocket(`${admin_chat_ws_scheme}://${admin_chat_domain}/ws/osichat-admin/${sessionId}/${chatId}/`);
osichatadminroomSocket.onopen = function () { osichatadminroomSocket.onopen = function () {
scrollBottom();
hideLoader();
markCurrentChatRead(chatId)
console.log('WebSocket connection to osichat established'); console.log('WebSocket connection to osichat established');
osichatadminroomSocket.send(JSON.stringify({ 'event_type': 'load_chat', 'client_type': 'website_admin' })); osichatadminroomSocket.send(JSON.stringify({ 'event_type': 'load_chat', 'client_type': 'website_admin' }));
osichatadminroomSocket.send(JSON.stringify({ 'event_type': 'update_read_messages', 'user_id': userId, 'chat_state': 'open' })); osichatadminroomSocket.send(JSON.stringify({ 'event_type': 'update_read_messages', 'user_id': userId, 'chat_state': 'open' }));
}; };
function handleLoadChatEvent(data, osichatadminroomSocket) {
function handleLoadChatEvent(data) {
let chatDiv = document.getElementById('widgetRightSide'); let chatDiv = document.getElementById('widgetRightSide');
chatDiv.innerHTML = data.html; chatDiv.innerHTML = data.html;
appendTextAreaScript(admin_chat_domain, chatDiv); appendTextAreaScript(chatDiv);
const sendMessageForm = document.querySelector('#sendMessage'); const sendMessageForm = document.querySelector('#sendMessage');
sendMessageForm.addEventListener('submit', function (event) { sendMessageForm.addEventListener('submit', function (event) {
@ -60,10 +103,10 @@
const messagesDiv = document.getElementById('messages_container'); const messagesDiv = document.getElementById('messages_container');
switch (data.event_type) { switch (data.event_type) {
case 'load_chat': case 'load_chat':
handleLoadChatEvent(data, osichatadminroomSocket); handleLoadChatEvent(data);
break; break;
case 'typing': case 'typing':
if(!typingDiv && data.user != userId){ if (!typingDiv && data.user != userId) {
messagesDiv.insertAdjacentHTML('beforeend', data.html); messagesDiv.insertAdjacentHTML('beforeend', data.html);
} }
break; break;
@ -75,13 +118,10 @@
case 'send_message': case 'send_message':
osichatadminroomSocket.send(JSON.stringify({ 'event_type': 'update_read_messages', 'user_id': userId, 'chat_state': 'open' })); osichatadminroomSocket.send(JSON.stringify({ 'event_type': 'update_read_messages', 'user_id': userId, 'chat_state': 'open' }));
messagesDiv.insertAdjacentHTML('beforeend', data.html); messagesDiv.insertAdjacentHTML('beforeend', data.html);
if (!data.user) { // If it is sent by a guest play a notification sound for the guest if (!data.user){
const notificationSound = document.getElementById('notification-sound');
notificationSound.play();
if (typingDiv) { if (typingDiv) {
typingDiv.remove(); typingDiv.remove();
} }
break;
} }
break; break;
default: default:
@ -90,11 +130,26 @@
}; };
osichatadminroomSocket.onclose = function () { osichatadminroomSocket.onclose = function () {
console.log('WebSocket connection to osichat closed'); console.log('WebSocket connection closed');
if (currentChatId === chatId) {
setTimeout(() => {
console.log('Attempting to reconnect to WebSocket...');
openConversation(sessionId, chatId);
}, 2000);
}
}; };
osichatadminroomSocket.onerror = function (error) { osichatadminroomSocket.onerror = function (error) {
console.error('WebSocket error:', error); console.error('WebSocket error:', error);
showLoader();
}; };
} }
window.addEventListener('offline', () => {
showLoader();
if (osichatadminroomSocket) {
osichatadminroomSocket.close();
}
});
})(); })();

@ -2,8 +2,24 @@ let admin_chat_ws_scheme = window.location.protocol === "https:" ? "wss" : "ws";
let protocol = window.location.protocol === "https:" ? "https" : "http"; let protocol = window.location.protocol === "https:" ? "https" : "http";
let admin_chat_domain = "osina.ositcom.com"; let admin_chat_domain = "osina.ositcom.com";
let userId = document.getElementById('userId').textContent.trim(); let userId = document.getElementById('userId').textContent.trim();
let osichatroomsSocket; let osichatadminroomSocket = null;
let osichatadminroomSocket; let currentChatId = null;
// FUNCTIONS TO SHOW & HIDE THE LOADER
function showLoader() {
const roomsLoader = document.getElementById('roomsLoader');
if (roomsLoader) {
roomsLoader.classList.remove('hidden');
}
}
function hideLoader() {
const roomsLoader = document.getElementById('roomsLoader');
if (roomsLoader) {
roomsLoader.classList.add('hidden');
}
}
function appendInnerConversationScript(div) { function appendInnerConversationScript(div) {
const innerConversationScript = document.createElement('script'); const innerConversationScript = document.createElement('script');
@ -12,11 +28,16 @@ function appendInnerConversationScript(div) {
div.appendChild(innerConversationScript); div.appendChild(innerConversationScript);
} }
function getRooms(){ function getRooms(){
osichatroomsSocket = new WebSocket(`${admin_chat_ws_scheme}://${admin_chat_domain}/ws/osichat/rooms/`); osichatroomsSocket = new WebSocket(`${admin_chat_ws_scheme}://${admin_chat_domain}/ws/osichat/rooms/`);
osichatroomsSocket.onopen = function () { osichatroomsSocket.onopen = function () {
console.log('WebSocket connection to rooms established'); console.log('WebSocket connection to rooms established');
hideLoader();
osichatroomsSocket.send(JSON.stringify({ osichatroomsSocket.send(JSON.stringify({
'event_type': 'set_client_type', 'event_type': 'set_client_type',
'client_type': 'website_admin', 'client_type': 'website_admin',
@ -39,11 +60,34 @@ function getRooms(){
if (chatRoomDiv) { if (chatRoomDiv) {
chatRoomDiv.remove(); // Remove the existing chat room div chatRoomDiv.remove(); // Remove the existing chat room div
} }
// Insert the new chat room HTML at the top of the container // Insert the new chat room HTML at the top of the container
const newChatRoomDiv = document.createElement('div'); const newChatRoomDiv = document.createElement('div');
newChatRoomDiv.innerHTML = data.html; newChatRoomDiv.innerHTML = data.html;
roomsContainer.insertAdjacentElement('afterbegin', newChatRoomDiv.firstElementChild); roomsContainer.insertAdjacentElement('afterbegin', newChatRoomDiv.firstElementChild);
if (parseInt(currentChatId) === parseInt(data.chatroom_id)) {
const unreadIndicator = roomsContainer.querySelector(`.unread[data-roomid='${data.chatroom_id}']`);
if (unreadIndicator) {
unreadIndicator.classList.add('hidden');
}
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();
}
} else {
const unreadIndicator = roomsContainer.querySelector(`.unread[data-roomid='${data.chatroom_id}']`);
if (unreadIndicator) {
unreadIndicator.classList.remove('hidden');
}
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();
}
}
appendInnerConversationScript(leftDiv); appendInnerConversationScript(leftDiv);
break; break;
@ -53,12 +97,25 @@ function getRooms(){
}; };
osichatroomsSocket.onclose = function () { osichatroomsSocket.onclose = function () {
console.log('WebSocket connection to rooms closed'); showLoader();
setTimeout(() => {
console.log('Attempting to reconnect to WebSocket...');
getRooms();
}, 2000);
}; };
osichatroomsSocket.onerror = function (error) { osichatroomsSocket.onerror = function (error) {
showLoader();
console.error('WebSocket error:', error); console.error('WebSocket error:', error);
}; };
window.addEventListener('offline', () => {
showLoader();
if (osichatroomsSocket) {
osichatroomsSocket.close();
}
});
} }
getRooms(); getRooms();

@ -1,12 +1,14 @@
(function() { (function() {
// FUNCTION TO ADJUST TEXTAREA HEIGHT AND SUBMIT BUTTON VISIBILITY // FUNCTION TO ADJUST TEXTAREA HEIGHT AND SUBMIT BUTTON VISIBILITY
function adjustTextAreaAndButton(textarea, submitButton) { function adjustTextAreaAndButton(textarea, submitButton) {
// Adjust the height of the textarea
if (textarea.value.trim() === '') { if (textarea.value.trim() === '') {
textarea.style.height = '50px'; textarea.style.height = '50px';
} else { } else {
textarea.style.height = textarea.scrollHeight + 'px'; textarea.style.height = textarea.scrollHeight + 'px';
} }
// Display and hide the submit button
if (textarea.value.trim() === '') { if (textarea.value.trim() === '') {
submitButton.classList.add('hidden'); submitButton.classList.add('hidden');
} else { } else {
@ -14,10 +16,21 @@
} }
} }
function scrollBottom() {
const conversationContainer = document.getElementById('messages_container');
if (conversationContainer) {
conversationContainer.scrollTo({
top: conversationContainer.scrollHeight,
behavior: 'smooth'
});
}
}
// INITIALIZE ELEMENTS // INITIALIZE ELEMENTS
const form = document.querySelector('#sendMessage'); const form = document.querySelector('#sendMessage');
const textarea = document.querySelector('#dynamicTextarea'); const textarea = document.querySelector('#dynamicTextarea');
const conversationContainer = document.getElementById('conversation');
const submitButton = document.getElementById('submitMessageButton'); const submitButton = document.getElementById('submitMessageButton');
const typingUserId = document.getElementById('userId').textContent.trim(); const typingUserId = document.getElementById('userId').textContent.trim();
let typingTimeout; let typingTimeout;
@ -54,8 +67,18 @@
submitButton.classList.add('hidden'); submitButton.classList.add('hidden');
setTimeout(() => { setTimeout(() => {
conversationContainer.scrollTop = conversationContainer.scrollHeight; scrollBottom();
}, 100); }, 100);
}); });
textarea.addEventListener('keydown', (event) => {
if (event.key === 'Enter' && !event.shiftKey) {
event.preventDefault();
if (!submitButton.classList.contains('hidden')) {
submitButton.click();
}
scrollBottom();
}
});
})(); })();

@ -18,15 +18,19 @@
function scrollBottom() { function scrollBottom() {
const conversationContainer = document.getElementById('conversation'); const conversationContainer = document.getElementById('conversation');
conversationContainer.scrollTop = conversationContainer.scrollHeight;
}
if (conversationContainer) {
conversationContainer.scrollTo({
top: conversationContainer.scrollHeight,
behavior: 'smooth'
});
}
}
// INITIALIZE ELEMENTS // INITIALIZE ELEMENTS
const form = document.querySelector('#sendMessage'); const form = document.querySelector('#sendMessage');
const textarea = document.querySelector('#dynamicTextarea'); const textarea = document.querySelector('#dynamicTextarea');
const conversationContainer = document.getElementById('conversation');
const submitButton = document.getElementById('submitMessageButton'); const submitButton = document.getElementById('submitMessageButton');
let typingTimeout; let typingTimeout;
let isTyping = false; let isTyping = false;

Loading…
Cancel
Save