diff --git a/osinaweb/customercore/__pycache__/models.cpython-310.pyc b/osinaweb/customercore/__pycache__/models.cpython-310.pyc index 3c19e301..7f1e0dc9 100644 Binary files a/osinaweb/customercore/__pycache__/models.cpython-310.pyc and b/osinaweb/customercore/__pycache__/models.cpython-310.pyc differ diff --git a/osinaweb/customercore/models.py b/osinaweb/customercore/models.py index fd01b2a6..78e59a15 100644 --- a/osinaweb/customercore/models.py +++ b/osinaweb/customercore/models.py @@ -41,16 +41,6 @@ class Ticket(models.Model): super().save(*args, **kwargs) -class TicketStatus(models.Model): - STATUS_CHOICES = ( - ('Open', 'Open'), - ('Working On', 'Working On'), - ('Closed', 'Closed'), - ) - ticket = models.ForeignKey(Ticket, on_delete=models.CASCADE) - status = models.CharField(max_length=50, choices=STATUS_CHOICES, null=True) - added_by = models.ForeignKey(User, on_delete=models.SET_NULL, null=True) - date_added = models.DateTimeField() class TicketStatus(models.Model): STATUS_CHOICES = ( ('Open', 'Open'), @@ -80,7 +70,7 @@ class TicketAttachment(models.Model): ticket_update = models.ForeignKey(TicketUpdate, on_delete=models.CASCADE, null=True, blank=True) file_path = models.CharField(max_length=255, null=True) - + class TicketUpdateReaction(models.Model): REACTION_CHOICES = ( ('Happy', 'Happy'), diff --git a/osinaweb/db.sqlite3 b/osinaweb/db.sqlite3 index 530b13e4..2b2aec04 100644 Binary files a/osinaweb/db.sqlite3 and b/osinaweb/db.sqlite3 differ diff --git a/osinaweb/osinacore/.DS_Store b/osinaweb/osinacore/.DS_Store index 8aa27d25..7ee74078 100644 Binary files a/osinaweb/osinacore/.DS_Store and b/osinaweb/osinacore/.DS_Store differ diff --git a/osinaweb/osinacore/__pycache__/consumers.cpython-310.pyc b/osinaweb/osinacore/__pycache__/consumers.cpython-310.pyc new file mode 100644 index 00000000..fd3c9920 Binary files /dev/null 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 1138dba7..99a3e2a7 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 new file mode 100644 index 00000000..eb8a776e Binary files /dev/null and b/osinaweb/osinacore/__pycache__/routing.cpython-310.pyc differ diff --git a/osinaweb/osinacore/consumers.py b/osinaweb/osinacore/consumers.py new file mode 100644 index 00000000..f4d27f77 --- /dev/null +++ b/osinaweb/osinacore/consumers.py @@ -0,0 +1,99 @@ +from channels.generic.websocket import WebsocketConsumer +from django.shortcuts import get_object_or_404 +from customercore.models import * +import json +from django.template.loader import render_to_string +from asgiref.sync import async_to_sync +from channels.generic.websocket import WebsocketConsumer +from django.shortcuts import get_object_or_404 +from customercore.models import * +import json +from django.template.loader import render_to_string +from asgiref.sync import async_to_sync + + +class TicketRoomConsumer(WebsocketConsumer): + 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_number = self.ticket.ticket_number + async_to_sync(self.channel_layer.group_add)( + self.ticket_number, self.channel_name + ) + self.accept() + + def disconnect(self, close_code): + async_to_sync(self.channel_layer.group_discard)( + self.ticket_number, self.channel_name + ) + + 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 + ) + elif event_type == 'stop_typing': + event = { + 'type': 'stop_typing_handler', + } + async_to_sync(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( + added_by=self.user, + description=body, + ticket=self.ticket, + date_added=datetime.now() + ) + for file_path in file_paths: + ticket_attachment = TicketAttachment( + ticket_update=ticketupdate, + file_path=file_path + ) + ticket_attachment.save() + event = { + 'type': 'update_handler', + 'update_id': ticketupdate.id + } + async_to_sync(self.channel_layer.group_send)( + self.ticket_number, event + ) + + def update_handler(self, event): + update_id = event['update_id'] + update = TicketUpdate.objects.get(id=update_id) + context = { + 'update': update, + 'user': self.user + } + html = render_to_string("details_templates/new-ticket-message.html", context=context) + self.send(text_data=json.dumps({ + 'event_type': 'update', + 'html': html + })) + + def typing_handler(self, event): + context = { + 'user': event['user'] + } + html = render_to_string("details_templates/typing-message.html", context=context) + self.send(text_data=json.dumps({ + 'event_type': 'typing', + 'html': html + })) + + def stop_typing_handler(self, event): + self.send(text_data=json.dumps({ + 'event_type': 'stop_typing' + })) diff --git a/osinaweb/osinacore/models.py b/osinaweb/osinacore/models.py index 2599f2cd..506623d2 100644 --- a/osinaweb/osinacore/models.py +++ b/osinaweb/osinacore/models.py @@ -211,10 +211,6 @@ class PinnedProject(models.Model): project = models.ForeignKey(Project, on_delete=models.CASCADE) -class PinnedProject(models.Model): - user = models.ForeignKey(User, on_delete=models.CASCADE) - project = models.ForeignKey(Project, on_delete=models.CASCADE) - class Milestone(models.Model): diff --git a/osinaweb/osinacore/routing.py b/osinaweb/osinacore/routing.py new file mode 100644 index 00000000..727f7416 --- /dev/null +++ b/osinaweb/osinacore/routing.py @@ -0,0 +1,8 @@ +from django.urls import path +from .consumers import * + +websocket_urlpatterns = [ + path("ws/ticketroom//", TicketRoomConsumer.as_asgi()), + + +] \ No newline at end of file diff --git a/osinaweb/osinacore/templates/.DS_Store b/osinaweb/osinacore/templates/.DS_Store index 3cfc3f62..4cf847ab 100644 Binary files a/osinaweb/osinacore/templates/.DS_Store and b/osinaweb/osinacore/templates/.DS_Store differ diff --git a/osinaweb/osinacore/templates/details_templates/new-ticket-message.html b/osinaweb/osinacore/templates/details_templates/new-ticket-message.html new file mode 100644 index 00000000..4614be03 --- /dev/null +++ b/osinaweb/osinacore/templates/details_templates/new-ticket-message.html @@ -0,0 +1,19 @@ +
+ +
+ {% include 'details_templates/ticket-message.html' %} +
+ + + + +
+ \ No newline at end of file diff --git a/osinaweb/osinacore/templates/details_templates/ticket-details.html b/osinaweb/osinacore/templates/details_templates/ticket-details.html index 50624d68..01b0a71c 100644 --- a/osinaweb/osinacore/templates/details_templates/ticket-details.html +++ b/osinaweb/osinacore/templates/details_templates/ticket-details.html @@ -7,7 +7,9 @@ @import url(https://cdnjs.cloudflare.com/ajax/libs/MaterialDesign-Webfont/5.3.45/css/materialdesignicons.min.css); - + + +
@@ -72,83 +74,20 @@
-
+
- {% for update in ticket_updates %} -
-
-
- {% if update.added_by.customerprofile %} - {% if update.added_by.customerprofile.image %} - - {% else %} -
- {{ update.added_by.first_name.0 }}{{ update.added_by.last_name.0 }} -
- {% endif %} - {% elif update.added_by.staffprofile %} - {% if update.added_by.staffprofile.image %} - - {% else %} -
- {{ update.added_by.first_name.0 }}{{ update.added_by.last_name.0 }} -
- {% endif %} - {% endif %} -
-
- - -
-
-

{{update.added_by.first_name}} - replied {{update.date_added}}

- - - - - - -
- -
- {{update.description | safe }} - - {% if update.ticketattachment_set.all %} -
- {% for file in update.ticketattachment_set.all %} - - {% endfor %} -
- {% endif %} - -
-
+
+ {% for update in ticket_updates %} + {% include 'details_templates/ticket-message.html' %} + {% endfor %}
- {% endfor %} + +
-
{% csrf_token %}
@@ -178,104 +117,9 @@
-
-
-
- - - - - - - - - - - - -
-
- -
-
-
- -
@@ -308,7 +152,92 @@
+ + +
+ + + + +
@@ -427,6 +356,7 @@
+ @@ -434,4 +364,5 @@ + {% endblock %} \ No newline at end of file diff --git a/osinaweb/osinacore/templates/details_templates/ticket-message.html b/osinaweb/osinacore/templates/details_templates/ticket-message.html new file mode 100644 index 00000000..1e7c337d --- /dev/null +++ b/osinaweb/osinacore/templates/details_templates/ticket-message.html @@ -0,0 +1,69 @@ +
+
+
+ {% if update.added_by.customerprofile %} + {% if update.added_by.customerprofile.image %} + + {% else %} +
+ {{ update.added_by.first_name.0 }}{{ update.added_by.last_name.0 }} +
+ {% endif %} + {% elif update.added_by.staffprofile %} + {% if update.added_by.staffprofile.image %} + + {% else %} +
+ {{ update.added_by.first_name.0 }}{{ update.added_by.last_name.0 }} +
+ {% endif %} + {% endif %} +
+
+ + +
+
+

{{update.added_by.first_name}} + replied {{update.date_added}}

+ + + + + + + +
+ +
+ {{update.description | safe }} + + {% if update.ticketattachment_set.all %} +
+ {% for file in update.ticketattachment_set.all %} + + {% endfor %} +
+ {% endif %} + +
+
+
\ No newline at end of file diff --git a/osinaweb/osinacore/templates/details_templates/typing-message.html b/osinaweb/osinacore/templates/details_templates/typing-message.html new file mode 100644 index 00000000..489bbfa3 --- /dev/null +++ b/osinaweb/osinacore/templates/details_templates/typing-message.html @@ -0,0 +1,36 @@ +
+
+
+ {% if user.customerprofile %} + {% if user.customerprofile.image %} + + {% else %} +
+ {{ user.first_name.0 }}{{ user.last_name.0 }} +
+ {% endif %} + {% elif user.staffprofile %} + {% if user.staffprofile.image %} + + {% else %} +
+ {{ user.first_name.0 }}{{ user.last_name.0 }} +
+ {% endif %} + {% endif %} +
+
+ + +
+
+

{{user.first_name}} is typing...

+
+
+
\ No newline at end of file diff --git a/osinaweb/osinaweb/__pycache__/asgi.cpython-310.pyc b/osinaweb/osinaweb/__pycache__/asgi.cpython-310.pyc new file mode 100644 index 00000000..5e557c39 Binary files /dev/null and b/osinaweb/osinaweb/__pycache__/asgi.cpython-310.pyc differ diff --git a/osinaweb/osinaweb/__pycache__/settings.cpython-310.pyc b/osinaweb/osinaweb/__pycache__/settings.cpython-310.pyc index 973a59ec..f8c5649f 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/asgi.py b/osinaweb/osinaweb/asgi.py index 1d67619f..a28116cd 100644 --- a/osinaweb/osinaweb/asgi.py +++ b/osinaweb/osinaweb/asgi.py @@ -10,7 +10,21 @@ https://docs.djangoproject.com/en/4.1/howto/deployment/asgi/ import os 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 osinacore import routing + os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'osinaweb.settings') -application = get_asgi_application() +django_asgi_app = get_asgi_application() + +application = ProtocolTypeRouter({ + "http": django_asgi_app, + "websocket": AllowedHostsOriginValidator( + AuthMiddlewareStack(URLRouter(routing.websocket_urlpatterns)) + ), +}) + + diff --git a/osinaweb/osinaweb/settings.py b/osinaweb/osinaweb/settings.py index 76480180..62bf51d7 100644 --- a/osinaweb/osinaweb/settings.py +++ b/osinaweb/osinaweb/settings.py @@ -40,6 +40,7 @@ LOGIN_URL = 'signin' # Application definition INSTALLED_APPS = [ + 'daphne', 'rest_framework', 'osinacore', 'customercore', @@ -89,7 +90,13 @@ TEMPLATES = [ }, ] -WSGI_APPLICATION = 'osinaweb.wsgi.application' +ASGI_APPLICATION = 'osinaweb.asgi.application' + +CHANNEL_LAYERS = { + 'default':{ + "BACKEND": "channels.layers.InMemoryChannelLayer", + } +} # Database diff --git a/osinaweb/static/dist/output.css b/osinaweb/static/dist/output.css index 84e331db..c0626453 100644 --- a/osinaweb/static/dist/output.css +++ b/osinaweb/static/dist/output.css @@ -1,5 +1,5 @@ /* -! tailwindcss v3.4.1 | MIT License | https://tailwindcss.com +! tailwindcss v3.3.3 | MIT License | https://tailwindcss.com */ /* @@ -32,11 +32,9 @@ 4. Use the user's configured `sans` font-family by default. 5. Use the user's configured `sans` font-feature-settings by default. 6. Use the user's configured `sans` font-variation-settings by default. -7. Disable tap highlights on iOS */ -html, -:host { +html { line-height: 1.5; /* 1 */ -webkit-text-size-adjust: 100%; @@ -46,14 +44,12 @@ html, -o-tab-size: 4; tab-size: 4; /* 3 */ - font-family: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; + font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; /* 4 */ font-feature-settings: normal; /* 5 */ font-variation-settings: normal; /* 6 */ - -webkit-tap-highlight-color: transparent; - /* 7 */ } /* @@ -125,10 +121,8 @@ strong { } /* -1. Use the user's configured `mono` font-family by default. -2. Use the user's configured `mono` font-feature-settings by default. -3. Use the user's configured `mono` font-variation-settings by default. -4. Correct the odd `em` font sizing in all browsers. +1. Use the user's configured `mono` font family by default. +2. Correct the odd `em` font sizing in all browsers. */ code, @@ -137,12 +131,8 @@ samp, pre { font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; /* 1 */ - font-feature-settings: normal; - /* 2 */ - font-variation-settings: normal; - /* 3 */ font-size: 1em; - /* 4 */ + /* 2 */ } /* @@ -1003,7 +993,8 @@ video { } .ms-0 { - margin-inline-start: 0px; + -webkit-margin-start: 0px; + margin-inline-start: 0px; } .mt-0 { @@ -1549,10 +1540,6 @@ video { width: 100%; } -.min-w-full { - min-width: 100%; -} - .min-w-\[250px\] { min-width: 250px; } @@ -1561,8 +1548,12 @@ video { min-width: 300px; } +.min-w-full { + min-width: 100%; +} + .max-w-0 { - max-width: 0px; + max-width: 0rem; } .max-w-2xl { @@ -3790,6 +3781,13 @@ video { color: rgb(255 255 255 / var(--tw-text-opacity)); } +@media (prefers-color-scheme: dark) { + .dark\:text-gray-600 { + --tw-text-opacity: 1; + color: rgb(75 85 99 / var(--tw-text-opacity)); + } +} + @media (min-width: 550px) { .sm\:flex { display: flex; @@ -4337,11 +4335,4 @@ video { .xxl\:text-\[70px\] { font-size: 70px; } -} - -@media (prefers-color-scheme: dark) { - .dark\:text-gray-600 { - --tw-text-opacity: 1; - color: rgb(75 85 99 / var(--tw-text-opacity)); - } } \ No newline at end of file diff --git a/osinaweb/static/images/uploaded_ticket_files/F7E963E7-CB86-46A5-9F4F-1725EF0A6215.jpeg b/osinaweb/static/images/uploaded_ticket_files/F7E963E7-CB86-46A5-9F4F-1725EF0A6215.jpeg new file mode 100644 index 00000000..7de5735d Binary files /dev/null and b/osinaweb/static/images/uploaded_ticket_files/F7E963E7-CB86-46A5-9F4F-1725EF0A6215.jpeg differ diff --git a/osinaweb/static/images/uploaded_ticket_files/Screenshot 2024-06-20 at 9.32.29 AM.png b/osinaweb/static/images/uploaded_ticket_files/Screenshot 2024-06-20 at 9.32.29 AM.png new file mode 100644 index 00000000..c6e4f406 Binary files /dev/null and b/osinaweb/static/images/uploaded_ticket_files/Screenshot 2024-06-20 at 9.32.29 AM.png differ diff --git a/osinaweb/static/images/uploaded_ticket_files/cPanel Alternative Control Panel.docx b/osinaweb/static/images/uploaded_ticket_files/cPanel Alternative Control Panel.docx new file mode 100644 index 00000000..738faa99 Binary files /dev/null and b/osinaweb/static/images/uploaded_ticket_files/cPanel Alternative Control Panel.docx differ diff --git a/osinaweb/static/images/uploaded_ticket_files/cPanel Alternative Control Panel_1.docx b/osinaweb/static/images/uploaded_ticket_files/cPanel Alternative Control Panel_1.docx new file mode 100644 index 00000000..738faa99 Binary files /dev/null and b/osinaweb/static/images/uploaded_ticket_files/cPanel Alternative Control Panel_1.docx differ