|
14 | 14 | <div class="flex space-x-3 text-xs mb-4 overflow-x-auto no-scrollbar whitespace-nowrap pr-2 border-t border-gray-200 dark:border-gray-800"> |
15 | 15 | <template x-for="(data, key) in tabs" :key="key"> |
16 | 16 | <button |
17 | | - @click="tab = key" |
18 | | - class="inline-block px-2 py-1 font-thin" |
19 | | - :class="tab === key ? ('text-blue-600! bg-blue-100/50 dark:text-blue-400! dark:bg-blue-900/50 rounded-xl') : 'text-gray-400!'" |
20 | | - > |
| 17 | + @click="tab = key" |
| 18 | + class="inline-block px-2 py-1 font-thin" |
| 19 | + :class="tab === key ? ('text-blue-600! bg-blue-100/50 dark:text-blue-400! dark:bg-blue-900/50 rounded-xl') : 'text-gray-400!'" |
| 20 | + > |
21 | 21 | <span x-text="data.tab"></span> |
22 | 22 | </button> |
23 | 23 | </template> |
24 | 24 | </div> |
25 | 25 |
|
26 | 26 | <!-- Valeur + barre + bouton + diff --> |
27 | | - <div class="flex items-center justify-between"> |
| 27 | + <div class="relative"> |
| 28 | + <div> |
| 29 | + <div class="flex items-center justify-between"> |
28 | 30 |
|
29 | | - <!-- 🔵 Gauche : valeur + barre + bouton --> |
30 | | - <div class="flex items-center space-x-4 text-2xl font-bold"> |
31 | 31 |
|
32 | | - <!-- Valeur --> |
33 | | - <span x-text="tabs[tab]?.value ?? ''"></span> |
34 | | - <span x-show="tab === 'ongoing' && tabs[tab]?.globalLimit">/</span> |
35 | | - <span x-show="tab === 'ongoing' && tabs[tab]?.globalLimit" x-text="tabs[tab]?.globalLimit ?? ''"></span> |
| 32 | + <!-- 🔵 Gauche : valeur + barre + bouton --> |
| 33 | + <div class="flex items-center space-x-1 text-2xl font-bold"> |
36 | 34 |
|
37 | | - <!-- Barre uniquement pour ongoing --> |
38 | | - <div x-show="tab === 'ongoing' && tabs[tab]?.globalLimit"> |
39 | | - <div class="flex items-center space-x-2"> |
| 35 | + <!-- Valeur --> |
| 36 | + <span x-text="tabs[tab]?.value ?? ''"></span> |
| 37 | + <span x-show="tab === 'ongoing' && tabs[tab]?.globalLimit">/</span> |
| 38 | + <span x-show="tab === 'ongoing' && tabs[tab]?.globalLimit" x-text="tabs[tab]?.globalLimit ?? ''"></span> |
| 39 | + <span class='text-sm font-semibold' x-show="tab === 'ongoing' && tabs[tab]?.queueSize" x-text="tabs[tab]?.queueSize ? '('+tabs[tab].queueSize+')' : ''"></span> |
| 40 | + </div> |
| 41 | + |
| 42 | + |
| 43 | + |
| 44 | + |
| 45 | + <!-- Barre uniquement pour ongoing --> |
| 46 | + <div x-show="tab === 'ongoing' && tabs[tab]?.value"> |
| 47 | + <div class="flex items-center space-x-2"> |
40 | 48 |
|
41 | | - <!-- Barre --> |
42 | | - <div class="w-20 bg-gray-200 h-2 rounded relative"> |
43 | | - <div class="bg-orange-500 h-2 rounded transition-all duration-500" |
44 | | - :style="'width:' + ((tabs[tab].value / tabs[tab].globalLimit) * 100) + '%'"> |
| 49 | + <!-- Barre --> |
| 50 | + <div class="w-20 bg-gray-200 h-2 rounded relative"> |
| 51 | + <div class="bg-blue-500 h-2 rounded transition-all duration-500" |
| 52 | + :style="'width:' + ((tabs[tab].value / tabs[tab].globalLimit) * 100) + '%'"> |
| 53 | + </div> |
45 | 54 | </div> |
| 55 | + |
46 | 56 | </div> |
47 | 57 |
|
48 | 58 | </div> |
49 | 59 |
|
50 | | - </div> |
51 | | - </div> |
52 | | - |
53 | | - <!-- 🟢 Droite : Diff --> |
54 | | - <div x-show="tabs[tab]?.diff !== undefined"> |
55 | | - <div class="flex items-center space-x-1 text-sm font-semibold" |
56 | | - :class="getDiffIconAndColor(tabs[tab].diff, tabs[tab].diffPositive).color"> |
57 | | - <i :data-lucide="getDiffIconAndColor(tabs[tab].diff, tabs[tab].diffPositive).icon" |
58 | | - class="w-4 h-4"></i> |
59 | | - <span x-text="computeDiffPercent(tabs[tab].currentValue, tabs[tab].previousValue)"></span> |
60 | | - </div> |
61 | | - </div> |
62 | | - <div x-show="tab === 'ongoing'" class="flex items-center space-x-1 text-sm font-semibold"> |
63 | | - <!-- Bouton hover --> |
64 | | - <div class="relative" x-data="{ open: false }" @mouseenter="open = true" @mouseleave="open = false"> |
65 | | - <button class="text-gray-500 hover:text-orange-500 transition" |
66 | | - x-init="$nextTick(() => window.lucide && lucide.createIcons())"> |
67 | | - <i data-lucide="list" class="w-4 h-4"></i> |
68 | | - </button> |
69 | | - |
70 | | - <div x-show="open" |
71 | | - class="absolute right-0 mt-2 w-64 bg-white dark:bg-gray-900 |
72 | | - border border-gray-200 dark:border-gray-700 |
73 | | - rounded-xl shadow-xl p-3 text-xs space-y-2 |
74 | | - transition-all duration-200 z-50" |
75 | | - x-transition:enter="transition ease-out duration-200" |
76 | | - x-transition:enter-start="opacity-0 translate-y-1" |
77 | | - x-transition:enter-end="opacity-100 translate-y-0" |
78 | | - x-transition:leave="transition ease-in duration-150" |
79 | | - x-transition:leave-start="opacity-100 translate-y-0" |
80 | | - x-transition:leave-end="opacity-0 translate-y-1"> |
81 | | - |
82 | | - <template x-for="exec in tabs[tab]?.runningList ?? []" :key="exec.id"> |
83 | | - <a :href="'./TestCaseExecution.jsp?id=' + exec.id" |
84 | | - class="block text-xs text-blue-500 hover:underline truncate"> |
85 | | - <span x-text="exec.test"></span> - |
86 | | - <span x-text="exec.testcase"></span> - |
87 | | - <span x-text="exec.environment"></span> |
88 | | - </a> |
89 | | - </template> |
90 | | - |
91 | | - <div x-show="!(tabs[tab]?.runningList?.length)" class="text-gray-400"> |
92 | | - No running executions |
| 60 | + <!-- 🟢 Droite : Diff --> |
| 61 | + <div x-show="tabs[tab]?.diff !== undefined"> |
| 62 | + <div class="flex items-center space-x-1 text-sm font-semibold" |
| 63 | + :class="getDiffIconAndColor(tabs[tab].diff, tabs[tab].diffPositive).color"> |
| 64 | + <i :data-lucide="getDiffIconAndColor(tabs[tab].diff, tabs[tab].diffPositive).icon" |
| 65 | + class="w-4 h-4"></i> |
| 66 | + <span x-text="computeDiffPercent(tabs[tab].currentValue, tabs[tab].previousValue)"></span> |
93 | 67 | </div> |
94 | 68 | </div> |
| 69 | + <div x-show="tab === 'ongoing' && tabs[tab]?.value" class="flex items-center space-x-1 text-sm font-semibold"> |
| 70 | + <!-- Bouton hover --> |
| 71 | + <div class="relative" x-data="{ open: false }" @mouseenter="open = true" @mouseleave="open = false"> |
| 72 | + <button class="text-gray-500 hover:text-orange-500 transition" |
| 73 | + x-init="$nextTick(() => window.lucide && lucide.createIcons())"> |
| 74 | + <i data-lucide="list" class="w-4 h-4"></i> |
| 75 | + </button> |
| 76 | + |
| 77 | + <div x-show="open" |
| 78 | + class="absolute right-0 mt-2 w-64 bg-white dark:bg-gray-900 |
| 79 | + border border-gray-200 dark:border-gray-700 |
| 80 | + rounded-xl shadow-xl p-3 text-xs space-y-2 |
| 81 | + transition-all duration-200 z-50" |
| 82 | + x-transition:enter="transition ease-out duration-200" |
| 83 | + x-transition:enter-start="opacity-0 translate-y-1" |
| 84 | + x-transition:enter-end="opacity-100 translate-y-0" |
| 85 | + x-transition:leave="transition ease-in duration-150" |
| 86 | + x-transition:leave-start="opacity-100 translate-y-0" |
| 87 | + x-transition:leave-end="opacity-0 translate-y-1"> |
| 88 | + |
| 89 | + <template x-for="exec in tabs[tab]?.runningList ?? []" :key="exec.id"> |
| 90 | + <a :href="'./TestCaseExecution.jsp?executionId=' + exec.id" |
| 91 | + class="block text-xs text-blue-500 hover:underline truncate"> |
| 92 | + <span x-text="exec.test"></span> - |
| 93 | + <span x-text="exec.testcase"></span> - |
| 94 | + <span x-text="exec.environment"></span> |
| 95 | + </a> |
| 96 | + </template> |
| 97 | + |
| 98 | + <div x-show="!(tabs[tab]?.runningList?.length)" class="text-gray-400"> |
| 99 | + No running executions |
| 100 | + </div> |
| 101 | + </div> |
| 102 | + </div> |
| 103 | + </div> |
| 104 | + |
| 105 | + </div> |
| 106 | + <div class="text-gray-500 text-sm mt-1 truncate" |
| 107 | + x-text="tabs[tab]?.label || ''"> |
95 | 108 | </div> |
96 | 109 | </div> |
97 | 110 |
|
| 111 | + <div |
| 112 | + x-show="tab === 'ongoing' && !tabs[tab]?.active" |
| 113 | + class="absolute inset-0 bg-white/70 flex items-center justify-center z-10"> |
| 114 | + |
| 115 | + <span class="text-black-500">No Data</span> |
| 116 | + |
| 117 | + </div> |
98 | 118 | </div> |
99 | 119 |
|
100 | | - <div class="text-gray-500 text-sm mt-1 truncate" |
101 | | - x-text="tabs[tab]?.label || ''"></div> |
102 | 120 |
|
103 | 121 | </div> |
104 | 122 | </template> |
|
145 | 163 | this.tab = keys.length ? keys[0] : ''; |
146 | 164 | for (let key in this.tabs) { |
147 | 165 | if (this.tabs[key]?.diff !== undefined) { |
148 | | - const { icon, color } = getDiffIconAndColor(this.tabs[key].diff); |
| 166 | + const {icon, color} = getDiffIconAndColor(this.tabs[key].diff); |
149 | 167 | this.tabs[key].diffIcon = icon; |
150 | 168 | this.tabs[key].diffColor = color; |
151 | 169 | } |
152 | 170 | } |
153 | 171 |
|
154 | 172 | window.addEventListener("queue-stats-updated", (event) => { |
155 | 173 | const data = event.detail; |
| 174 | + if (!this.tabs.ongoing) |
| 175 | + return; |
| 176 | + |
| 177 | +// console.info(event); |
| 178 | + |
| 179 | + // label |
| 180 | + this.tabs.ongoing.active = (data?.active || true) ? true : false; |
156 | 181 |
|
157 | | - if (!this.tabs.ongoing) return; |
| 182 | + // label |
| 183 | + this.tabs.ongoing.label = (data.queueStats?.running || 0) > 0 ? "Currently Executing" : "No execution running"; |
158 | 184 |
|
159 | 185 | // compteur principal |
160 | 186 | this.tabs.ongoing.value = data.queueStats?.running || 0; |
|
177 | 203 | } |
178 | 204 |
|
179 | 205 | function getDiffIconAndColor(diff, diffPositive = true) { |
180 | | - if (diff > 0) return diffPositive ? { icon: 'trending-up', color: 'text-green-500' } |
181 | | - : { icon: 'trending-up', color: 'text-red-500' }; |
182 | | - if (diff < 0) return diffPositive ? { icon: 'trending-down', color: 'text-red-500' } |
183 | | - : { icon: 'trending-down', color: 'text-green-500' }; |
184 | | - return { icon: 'minus', color: 'text-orange-500' }; |
| 206 | + if (diff > 0) |
| 207 | + return diffPositive ? {icon: 'trending-up', color: 'text-green-500'} |
| 208 | + : {icon: 'trending-up', color: 'text-red-500'}; |
| 209 | + if (diff < 0) |
| 210 | + return diffPositive ? {icon: 'trending-down', color: 'text-red-500'} |
| 211 | + : {icon: 'trending-down', color: 'text-green-500'}; |
| 212 | + return {icon: 'minus', color: 'text-orange-500'}; |
185 | 213 | } |
186 | 214 |
|
187 | 215 | function computeDiffPercent(currentValue, previousValue) { |
188 | | - if (previousValue === 0) return "—"; // éviter division par zéro |
| 216 | + if (previousValue === 0) |
| 217 | + return "—"; // éviter division par zéro |
189 | 218 | return ((currentValue - previousValue) / previousValue * 100).toFixed(1) + "%"; |
190 | 219 | } |
191 | 220 |
|
192 | 221 | function formatTokens(value) { |
193 | | - if (value >= 1_000_000) return (value / 1_000_000).toFixed(1) + "M"; |
194 | | - if (value >= 1_000) return (value / 1_000).toFixed(1) + "K"; |
| 222 | + if (value >= 1_000_000) |
| 223 | + return (value / 1_000_000).toFixed(1) + "M"; |
| 224 | + if (value >= 1_000) |
| 225 | + return (value / 1_000).toFixed(1) + "K"; |
195 | 226 | return value.toString(); |
196 | 227 | } |
197 | 228 |
|
|
0 commit comments