From 5cd032393e77f4559536c486f0bce56e6999a4a2 Mon Sep 17 00:00:00 2001 From: Laurent Deleers Date: Wed, 23 Sep 2026 13:42:00 +0200 Subject: [PATCH] add clear style + switcher. --- index.html | 14 ++- public/css/style.css | 216 ++++++++++++++++++++++++++++++++++++------- public/js/script.js | 34 +++++++ 3 files changed, 229 insertions(+), 35 deletions(-) diff --git a/index.html b/index.html index 5eb7017..678f600 100644 --- a/index.html +++ b/index.html @@ -7,6 +7,12 @@ +
@@ -20,7 +26,13 @@

Jira Ticket Extractor

Extraction via API locale — Proxy transparent

-
API : localhost:3000
+
+
API : localhost:3000
+ +
diff --git a/public/css/style.css b/public/css/style.css index 76dc0fe..3bcb64e 100644 --- a/public/css/style.css +++ b/public/css/style.css @@ -17,6 +17,37 @@ --radius: 10px; --radius-lg: 16px; --shadow: 0 4px 24px rgba(0, 0, 0, 0.4); + --fg-btn-primary: #0f0a0f; + --gantt-bg: #0a0f0d; + --gantt-header-bg: #111a16; + --gantt-sticky-bg: #1a1a1a; + --gantt-group-bg: rgba(255, 255, 255, 0.03); + --gantt-grid-border: rgba(255, 255, 255, 0.05); +} + +[data-theme="light"] { + --bg: #f3f6f4; + --bg-elevated: #ffffff; + --bg-card: #ffffff; + --bg-input: #f8faf9; + --fg: #13221b; + --fg-muted: #4e6b5d; + --fg-dim: #8ba295; + --accent: #00995c; + --accent-dim: #007a49; + --accent-glow: rgba(0, 153, 92, 0.12); + --accent-glow-strong: rgba(0, 153, 92, 0.22); + --border: #d2ded6; + --danger: #dc2626; + --warning: #d97706; + --info: #0284c7; + --shadow: 0 4px 20px rgba(0, 0, 0, 0.06); + --fg-btn-primary: #ffffff; + --gantt-bg: #f8faf9; + --gantt-header-bg: #eef4f0; + --gantt-sticky-bg: #e6ede8; + --gantt-group-bg: rgba(0, 0, 0, 0.03); + --gantt-grid-border: rgba(0, 0, 0, 0.06); } * { @@ -30,6 +61,7 @@ body { background: var(--bg); color: var(--fg); min-height: 100vh; + transition: background-color 0.25s ease, color 0.25s ease; } .bg-grid { @@ -88,6 +120,7 @@ body { margin-bottom: 40px; padding-bottom: 24px; border-bottom: 1px solid var(--border); + flex-wrap: wrap; } .header-icon { @@ -99,7 +132,7 @@ body { align-items: center; justify-content: center; font-size: 22px; - color: var(--bg); + color: var(--fg-btn-primary); box-shadow: 0 0 30px var(--accent-glow-strong); } @@ -115,16 +148,68 @@ body { margin-top: 4px; } +.header-actions { + display: flex; + align-items: center; + gap: 12px; + margin-left: auto; +} + .badge-api { background: var(--accent-glow); color: var(--accent); font-size: 11px; font-weight: 700; - padding: 4px 10px; + padding: 6px 12px; border-radius: 20px; border: 1px solid rgba(0, 230, 138, 0.2); - margin-left: auto; font-family: 'JetBrains Mono', monospace; + display: inline-flex; + align-items: center; +} + +[data-theme="light"] .badge-api { + border-color: rgba(0, 153, 92, 0.25); +} + +.theme-toggle-btn { + display: inline-flex; + align-items: center; + gap: 8px; + background: var(--bg-card); + color: var(--fg); + border: 1px solid var(--border); + border-radius: 20px; + padding: 6px 14px; + font-family: 'DM Sans', sans-serif; + font-size: 12px; + font-weight: 600; + cursor: pointer; + transition: all 0.25s ease; + outline: none; + user-select: none; + box-shadow: var(--shadow); +} + +.theme-toggle-btn:hover { + border-color: var(--accent); + background: var(--accent-glow); + color: var(--accent); + transform: translateY(-1px); +} + +.theme-toggle-btn i { + font-size: 13px; + color: var(--warning); + transition: transform 0.3s ease; +} + +[data-theme="light"] .theme-toggle-btn i { + color: var(--info); +} + +.theme-toggle-btn:hover i { + transform: rotate(25deg); } .card-form { @@ -230,7 +315,7 @@ body { .btn-primary { background: linear-gradient(135deg, var(--accent), var(--accent-dim)); - color: var(--bg); + color: var(--fg-btn-primary); box-shadow: 0 4px 20px var(--accent-glow-strong); } @@ -252,6 +337,7 @@ body { .btn-secondary:hover { border-color: var(--fg-dim); + background: var(--bg-elevated); } .btn-danger { @@ -260,6 +346,11 @@ body { border: 1px solid rgba(255, 77, 106, 0.2); } +[data-theme="light"] .btn-danger { + background: rgba(220, 38, 38, 0.08); + border-color: rgba(220, 38, 38, 0.2); +} + .btn-group { display: flex; gap: 12px; @@ -380,7 +471,7 @@ body { .tab-btn.active { background: var(--accent); - color: var(--bg); + color: var(--fg-btn-primary); box-shadow: 0 2px 12px var(--accent-glow-strong); } @@ -435,7 +526,7 @@ td { } tr:hover td { - background: rgba(0, 230, 138, 0.03); + background: var(--accent-glow); } .ticket-key { @@ -481,6 +572,31 @@ tr:hover td { color: #7a9488; } +[data-theme="light"] .s-done { + background: rgba(0, 153, 92, 0.12); + color: #007a49; +} + +[data-theme="light"] .s-progress { + background: rgba(2, 132, 199, 0.12); + color: #0284c7; +} + +[data-theme="light"] .s-todo { + background: rgba(217, 119, 6, 0.12); + color: #b45309; +} + +[data-theme="light"] .s-blocked { + background: rgba(220, 38, 38, 0.12); + color: #dc2626; +} + +[data-theme="light"] .s-other { + background: rgba(83, 110, 97, 0.12); + color: #4e6b5d; +} + .empty-cell { color: var(--fg-dim); font-style: italic; @@ -515,6 +631,10 @@ tr:hover td { opacity: 1; } +[data-theme="light"] .date-input::-webkit-calendar-picker-indicator { + filter: none; +} + /* Update button styling */ .btn-update { display: inline-flex; @@ -529,7 +649,7 @@ tr:hover td { cursor: pointer; transition: all 0.25s; background: linear-gradient(135deg, var(--accent), var(--accent-dim)); - color: var(--bg); + color: var(--fg-btn-primary); } .btn-update:hover { @@ -588,6 +708,22 @@ tr:hover td { color: var(--fg-dim); } +[data-theme="light"] .json-key { + color: #0284c7; +} + +[data-theme="light"] .json-string { + color: #00874e; +} + +[data-theme="light"] .json-number { + color: #d97706; +} + +[data-theme="light"] .json-bool { + color: #dc2626; +} + .search-bar { position: relative; margin-bottom: 16px; @@ -646,7 +782,7 @@ tr:hover td { display: flex; align-items: center; gap: 10px; - box-shadow: 0 8px 30px rgba(0, 0, 0, 0.5); + box-shadow: var(--shadow); animation: tIn 0.35s ease, tOut 0.35s ease 3s forwards; max-width: 400px; } @@ -663,6 +799,18 @@ tr:hover td { color: var(--danger); } +[data-theme="light"] .toast-success { + background: #ecfdf5; + border: 1px solid rgba(0, 153, 92, 0.3); + color: #065f46; +} + +[data-theme="light"] .toast-error { + background: #fef2f2; + border: 1px solid rgba(220, 38, 38, 0.3); + color: #991b1b; +} + @keyframes tIn { from { opacity: 0; @@ -781,8 +929,8 @@ GANTT position: relative; height: 600px; overflow: auto; /* Un seul scroll géré ici */ - background: #0a0f0d; - border: 1px solid #1e3028; + background: var(--gantt-bg); + border: 1px solid var(--border); border-radius: 8px; } @@ -792,27 +940,27 @@ GANTT position: sticky; top: 0; z-index: 100; - background: #111a16; - border-bottom: 2px solid #1e3028; + background: var(--gantt-header-bg); + border-bottom: 2px solid var(--border); } .gantt-header-label { position: sticky; left: 0; z-index: 101; - background: #1a1a1a; + background: var(--gantt-sticky-bg); border-right: 2px solid var(--border); padding-left: 10px; display: flex; align-items: center; font-weight: bold; - color: var(--primary); + color: var(--accent); } /* Groupes par Assigné */ .gantt-group-row { display: flex; - background: rgba(255, 255, 255, 0.03); + background: var(--gantt-group-bg); border-bottom: 1px solid var(--border); font-weight: 600; } @@ -821,7 +969,7 @@ GANTT position: sticky; left: 0; z-index: 50; - background: #1a1a1a; + background: var(--gantt-sticky-bg); padding: 8px 10px; border-right: 2px solid var(--border); color: var(--accent); @@ -860,7 +1008,7 @@ GANTT align-items: center; padding: 0 8px; font-size: 10px; - color: white; + color: var(--fg); overflow: hidden; white-space: nowrap; text-overflow: ellipsis; @@ -873,8 +1021,8 @@ GANTT position: sticky; left: 0; z-index: 110; - background: #111a16; - border-right: 2px solid #1e3028; + background: var(--gantt-header-bg); + border-right: 2px solid var(--border); padding: 0 10px; display: flex; align-items: center; @@ -886,7 +1034,7 @@ GANTT top: 0; bottom: 0; width: 2px; - background-color: #ff4d6a; + background-color: var(--danger); z-index: 80; pointer-events: none; } @@ -895,7 +1043,7 @@ GANTT position: absolute; top: 2px; transform: translateX(-50%); - background: #ff4d6a; + background: var(--danger); color: white; padding: 2px 5px; border-radius: 3px; @@ -919,18 +1067,18 @@ GANTT width: 140px; text-align: center; font-size: 11px; - color: #7a9488; + color: var(--fg-muted); display: flex; align-items: center; justify-content: center; - border-left: 1px solid #1e3028; + border-left: 1px solid var(--border); } /* Ligne de groupe (Assigné) */ .gantt-group-header { display: flex; - background: rgba(255, 255, 255, 0.03); - border-bottom: 1px solid #1e3028; + background: var(--gantt-group-bg); + border-bottom: 1px solid var(--border); } .gantt-group-name { @@ -944,7 +1092,7 @@ GANTT .gantt-row { display: flex; height: 45px; - border-bottom: 1px solid #1e3028; + border-bottom: 1px solid var(--border); position: relative; align-items: center; } @@ -953,14 +1101,14 @@ GANTT width: 250px; /* leftWidth */ height: 100%; font-size: 11px; - color: #7a9488; + color: var(--fg-muted); padding-left: 20px; } /* Grille de fond (colonnes verticales sous les barres) */ .gantt-grid-col { min-width: 140px; - border-right: 1px solid rgba(255, 255, 255, 0.05); + border-right: 1px solid var(--gantt-grid-border); height: 100%; } @@ -974,9 +1122,9 @@ GANTT /* Optionnel : style pour le bouton de vue actif */ .view-controls .btn.active { - background-color: var(--primary); - color: white; - border-color: var(--primary); + background-color: var(--accent); + color: var(--fg-btn-primary); + border-color: var(--accent); } /* --- ALIGNEMENT ROADMAP --- */ @@ -1003,7 +1151,7 @@ GANTT margin-left: auto; /* Sécurité supplémentaire pour pousser à droite */ border: 1px solid var(--accent); /* Optionnel: pour bien la voir */ border-radius: var(--radius-lg); - background: rgba(0, 230, 138, 0.05); + background: var(--accent-glow); padding: 5px 15px; } @@ -1012,8 +1160,8 @@ GANTT display: flex; align-items: center; gap: 15px; - background: rgba(0, 230, 138, 0.1); /* Fond vert transparent */ - border: 1px solid var(--accent); /* Bordure verte */ + background: var(--accent-glow); + border: 1px solid var(--accent); padding: 6px 15px; border-radius: var(--radius); } diff --git a/public/js/script.js b/public/js/script.js index 1404093..82d3ae3 100644 --- a/public/js/script.js +++ b/public/js/script.js @@ -9,6 +9,39 @@ let currentSortCol = null; let isAsc = true; +// --- GESTION DU THÈME (CLAIR / SOMBRE) --- +function initTheme() { + const savedTheme = localStorage.getItem('jira_extractor_theme') || 'dark'; + setTheme(savedTheme, false); +} + +function toggleTheme() { + const currentTheme = document.documentElement.getAttribute('data-theme') === 'light' ? 'light' : 'dark'; + const newTheme = currentTheme === 'light' ? 'dark' : 'light'; + setTheme(newTheme, true); +} + +function setTheme(theme, withToast = false) { + document.documentElement.setAttribute('data-theme', theme); + localStorage.setItem('jira_extractor_theme', theme); + + const icon = document.getElementById('themeIcon'); + const label = document.getElementById('themeLabel'); + if (icon && label) { + if (theme === 'light') { + icon.className = 'fa-solid fa-moon'; + label.textContent = 'Mode sombre'; + } else { + icon.className = 'fa-solid fa-sun'; + label.textContent = 'Mode clair'; + } + } + + if (withToast) { + showToast(theme === 'light' ? 'Mode clair activé' : 'Mode sombre activé'); + } +} + // Sauvegarde les paramètres dans le stockage local du navigateur function saveSettings() { const settings = { @@ -682,6 +715,7 @@ function clearResults() { allTickets=[]; filteredTickets=[]; document.getElement document.addEventListener('keydown', e => { if((e.ctrlKey||e.metaKey)&&e.key==='Enter'){e.preventDefault();startExtraction()} }); // Cet événement se déclenche quand le navigateur a fini de charger le HTML document.addEventListener('DOMContentLoaded', () => { + initTheme(); loadSettings(); console.log("Paramètres chargés depuis le stockage local."); }); \ No newline at end of file