diff --git a/osinaweb/db.sqlite3 b/osinaweb/db.sqlite3 index e2e8c161..77fbd39b 100644 Binary files a/osinaweb/db.sqlite3 and b/osinaweb/db.sqlite3 differ diff --git a/osinaweb/osinacore/__pycache__/consumers.cpython-310.pyc b/osinaweb/osinacore/__pycache__/consumers.cpython-310.pyc index a2c6de55..6ea27c69 100644 Binary files a/osinaweb/osinacore/__pycache__/consumers.cpython-310.pyc and b/osinaweb/osinacore/__pycache__/consumers.cpython-310.pyc differ diff --git a/osinaweb/osinacore/__pycache__/models.cpython-310.pyc b/osinaweb/osinacore/__pycache__/models.cpython-310.pyc index 011ae3a3..9bc99fcf 100644 Binary files a/osinaweb/osinacore/__pycache__/models.cpython-310.pyc and b/osinaweb/osinacore/__pycache__/models.cpython-310.pyc differ diff --git a/osinaweb/osinacore/__pycache__/routing.cpython-310.pyc b/osinaweb/osinacore/__pycache__/routing.cpython-310.pyc index 17c9ec1a..f1d97082 100644 Binary files a/osinaweb/osinacore/__pycache__/routing.cpython-310.pyc and b/osinaweb/osinacore/__pycache__/routing.cpython-310.pyc differ diff --git a/osinaweb/osinacore/__pycache__/urls.cpython-310.pyc b/osinaweb/osinacore/__pycache__/urls.cpython-310.pyc index ca94c75d..ee0e7cb6 100644 Binary files a/osinaweb/osinacore/__pycache__/urls.cpython-310.pyc and b/osinaweb/osinacore/__pycache__/urls.cpython-310.pyc differ diff --git a/osinaweb/osinacore/__pycache__/views.cpython-310.pyc b/osinaweb/osinacore/__pycache__/views.cpython-310.pyc index d5b16058..2cc12aca 100644 Binary files a/osinaweb/osinacore/__pycache__/views.cpython-310.pyc and b/osinaweb/osinacore/__pycache__/views.cpython-310.pyc differ diff --git a/osinaweb/osinacore/consumers.py b/osinaweb/osinacore/consumers.py index 394d4bd0..a3387881 100644 --- a/osinaweb/osinacore/consumers.py +++ b/osinaweb/osinacore/consumers.py @@ -77,3 +77,30 @@ class OnlineUserConsumer(WebsocketConsumer): 'html': html, 'online_users_ids': event.get('online_users_ids', []) })) + + + +class NewStatusConsumer(WebsocketConsumer): + def connect(self): + self.user = self.scope['user'] + async_to_sync(self.channel_layer.group_add)( + "new_status_group", + self.channel_name + ) + self.accept() + + def disconnect(self, close_code): + async_to_sync(self.channel_layer.group_discard)( + "new_status_group", + self.channel_name + ) + + def new_status_event(self, event): + status_id = event['status_id'] + status = Status.objects.get(id=status_id) + context = {'status': status, 'new': True} + html = render_to_string("details_templates/partials/new-status-activity.html", context) + self.send(text_data=json.dumps({ + 'event_type': 'new_status', + 'html': html, + })) diff --git a/osinaweb/osinacore/migrations/0096_status_date_time.py b/osinaweb/osinacore/migrations/0096_status_date_time.py new file mode 100644 index 00000000..cda895e3 --- /dev/null +++ b/osinaweb/osinacore/migrations/0096_status_date_time.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.5 on 2024-07-09 07:50 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('osinacore', '0095_delete_customuser'), + ] + + operations = [ + migrations.AddField( + model_name='status', + name='date_time', + field=models.DateTimeField(blank=True, null=True), + ), + ] diff --git a/osinaweb/osinacore/migrations/__pycache__/0096_status_date_time.cpython-310.pyc b/osinaweb/osinacore/migrations/__pycache__/0096_status_date_time.cpython-310.pyc new file mode 100644 index 00000000..5acdb584 Binary files /dev/null and b/osinaweb/osinacore/migrations/__pycache__/0096_status_date_time.cpython-310.pyc differ diff --git a/osinaweb/osinacore/models.py b/osinaweb/osinacore/models.py index 1ffa2079..a1338aba 100644 --- a/osinaweb/osinacore/models.py +++ b/osinaweb/osinacore/models.py @@ -6,6 +6,10 @@ from django.db.models import Max from django.utils import timezone from django.db.models import Sum, F from datetime import timedelta +from django.db.models.signals import post_save +from django.dispatch import receiver +from asgiref.sync import async_to_sync +from channels.layers import get_channel_layer # Create your models here. @@ -407,10 +411,23 @@ class Status(models.Model): time = models.CharField(max_length=40) staff = models.ForeignKey(StaffProfile, on_delete=models.CASCADE, null=True,blank=True, related_name='staff') task = models.ForeignKey(Task, on_delete=models.SET_NULL ,null=True, blank=True, related_name='reference_task') + date_time = models.DateTimeField(null=True, blank=True) def __str__(self): return self.text +@receiver(post_save, sender=Status) +def new_ticket_update_handler(sender, instance, created, **kwargs): + if created: + channel_layer = get_channel_layer() + event = { + 'type': 'new_status_event', + 'status_id': instance.id, + } + async_to_sync(channel_layer.group_send)("new_status_group", event) + + + class Reaction(models.Model): status = models.ForeignKey(Status, on_delete=models.CASCADE) emoji = models.CharField(max_length=15) diff --git a/osinaweb/osinacore/routing.py b/osinaweb/osinacore/routing.py index 30b01d3f..e28f87b4 100644 --- a/osinaweb/osinacore/routing.py +++ b/osinaweb/osinacore/routing.py @@ -3,6 +3,8 @@ from .consumers import * websocket_urlpatterns = [ path("ws/online-users/", OnlineUserConsumer.as_asgi()), + path("ws/new-statuses/", NewStatusConsumer.as_asgi()), + ] \ No newline at end of file diff --git a/osinaweb/osinacore/templates/details_templates/partials/new-status-activity.html b/osinaweb/osinacore/templates/details_templates/partials/new-status-activity.html new file mode 100644 index 00000000..32a8f0c9 --- /dev/null +++ b/osinaweb/osinacore/templates/details_templates/partials/new-status-activity.html @@ -0,0 +1,203 @@ +{% load static %} + + + + + + + + + + + + + +
+
+
+
+
+
+ user profile +
+ +
+
+
+
+
+ +
+

{{status.staff.user.first_name}} + {{status.staff.user.last_name}}

+ {% if status.time_ago == '0min ago' %} +

Just Now

+ {%else %} +

{{ status.time_ago}}

+ {%endif%} +
+
+ +
+
+ +
+
+
+ + +
+

{{status.text}}

+ + {% if status.task.project %} + +
+

{{status.task.project}}

+ + + +
+
+ {% endif %} + +
+ + +
+ + +
+ +
+
+ + diff --git a/osinaweb/osinacore/templates/details_templates/partials/recent-activities.html b/osinaweb/osinacore/templates/details_templates/partials/recent-activities.html index 3322d669..d89254bd 100644 --- a/osinaweb/osinacore/templates/details_templates/partials/recent-activities.html +++ b/osinaweb/osinacore/templates/details_templates/partials/recent-activities.html @@ -166,11 +166,7 @@
- {% if "Completed" in latest.status.text %} -

{{latest.status.text}}

- {% else %} -

{{latest.status.text}}

- {% endif %} +

{{latest.status.text}}

{% if latest.status.task.project %} diff --git a/osinaweb/osinacore/templates/index.html b/osinaweb/osinacore/templates/index.html index a5821156..0f416a5f 100644 --- a/osinaweb/osinacore/templates/index.html +++ b/osinaweb/osinacore/templates/index.html @@ -359,6 +359,9 @@ }; + + + {% endblock content %} \ No newline at end of file diff --git a/osinaweb/osinacore/templates/main.html b/osinaweb/osinacore/templates/main.html index 875021da..7fdc53f5 100644 --- a/osinaweb/osinacore/templates/main.html +++ b/osinaweb/osinacore/templates/main.html @@ -21,20 +21,7 @@ - - {% if user_offline %} -
-
-
-

You are Currently Offline

-
- -
-
- {% endif %}
@@ -1222,10 +1209,13 @@ + + + + - diff --git a/osinaweb/osinacore/templates/recent-activities-page.html b/osinaweb/osinacore/templates/recent-activities-page.html index 536b58dd..c476930e 100644 --- a/osinaweb/osinacore/templates/recent-activities-page.html +++ b/osinaweb/osinacore/templates/recent-activities-page.html @@ -14,20 +14,7 @@ - - {% if user_offline %} -
-
-
-

You are Currently Offline

-
- -
-
- {% endif %} @@ -723,7 +710,7 @@
- {% include 'recent-activities.html' %} + {% include 'details_templates/partials/recent-activities.html' %}
@@ -743,6 +730,9 @@
+ + + diff --git a/osinaweb/osinacore/urls.py b/osinaweb/osinacore/urls.py index 57466603..84aebf5a 100644 --- a/osinaweb/osinacore/urls.py +++ b/osinaweb/osinacore/urls.py @@ -83,7 +83,7 @@ urlpatterns = [ path('projects/status//', views.fetch_projects_by_status, name='projects_by_status'), path('all-projects/', views.fetch_projects_by_status, name='all_projects'), - path('delete-connections', views.delete_connections, name='delete-connections') + path('status-date/', views.update_all_date_time, name='update-status') ] urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) \ No newline at end of file diff --git a/osinaweb/osinacore/views.py b/osinaweb/osinacore/views.py index 626c1065..056b0a6d 100644 --- a/osinaweb/osinacore/views.py +++ b/osinaweb/osinacore/views.py @@ -879,5 +879,22 @@ def fetch_projects_by_status(request, status=None): -def delete_connections(request): - connections= Connection.objects.all().delete() \ No newline at end of file +from django.shortcuts import render +from django.http import HttpResponse +from django.utils.dateparse import parse_datetime + + +def update_all_date_time(request): + statuses = Status.objects.all() + for status in statuses: + if status.date and status.time: + date_str = f"{status.date} {status.time}" + try: + date_time_obj = datetime.strptime(date_str, "%Y-%m-%d %I:%M %p") + status.date_time = date_time_obj + status.save() + except ValueError as e: + # Handle any errors in date/time parsing + print(f"Error parsing date/time for status {status.id}: {e}") + + return JsonResponse({"status": "success", "message": "DateTime fields updated for all statuses."}) \ No newline at end of file diff --git a/osinaweb/osinaweb/__pycache__/settings.cpython-310.pyc b/osinaweb/osinaweb/__pycache__/settings.cpython-310.pyc index e471f152..f6eb4c1d 100644 Binary files a/osinaweb/osinaweb/__pycache__/settings.cpython-310.pyc and b/osinaweb/osinaweb/__pycache__/settings.cpython-310.pyc differ diff --git a/osinaweb/osinaweb/settings.py b/osinaweb/osinaweb/settings.py index eba5bddc..31ff1d42 100644 --- a/osinaweb/osinaweb/settings.py +++ b/osinaweb/osinaweb/settings.py @@ -160,7 +160,7 @@ DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' EMAIL_HOST = 'osinamail.ositcom.com' EMAIL_PORT = 587 -EMAIL_HOST_USER = 'osina@ositcom.com' +EMAIL_HOST_USER = 'osina@eositcom.com' DEFAULT_FROM_EMAIL = 'osina@ositcom.com' EMAIL_HOST_PASSWORD = 'EMILEselim!@67' EMAIL_USE_TLS = True diff --git a/osinaweb/static/js/status/new-status-consumer.js b/osinaweb/static/js/status/new-status-consumer.js new file mode 100644 index 00000000..34d88ba7 --- /dev/null +++ b/osinaweb/static/js/status/new-status-consumer.js @@ -0,0 +1,27 @@ +// WebSocket connection for new statuses + const ws_theme = window.location.protocol === "https:" ? "wss" : "ws"; + const newStatusesSocketUrl = `${ws_theme}://${window.location.host}/ws/new-statuses/`; + const newStatusesSocket = new WebSocket(newStatusesSocketUrl); + + newStatusesSocket.onopen = () => { + console.log('WebSocket connection to new statuses established'); + }; + newStatusesSocket.onmessage = function(e) { + const data = JSON.parse(e.data); + if (data.event_type === 'new_status') { + const activityDiv = document.getElementById('activitiesContainer'); + console.log(activityDiv); + activityDiv.insertAdjacentHTML('afterbegin', data.html); + } + }; + + newStatusesSocket.onclose = () => { + console.log('WebSocket connection to new statuses closed'); + }; + + newStatusesSocket.onerror = (error) => { + console.log('WebSocket error:', error); + }; + + +