|
|
|
@ -11,65 +11,59 @@ import json
|
|
|
|
|
from django.template.loader import render_to_string
|
|
|
|
|
from asgiref.sync import async_to_sync
|
|
|
|
|
|
|
|
|
|
from channels.generic.websocket import AsyncWebsocketConsumer
|
|
|
|
|
from django.shortcuts import get_object_or_404
|
|
|
|
|
from datetime import datetime
|
|
|
|
|
from asgiref.sync import sync_to_async
|
|
|
|
|
import json
|
|
|
|
|
|
|
|
|
|
class TicketRoomConsumer(WebsocketConsumer):
|
|
|
|
|
def connect(self):
|
|
|
|
|
class TicketRoomConsumer(AsyncWebsocketConsumer):
|
|
|
|
|
async def connect(self):
|
|
|
|
|
self.user = self.scope['user']
|
|
|
|
|
self.ticket_id = self.scope['url_route']['kwargs']['ticket_id']
|
|
|
|
|
self.ticket = get_object_or_404(Ticket, id=self.ticket_id)
|
|
|
|
|
self.ticket = await sync_to_async(get_object_or_404)(Ticket, id=self.ticket_id)
|
|
|
|
|
self.ticket_number = self.ticket.ticket_number
|
|
|
|
|
|
|
|
|
|
existing_connection = TicketConnection.objects.filter(ticket=self.ticket, user=self.user, terminated_at__isnull=True).delete()
|
|
|
|
|
TicketConnection.objects.create(
|
|
|
|
|
await sync_to_async(TicketConnection.objects.filter(ticket=self.ticket, user=self.user, terminated_at__isnull=True).delete)()
|
|
|
|
|
await sync_to_async(TicketConnection.objects.create)(
|
|
|
|
|
ticket=self.ticket,
|
|
|
|
|
user=self.user,
|
|
|
|
|
date=datetime.now()
|
|
|
|
|
)
|
|
|
|
|
staff_profile = StaffProfile.objects.filter(user=self.user).first()
|
|
|
|
|
|
|
|
|
|
staff_profile = await sync_to_async(StaffProfile.objects.filter(user=self.user).first)()
|
|
|
|
|
if staff_profile:
|
|
|
|
|
if not TicketStaff.objects.filter(staff=staff_profile, ticket=self.ticket).exists():
|
|
|
|
|
TicketStaff.objects.create(
|
|
|
|
|
if not await sync_to_async(TicketStaff.objects.filter(staff=staff_profile, ticket=self.ticket).exists)():
|
|
|
|
|
await sync_to_async(TicketStaff.objects.create)(
|
|
|
|
|
staff=staff_profile,
|
|
|
|
|
ticket=self.ticket,
|
|
|
|
|
date_added=datetime.now()
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
async_to_sync(self.channel_layer.group_add)(
|
|
|
|
|
self.ticket_number, self.channel_name
|
|
|
|
|
)
|
|
|
|
|
self.accept()
|
|
|
|
|
self.modify_online_user()
|
|
|
|
|
await self.channel_layer.group_add(self.ticket_number, self.channel_name)
|
|
|
|
|
await self.accept()
|
|
|
|
|
await self.modify_online_user()
|
|
|
|
|
|
|
|
|
|
async def disconnect(self, close_code):
|
|
|
|
|
await sync_to_async(TicketConnection.objects.filter(ticket=self.ticket, user=self.user).update)(terminated_at=datetime.now())
|
|
|
|
|
await self.channel_layer.group_discard(self.ticket_number, self.channel_name)
|
|
|
|
|
await self.modify_online_user()
|
|
|
|
|
|
|
|
|
|
def disconnect(self, close_code):
|
|
|
|
|
TicketConnection.objects.filter(
|
|
|
|
|
ticket=self.ticket,
|
|
|
|
|
user=self.user,
|
|
|
|
|
).update(terminated_at=datetime.now())
|
|
|
|
|
async_to_sync(self.channel_layer.group_discard)(
|
|
|
|
|
self.ticket_number, self.channel_name
|
|
|
|
|
)
|
|
|
|
|
self.modify_online_user()
|
|
|
|
|
|
|
|
|
|
def receive(self, text_data):
|
|
|
|
|
async def receive(self, text_data):
|
|
|
|
|
text_data_json = json.loads(text_data)
|
|
|
|
|
event_type = text_data_json.get('event_type')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if event_type == 'typing':
|
|
|
|
|
event = {
|
|
|
|
|
'type': 'typing_handler',
|
|
|
|
|
'user': self.scope['user']
|
|
|
|
|
}
|
|
|
|
|
async_to_sync(self.channel_layer.group_send)(
|
|
|
|
|
self.ticket_number, event
|
|
|
|
|
)
|
|
|
|
|
await self.channel_layer.group_send(self.ticket_number, event)
|
|
|
|
|
elif event_type == 'stop_typing':
|
|
|
|
|
event = {
|
|
|
|
|
'type': 'stop_typing_handler',
|
|
|
|
|
}
|
|
|
|
|
async_to_sync(self.channel_layer.group_send)(
|
|
|
|
|
self.ticket_number, event
|
|
|
|
|
)
|
|
|
|
|
await self.channel_layer.group_send(self.ticket_number, event)
|
|
|
|
|
elif event_type == 'update_reaction':
|
|
|
|
|
reaction = text_data_json['reaction']
|
|
|
|
|
update_id = text_data_json['update_id']
|
|
|
|
@ -79,13 +73,11 @@ class TicketRoomConsumer(WebsocketConsumer):
|
|
|
|
|
'reaction': reaction,
|
|
|
|
|
'user': self.scope['user']
|
|
|
|
|
}
|
|
|
|
|
async_to_sync(self.channel_layer.group_send)(
|
|
|
|
|
self.ticket_number, event
|
|
|
|
|
)
|
|
|
|
|
await self.channel_layer.group_send(self.ticket_number, event)
|
|
|
|
|
else:
|
|
|
|
|
body = text_data_json['description']
|
|
|
|
|
file_paths = text_data_json['filePath']
|
|
|
|
|
ticketupdate = TicketUpdate.objects.create(
|
|
|
|
|
ticketupdate = await sync_to_async(TicketUpdate.objects.create)(
|
|
|
|
|
added_by=self.user,
|
|
|
|
|
description=body,
|
|
|
|
|
ticket=self.ticket,
|
|
|
|
@ -96,94 +88,88 @@ class TicketRoomConsumer(WebsocketConsumer):
|
|
|
|
|
ticket_update=ticketupdate,
|
|
|
|
|
file_path=file_path
|
|
|
|
|
)
|
|
|
|
|
ticket_attachment.save()
|
|
|
|
|
await sync_to_async(ticket_attachment.save)()
|
|
|
|
|
event = {
|
|
|
|
|
'type': 'update_handler',
|
|
|
|
|
'update_id': ticketupdate.id
|
|
|
|
|
}
|
|
|
|
|
async_to_sync(self.channel_layer.group_send)(
|
|
|
|
|
self.ticket_number, event
|
|
|
|
|
)
|
|
|
|
|
await self.channel_layer.group_send(self.ticket_number, event)
|
|
|
|
|
|
|
|
|
|
def update_handler(self, event):
|
|
|
|
|
async def update_handler(self, event):
|
|
|
|
|
update_id = event['update_id']
|
|
|
|
|
update = TicketUpdate.objects.get(id=update_id)
|
|
|
|
|
update = await sync_to_async(TicketUpdate.objects.get)(id=update_id)
|
|
|
|
|
context = {
|
|
|
|
|
'update': update,
|
|
|
|
|
'user': self.user
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
html = render_to_string("details_templates/partials/new-ticket-message.html", context=context)
|
|
|
|
|
self.send(text_data=json.dumps({
|
|
|
|
|
html = await sync_to_async(render_to_string)("details_templates/partials/new-ticket-message.html", context=context)
|
|
|
|
|
await self.send(text_data=json.dumps({
|
|
|
|
|
'event_type': 'update',
|
|
|
|
|
'html': html
|
|
|
|
|
}))
|
|
|
|
|
|
|
|
|
|
def typing_handler(self, event):
|
|
|
|
|
async def typing_handler(self, event):
|
|
|
|
|
context = {
|
|
|
|
|
'user': event['user']
|
|
|
|
|
}
|
|
|
|
|
html = render_to_string("details_templates/partials/typing-message.html", context=context)
|
|
|
|
|
self.send(text_data=json.dumps({
|
|
|
|
|
html = await sync_to_async(render_to_string)("details_templates/partials/typing-message.html", context=context)
|
|
|
|
|
await self.send(text_data=json.dumps({
|
|
|
|
|
'event_type': 'typing',
|
|
|
|
|
'html': html
|
|
|
|
|
}))
|
|
|
|
|
|
|
|
|
|
def stop_typing_handler(self, event):
|
|
|
|
|
self.send(text_data=json.dumps({
|
|
|
|
|
async def stop_typing_handler(self, event):
|
|
|
|
|
await self.send(text_data=json.dumps({
|
|
|
|
|
'event_type': 'stop_typing'
|
|
|
|
|
}))
|
|
|
|
|
|
|
|
|
|
def reaction_handler(self, event):
|
|
|
|
|
async def reaction_handler(self, event):
|
|
|
|
|
update_id = event['update_id']
|
|
|
|
|
reaction = event['reaction']
|
|
|
|
|
user = self.user
|
|
|
|
|
|
|
|
|
|
update = TicketUpdate.objects.get(id=update_id)
|
|
|
|
|
existing_reaction = TicketUpdateReaction.objects.filter(ticket_update=update, customer=user).first()
|
|
|
|
|
update = await sync_to_async(TicketUpdate.objects.get)(id=update_id)
|
|
|
|
|
existing_reaction = await sync_to_async(TicketUpdateReaction.objects.filter)(ticket_update=update, customer=user).first()
|
|
|
|
|
new_reaction = None
|
|
|
|
|
if existing_reaction:
|
|
|
|
|
# If the existing reaction type is equal to the new reaction, delete it
|
|
|
|
|
if existing_reaction.reaction == reaction:
|
|
|
|
|
existing_reaction.delete()
|
|
|
|
|
await sync_to_async(existing_reaction.delete)()
|
|
|
|
|
else:
|
|
|
|
|
# If not, delete all previous reactions and add a new one
|
|
|
|
|
TicketUpdateReaction.objects.filter(ticket_update=update, customer=user).delete()
|
|
|
|
|
new_reaction = TicketUpdateReaction.objects.create(
|
|
|
|
|
await sync_to_async(TicketUpdateReaction.objects.filter)(ticket_update=update, customer=user).delete()
|
|
|
|
|
new_reaction = await sync_to_async(TicketUpdateReaction.objects.create)(
|
|
|
|
|
ticket_update=update,
|
|
|
|
|
reaction=reaction,
|
|
|
|
|
customer=user
|
|
|
|
|
)
|
|
|
|
|
else:
|
|
|
|
|
# If there's no existing reaction, simply add the new one
|
|
|
|
|
new_reaction = TicketUpdateReaction.objects.create(
|
|
|
|
|
new_reaction = await sync_to_async(TicketUpdateReaction.objects.create)(
|
|
|
|
|
ticket_update=update,
|
|
|
|
|
reaction=reaction,
|
|
|
|
|
customer=user
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
self.send(text_data=json.dumps({
|
|
|
|
|
await self.send(text_data=json.dumps({
|
|
|
|
|
'event_type': 'reaction',
|
|
|
|
|
'update_id': update_id,
|
|
|
|
|
'reaction': new_reaction.reaction if new_reaction else None
|
|
|
|
|
}))
|
|
|
|
|
|
|
|
|
|
def modify_online_user(self):
|
|
|
|
|
async def modify_online_user(self):
|
|
|
|
|
connections = await sync_to_async(TicketConnection.objects.filter)(ticket=self.ticket, terminated_at__isnull=True)
|
|
|
|
|
event = {
|
|
|
|
|
'type': 'user_connection_handler',
|
|
|
|
|
'user': self.user,
|
|
|
|
|
'connections': connections,
|
|
|
|
|
}
|
|
|
|
|
async_to_sync(self.channel_layer.group_send)(
|
|
|
|
|
self.ticket_number, event
|
|
|
|
|
)
|
|
|
|
|
await self.channel_layer.group_send(self.ticket_number, event)
|
|
|
|
|
|
|
|
|
|
def user_connection_handler(self, event):
|
|
|
|
|
async def user_connection_handler(self, event):
|
|
|
|
|
context = {
|
|
|
|
|
'connections': event['connections'],
|
|
|
|
|
'user': event['user']
|
|
|
|
|
}
|
|
|
|
|
html = render_to_string("details_templates/partials/ticket-online-users.html", context=context)
|
|
|
|
|
self.send(text_data=json.dumps({
|
|
|
|
|
html = await sync_to_async(render_to_string)("details_templates/partials/ticket-online-users.html", context=context)
|
|
|
|
|
await self.send(text_data=json.dumps({
|
|
|
|
|
'event_type': 'user_status',
|
|
|
|
|
'html': html
|
|
|
|
|
}))
|
|
|
|
|