feat: Comment edit/delete, auto-link URLs, markdown tables, mobile fixes
- Add comment edit/delete functionality (owner or admin can modify) - Add edit/delete buttons to comments in TicketView - Create update_comment.php and delete_comment.php API endpoints - Add updateComment() and deleteComment() methods to CommentModel - Show "(edited)" indicator on modified comments - Add migration script for updated_at column - Auto-link URLs in plain text comments (non-markdown) - Add markdown table support with proper HTML rendering - Preserve code blocks during markdown parsing - Fix mobile UI elements showing on desktop (add display:none defaults) - Add mobile styles for CreateTicketView form elements - Stack status-priority-row on mobile devices - Update cache busters to v20260124e - Update Claude.md and README.md documentation Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -8,9 +8,9 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Create New Ticket</title>
|
||||
<link rel="icon" type="image/png" href="<?php echo $GLOBALS['config']['ASSETS_URL']; ?>/images/favicon.png">
|
||||
<link rel="stylesheet" href="<?php echo $GLOBALS['config']['ASSETS_URL']; ?>/css/dashboard.css?v=20260124d">
|
||||
<link rel="stylesheet" href="<?php echo $GLOBALS['config']['ASSETS_URL']; ?>/css/ticket.css?v=20260124d">
|
||||
<script src="<?php echo $GLOBALS['config']['ASSETS_URL']; ?>/js/dashboard.js?v=20260124d"></script>
|
||||
<link rel="stylesheet" href="<?php echo $GLOBALS['config']['ASSETS_URL']; ?>/css/dashboard.css?v=20260124e">
|
||||
<link rel="stylesheet" href="<?php echo $GLOBALS['config']['ASSETS_URL']; ?>/css/ticket.css?v=20260124e">
|
||||
<script src="<?php echo $GLOBALS['config']['ASSETS_URL']; ?>/js/dashboard.js?v=20260124e"></script>
|
||||
<script>
|
||||
// CSRF Token for AJAX requests
|
||||
window.CSRF_TOKEN = '<?php
|
||||
|
||||
@@ -9,11 +9,11 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Ticket Dashboard</title>
|
||||
<link rel="icon" type="image/png" href="<?php echo $GLOBALS['config']['ASSETS_URL']; ?>/images/favicon.png">
|
||||
<link rel="stylesheet" href="<?php echo $GLOBALS['config']['ASSETS_URL']; ?>/css/dashboard.css?v=20260124dc">
|
||||
<link rel="stylesheet" href="<?php echo $GLOBALS['config']['ASSETS_URL']; ?>/css/dashboard.css?v=20260124e">
|
||||
<script src="<?php echo $GLOBALS['config']['ASSETS_URL']; ?>/js/ascii-banner.js"></script>
|
||||
<script src="<?php echo $GLOBALS['config']['ASSETS_URL']; ?>/js/toast.js"></script>
|
||||
<script src="<?php echo $GLOBALS['config']['ASSETS_URL']; ?>/js/markdown.js?v=20260124dc"></script>
|
||||
<script src="<?php echo $GLOBALS['config']['ASSETS_URL']; ?>/js/dashboard.js?v=20260124dc"></script>
|
||||
<script src="<?php echo $GLOBALS['config']['ASSETS_URL']; ?>/js/markdown.js?v=20260124e"></script>
|
||||
<script src="<?php echo $GLOBALS['config']['ASSETS_URL']; ?>/js/dashboard.js?v=20260124e"></script>
|
||||
<script>
|
||||
// CSRF Token for AJAX requests
|
||||
window.CSRF_TOKEN = '<?php
|
||||
|
||||
@@ -46,12 +46,12 @@ function formatDetails($details, $actionType) {
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Ticket #<?php echo $ticket['ticket_id']; ?></title>
|
||||
<link rel="icon" type="image/png" href="<?php echo $GLOBALS['config']['ASSETS_URL']; ?>/images/favicon.png">
|
||||
<link rel="stylesheet" href="<?php echo $GLOBALS['config']['ASSETS_URL']; ?>/css/dashboard.css?v=20260124d">
|
||||
<link rel="stylesheet" href="<?php echo $GLOBALS['config']['ASSETS_URL']; ?>/css/ticket.css?v=20260124d">
|
||||
<link rel="stylesheet" href="<?php echo $GLOBALS['config']['ASSETS_URL']; ?>/css/dashboard.css?v=20260124e">
|
||||
<link rel="stylesheet" href="<?php echo $GLOBALS['config']['ASSETS_URL']; ?>/css/ticket.css?v=20260124e">
|
||||
<script src="<?php echo $GLOBALS['config']['ASSETS_URL']; ?>/js/toast.js"></script>
|
||||
<script src="<?php echo $GLOBALS['config']['ASSETS_URL']; ?>/js/markdown.js?v=20260124d"></script>
|
||||
<script src="<?php echo $GLOBALS['config']['ASSETS_URL']; ?>/js/dashboard.js?v=20260124d"></script>
|
||||
<script src="<?php echo $GLOBALS['config']['ASSETS_URL']; ?>/js/ticket.js?v=20260124d"></script>
|
||||
<script src="<?php echo $GLOBALS['config']['ASSETS_URL']; ?>/js/markdown.js?v=20260124e"></script>
|
||||
<script src="<?php echo $GLOBALS['config']['ASSETS_URL']; ?>/js/dashboard.js?v=20260124e"></script>
|
||||
<script src="<?php echo $GLOBALS['config']['ASSETS_URL']; ?>/js/ticket.js?v=20260124e"></script>
|
||||
<script>
|
||||
// CSRF Token for AJAX requests
|
||||
window.CSRF_TOKEN = '<?php
|
||||
@@ -298,15 +298,34 @@ function formatDetails($details, $actionType) {
|
||||
<h2>Comment History</h2>
|
||||
<div class="comments-list">
|
||||
<?php
|
||||
$currentUserId = $GLOBALS['currentUser']['user_id'] ?? null;
|
||||
$isAdmin = $GLOBALS['currentUser']['is_admin'] ?? false;
|
||||
|
||||
foreach ($comments as $comment) {
|
||||
// Use display_name_formatted which falls back appropriately
|
||||
$displayName = $comment['display_name_formatted'] ?? $comment['user_name'] ?? 'Unknown User';
|
||||
echo "<div class='comment'>";
|
||||
$commentId = $comment['comment_id'];
|
||||
$isOwner = ($comment['user_id'] == $currentUserId);
|
||||
$canModify = $isOwner || $isAdmin;
|
||||
$markdownEnabled = $comment['markdown_enabled'] ? 1 : 0;
|
||||
|
||||
echo "<div class='comment' data-comment-id='{$commentId}' data-markdown-enabled='{$markdownEnabled}'>";
|
||||
echo "<div class='comment-header'>";
|
||||
echo "<span class='comment-user'>" . htmlspecialchars($displayName) . "</span>";
|
||||
echo "<span class='comment-date'>" . date('M d, Y H:i', strtotime($comment['created_at'])) . "</span>";
|
||||
$dateStr = date('M d, Y H:i', strtotime($comment['created_at']));
|
||||
$editedIndicator = !empty($comment['updated_at']) ? ' <span class="comment-edited">(edited)</span>' : '';
|
||||
echo "<span class='comment-date'>{$dateStr}{$editedIndicator}</span>";
|
||||
|
||||
// Edit/Delete buttons for owner or admin
|
||||
if ($canModify) {
|
||||
echo "<div class='comment-actions'>";
|
||||
echo "<button type='button' class='comment-action-btn edit-btn' onclick='editComment({$commentId})' title='Edit comment'>✏️</button>";
|
||||
echo "<button type='button' class='comment-action-btn delete-btn' onclick='deleteComment({$commentId})' title='Delete comment'>🗑️</button>";
|
||||
echo "</div>";
|
||||
}
|
||||
|
||||
echo "</div>";
|
||||
echo "<div class='comment-text' " . ($comment['markdown_enabled'] ? "data-markdown" : "") . ">";
|
||||
echo "<div class='comment-text' id='comment-text-{$commentId}' " . ($comment['markdown_enabled'] ? "data-markdown" : "") . ">";
|
||||
if ($comment['markdown_enabled']) {
|
||||
// Markdown will be rendered by JavaScript
|
||||
echo htmlspecialchars($comment['comment_text']);
|
||||
@@ -315,6 +334,8 @@ function formatDetails($details, $actionType) {
|
||||
echo nl2br(htmlspecialchars($comment['comment_text']));
|
||||
}
|
||||
echo "</div>";
|
||||
// Hidden raw text for editing
|
||||
echo "<textarea class='comment-edit-raw' id='comment-raw-{$commentId}' style='display:none;'>" . htmlspecialchars($comment['comment_text']) . "</textarea>";
|
||||
echo "</div>";
|
||||
}
|
||||
?>
|
||||
|
||||
Reference in New Issue
Block a user