From d8828d487a9e86a1a014b3aece3489aee7cdfe78 Mon Sep 17 00:00:00 2001 From: NguyenND Date: Fri, 27 Mar 2026 10:48:28 -0400 Subject: [PATCH] Fix ticket details page, comments updated real-time --- app/routes/api.py | 39 +++++ app/services/notification_service.py | 23 +++ app/templates/tickets/dashboard_it.html | 13 +- app/templates/tickets/detail.html | 209 +++++++++++++++++++++++- 4 files changed, 275 insertions(+), 9 deletions(-) diff --git a/app/routes/api.py b/app/routes/api.py index 3d6cfbd..2da07a6 100644 --- a/app/routes/api.py +++ b/app/routes/api.py @@ -59,6 +59,45 @@ def mark_all_read(): return jsonify({'ok': True}) +# ─── Ticket Comments API ────────────────────────────────────────────────────── + +@api_bp.route('/tickets//comments') +@login_required +def get_comments(ticket_id): + """Return all visible comments for a ticket as JSON.""" + from app.models import Ticket, Comment, UserRole + ticket = Ticket.query.get_or_404(ticket_id) + # Employees may only see their own tickets + if not current_user.is_it_staff and ticket.created_by_id != current_user.id: + return jsonify({'error': 'Forbidden'}), 403 + + q = Comment.query.filter_by(ticket_id=ticket_id) + if not current_user.is_it_staff: + q = q.filter_by(is_internal=False) + comments = q.order_by(Comment.created_at.asc()).all() + + return jsonify({'comments': [ + { + 'id' : c.id, + 'author_name': c.author.full_name, + 'author_init': c.author.full_name[0].upper(), + 'is_it_staff': c.author.is_it_staff, + 'is_internal': c.is_internal, + 'body' : c.body, + 'created_at' : c.created_at.strftime('%b %d, %Y %H:%M'), + 'can_delete' : current_user.is_it_staff or c.author_id == current_user.id, + 'attachments': [ + { + 'id' : a.id, + 'filename': a.filename, + } + for a in c.attachments.all() + ], + } + for c in comments + ]}) + + # ─── Ticket Stats API (IT) ──────────────────────────────────────────────────── @api_bp.route('/stats/tickets') diff --git a/app/services/notification_service.py b/app/services/notification_service.py index 031633a..7dd0e06 100644 --- a/app/services/notification_service.py +++ b/app/services/notification_service.py @@ -214,6 +214,29 @@ def notify_comment_added(comment): base_url = current_app.config.get('APP_BASE_URL', '') ticket_url = f"{base_url}/tickets/{ticket.id}" + # ── Real-time push to everyone viewing this ticket ──────────────────────── + # Emit to the ticket room so all users currently on the ticket detail page + # receive the new comment immediately without needing to reload. + payload = { + 'id' : comment.id, + 'author_name': comment.author.full_name, + 'author_init': comment.author.full_name[0].upper(), + 'is_it_staff': comment.author.is_it_staff, + 'is_internal': comment.is_internal, + 'body' : comment.body, + 'created_at' : comment.created_at.strftime('%b %d, %Y %H:%M'), + 'author_id' : comment.author_id, + } + def _emit_comment(): + socketio.emit( + 'new_comment', + payload, + to = f'ticket_{ticket.id}', + namespace = '/', + ) + socketio.start_background_task(_emit_comment) + # ───────────────────────────────────────────────────────────────────────── + notified = set() def _notify(user_id, is_internal=False): diff --git a/app/templates/tickets/dashboard_it.html b/app/templates/tickets/dashboard_it.html index 3a30019..2f5d54b 100644 --- a/app/templates/tickets/dashboard_it.html +++ b/app/templates/tickets/dashboard_it.html @@ -67,14 +67,21 @@
- + {% for t in recent_tickets %} - + + {% endfor %} @@ -101,4 +108,4 @@ -{% endblock %} +{% endblock %} \ No newline at end of file diff --git a/app/templates/tickets/detail.html b/app/templates/tickets/detail.html index 8203e95..401fb29 100644 --- a/app/templates/tickets/detail.html +++ b/app/templates/tickets/detail.html @@ -64,10 +64,15 @@
Comments - ({{ comments|length }}) + ({{ comments|length }})
+
+
{% for comment in comments %}
@@ -98,7 +103,6 @@
{{ comment.body }}
- {% set c_atts = comment.attachments.all() %} {% if c_atts %}
@@ -111,21 +115,22 @@ {% endif %}
{% else %} -
+
No comments yet. Be the first to add an update.
{% endfor %} +
{% if ticket.status not in ('closed',) %}
Add Comment
-
+
-
@@ -141,13 +146,205 @@
{% endif %} -
{% endif %} + + + +
Ticket #UserCategoryPriority
Ticket #UserPriorityStatusAssignee
{{ t.ticket_number }} {{ t.creator.full_name.split()[0] }}{{ t.category.replace('_',' ').title() }} {{ t.priority.upper() }}{{ t.status.replace('_',' ').upper() }} + {% if t.assignee %} + {{ t.assignee.full_name.split()[0] }} + {% else %} + Unassigned + {% endif %} +