Implement complete ANSI art terminal redesign
Transform entire UI into retro terminal aesthetic with ASCII/ANSI art: Visual Changes: - Add large ASCII art "TINKER TICKETS" banner with typewriter animation - Terminal black background (#0a0a0a) with matrix green text (#00ff41) - ASCII borders throughout using box-drawing characters (┌─┐│└─┘╔═╗║╚╝) - Monospace fonts (Courier New, Consolas, Monaco) everywhere - All rounded corners removed (border-radius: 0) - Text glow effects on important elements - Terminal prompts (>, $) and brackets ([]) on all UI elements Dashboard: - Table with ASCII corner decorations and terminal green borders - Headers with > prefix and amber glow - Priority badges: [P1] [P2] format with colored glows - Status badges: [OPEN] [CLOSED] with borders and glows - Search box with $ SEARCH prompt - All buttons in [ BRACKET ] format Ticket View: - Ticket container with double ASCII borders (╔╗╚╝) - Priority-colored corner characters - UUID display: [UUID: xxx] format - Comments section: ╔═══ COMMENTS ═══╗ header - Activity timeline with ASCII tree (├──, │, └──) - Tabs with [ ] brackets and ▼ active indicator Components: - Modals with ╔═══ TITLE ═══╗ headers and ASCII corners - Hamburger menu with MENU SYSTEM box decoration - Settings modal with terminal styling - All inputs with green borders and amber focus glow - Checkboxes with ✓ characters Technical: - New file: ascii-banner.js with banner artwork and typewriter renderer - Comprehensive responsive design (1024px, 768px, 480px breakpoints) - Mobile: simplified ASCII, hidden decorations, full-width menu - Print styles for clean black/white output - All functionality preserved, purely visual transformation Colors preserved: - Priority: P1=red, P2=orange, P3=blue, P4=green, P5=gray - Status: Open=green, In Progress=yellow, Closed=red - Accents: Terminal green, amber, cyan 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -1,43 +1,115 @@
|
|||||||
/* ===== TICKET PAGE SPECIFIC STYLES ===== */
|
/* ===== TICKET PAGE SPECIFIC STYLES - TERMINAL EDITION ===== */
|
||||||
|
|
||||||
/* Status colors for ticket page */
|
/* Import terminal variables (should be loaded from dashboard.css globally) */
|
||||||
.status-Open,
|
/* This file uses the same CSS variables defined in dashboard.css */
|
||||||
|
|
||||||
|
/* Status colors for ticket page - TERMINAL STYLE */
|
||||||
|
.status-Open,
|
||||||
[id="statusDisplay"].status-Open {
|
[id="statusDisplay"].status-Open {
|
||||||
background-color: var(--status-open) !important;
|
background-color: transparent !important;
|
||||||
color: white !important;
|
color: var(--status-open) !important;
|
||||||
padding: 8px 16px;
|
padding: 8px 16px;
|
||||||
border-radius: 6px;
|
border-radius: 0 !important;
|
||||||
|
border: 2px solid var(--status-open) !important;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
font-size: 0.9em;
|
font-size: 0.9em;
|
||||||
letter-spacing: 0.5px;
|
letter-spacing: 0.5px;
|
||||||
|
font-family: var(--font-mono);
|
||||||
|
text-shadow: 0 0 5px var(--status-open), 0 0 10px var(--status-open);
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-Open::before,
|
||||||
|
[id="statusDisplay"].status-Open::before {
|
||||||
|
content: '[';
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-Open::after,
|
||||||
|
[id="statusDisplay"].status-Open::after {
|
||||||
|
content: ']';
|
||||||
|
margin-left: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-In-Progress,
|
.status-In-Progress,
|
||||||
[id="statusDisplay"].status-In-Progress {
|
[id="statusDisplay"].status-In-Progress {
|
||||||
background-color: var(--status-in-progress) !important;
|
background-color: transparent !important;
|
||||||
color: #212529 !important;
|
color: var(--status-in-progress) !important;
|
||||||
padding: 8px 16px;
|
padding: 8px 16px;
|
||||||
border-radius: 6px;
|
border-radius: 0 !important;
|
||||||
|
border: 2px solid var(--status-in-progress) !important;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
font-size: 0.9em;
|
font-size: 0.9em;
|
||||||
letter-spacing: 0.5px;
|
letter-spacing: 0.5px;
|
||||||
|
font-family: var(--font-mono);
|
||||||
|
text-shadow: 0 0 5px var(--status-in-progress), 0 0 10px var(--status-in-progress);
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-In-Progress::before,
|
||||||
|
[id="statusDisplay"].status-In-Progress::before {
|
||||||
|
content: '[';
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-In-Progress::after,
|
||||||
|
[id="statusDisplay"].status-In-Progress::after {
|
||||||
|
content: ']';
|
||||||
|
margin-left: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-Closed,
|
.status-Closed,
|
||||||
[id="statusDisplay"].status-Closed {
|
[id="statusDisplay"].status-Closed {
|
||||||
background-color: var(--status-closed) !important;
|
background-color: transparent !important;
|
||||||
color: white !important;
|
color: var(--status-closed) !important;
|
||||||
padding: 8px 16px;
|
padding: 8px 16px;
|
||||||
border-radius: 6px;
|
border-radius: 0 !important;
|
||||||
|
border: 2px solid var(--status-closed) !important;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
font-size: 0.9em;
|
font-size: 0.9em;
|
||||||
letter-spacing: 0.5px;
|
letter-spacing: 0.5px;
|
||||||
|
font-family: var(--font-mono);
|
||||||
|
text-shadow: 0 0 5px var(--status-closed), 0 0 10px var(--status-closed);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Base Layout Components */
|
.status-Closed::before,
|
||||||
|
[id="statusDisplay"].status-Closed::before {
|
||||||
|
content: '[';
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-Closed::after,
|
||||||
|
[id="statusDisplay"].status-Closed::after {
|
||||||
|
content: ']';
|
||||||
|
margin-left: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-Resolved {
|
||||||
|
background-color: transparent !important;
|
||||||
|
color: var(--status-open) !important;
|
||||||
|
padding: 8px 16px;
|
||||||
|
border-radius: 0 !important;
|
||||||
|
border: 2px solid var(--status-open) !important;
|
||||||
|
font-weight: 500;
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-size: 0.9em;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
font-family: var(--font-mono);
|
||||||
|
text-shadow: 0 0 5px var(--status-open), 0 0 10px var(--status-open);
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-Resolved::before {
|
||||||
|
content: '[';
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-Resolved::after {
|
||||||
|
content: ']';
|
||||||
|
margin-left: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Base Layout Components - TERMINAL STYLE */
|
||||||
.ticket-container {
|
.ticket-container {
|
||||||
width: 90%;
|
width: 90%;
|
||||||
height: auto !important;
|
height: auto !important;
|
||||||
@@ -45,28 +117,101 @@
|
|||||||
min-width: 800px;
|
min-width: 800px;
|
||||||
max-width: 1800px;
|
max-width: 1800px;
|
||||||
margin: 40px auto;
|
margin: 40px auto;
|
||||||
padding: 20px;
|
padding: 0;
|
||||||
background: var(--bg-secondary);
|
background: var(--bg-primary);
|
||||||
border-radius: 12px;
|
border: 3px double var(--terminal-green);
|
||||||
box-shadow: var(--shadow);
|
border-radius: 0;
|
||||||
border-left: 6px solid;
|
box-shadow: none;
|
||||||
transition: border-color 0.3s ease;
|
transition: border-color 0.3s ease;
|
||||||
|
position: relative;
|
||||||
|
font-family: var(--font-mono);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Priority border colors */
|
/* ASCII corner decorations */
|
||||||
[data-priority="1"] { border-color: var(--priority-1); }
|
.ticket-container::before {
|
||||||
[data-priority="2"] { border-color: var(--priority-2); }
|
content: '╔';
|
||||||
[data-priority="3"] { border-color: var(--priority-3); }
|
position: absolute;
|
||||||
[data-priority="4"] { border-color: var(--priority-4); }
|
top: -3px;
|
||||||
[data-priority="5"] { border-color: var(--priority-5); }
|
left: -3px;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
color: var(--terminal-green);
|
||||||
|
line-height: 1;
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
|
||||||
/* Header Components */
|
.ticket-container::after {
|
||||||
|
content: '╗';
|
||||||
|
position: absolute;
|
||||||
|
top: -3px;
|
||||||
|
right: -3px;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
color: var(--terminal-green);
|
||||||
|
line-height: 1;
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Priority-based border colors */
|
||||||
|
[data-priority="1"] {
|
||||||
|
border-color: var(--priority-1);
|
||||||
|
}
|
||||||
|
[data-priority="1"]::before,
|
||||||
|
[data-priority="1"]::after {
|
||||||
|
color: var(--priority-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-priority="2"] {
|
||||||
|
border-color: var(--priority-2);
|
||||||
|
}
|
||||||
|
[data-priority="2"]::before,
|
||||||
|
[data-priority="2"]::after {
|
||||||
|
color: var(--priority-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-priority="3"] {
|
||||||
|
border-color: var(--priority-3);
|
||||||
|
}
|
||||||
|
[data-priority="3"]::before,
|
||||||
|
[data-priority="3"]::after {
|
||||||
|
color: var(--priority-3);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-priority="4"] {
|
||||||
|
border-color: var(--priority-4);
|
||||||
|
}
|
||||||
|
[data-priority="4"]::before,
|
||||||
|
[data-priority="4"]::after {
|
||||||
|
color: var(--priority-4);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-priority="5"] {
|
||||||
|
border-color: var(--priority-5);
|
||||||
|
}
|
||||||
|
[data-priority="5"]::before,
|
||||||
|
[data-priority="5"]::after {
|
||||||
|
color: var(--priority-5);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Header Components - TERMINAL STYLE */
|
||||||
.ticket-header {
|
.ticket-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
margin-bottom: 30px;
|
margin-bottom: 30px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
overflow-wrap: break-word;
|
overflow-wrap: break-word;
|
||||||
|
padding: 20px;
|
||||||
|
border-bottom: 2px solid var(--terminal-green);
|
||||||
|
background: var(--bg-secondary);
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ticket-header::before {
|
||||||
|
content: '═══════════════════════════════════════════════════════';
|
||||||
|
display: block;
|
||||||
|
color: var(--terminal-green);
|
||||||
|
font-family: var(--font-mono);
|
||||||
|
font-size: 0.8rem;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
opacity: 0.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ticket-subheader {
|
.ticket-subheader {
|
||||||
@@ -79,8 +224,9 @@
|
|||||||
.ticket-details {
|
.ticket-details {
|
||||||
margin-top: 30px;
|
margin-top: 30px;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
background: var(--bg-primary);
|
background: var(--bg-secondary);
|
||||||
border-radius: 8px;
|
border: 2px solid var(--terminal-green);
|
||||||
|
border-radius: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header-controls {
|
.header-controls {
|
||||||
@@ -90,8 +236,20 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.ticket-id {
|
.ticket-id {
|
||||||
font-family: 'Courier New', monospace;
|
font-family: var(--font-mono);
|
||||||
margin-right: 20px;
|
margin-right: 20px;
|
||||||
|
color: var(--terminal-amber);
|
||||||
|
text-shadow: var(--glow-amber);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ticket-id::before {
|
||||||
|
content: '[UUID: ';
|
||||||
|
color: var(--terminal-green);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ticket-id::after {
|
||||||
|
content: ']';
|
||||||
|
color: var(--terminal-green);
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-priority-group {
|
.status-priority-group {
|
||||||
@@ -103,23 +261,39 @@
|
|||||||
|
|
||||||
.priority-indicator {
|
.priority-indicator {
|
||||||
padding: 4px 8px;
|
padding: 4px 8px;
|
||||||
border-radius: 4px;
|
border: 2px solid;
|
||||||
|
border-radius: 0;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
font-family: var(--font-mono);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Title Input Styles */
|
.priority-indicator::before {
|
||||||
|
content: '[';
|
||||||
|
margin-right: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.priority-indicator::after {
|
||||||
|
content: ']';
|
||||||
|
margin-left: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Title Input Styles - TERMINAL */
|
||||||
.title-input {
|
.title-input {
|
||||||
font-size: 1em;
|
font-size: 1.2em;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
font-family: var(--font-mono);
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border: 2px solid transparent;
|
border: none;
|
||||||
border-radius: 4px;
|
border-bottom: 2px solid transparent;
|
||||||
padding: 12px;
|
border-radius: 0;
|
||||||
margin: -4px;
|
padding: 8px 0;
|
||||||
|
margin: 0;
|
||||||
word-break: break-word;
|
word-break: break-word;
|
||||||
overflow-wrap: break-word;
|
overflow-wrap: break-word;
|
||||||
white-space: pre-wrap;
|
white-space: pre-wrap;
|
||||||
display: block;
|
display: block;
|
||||||
|
background: transparent;
|
||||||
|
color: var(--terminal-green);
|
||||||
line-height: 1.4;
|
line-height: 1.4;
|
||||||
min-height: fit-content;
|
min-height: fit-content;
|
||||||
height: auto;
|
height: auto;
|
||||||
@@ -220,12 +394,29 @@ textarea.editable {
|
|||||||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Comments Section */
|
/* Comments Section - TERMINAL STYLE */
|
||||||
.comments-section {
|
.comments-section {
|
||||||
margin-top: 40px;
|
margin-top: 40px;
|
||||||
padding: 25px;
|
padding: 20px;
|
||||||
background: var(--bg-secondary);
|
background: var(--bg-secondary);
|
||||||
border-radius: 8px;
|
border: 2px solid var(--terminal-green);
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.comments-section h2 {
|
||||||
|
font-family: var(--font-mono);
|
||||||
|
color: var(--terminal-amber);
|
||||||
|
text-shadow: var(--glow-amber);
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.comments-section h2::before {
|
||||||
|
content: '╔═══ ';
|
||||||
|
}
|
||||||
|
|
||||||
|
.comments-section h2::after {
|
||||||
|
content: ' ═══╗';
|
||||||
}
|
}
|
||||||
|
|
||||||
.comment-form {
|
.comment-form {
|
||||||
@@ -234,41 +425,68 @@ textarea.editable {
|
|||||||
|
|
||||||
.comment-form textarea {
|
.comment-form textarea {
|
||||||
width: calc(100% - 20px);
|
width: calc(100% - 20px);
|
||||||
min-height: 80px;
|
min-height: 100px;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
border-radius: 6px;
|
border-radius: 0;
|
||||||
border: 1px solid var(--border-color);
|
border: 2px solid var(--terminal-green);
|
||||||
background: var(--bg-primary);
|
background: var(--bg-primary);
|
||||||
color: var(--text-primary);
|
color: var(--terminal-green);
|
||||||
|
font-family: var(--font-mono);
|
||||||
|
}
|
||||||
|
|
||||||
|
.comment-form textarea::placeholder {
|
||||||
|
color: rgba(0, 255, 65, 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
.comment {
|
.comment {
|
||||||
background: var(--bg-primary);
|
background: var(--bg-primary);
|
||||||
padding: 20px;
|
padding: 15px;
|
||||||
border-radius: 8px;
|
border: 2px solid var(--terminal-green);
|
||||||
margin-bottom: 20px;
|
border-radius: 0;
|
||||||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
margin-bottom: 15px;
|
||||||
|
position: relative;
|
||||||
|
box-shadow: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.comment-header {
|
.comment-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
margin-bottom: 8px;
|
margin-bottom: 10px;
|
||||||
|
padding-bottom: 8px;
|
||||||
|
border-bottom: 1px solid var(--terminal-green);
|
||||||
|
font-family: var(--font-mono);
|
||||||
font-size: 0.9em;
|
font-size: 0.9em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.comment-user {
|
.comment-user {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
color: var(--text-primary);
|
color: var(--terminal-amber);
|
||||||
|
}
|
||||||
|
|
||||||
|
.comment-user::before {
|
||||||
|
content: '> ';
|
||||||
|
color: var(--terminal-green);
|
||||||
}
|
}
|
||||||
|
|
||||||
.comment-date {
|
.comment-date {
|
||||||
color: var(--text-secondary);
|
color: var(--terminal-cyan);
|
||||||
|
font-size: 0.85em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.comment-date::before {
|
||||||
|
content: '[';
|
||||||
|
color: var(--terminal-green);
|
||||||
|
}
|
||||||
|
|
||||||
|
.comment-date::after {
|
||||||
|
content: ']';
|
||||||
|
color: var(--terminal-green);
|
||||||
}
|
}
|
||||||
|
|
||||||
.comment-text {
|
.comment-text {
|
||||||
color: var(--text-primary);
|
color: var(--terminal-green);
|
||||||
|
font-family: var(--font-mono);
|
||||||
line-height: 1.6;
|
line-height: 1.6;
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
@@ -295,37 +513,64 @@ textarea.editable {
|
|||||||
margin: 10px 0;
|
margin: 10px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Comment Tabs */
|
/* Comment Tabs - TERMINAL STYLE */
|
||||||
.ticket-tabs {
|
.ticket-tabs {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 10px;
|
gap: 0;
|
||||||
margin: 20px 0;
|
margin: 20px 0;
|
||||||
|
border-bottom: 2px solid var(--terminal-green);
|
||||||
}
|
}
|
||||||
|
|
||||||
.tab-btn {
|
.tab-btn {
|
||||||
padding: 12px 24px;
|
padding: 12px 24px;
|
||||||
border: 1px solid var(--border-color);
|
border: 2px solid var(--terminal-green);
|
||||||
background: var(--bg-secondary);
|
border-bottom: none;
|
||||||
border-radius: 6px;
|
background: var(--bg-primary);
|
||||||
|
border-radius: 0;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
font-weight: 500;
|
font-weight: bold;
|
||||||
font-size: 1.1em;
|
font-size: 1em;
|
||||||
|
font-family: var(--font-mono);
|
||||||
|
color: var(--terminal-green);
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
position: relative;
|
||||||
|
margin-right: -2px;
|
||||||
transition: all 0.3s ease;
|
transition: all 0.3s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tab-btn::before {
|
||||||
|
content: '[ ';
|
||||||
|
color: var(--terminal-green);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-btn::after {
|
||||||
|
content: ' ]';
|
||||||
|
color: var(--terminal-green);
|
||||||
|
}
|
||||||
|
|
||||||
.tab-btn:hover {
|
.tab-btn:hover {
|
||||||
transform: translateY(-2px);
|
background: rgba(0, 255, 65, 0.05);
|
||||||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
color: var(--terminal-amber);
|
||||||
}
|
}
|
||||||
|
|
||||||
.tab-btn.active {
|
.tab-btn.active {
|
||||||
background: #3b82f6;
|
background: var(--bg-secondary);
|
||||||
color: white;
|
color: var(--terminal-amber);
|
||||||
border-color: #3b82f6;
|
border-color: var(--terminal-amber);
|
||||||
|
text-shadow: var(--glow-amber);
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-btn.active::after {
|
||||||
|
content: ' ▼ ]';
|
||||||
}
|
}
|
||||||
|
|
||||||
.tab-content {
|
.tab-content {
|
||||||
display: none;
|
display: none;
|
||||||
|
padding: 20px;
|
||||||
|
border: 2px solid var(--terminal-green);
|
||||||
|
border-top: none;
|
||||||
|
background: var(--bg-secondary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.tab-content.active {
|
.tab-content.active {
|
||||||
@@ -443,10 +688,11 @@ input:checked + .slider:before {
|
|||||||
background: var(--border-color);
|
background: var(--border-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Activity Timeline Styles */
|
/* Activity Timeline Styles - ASCII TREE */
|
||||||
.timeline-container {
|
.timeline-container {
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
max-width: 800px;
|
max-width: 800px;
|
||||||
|
font-family: var(--font-mono);
|
||||||
}
|
}
|
||||||
|
|
||||||
.timeline-event {
|
.timeline-event {
|
||||||
@@ -456,32 +702,61 @@ input:checked + .slider:before {
|
|||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ASCII tree connector */
|
||||||
.timeline-event:not(:last-child)::before {
|
.timeline-event:not(:last-child)::before {
|
||||||
content: '';
|
content: '│';
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 12px;
|
left: 12px;
|
||||||
top: 30px;
|
top: 30px;
|
||||||
bottom: -24px;
|
bottom: -24px;
|
||||||
width: 2px;
|
color: var(--terminal-green);
|
||||||
background: var(--border-color, #ddd);
|
font-family: var(--font-mono);
|
||||||
|
font-size: 1.2rem;
|
||||||
|
line-height: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Branch connector */
|
||||||
|
.timeline-event::after {
|
||||||
|
content: '├──';
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 12px;
|
||||||
|
color: var(--terminal-green);
|
||||||
|
font-family: var(--font-mono);
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline-event:last-child::after {
|
||||||
|
content: '└──';
|
||||||
}
|
}
|
||||||
|
|
||||||
.timeline-icon {
|
.timeline-icon {
|
||||||
font-size: 1.5rem;
|
font-size: 1.2rem;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
width: 24px;
|
width: 24px;
|
||||||
height: 24px;
|
height: 24px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
margin-left: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.timeline-content {
|
.timeline-content {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
background: var(--card-bg, #f8f9fa);
|
background: var(--bg-primary);
|
||||||
padding: 0.75rem 1rem;
|
padding: 12px 16px;
|
||||||
border-radius: 8px;
|
border: 2px solid var(--terminal-green);
|
||||||
border: 1px solid var(--border-color, #ddd);
|
border-radius: 0;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Terminal box corner */
|
||||||
|
.timeline-content::before {
|
||||||
|
content: '┌─';
|
||||||
|
position: absolute;
|
||||||
|
top: -2px;
|
||||||
|
left: -2px;
|
||||||
|
color: var(--terminal-green);
|
||||||
|
font-family: var(--font-mono);
|
||||||
}
|
}
|
||||||
|
|
||||||
.timeline-header {
|
.timeline-header {
|
||||||
@@ -489,25 +764,40 @@ input:checked + .slider:before {
|
|||||||
gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin-bottom: 0.5rem;
|
margin-bottom: 0.5rem;
|
||||||
flex-wrap: wrap;
|
font-family: var(--font-mono);
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline-header strong {
|
||||||
|
color: var(--terminal-amber);
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline-header strong::before {
|
||||||
|
content: '[';
|
||||||
|
color: var(--terminal-green);
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline-header strong::after {
|
||||||
|
content: ']';
|
||||||
|
color: var(--terminal-green);
|
||||||
}
|
}
|
||||||
|
|
||||||
.timeline-action {
|
.timeline-action {
|
||||||
color: var(--text-muted, #666);
|
color: var(--terminal-green);
|
||||||
font-size: 0.9rem;
|
font-size: 0.9rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.timeline-date {
|
.timeline-date {
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
color: var(--text-muted, #999);
|
color: var(--terminal-cyan);
|
||||||
font-size: 0.85rem;
|
font-size: 0.85rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.timeline-details {
|
.timeline-details {
|
||||||
font-size: 0.9rem;
|
font-size: 0.9rem;
|
||||||
color: var(--text-secondary, #555);
|
color: var(--terminal-green);
|
||||||
padding-top: 0.5rem;
|
padding-top: 0.5rem;
|
||||||
border-top: 1px solid var(--border-color, #eee);
|
border-top: 1px solid var(--terminal-green);
|
||||||
|
font-family: var(--font-mono);
|
||||||
}
|
}
|
||||||
|
|
||||||
body.dark-mode .timeline-content {
|
body.dark-mode .timeline-content {
|
||||||
@@ -676,3 +966,108 @@ body.dark-mode .editable {
|
|||||||
color: #e2e8f0 !important;
|
color: #e2e8f0 !important;
|
||||||
border-color: #4a5568 !important;
|
border-color: #4a5568 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ===== RESPONSIVE DESIGN - TERMINAL EDITION ===== */
|
||||||
|
|
||||||
|
/* Tablet and smaller */
|
||||||
|
@media (max-width: 1024px) {
|
||||||
|
.ticket-container {
|
||||||
|
width: 95%;
|
||||||
|
min-width: 600px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reduce timeline spacing */
|
||||||
|
.timeline-event {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Mobile */
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.ticket-container {
|
||||||
|
width: 98%;
|
||||||
|
min-width: unset;
|
||||||
|
margin: 20px auto;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hide ASCII corner decorations on mobile */
|
||||||
|
.ticket-container::before,
|
||||||
|
.ticket-container::after {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Simplify ticket header */
|
||||||
|
.ticket-header::before {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ticket-header {
|
||||||
|
padding: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Stack header controls */
|
||||||
|
.header-controls {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reduce comment padding */
|
||||||
|
.comment {
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Simplify timeline on mobile */
|
||||||
|
.timeline-icon {
|
||||||
|
margin-left: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline-event::after {
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Smaller tabs */
|
||||||
|
.tab-btn {
|
||||||
|
padding: 8px 16px;
|
||||||
|
font-size: 0.9em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reduce glow effects */
|
||||||
|
.glow-text,
|
||||||
|
[class*="glow-"] {
|
||||||
|
text-shadow: 0 0 3px currentColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Very small mobile */
|
||||||
|
@media (max-width: 480px) {
|
||||||
|
.ticket-container {
|
||||||
|
width: 100%;
|
||||||
|
margin: 10px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove timeline connectors on very small screens */
|
||||||
|
.timeline-event::before,
|
||||||
|
.timeline-event::after {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline-content::before {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline-icon {
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Stack tabs vertically */
|
||||||
|
.ticket-tabs {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-btn {
|
||||||
|
width: 100%;
|
||||||
|
border: 2px solid var(--terminal-green);
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
197
assets/js/ascii-banner.js
Normal file
197
assets/js/ascii-banner.js
Normal file
@@ -0,0 +1,197 @@
|
|||||||
|
/**
|
||||||
|
* ASCII Art Banners for Tinker Tickets - Terminal Edition
|
||||||
|
*
|
||||||
|
* This file contains ASCII art banners and rendering functions
|
||||||
|
* for the retro terminal aesthetic redesign.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// ASCII Art Banner Definitions
|
||||||
|
const ASCII_BANNERS = {
|
||||||
|
// Main large banner for desktop
|
||||||
|
main: `
|
||||||
|
╔══════════════════════════════════════════════════════════════════════════╗
|
||||||
|
║ ║
|
||||||
|
║ ████████╗██╗███╗ ██╗██╗ ██╗███████╗██████╗ ║
|
||||||
|
║ ╚══██╔══╝██║████╗ ██║██║ ██╔╝██╔════╝██╔══██╗ ║
|
||||||
|
║ ██║ ██║██╔██╗ ██║█████╔╝ █████╗ ██████╔╝ ║
|
||||||
|
║ ██║ ██║██║╚██╗██║██╔═██╗ ██╔══╝ ██╔══██╗ ║
|
||||||
|
║ ██║ ██║██║ ╚████║██║ ██╗███████╗██║ ██║ ║
|
||||||
|
║ ╚═╝ ╚═╝╚═╝ ╚═══╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝ ║
|
||||||
|
║ ║
|
||||||
|
║ ████████╗██╗ ██████╗██╗ ██╗███████╗████████╗███████╗ ║
|
||||||
|
║ ╚══██╔══╝██║██╔════╝██║ ██╔╝██╔════╝╚══██╔══╝██╔════╝ ║
|
||||||
|
║ ██║ ██║██║ █████╔╝ █████╗ ██║ ███████╗ ║
|
||||||
|
║ ██║ ██║██║ ██╔═██╗ ██╔══╝ ██║ ╚════██║ ║
|
||||||
|
║ ██║ ██║╚██████╗██║ ██╗███████╗ ██║ ███████║ ║
|
||||||
|
║ ╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝╚══════╝ ╚═╝ ╚══════╝ ║
|
||||||
|
║ ║
|
||||||
|
║ >> RETRO TERMINAL TICKETING SYSTEM v1.0 << ║
|
||||||
|
║ ║
|
||||||
|
╚══════════════════════════════════════════════════════════════════════════╝
|
||||||
|
`,
|
||||||
|
|
||||||
|
// Compact version for smaller screens
|
||||||
|
compact: `
|
||||||
|
┌──────────────────────────────────────────────────────────┐
|
||||||
|
│ ▀█▀ █ █▄ █ █▄▀ █▀▀ █▀█ ▀█▀ █ █▀▀ █▄▀ █▀▀ ▀█▀ █▀ │
|
||||||
|
│ █ █ █ ▀█ █ █ ██▄ █▀▄ █ █ █▄▄ █ █ ██▄ █ ▄█ │
|
||||||
|
│ Terminal Ticketing System v1.0 │
|
||||||
|
└──────────────────────────────────────────────────────────┘
|
||||||
|
`,
|
||||||
|
|
||||||
|
// Minimal version for mobile
|
||||||
|
minimal: `
|
||||||
|
╔════════════════════════════╗
|
||||||
|
║ TINKER TICKETS v1.0 ║
|
||||||
|
╚════════════════════════════╝
|
||||||
|
`
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders ASCII banner with optional typewriter effect
|
||||||
|
*
|
||||||
|
* @param {string} bannerId - ID of banner to render ('main', 'compact', or 'minimal')
|
||||||
|
* @param {string} containerSelector - CSS selector for container element
|
||||||
|
* @param {number} speed - Speed of typewriter effect in milliseconds (0 = instant)
|
||||||
|
* @param {boolean} addGlow - Whether to add text glow effect
|
||||||
|
*/
|
||||||
|
function renderASCIIBanner(bannerId, containerSelector, speed = 5, addGlow = true) {
|
||||||
|
const banner = ASCII_BANNERS[bannerId];
|
||||||
|
const container = document.querySelector(containerSelector);
|
||||||
|
|
||||||
|
if (!container || !banner) {
|
||||||
|
console.error('ASCII Banner: Container or banner not found', { bannerId, containerSelector });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create pre element for ASCII art
|
||||||
|
const pre = document.createElement('pre');
|
||||||
|
pre.className = 'ascii-banner';
|
||||||
|
pre.style.margin = '0';
|
||||||
|
pre.style.fontFamily = 'var(--font-mono)';
|
||||||
|
pre.style.color = 'var(--terminal-green)';
|
||||||
|
|
||||||
|
if (addGlow) {
|
||||||
|
pre.style.textShadow = 'var(--glow-green)';
|
||||||
|
}
|
||||||
|
|
||||||
|
pre.style.fontSize = getBannerFontSize(bannerId);
|
||||||
|
pre.style.lineHeight = '1.2';
|
||||||
|
pre.style.whiteSpace = 'pre';
|
||||||
|
pre.style.overflow = 'visible';
|
||||||
|
pre.style.textAlign = 'center';
|
||||||
|
|
||||||
|
container.appendChild(pre);
|
||||||
|
|
||||||
|
// Instant render or typewriter effect
|
||||||
|
if (speed === 0) {
|
||||||
|
pre.textContent = banner;
|
||||||
|
} else {
|
||||||
|
renderWithTypewriter(pre, banner, speed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get appropriate font size for banner type
|
||||||
|
*
|
||||||
|
* @param {string} bannerId - Banner ID
|
||||||
|
* @returns {string} - CSS font size
|
||||||
|
*/
|
||||||
|
function getBannerFontSize(bannerId) {
|
||||||
|
const width = window.innerWidth;
|
||||||
|
|
||||||
|
if (bannerId === 'main') {
|
||||||
|
if (width < 768) return '0.4rem';
|
||||||
|
if (width < 1024) return '0.6rem';
|
||||||
|
return '0.8rem';
|
||||||
|
} else if (bannerId === 'compact') {
|
||||||
|
if (width < 768) return '0.6rem';
|
||||||
|
return '0.8rem';
|
||||||
|
} else {
|
||||||
|
return '0.8rem';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders text with typewriter effect
|
||||||
|
*
|
||||||
|
* @param {HTMLElement} element - Element to render into
|
||||||
|
* @param {string} text - Text to render
|
||||||
|
* @param {number} speed - Speed in milliseconds per character
|
||||||
|
*/
|
||||||
|
function renderWithTypewriter(element, text, speed) {
|
||||||
|
let index = 0;
|
||||||
|
|
||||||
|
const typeInterval = setInterval(() => {
|
||||||
|
element.textContent = text.substring(0, index);
|
||||||
|
index++;
|
||||||
|
|
||||||
|
if (index > text.length) {
|
||||||
|
clearInterval(typeInterval);
|
||||||
|
// Trigger completion event
|
||||||
|
const event = new CustomEvent('bannerComplete');
|
||||||
|
element.dispatchEvent(event);
|
||||||
|
}
|
||||||
|
}, speed);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders responsive banner based on screen size
|
||||||
|
*
|
||||||
|
* @param {string} containerSelector - CSS selector for container
|
||||||
|
* @param {number} speed - Typewriter speed (0 = instant)
|
||||||
|
*/
|
||||||
|
function renderResponsiveBanner(containerSelector, speed = 5) {
|
||||||
|
const width = window.innerWidth;
|
||||||
|
|
||||||
|
let bannerId;
|
||||||
|
if (width < 480) {
|
||||||
|
bannerId = 'minimal';
|
||||||
|
} else if (width < 1024) {
|
||||||
|
bannerId = 'compact';
|
||||||
|
} else {
|
||||||
|
bannerId = 'main';
|
||||||
|
}
|
||||||
|
|
||||||
|
renderASCIIBanner(bannerId, containerSelector, speed, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Animated welcome sequence
|
||||||
|
* Shows banner followed by a blinking cursor effect
|
||||||
|
*
|
||||||
|
* @param {string} containerSelector - CSS selector for container
|
||||||
|
*/
|
||||||
|
function animatedWelcome(containerSelector) {
|
||||||
|
const container = document.querySelector(containerSelector);
|
||||||
|
|
||||||
|
if (!container) return;
|
||||||
|
|
||||||
|
// Clear container
|
||||||
|
container.innerHTML = '';
|
||||||
|
|
||||||
|
// Render banner
|
||||||
|
renderResponsiveBanner(containerSelector, 3);
|
||||||
|
|
||||||
|
// Add blinking cursor after banner
|
||||||
|
const banner = container.querySelector('.ascii-banner');
|
||||||
|
if (banner) {
|
||||||
|
banner.addEventListener('bannerComplete', () => {
|
||||||
|
const cursor = document.createElement('span');
|
||||||
|
cursor.textContent = '█';
|
||||||
|
cursor.style.animation = 'blink-caret 0.75s step-end infinite';
|
||||||
|
cursor.style.marginLeft = '5px';
|
||||||
|
banner.appendChild(cursor);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Export functions for use in other scripts
|
||||||
|
if (typeof module !== 'undefined' && module.exports) {
|
||||||
|
module.exports = {
|
||||||
|
ASCII_BANNERS,
|
||||||
|
renderASCIIBanner,
|
||||||
|
renderResponsiveBanner,
|
||||||
|
animatedWelcome
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -10,6 +10,7 @@
|
|||||||
<title>Ticket Dashboard</title>
|
<title>Ticket Dashboard</title>
|
||||||
<link rel="icon" type="image/png" href="<?php echo $GLOBALS['config']['ASSETS_URL']; ?>/images/favicon.png">
|
<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">
|
<link rel="stylesheet" href="<?php echo $GLOBALS['config']['ASSETS_URL']; ?>/css/dashboard.css">
|
||||||
|
<script src="<?php echo $GLOBALS['config']['ASSETS_URL']; ?>/js/ascii-banner.js"></script>
|
||||||
<script src="<?php echo $GLOBALS['config']['ASSETS_URL']; ?>/js/dashboard.js"></script>
|
<script src="<?php echo $GLOBALS['config']['ASSETS_URL']; ?>/js/dashboard.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body data-categories='<?php echo json_encode($categories); ?>' data-types='<?php echo json_encode($types); ?>'>
|
<body data-categories='<?php echo json_encode($categories); ?>' data-types='<?php echo json_encode($types); ?>'>
|
||||||
@@ -90,6 +91,16 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<!-- ASCII Banner Container -->
|
||||||
|
<div id="ascii-banner-container" style="margin: 2rem auto; text-align: center; max-width: 1200px;"></div>
|
||||||
|
<script>
|
||||||
|
// Render ASCII banner on page load with typewriter effect
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
renderResponsiveBanner('#ascii-banner-container', 3);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
<div class="dashboard-header">
|
<div class="dashboard-header">
|
||||||
<h1>Ticket Dashboard</h1>
|
<h1>Ticket Dashboard</h1>
|
||||||
<button onclick="window.location.href='<?php echo $GLOBALS['config']['BASE_URL']; ?>/ticket/create'" class="btn create-ticket">New Ticket</button> </div>
|
<button onclick="window.location.href='<?php echo $GLOBALS['config']['BASE_URL']; ?>/ticket/create'" class="btn create-ticket">New Ticket</button> </div>
|
||||||
|
|||||||
Reference in New Issue
Block a user