Add UI enhancements and new features

Keyboard Navigation:
- Add J/K keys for Gmail-style ticket list navigation
- Add N key for new ticket, C for comment focus
- Add G then D for go to dashboard (vim-style)
- Add 1-4 number keys for quick status changes on ticket page
- Add Enter to open selected ticket
- Update keyboard help modal with all new shortcuts

Ticket Age Indicator:
- Show "Last activity: X days ago" on ticket view
- Visual warning (yellow pulse) for tickets idle >5 days
- Critical warning (red pulse) for tickets idle >10 days

Ticket Clone Feature:
- Add "Clone" button on ticket view
- Creates copy with [CLONE] prefix in title
- Preserves description, priority, category, type, visibility
- Automatically creates "relates_to" dependency to original

Active Filter Badges:
- Show visual badges above ticket table for active filters
- Click X on badge to remove individual filter
- "Clear All" button to reset all filters
- Color-coded by filter type (status, priority, search)

Visual Enhancements:
- Add keyboard-selected row highlighting for J/K navigation
- Smooth animations for filter badges

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-30 19:21:36 -05:00
parent 9b40a714ed
commit 1c1eb19876
7 changed files with 565 additions and 6 deletions

View File

@@ -981,6 +981,19 @@ tr:hover {
box-shadow: inset 0 0 20px rgba(0, 255, 65, 0.1);
}
/* Keyboard navigation selected row */
tbody tr.keyboard-selected {
background-color: rgba(0, 255, 65, 0.15) !important;
box-shadow: inset 0 0 30px rgba(0, 255, 65, 0.2), 0 0 10px rgba(0, 255, 65, 0.3);
outline: 2px solid var(--terminal-green);
outline-offset: -2px;
}
tbody tr.keyboard-selected td {
color: var(--terminal-green);
text-shadow: 0 0 5px rgba(0, 255, 65, 0.5);
}
tbody tr td:first-child {
border-left: 6px solid;
}
@@ -1172,6 +1185,95 @@ td:nth-child(2) span::after {
margin-left: 4px;
}
/* ===== ACTIVE FILTERS BAR ===== */
.active-filters-bar {
display: flex;
align-items: center;
flex-wrap: wrap;
gap: 0.5rem;
padding: 0.75rem 1rem;
margin-bottom: 1rem;
background: rgba(0, 255, 65, 0.05);
border: 1px solid var(--terminal-green);
border-left: 4px solid var(--terminal-amber);
}
.active-filters-label {
font-family: var(--font-mono);
font-size: 0.85rem;
color: var(--terminal-amber);
font-weight: 600;
margin-right: 0.5rem;
}
.active-filters-list {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
flex: 1;
}
.filter-badge {
display: inline-flex;
align-items: center;
gap: 0.4rem;
padding: 0.3rem 0.6rem;
background: rgba(0, 255, 65, 0.1);
border: 1px solid var(--terminal-green);
font-family: var(--font-mono);
font-size: 0.8rem;
color: var(--terminal-green);
animation: filter-appear 0.3s ease-out;
}
@keyframes filter-appear {
from {
opacity: 0;
transform: scale(0.9);
}
to {
opacity: 1;
transform: scale(1);
}
}
.filter-badge[data-filter-type="status"] {
border-color: var(--terminal-cyan);
color: var(--terminal-cyan);
}
.filter-badge[data-filter-type="priority"] {
border-color: var(--terminal-amber);
color: var(--terminal-amber);
}
.filter-badge[data-filter-type="search"] {
border-color: var(--terminal-magenta, #ff79c6);
color: var(--terminal-magenta, #ff79c6);
}
.filter-remove {
background: none;
border: none;
color: inherit;
font-size: 1.1rem;
line-height: 1;
cursor: pointer;
padding: 0 0.2rem;
opacity: 0.7;
transition: opacity 0.2s, transform 0.2s;
}
.filter-remove:hover {
opacity: 1;
transform: scale(1.2);
}
.btn-sm {
padding: 0.3rem 0.6rem;
font-size: 0.8rem;
}
/* ===== SEARCH AND FILTER STYLES - TERMINAL EDITION ===== */
.search-box,
input[type="text"],

View File

@@ -329,6 +329,57 @@ textarea[data-field="description"]:not(:disabled)::after {
color: var(--terminal-green);
}
/* Ticket Age Indicator */
.ticket-age {
display: inline-flex;
align-items: center;
gap: 0.5rem;
padding: 0.35rem 0.75rem;
margin-top: 0.5rem;
font-family: var(--font-mono);
font-size: 0.85rem;
border-radius: 0;
border: 1px solid var(--terminal-green);
background: rgba(0, 255, 65, 0.05);
}
.ticket-age.age-normal {
color: var(--terminal-green);
border-color: var(--terminal-green);
}
.ticket-age.age-warning {
color: var(--terminal-amber);
border-color: var(--terminal-amber);
background: rgba(255, 176, 0, 0.1);
animation: pulse-warning 2s ease-in-out infinite;
}
.ticket-age.age-critical {
color: var(--priority-1);
border-color: var(--priority-1);
background: rgba(255, 77, 77, 0.15);
animation: pulse-critical 1s ease-in-out infinite;
}
@keyframes pulse-warning {
0%, 100% { box-shadow: 0 0 5px rgba(255, 176, 0, 0.3); }
50% { box-shadow: 0 0 15px rgba(255, 176, 0, 0.6); }
}
@keyframes pulse-critical {
0%, 100% { box-shadow: 0 0 5px rgba(255, 77, 77, 0.3); }
50% { box-shadow: 0 0 20px rgba(255, 77, 77, 0.8); }
}
.ticket-age .age-icon {
font-size: 1rem;
}
.ticket-age .age-text {
font-weight: 500;
}
.status-priority-group {
display: flex;
gap: 10px;