emile 10 months ago
parent 8a31343fcf
commit 7eb89e5418

Binary file not shown.

@ -0,0 +1,93 @@
from channels.generic.websocket import WebsocketConsumer
from .models import *
import json
from django.template.loader import render_to_string
from asgiref.sync import async_to_sync
import threading
def get_last_seen(user):
connection = Connection.objects.filter(user=user).last()
if not connection.exists():
return "Not seen yet"
if connection.online:
return "Online"
last_seen_time = connection.last_seen
now = timezone.now()
time_diff = now - last_seen_time
if time_diff < timedelta(days=1):
if last_seen_time.date() == now.date():
return f"last seen today at {last_seen_time.strftime('%I:%M %p')}"
else:
return f"last seen yesterday at {last_seen_time.strftime('%I:%M %p')}"
else:
return f"last seen on {last_seen_time.strftime('%b %d at %I:%M %p')}"
class OnlineUserConsumer(WebsocketConsumer):
def connect(self):
self.user = self.scope['user']
existing_connection = Connection.objects.filter(user=self.user).last()
if existing_connection:
self.connection = existing_connection
self.connection.online = True
self.connection.disconnected = False
self.connection.save()
else:
self.connection = Connection.objects.create(user=self.user, online=True)
async_to_sync(self.channel_layer.group_add)(
'online_users', self.channel_name
)
self.accept()
self.modify_online_user()
def disconnect(self, close_code):
self.last_seen = datetime.now()
self.connection.disconnected = True
self.connection.save()
timer_thread = threading.Timer(10, self.check_disconnect_status)
timer_thread.start()
def check_disconnect_status(self):
connection = Connection.objects.filter(user=self.user).last()
if connection.disconnected:
self.connection.last_seen = self.last_seen
self.connection.online = False
self.connection.save()
self.modify_online_user()
def modify_online_user(self):
connections = Connection.objects.filter(online=True)
online_users_ids = [connection.user.id for connection in connections]
customer_connections = []
staff_connections = []
for connection in connections:
if hasattr(connection.user, 'customerprofile'):
customer_connections.append(connection)
elif hasattr(connection.user, 'staffprofile'):
staff_connections.append(connection)
print(staff_connections)
event = {
'type': 'online_user_connection_handler',
'staff_connections': staff_connections,
'customer_connections': customer_connections,
'online_users_ids': online_users_ids
}
async_to_sync(self.channel_layer.group_send)(
'online_users', event
)
def online_user_connection_handler(self, event):
context = {
'staff_connections': event['staff_connections'],
'customer_connections': event['customer_connections'],
}
html = render_to_string("details_templates/partials/recently-online.html", context=context)
self.send(text_data=json.dumps({
'event_type': 'online_user_status',
'html': html,
'online_users_ids': event.get('online_users_ids', [])
}))

@ -23,15 +23,6 @@ def calculate_time_ago(status):
def utilities(request):
latest_connections = Connection.objects.filter(user__staffprofile__isnull=False).values('user').annotate(latest_connection=Max('date'))
online_staff_profiles = []
for connection in latest_connections:
user_id = connection['user']
latest_connection = connection['latest_connection']
last_connection = Connection.objects.filter(user_id=user_id, date=latest_connection).first()
if last_connection.status == 'Online':
online_staff_profiles.append(last_connection.user.staffprofile)
notes = None
recent_note = None
@ -45,12 +36,6 @@ def utilities(request):
if request.user.is_authenticated and StaffProfile.objects.filter(user=request.user):
notes = Note.objects.filter(user=request.user).order_by('-date')[:6]
recent_note = Note.objects.filter(user=request.user).last()
last_user_activity = Connection.objects.filter(user=request.user).last()
if last_user_activity and last_user_activity.status == 'Offline':
user_offline = True
else:
user_offline = False
if request.user.is_superuser:
open_task_count = Task.objects.filter(status='Open').count()
@ -141,7 +126,6 @@ def utilities(request):
'latest_statuses_time_ago': latest_statuses_time_ago,
'notes' : notes,
'recent_note' : recent_note,
'online_staff_profiles' : online_staff_profiles,
'user_offline' : user_offline,
'recent_logged_in_staffs' : recent_logged_in_staffs,
'recent_logged_in_customers' : recent_logged_in_customers,

@ -0,0 +1,22 @@
# Generated by Django 4.2.5 on 2024-07-08 05:45
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('osinacore', '0085_rename_date_staffposition_start_date_and_more'),
]
operations = [
migrations.RemoveField(
model_name='connection',
name='status',
),
migrations.AddField(
model_name='connection',
name='terminated_at',
field=models.DateTimeField(blank=True, null=True),
),
]

@ -0,0 +1,17 @@
# Generated by Django 4.2.5 on 2024-07-08 06:05
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('osinacore', '0086_remove_connection_status_connection_terminated_at'),
]
operations = [
migrations.RemoveField(
model_name='connection',
name='date',
),
]

@ -0,0 +1,18 @@
# Generated by Django 4.2.5 on 2024-07-08 06:15
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('osinacore', '0087_remove_connection_date'),
]
operations = [
migrations.AddField(
model_name='connection',
name='date',
field=models.DateTimeField(null=True),
),
]

@ -0,0 +1,18 @@
# Generated by Django 4.2.5 on 2024-07-08 08:52
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('osinacore', '0088_connection_date'),
]
operations = [
migrations.AddField(
model_name='connection',
name='connected',
field=models.BooleanField(default=True),
),
]

@ -0,0 +1,18 @@
# Generated by Django 4.2.5 on 2024-07-08 08:55
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('osinacore', '0089_connection_connected'),
]
operations = [
migrations.RenameField(
model_name='connection',
old_name='terminated_at',
new_name='last_seen',
),
]

@ -0,0 +1,21 @@
# Generated by Django 4.2.5 on 2024-07-08 08:55
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('osinacore', '0090_rename_terminated_at_connection_last_seen'),
]
operations = [
migrations.AlterField(
model_name='connection',
name='user',
field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
),
]

@ -0,0 +1,18 @@
# Generated by Django 4.2.5 on 2024-07-08 08:57
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('osinacore', '0091_alter_connection_user'),
]
operations = [
migrations.RenameField(
model_name='connection',
old_name='connected',
new_name='online',
),
]

@ -0,0 +1,18 @@
# Generated by Django 4.2.5 on 2024-07-08 09:06
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('osinacore', '0092_rename_connected_connection_online'),
]
operations = [
migrations.AddField(
model_name='connection',
name='disconnected',
field=models.BooleanField(default=False),
),
]

@ -388,12 +388,9 @@ class DailyReport(models.Model):
class Connection(models.Model):
STATUS_CHOICES = (
('Online', 'Online'),
('Offline', 'Offline'),
)
status = models.CharField(max_length=200, choices=STATUS_CHOICES, null=True)
date = models.DateTimeField(null=True)
user = models.ForeignKey(User, on_delete=models.CASCADE)
user = models.OneToOneField(User, on_delete=models.CASCADE)
online = models.BooleanField(default=True)
last_seen = models.DateTimeField(null=True, blank=True)
disconnected = models.BooleanField(default=False)

@ -0,0 +1,8 @@
from django.urls import path
from .consumers import *
websocket_urlpatterns = [
path("ws/online-users/", OnlineUserConsumer.as_asgi()),
]

@ -944,6 +944,9 @@
<!---------------------- JS SCRIPTS -------------------->
<!-- SIDE BAR SCRIPT -->
<script type="text/javascript" src='{% static "js/online/online-consumer.js" %}'></script>
<!-- SIDE BAR SCRIPT -->
<script type="text/javascript" src='{% static "js/side-bar.js" %}'></script>

@ -610,6 +610,9 @@
<!---------------------- JS SCRIPTS -------------------->
<!-- SIDE BAR SCRIPT -->
<script type="text/javascript" src='{% static "js/online/online-consumer.js" %}'></script>
<!-- SIDE BAR SCRIPT -->
<script type="text/javascript" src='{% static "js/side-bar.js" %}'></script>

@ -126,7 +126,7 @@
{% if latest_statuses_time_ago %}
{% for latest in latest_statuses_time_ago %}
<div class="w-full flex flex-col py-3">
<div class="w-full flex flex-col py-3 users-activities" data-userId="{{ latest.status.staff.user.id }}">
<div class="w-full flex flex-col justify-center items-start gap-3 bg-gray-50 pt-2 px-2 pb-6 rounded-md relative">
<div class="w-full flex justify-between items-center gap-2">
<div class="flex justify-start gap-2 cursor-pointer userRecentActivitiesButton"
@ -137,15 +137,12 @@
class="w-full h-full object-cover rounded-full">
</div>
{% if latest.status.staff in online_staff_profiles %}
<div
<div id="connected"
class="w-[12px] h-[12px] absolute rounded-full bg-green-600 bottom-0 right-0 border-2 border-white">
</div>
{% else %}
<div
<div id="not-connected"
class="w-[12px] h-[12px] absolute rounded-full bg-red-500 bottom-0 right-0 border-2 border-white">
</div>
{% endif %}
</div>
<div class="flex flex-col">

@ -0,0 +1,61 @@
{% load static %}
<div
class="w-full xxlg1:flex flex-col justify-center items-center gap-3 bg-white shadow-md rounded-md p-5 logged-in-container">
<div class="w-full flex justify-center items-center">
<p class="text-[20px] text-secondosiblue font-bold text-center">Recently Online</p>
</div>
<div class="w-full recentltLoggedStaffsContainer">
<div class="w-full rounded-md bg-gray-200 grid grid-cols-2 shadow-sm">
<button
class="w-full rounded-md text-secondosiblue text-sm cursor-pointer p-2 customerButton">Customers</button>
<button class="w-full bg-white rounded-md text-secondosiblue text-sm cursor-pointer p-2 staffButton"
style="box-shadow: 0 0 6px rgba(88, 88, 88, 0.043), 6px 0 6px rgba(88, 88, 88, 0.043), 0 6px 6px rgba(88, 88, 88, 0.043), -6px 0 6px rgba(88, 88, 88, 0.043);">Staffs</button>
</div>
<div class="w-full flex flex-col gap-3 mt-3">
{% for staff_connection in staff_connections %}
<div class="w-full flex justify-start items-center gap-2">
<div class="relative">
<div class="w-[40px] h-[40px] rounded-full">
<img src="{{staff_connection.user.staffprofile.image.url}}"
class="w-full h-full object-cover rounded-full">
</div>
</div>
<div class="flex flex-col">
<p class="text-secondosiblue text-sm">{{staff_connection.user.first_name}}
{{staff_connection.user.last_name}}</p>
<p class="text-gray-500 text-sm">Online</p>
</div>
</div>
{% endfor %}
</div>
</div>
<div class="w-full hidden recentltLoggedCustomersContainer">
<div class="w-full rounded-md bg-gray-200 grid grid-cols-2 shadow-sm">
<button class="w-full bg-white rounded-md text-secondosiblue text-sm cursor-pointer p-2 customerButton"
style="box-shadow: 0 0 6px rgba(88, 88, 88, 0.043), 6px 0 6px rgba(88, 88, 88, 0.043), 0 6px 6px rgba(88, 88, 88, 0.043), -6px 0 6px rgba(88, 88, 88, 0.043);">Customers</button>
<button class="w-full text-secondosiblue text-sm cursor-pointer p-2 staffButton">Staffs</button>
</div>
<div class="w-full mt-3 flex flex-col gap-3 recentltLoggedCustomers">
{% for customer_connection in customer_connections %}
<div class="w-full flex justify-start items-center gap-2">
<div
class="w-[40px] h-[40px] bg-secondosiblue flex justify-center items-center rounded-full text-white">
<p>{{customer_connection.user.first_name|slice:":1"}}{{customer_connection.user.last_name|slice:":1"}}
</p>
</div>
<div class="flex flex-col">
<p class="text-secondosiblue text-sm">{{recent_logged_in_customer.first_name}}
{{recent_logged_in_customer.last_name}}</p>
<p class="text-gray-500 text-sm">
{{recent_logged_in_customer.last_login|date:"g:i A"}}</p>
</div>
</div>
{% endfor %}
</div>
</div>
</div>

@ -292,7 +292,9 @@
<script type="text/javascript" src='{% static "js/tickets/share-ticket.js" %}'></script>
<script>
// WebSocket connection for new tickets
const newTicketsSocket = new WebSocket('wss://' + window.location.host + '/ws/new-tickets/');
const ws_scheme = window.location.protocol === "https:" ? "wss" : "ws";
const newTicketsSocketUrl = `${ws_scheme}://${window.location.host}/ws/new-tickets/`;
const newTicketsSocket = new WebSocket(newTicketsSocketUrl);
newTicketsSocket.onopen = () => {
console.log('WebSocket connection to new tickets established');
@ -320,7 +322,8 @@
// WebSocket connection for new ticket updates
const newTicketUpdatesSocket = new WebSocket('wss://' + window.location.host + '/ws/new-ticket-updates/');
const newTicketUpdatesSocketUrl = `${ws_scheme}://${window.location.host}/ws/new-tickets/`;
const newTicketUpdatesSocket = new WebSocket(newTicketsSocketUrl);
newTicketUpdatesSocket.onopen = () => {
console.log('WebSocket connection to new ticket updates established');

@ -1158,204 +1158,23 @@
<h1 class="text-2xl text-secondosiblue text-center font-semibold">Users Activity</h1>
<div class="w-full h-fit mt-2" id="activitiesContainer">
{% include 'recent-activities.html' %}
{% include 'details_templates/partials/recent-activities.html' %}
</div>
</div>
<!-- CONNECTED USERS -->
<div class="w-full hidden xxlg1:block bg-white shadow-md rounded-md p-5">
<div class="w-full h-full flex flex-col gap-3 items-center">
<div class="w-full flex justify-center items-center">
<p class="text-[20px] text-secondosiblue font-bold text-center">
Connected Users
</p>
</div>
<div class="w-full flex flex-wrap gap-4 items-center justify-center">
{% for online in online_staff_profiles %}
<div class="flex flex-col justify-center items-center gap-1">
<div class="w-[30px] h-[30px] rounded-full">
<img src="{{online.image.url}}" alt="User Image"
class="w-full h-full rounded-full object-cover">
</div>
<p class="text-gray-500 text-[10px] font-light">{{online.user.first_name}}</p>
</div>
{% endfor %}
</div>
</div>
<div class="connected-users">
<!-- RECENTLY LOGGED IN USERS -->
{% include 'details_templates/partials/recently-online.html' %}
</div>
<!-- RECENTLY LOGGED IN USERS -->
<div
class="w-full hidden xxlg1:flex flex-col justify-center items-center gap-3 bg-white shadow-md rounded-md p-5 logged-in-container">
<div class="w-full flex justify-center items-center">
<p class="text-[20px] text-secondosiblue font-bold text-center">Recently Logged In</p>
</div>
<div class="w-full recentltLoggedCustomersContainer">
<div class="w-full rounded-md bg-gray-200 grid grid-cols-2 shadow-sm">
<button
class="w-full bg-white rounded-md text-secondosiblue text-sm cursor-pointer p-2 customerButton"
style="box-shadow: 0 0 6px rgba(88, 88, 88, 0.043), 6px 0 6px rgba(88, 88, 88, 0.043), 0 6px 6px rgba(88, 88, 88, 0.043), -6px 0 6px rgba(88, 88, 88, 0.043);">Customers</button>
<button
class="w-full text-secondosiblue text-sm cursor-pointer p-2 staffButton">Staffs</button>
</div>
<div class="w-full mt-3 flex flex-col gap-3 recentltLoggedCustomers">
{% for recent_logged_in_customer in recent_logged_in_customers %}
<div class="w-full flex justify-start items-center gap-2">
<div
class="w-[40px] h-[40px] bg-secondosiblue flex justify-center items-center rounded-full text-white">
<p>{{recent_logged_in_customer.first_name|slice:":1"}}{{recent_logged_in_customer.last_name|slice:":1"}}
</p>
</div>
<div class="flex flex-col">
<p class="text-secondosiblue text-sm">{{recent_logged_in_customer.first_name}}
{{recent_logged_in_customer.last_name}}</p>
<p class="text-gray-500 text-sm">
{{recent_logged_in_customer.last_login|date:"g:i A"}}</p>
</div>
</div>
{% endfor %}
</div>
</div>
<div class="w-full hidden recentltLoggedStaffsContainer">
<div class="w-full rounded-md bg-gray-200 grid grid-cols-2 shadow-sm">
<button
class="w-full rounded-md text-secondosiblue text-sm cursor-pointer p-2 customerButton">Customers</button>
<button
class="w-full bg-white rounded-md text-secondosiblue text-sm cursor-pointer p-2 staffButton"
style="box-shadow: 0 0 6px rgba(88, 88, 88, 0.043), 6px 0 6px rgba(88, 88, 88, 0.043), 0 6px 6px rgba(88, 88, 88, 0.043), -6px 0 6px rgba(88, 88, 88, 0.043);">Staffs</button>
</div>
<div class="w-full flex flex-col gap-3 mt-3">
{% for recent_logged_in_staff in recent_logged_in_staffs %}
<div class="w-full flex justify-start items-center gap-2">
<div class="relative">
<div class="w-[40px] h-[40px] rounded-full">
<img src="{{recent_logged_in_staff.staffprofile.image.url}}"
class="w-full h-full object-cover rounded-full">
</div>
{% if recent_logged_in_staff.staffprofile in online_staff_profiles %}
<div
class="w-[12px] h-[12px] absolute rounded-full bg-green-600 bottom-0 right-0 border-2 border-white">
</div>
{% else %}
<div
class="w-[12px] h-[12px] absolute rounded-full bg-red-500 bottom-0 right-0 border-2 border-white">
</div>
{% endif %}
</div>
<div class="flex flex-col">
<p class="text-secondosiblue text-sm">{{recent_logged_in_staff.first_name}}
{{recent_logged_in_staff.last_name}}</p>
<p class="text-gray-500 text-sm">{{recent_logged_in_staff.last_login|date:"g:i A"}}</p>
</div>
</div>
{% endfor %}
</div>
</div>
</div>
</div>
</div>
<!-- CONNECTED USERS / RECENTLY LOGGED IN ON MOBILE -->
<div class="grid grid-cols-1 s:grid-cols-2 gap-5 px-5 s:px-9 pb-5 xxlg1:hidden">
<!-- CONNECTED USERS ON MOBILE -->
<div class="w-full bg-white shadow-md rounded-md p-5">
<div class="w-full h-full flex flex-col gap-3 items-center">
<div class="w-full flex justify-center items-center">
<p class="text-[20px] text-secondosiblue font-bold text-center">
Connected Users
</p>
</div>
<div class="w-full flex flex-wrap gap-4">
{% for online in online_staff_profiles %}
<div class="flex flex-col justify-center items-center gap-1">
<div class="w-[30px] h-[30px] rounded-full">
<img src="{{online.image.url}}" alt="User Image"
class="w-full h-full rounded-full object-cover">
</div>
<p class="text-gray-500 text-[10px] font-light">{{online.user.first_name}}</p>
</div>
{% endfor %}
</div>
</div>
</div>
<!-- RECENTLY LOGGED IN ON MOBILE -->
<div class="grid grid-cols-1 s:grid-cols-2 gap-5 px-5 s:px-9 pb-5 xxlg1:hidden connected-users">
<!-- RECENTLY LOGGED IN USERS ON MOBILE -->
<div
class="w-full flex flex-col justify-center items-center gap-3 bg-white shadow-md rounded-md p-5 logged-in-container">
<div class="w-full flex justify-center items-center">
<p class="text-[20px] text-secondosiblue font-bold text-center">Recently Logged In</p>
</div>
<div class="w-full recentltLoggedCustomersContainer">
<div class="w-full rounded-md bg-gray-200 grid grid-cols-2 shadow-sm">
<button
class="w-full bg-white rounded-md text-secondosiblue text-sm cursor-pointer p-2 customerButton"
style="box-shadow: 0 0 6px rgba(88, 88, 88, 0.043), 6px 0 6px rgba(88, 88, 88, 0.043), 0 6px 6px rgba(88, 88, 88, 0.043), -6px 0 6px rgba(88, 88, 88, 0.043);">Customers</button>
<button
class="w-full text-secondosiblue text-sm cursor-pointer p-2 staffButton">Staffs</button>
</div>
<div class="w-full mt-3 flex flex-col gap-3 recentltLoggedCustomers">
{% for recent_logged_in_customer in recent_logged_in_customers %}
<div class="w-full flex justify-start items-center gap-2">
<div
class="w-[40px] h-[40px] bg-secondosiblue flex justify-center items-center rounded-full text-white">
<p>{{recent_logged_in_customer.first_name|slice:":1"}}{{recent_logged_in_customer.last_name|slice:":1"}}
</p>
</div>
<div class="flex flex-col">
<p class="text-secondosiblue text-sm">{{recent_logged_in_customer.first_name}}
{{recent_logged_in_customer.last_name}}</p>
<p class="text-gray-500 text-sm">
{{recent_logged_in_customer.last_login|date:"g:i A"}}</p>
</div>
</div>
{% endfor %}
</div>
</div>
<div class="w-full hidden recentltLoggedStaffsContainer">
<div class="w-full rounded-md bg-gray-200 grid grid-cols-2 shadow-sm">
<button
class="w-full rounded-md text-secondosiblue text-sm cursor-pointer p-2 customerButton">Customers</button>
<button
class="w-full bg-white rounded-md text-secondosiblue text-sm cursor-pointer p-2 staffButton"
style="box-shadow: 0 0 6px rgba(88, 88, 88, 0.043), 6px 0 6px rgba(88, 88, 88, 0.043), 0 6px 6px rgba(88, 88, 88, 0.043), -6px 0 6px rgba(88, 88, 88, 0.043);">Staffs</button>
</div>
<div class="w-full flex flex-col gap-3 mt-3">
{% for recent_logged_in_staff in recent_logged_in_staffs %}
<div class="w-full flex justify-start items-center gap-2">
<div class="relative">
<div class="w-[40px] h-[40px] rounded-full">
<img src="{{recent_logged_in_staff.staffprofile.image.url}}"
class="w-full h-full object-cover rounded-full">
</div>
{% if recent_logged_in_staff.staffprofile in online_staff_profiles %}
<div
class="w-[12px] h-[12px] absolute rounded-full bg-green-600 bottom-0 right-0 border-2 border-white">
</div>
{% else %}
<div
class="w-[12px] h-[12px] absolute rounded-full bg-red-500 bottom-0 right-0 border-2 border-white">
</div>
{% endif %}
</div>
<div class="flex flex-col">
<p class="text-secondosiblue text-sm">{{recent_logged_in_staff.first_name}}
{{recent_logged_in_staff.last_name}}</p>
<p class="text-gray-500 text-sm">
{{recent_logged_in_staff.last_login|date:"g:i A"}}</p>
</div>
</div>
{% endfor %}
</div>
</div>
</div>
{% include 'details_templates/partials/recently-online.html' %}
</div>
<!-- MOBILE FOOTER -->
@ -1398,9 +1217,15 @@
</div>
</div>
<script type="module" src='{% static "js/pop-modals.js" %}'></script>
<!---------------------- JS SCRIPTS -------------------->
<!-- SIDE BAR SCRIPT -->
<script type="text/javascript" src='{% static "js/online/online-consumer.js" %}'></script>
<!-- SIDE BAR SCRIPT -->
<script type="text/javascript" src='{% static "js/side-bar.js" %}'></script>
@ -1431,9 +1256,6 @@
<!-- NOTIFICATIONS SIDE BAR -->
<script type="text/javascript" src='{% static "js/notifications-side-bar.js" %}'></script>
<!-- TO SWITCH BETWEEN THE CUSTOMERS AND STAFFS TABS IN THE RECENTLY LOGGED IN CONTAINER -->
<script type="text/javascript" src='{% static "js/recently-logged-in-users.js" %}'></script>
<!-- MODULES DROP DOWN ON MOBILE -->
<script type="text/javascript" src='{% static "js/accessibilities-dropdown.js" %}'></script>
</body>

@ -54,7 +54,6 @@ def signin(request):
if user is not None:
login(request, user)
Connection.objects.create(status='Online', date=datetime.now(), user=user)
if next_page:
return redirect(next_page)
else:
@ -205,7 +204,7 @@ def home(request, *args, **kwargs):
@staff_login_required
def status_mobile_modal (request, *args, **kwargs):
def status_mobile_modal(request, *args, **kwargs):
context = {
}
@ -733,7 +732,7 @@ def get_updated_last_status(request):
'hours_minutes_ago': hours_minutes_ago,
}
recent_status = render_to_string('recent-status.html', response_data)
recent_status = render_to_string('details_templates/partials/recent-status.html', response_data)
return HttpResponse(recent_status)
@ -741,31 +740,6 @@ def get_updated_last_status(request):
# TO GET USER ACTIVITIES
@staff_login_required
def get_latest_activities(request):
latest_connections = Connection.objects.filter(
user__staffprofile__isnull=False
).values('user').annotate(
latest_connection=Max('date')
)
online_staff_profiles = []
for connection in latest_connections:
user_id = connection['user']
latest_connection = connection['latest_connection']
last_connection = Connection.objects.filter(user_id=user_id, date=latest_connection).first()
if last_connection.status == 'Online':
online_staff_profiles.append(last_connection.user.staffprofile)
if request.user.is_authenticated and request.user.is_superuser:
open_task_count = Task.objects.filter(status='Open').count()
working_on_task_count = Task.objects.filter(status='Working On').count()
elif request.user.is_authenticated:
open_task_count = Task.objects.filter(assigned_to=request.user.staffprofile, status='Open').count()
working_on_task_count = Task.objects.filter(assigned_to=request.user.staffprofile, status='Working On').count()
else:
open_task_count = 0
working_on_task_count = 0
total_tasks = open_task_count + working_on_task_count
today = datetime.now().date()
@ -776,9 +750,8 @@ def get_latest_activities(request):
latest_statuses_time_ago = [{'status': status, 'time_ago': calculate_time_ago(status)} for status in latest_statuses]
response_data = {
'total_tasks': total_tasks,
'latest_statuses_time_ago': latest_statuses_time_ago,
'online_staff_profiles' : online_staff_profiles,
}
recent_activities = render_to_string('recent-activities.html', response_data)

@ -13,7 +13,7 @@ from django.core.asgi import get_asgi_application
from channels.routing import ProtocolTypeRouter, URLRouter
from channels.security.websocket import AllowedHostsOriginValidator
from channels.auth import AuthMiddlewareStack
from support import routing
from osinaweb.routing import websocket_urlpatterns
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'osinaweb.settings')
@ -23,7 +23,7 @@ django_asgi_app = get_asgi_application()
application = ProtocolTypeRouter({
"http": django_asgi_app,
"websocket": AllowedHostsOriginValidator(
AuthMiddlewareStack(URLRouter(routing.websocket_urlpatterns))
AuthMiddlewareStack(URLRouter(websocket_urlpatterns))
),
})

@ -0,0 +1,4 @@
from support.routing import websocket_urlpatterns as support_websocket_urlpatterns
from osinacore.routing import websocket_urlpatterns as osinacore_websocket_urlpatterns
websocket_urlpatterns = support_websocket_urlpatterns + osinacore_websocket_urlpatterns

Binary file not shown.

After

Width:  |  Height:  |  Size: 711 KiB

@ -0,0 +1,67 @@
document.addEventListener("DOMContentLoaded", function () {
const ws_scheme = window.location.protocol === "https:" ? "wss" : "ws";
const webSocketUrl = `${ws_scheme}://${window.location.host}/ws/online-users/`;
const webSocket = new WebSocket(webSocketUrl);
webSocket.onopen = function (event) {
console.log("WebSocket connection to online established");
};
webSocket.onmessage = function (event) {
const data = JSON.parse(event.data);
if (data.event_type === "online_user_status") {
// Update connected users containers
const connectedUsersContainers = document.querySelectorAll(".connected-users");
connectedUsersContainers.forEach(container => {
container.innerHTML = data.html;
});
// Rebind event listeners to switch between containers
const customerButtons = document.querySelectorAll('.customerButton');
const staffButtons = document.querySelectorAll('.staffButton');
const customerContainers = document.querySelectorAll('.recentltLoggedCustomersContainer');
const staffContainers = document.querySelectorAll('.recentltLoggedStaffsContainer');
customerButtons.forEach(button => {
button.addEventListener('click', function () {
customerContainers.forEach(container => container.classList.remove('hidden'));
staffContainers.forEach(container => container.classList.add('hidden'));
});
});
staffButtons.forEach(button => {
button.addEventListener('click', function () {
staffContainers.forEach(container => container.classList.remove('hidden'));
customerContainers.forEach(container => container.classList.add('hidden'));
});
});
const onlineUsersIds = data.online_users_ids || [];
console.log(onlineUsersIds);
// Update user activity containers based on online status
const userActivityContainers = document.querySelectorAll(".users-activities");
userActivityContainers.forEach(container => {
const userId = container.getAttribute("data-userId");
console.log(userId);
if (onlineUsersIds.map(id => id.toString()).includes(userId)) {
container.querySelector("#connected").classList.remove("hidden");
container.querySelector("#not-connected").classList.add("hidden");
} else {
container.querySelector("#connected").classList.add("hidden");
container.querySelector("#not-connected").classList.remove("hidden");
}
});
}
};
webSocket.onclose = function (event) {
console.log("WebSocket connection to online closed");
};
webSocket.onerror = function (error) {
console.error("WebSocket error:", error);
};
});

@ -1,20 +0,0 @@
document.addEventListener('DOMContentLoaded', function () {
const customerButtons = document.querySelectorAll('.customerButton');
const staffButtons = document.querySelectorAll('.staffButton');
const customerContainers = document.querySelectorAll('.recentltLoggedCustomersContainer');
const staffContainers = document.querySelectorAll('.recentltLoggedStaffsContainer');
customerButtons.forEach(button => {
button.addEventListener('click', function () {
customerContainers.forEach(container => container.classList.remove('hidden'));
staffContainers.forEach(container => container.classList.add('hidden'));
});
});
staffButtons.forEach(button => {
button.addEventListener('click', function () {
staffContainers.forEach(container => container.classList.remove('hidden'));
customerContainers.forEach(container => container.classList.add('hidden'));
});
});
});
Loading…
Cancel
Save