Ticket Comments System¶
Version: Arctyk ITSM v0.6.0+
Last Updated: January 2026
Overview¶
The Ticket Comments System in Arctyk ITSM provides a comprehensive two-tier communication system for tickets, enabling both public discussions and internal notes. The system features real-time AJAX updates, rich text editing with TinyMCE, inline editing, and complete audit trails.
Key Features:
- 🔓 Public Comments - Visible to all users with ticket access
- 🔒 Internal Notes - Restricted to staff and assignees only
- ✏️ Inline Editing - Edit comments in place with full revision history
- 🗑️ Soft Deletion - Comments are marked as deleted, not removed
- 📝 Rich Text - Full TinyMCE editor with formatting, lists, links, tables
- 🚀 AJAX Operations - No page reloads for create/edit/delete
- 🔍 Full Audit Trail - Automatic change tracking via ChangeLog
Architecture¶
Models¶
Comment Model¶
class Comment(models.Model):
ticket = ForeignKey(Ticket, on_delete=CASCADE, related_name='comments')
author = ForeignKey(User, on_delete=CASCADE, related_name='ticket_comments')
body = TextField() # Rich HTML content from TinyMCE
comment_type = CharField(max_length=10, choices=[
('public', 'Public Comment'),
('internal', 'Internal Note'),
], default='public')
# Timestamps
created_at = DateTimeField(auto_now_add=True)
updated_at = DateTimeField(auto_now=True)
edited_at = DateTimeField(null=True, blank=True)
# Deletion tracking
is_deleted = BooleanField(default=False)
deleted_at = DateTimeField(null=True, blank=True)
deleted_by = ForeignKey(User, on_delete=SET_NULL, null=True, related_name='deleted_comments')
# Editing tracking
edited_by = ForeignKey(User, on_delete=SET_NULL, null=True, related_name='edited_comments')
# Convenience properties
@property
def is_internal(self):
return self.comment_type == 'internal'
@property
def is_edited(self):
return self.edited_at is not None
CommentEditHistory Model¶
Tracks all edits to comments for complete audit trail:
class CommentEditHistory(models.Model):
comment = ForeignKey(Comment, on_delete=CASCADE, related_name='edit_history')
edited_by = ForeignKey(User, on_delete=SET_NULL, null=True)
previous_body = TextField() # Content before edit
edited_at = DateTimeField(auto_now_add=True)
API Endpoints¶
All endpoints use AJAX with JSON responses:
POST /tickets/<ticket_id>/comments/add/¶
Creates a new comment.
Request:
Response (201 Created):
{
"success": true,
"comment": {
"id": 123,
"body": "...",
"comment_type": "public",
"author": "John Doe",
"created_at": "Jan 02, 2026 15:30",
"is_internal": false
}
}
PATCH /tickets/comments/<comment_id>/edit/¶
Updates an existing comment (creates edit history).
Request:
DELETE /tickets/comments/<comment_id>/delete/¶
Soft-deletes a comment (marks as deleted, doesn't remove).
Response (200 OK):
GET /tickets/<ticket_id>/comments/¶
Retrieves all comments for a ticket (with permission filtering).
Frontend Implementation¶
JavaScript Class: TicketComments¶
The TicketComments class handles all client-side operations:
class TicketComments {
constructor(ticketId) {
this.ticketId = ticketId;
this.init();
}
init() {
this.initEventListeners();
this.initTinyMCE();
}
// Key methods:
// - submitComment()
// - editComment(commentId)
// - deleteComment(commentId)
// - addCommentToUI(commentData)
}
Features:
- Prevents default form submission
- AJAX POST with CSRF token
- Dynamic UI updates without page reload
- TinyMCE initialization and management
- Loading states with spinner
- Error handling with user feedback
- Internal note warning toggle
Templates¶
comment_form.html¶
<form id="commentForm" method="POST" data-ticket-id="{{ ticket.id }}">
{% csrf_token %}
{# Comment Type Toggle #}
<div class="btn-group">
<input type="radio" name="comment_type" id="typePublic" value="public" checked>
<label for="typePublic">Public Comment</label>
<input type="radio" name="comment_type" id="typeInternal" value="internal">
<label for="typeInternal">Internal Note</label>
</div>
{# Internal Warning (hidden by default) #}
<div class="internal-note-warning d-none">
Warning: This note will not be visible to the requester.
</div>
{# TinyMCE Editor #}
<textarea id="commentBody" name="body"></textarea>
<button type="submit">Add Comment</button>
</form>
comment_list.html¶
Displays all comments with badges, timestamps, and edit/delete actions:
<div class="comments-list">
{% for comment in comments %}
<div class="comment-item {% if comment.is_internal %}comment-internal{% endif %}">
<div class="comment-header">
<strong>{{ comment.author.get_full_name }}</strong>
{% if comment.is_internal %}
<span class="badge bg-warning">Internal</span>
{% endif %}
<span class="text-muted">{{ comment.created_at }}</span>
</div>
<div class="comment-body">{{ comment.body|safe }}</div>
<div class="comment-actions">
<button class="edit-comment" data-comment-id="{{ comment.id }}">Edit</button>
<button class="delete-comment" data-comment-id="{{ comment.id }}">Delete</button>
</div>
</div>
{% endfor %}
</div>
Permissions¶
View Permissions¶
- Public Comments: Visible to anyone with ticket access
- Internal Notes: Only visible to:
- Staff users (
is_staff=True) - Ticket assignee
- Ticket assigned group members
Action Permissions¶
- Create Public Comment: Any authenticated user with ticket access
- Create Internal Note: Staff, assignee, or assigned group only
- Edit Comment: Author or staff
- Delete Comment: Author or staff
Permission helper function:
def can_view_internal_notes(user):
return user.is_staff or user.groups.filter(name__in=['Agents', 'Administrators']).exists()
Styling¶
The comment system uses a dedicated SCSS file with matching aesthetics to the overall design:
Key CSS Classes:
.comments-container- Main container.comment-item- Individual comment card.comment-internal- Internal note styling (yellow background).comment-form-container- Form wrapper with background.internal-note-warning- Warning message styling.comment-actions- Edit/delete buttons (visible on hover)
Design Features:
- Responsive design with mobile support
- Hover effects on comment cards
- Color-coded internal notes (yellow)
- Visual badges for internal notes
- Clean timeline layout
- Smooth transitions and animations
Security Features¶
- Authentication: All endpoints require login (
@login_required) - Permission Checks:
- Internal note visibility restricted
- Edit/delete restricted to author or staff
- XSS Protection: HTML sanitization in admin
- CSRF Protection: Token validation on all POST requests
- Audit Trail: All changes logged via changelog app
- Data Validation:
- Non-empty comment bodies
- Valid comment types
- User permission verification
Usage Examples¶
Creating a Public Comment¶
- Navigate to ticket detail page
- Click "Comments" tab
- Ensure "Public Comment" is selected
- Type comment in TinyMCE editor
- Click "Add Comment"
- Comment appears immediately without page reload
Creating an Internal Note¶
- Click "Internal Note" toggle
- Yellow warning appears
- Type internal note
- Click "Add Comment"
- Note marked with yellow badge
Editing a Comment¶
- Hover over your comment
- Click "Edit" button
- Modify text in editor
- Save changes
- "Edited" indicator appears with timestamp
Testing¶
Comprehensive test suite in src/tickets/tests/test_comments.py:
- Model Tests: Comment creation, properties, relationships
- Permission Tests: Public/internal visibility rules
- API Tests: AJAX endpoints, response formats
- Edit History Tests: Revision tracking
- Deletion Tests: Soft delete functionality
- Filter Tests: Comment list filtering by type
Run tests:
Configuration¶
TinyMCE Settings¶
tinymce.init({
selector: "#commentBody",
plugins: "lists link image code table",
toolbar:
"undo redo | formatselect | bold italic | bullist numlist | link image | code table",
menubar: false,
statusbar: false,
height: 200,
content_css: "/static/css/app.css",
});
Admin Configuration¶
Comments are manageable in Django admin with:
- List filters: ticket, comment type, author, date
- Search fields: body, author name
- Color-coded badges for internal notes
- Edit history inline
- Change log integration
Future Enhancements¶
Potential improvements for future versions:
- Comment threading/replies
- @mentions with notifications
- Comment reactions (emoji)
- Comment attachments
- Rich notifications (email/push)
- Comment templates
- Scheduled comments
- Comment export
Related Documentation¶
- Ticket History System - Audit trail for ticket changes
- Django Admin Guide
- API Reference
Summary¶
The Ticket Comments System provides a production-ready, two-tier communication platform with rich text editing, real-time updates, comprehensive permissions, and full audit trails. It's designed for both internal collaboration and external customer communication within the Arctyk ITSM platform.