Add comment threading and fix fetch authentication
- Add comment threading/reply functionality with nested display - Database migration for parent_comment_id and thread_depth columns - Recursive comment rendering with depth-based indentation - Reply form with inline UI and smooth animations - Thread collapse/expand capability - Max thread depth of 3 levels - Fix 401 authentication errors on API calls - Add credentials: 'same-origin' to all fetch calls - Affects settings.js, ticket.js, dashboard.js, advanced-search.js - Ensures session cookies are sent with requests - Enhanced comment styling - Thread connector lines for visual hierarchy - Reply button on comments (up to depth 3) - Quote block styling for replies Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -372,6 +372,29 @@ textarea[data-field="description"]:not(:disabled)::after {
|
||||
50% { box-shadow: 0 0 20px rgba(255, 77, 77, 0.8); }
|
||||
}
|
||||
|
||||
/* Tab transition animations */
|
||||
@keyframes tab-fade-in {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-10px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes tab-slide-in {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateX(-20px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateX(0);
|
||||
}
|
||||
}
|
||||
|
||||
.ticket-age .age-icon {
|
||||
font-size: 1rem;
|
||||
}
|
||||
@@ -601,13 +624,37 @@ textarea.editable {
|
||||
}
|
||||
|
||||
.comment {
|
||||
background: var(--bg-primary);
|
||||
background: linear-gradient(135deg, var(--bg-primary) 0%, rgba(0, 255, 65, 0.02) 100%);
|
||||
padding: 15px;
|
||||
border: 1px solid var(--terminal-green);
|
||||
border-radius: 0;
|
||||
margin-bottom: 1rem;
|
||||
position: relative;
|
||||
box-shadow: none;
|
||||
transition: all 0.3s ease;
|
||||
animation: comment-appear 0.4s ease-out;
|
||||
}
|
||||
|
||||
@keyframes comment-appear {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateX(-10px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateX(0);
|
||||
}
|
||||
}
|
||||
|
||||
.comment:hover {
|
||||
border-color: var(--terminal-amber);
|
||||
background: linear-gradient(135deg, var(--bg-primary) 0%, rgba(255, 176, 0, 0.03) 100%);
|
||||
box-shadow: 0 0 15px rgba(0, 255, 65, 0.1);
|
||||
}
|
||||
|
||||
.comment:hover::before,
|
||||
.comment:hover::after {
|
||||
color: var(--terminal-amber);
|
||||
}
|
||||
|
||||
/* Add corner decorations to individual comments */
|
||||
@@ -802,6 +849,182 @@ textarea.editable {
|
||||
min-height: auto !important;
|
||||
}
|
||||
|
||||
/* ===== COMMENT THREADING STYLES ===== */
|
||||
|
||||
/* Thread depth indentation */
|
||||
.comment.thread-depth-1 {
|
||||
margin-left: 2rem;
|
||||
}
|
||||
|
||||
.comment.thread-depth-2 {
|
||||
margin-left: 4rem;
|
||||
}
|
||||
|
||||
.comment.thread-depth-3 {
|
||||
margin-left: 6rem;
|
||||
}
|
||||
|
||||
/* Reply styling */
|
||||
.comment.comment-reply {
|
||||
position: relative;
|
||||
border-left: 2px solid var(--terminal-green-dim);
|
||||
margin-top: 0.5rem;
|
||||
padding-left: 1rem;
|
||||
}
|
||||
|
||||
.comment.comment-reply::before {
|
||||
content: none;
|
||||
}
|
||||
|
||||
/* Thread connector line */
|
||||
.comment .thread-line {
|
||||
position: absolute;
|
||||
left: -1rem;
|
||||
top: 0;
|
||||
width: 0.75rem;
|
||||
height: 1rem;
|
||||
border-left: 2px solid var(--terminal-green-dim);
|
||||
border-bottom: 2px solid var(--terminal-green-dim);
|
||||
}
|
||||
|
||||
/* Comment content wrapper for threading */
|
||||
.comment .comment-content {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
/* Replies container */
|
||||
.comment-replies {
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
|
||||
/* Reply button styling */
|
||||
.comment-action-btn.reply-btn {
|
||||
color: var(--terminal-green);
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.comment-action-btn.reply-btn:hover {
|
||||
color: var(--terminal-cyan);
|
||||
border-color: var(--terminal-cyan);
|
||||
}
|
||||
|
||||
/* Reply form inline */
|
||||
.reply-form-container {
|
||||
margin-top: 1rem;
|
||||
padding: 1rem;
|
||||
background: rgba(0, 255, 65, 0.03);
|
||||
border: 1px dashed var(--terminal-green);
|
||||
animation: fadeIn 0.3s ease;
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-10px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
.reply-form-container .reply-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 0.75rem;
|
||||
color: var(--terminal-green);
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
.reply-form-container .reply-header .replying-to {
|
||||
color: var(--terminal-amber);
|
||||
}
|
||||
|
||||
.reply-form-container .close-reply-btn {
|
||||
background: none;
|
||||
border: 1px solid var(--terminal-red);
|
||||
color: var(--terminal-red);
|
||||
padding: 0.25rem 0.5rem;
|
||||
cursor: pointer;
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
.reply-form-container .close-reply-btn:hover {
|
||||
background: rgba(255, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.reply-form-container textarea {
|
||||
width: 100%;
|
||||
min-height: 80px;
|
||||
padding: 0.75rem;
|
||||
background: var(--bg-secondary);
|
||||
border: 2px solid var(--terminal-green);
|
||||
color: var(--terminal-green);
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.9rem;
|
||||
resize: vertical;
|
||||
margin-bottom: 0.75rem;
|
||||
}
|
||||
|
||||
.reply-form-container textarea:focus {
|
||||
outline: none;
|
||||
border-color: var(--terminal-amber);
|
||||
box-shadow: 0 0 10px rgba(255, 176, 0, 0.3);
|
||||
}
|
||||
|
||||
.reply-form-container .reply-actions {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.reply-form-container .reply-buttons {
|
||||
display: flex;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
/* Quote block in replies */
|
||||
.comment-text blockquote {
|
||||
border-left: 3px solid var(--terminal-green-dim);
|
||||
padding-left: 1rem;
|
||||
margin: 0.5rem 0;
|
||||
color: var(--terminal-green-dim);
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/* Thread collapse indicator */
|
||||
.thread-collapse-btn {
|
||||
background: none;
|
||||
border: none;
|
||||
color: var(--terminal-green-dim);
|
||||
cursor: pointer;
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.8rem;
|
||||
padding: 0.25rem;
|
||||
margin-left: 0.5rem;
|
||||
}
|
||||
|
||||
.thread-collapse-btn:hover {
|
||||
color: var(--terminal-green);
|
||||
}
|
||||
|
||||
.comment.collapsed .comment-replies {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.comment.collapsed .thread-collapse-btn::after {
|
||||
content: ' [+]';
|
||||
}
|
||||
|
||||
.comment:not(.collapsed) .thread-collapse-btn::after {
|
||||
content: ' [-]';
|
||||
}
|
||||
|
||||
/* ===== END COMMENT THREADING STYLES ===== */
|
||||
|
||||
/* Comment Tabs - TERMINAL STYLE */
|
||||
.ticket-tabs {
|
||||
display: flex;
|
||||
@@ -857,6 +1080,7 @@ textarea.editable {
|
||||
.tab-content {
|
||||
display: none;
|
||||
padding: 20px;
|
||||
animation: tab-fade-in 0.3s ease-out;
|
||||
border: 2px solid var(--terminal-green);
|
||||
border-top: none;
|
||||
background: var(--bg-secondary);
|
||||
|
||||
Reference in New Issue
Block a user