| OLD | NEW |
| (Empty) |
| 1 {% extends "swarming/base.html" %} | |
| 2 | |
| 3 | |
| 4 {% block headers %} | |
| 5 <style> | |
| 6 h1 { | |
| 7 margin-top: 10px; | |
| 8 margin-bottom: 10px; | |
| 9 } | |
| 10 | |
| 11 table.layout_table { | |
| 12 border-spacing: 0; | |
| 13 font-family: monospace; | |
| 14 } | |
| 15 | |
| 16 table.layout_table thead { | |
| 17 background-color: #C0C0C0; | |
| 18 font-weight:bold; | |
| 19 } | |
| 20 | |
| 21 table.layout_table tbody tr:nth-child(even) { | |
| 22 background-color: #eeeeee; | |
| 23 } | |
| 24 | |
| 25 table.layout_table td:first-child { | |
| 26 border-color: black; | |
| 27 border-right: thin solid; | |
| 28 padding-right: 1em; | |
| 29 } | |
| 30 | |
| 31 table.layout_table td:nth-child(2) { | |
| 32 padding-left: 1em; | |
| 33 } | |
| 34 | |
| 35 table.layout_table td:nth-child(4) { | |
| 36 border-color: black; | |
| 37 border-right: thin solid; | |
| 38 padding-right: 1em; | |
| 39 } | |
| 40 | |
| 41 table.layout_table td:nth-child(5) { | |
| 42 border-color: black; | |
| 43 border-right: thin solid; | |
| 44 padding-left: 1em; | |
| 45 padding-right: 1em; | |
| 46 } | |
| 47 | |
| 48 table.layout_table td:nth-child(6) { | |
| 49 padding-left: 1em; | |
| 50 padding-right: 0.5em; | |
| 51 } | |
| 52 | |
| 53 table.alterning_background td:nth-child(3) { | |
| 54 text-align: center; | |
| 55 white-space: nowrap; | |
| 56 } | |
| 57 | |
| 58 table.alterning_background td:nth-child(4) { | |
| 59 text-align: right; | |
| 60 white-space: nowrap; | |
| 61 } | |
| 62 | |
| 63 table.alterning_background td:nth-child(5) { | |
| 64 text-align: right; | |
| 65 white-space: nowrap; | |
| 66 } | |
| 67 | |
| 68 table.alterning_background td:nth-child(6) { | |
| 69 white-space: nowrap; | |
| 70 } | |
| 71 | |
| 72 table.alterning_background td:nth-child(7) { | |
| 73 text-align: right; | |
| 74 white-space: nowrap; | |
| 75 } | |
| 76 | |
| 77 #limitRange { | |
| 78 width: inherit; | |
| 79 } | |
| 80 </style> | |
| 81 <script> | |
| 82 function radio_value(field) { | |
| 83 var radios = document.getElementsByName(field); | |
| 84 for (var i = 0, length = radios.length; i < length; i++) { | |
| 85 if (radios[i].checked) { | |
| 86 return radios[i].value; | |
| 87 } | |
| 88 } | |
| 89 } | |
| 90 | |
| 91 function get_limit() { | |
| 92 return document.getElementById('limitText').value; | |
| 93 } | |
| 94 | |
| 95 function update_limit_text(val) { | |
| 96 document.getElementById('limitText').value = val; | |
| 97 } | |
| 98 | |
| 99 function update_limit_range(val) { | |
| 100 document.getElementById('limitRange').value = val; | |
| 101 } | |
| 102 | |
| 103 function update_sort() { | |
| 104 // This resets the cursor and filters. | |
| 105 var sort = radio_value("sort"); | |
| 106 var url = '/user/tasks?sort=' + sort + '&limit=' + get_limit(); | |
| 107 document.location.href = url; | |
| 108 } | |
| 109 | |
| 110 function update_filter() { | |
| 111 // This resets the cursor, sort and task name. | |
| 112 var task_tag = document.getElementById("task_tag").value; | |
| 113 var url = '/user/tasks?state=' + encodeURIComponent(radio_value("state")) + | |
| 114 '&limit=' + encodeURIComponent(get_limit()) + | |
| 115 '&task_tag=' + encodeURIComponent(task_tag); | |
| 116 document.location.href = url; | |
| 117 } | |
| 118 </script> | |
| 119 {% endblock %} | |
| 120 | |
| 121 | |
| 122 {% block body %} | |
| 123 {% import 'swarming/bot_view.html' as bot_view %} | |
| 124 | |
| 125 <h1>Tasks</h1> | |
| 126 <a href="/">Back to root</a> | |
| 127 <br/> | |
| 128 <a href="{{try_link}}">Try out the new task list UI</a> | |
| 129 <p> | |
| 130 <form id="filter" name="filter" method="GET"> | |
| 131 <input type="range" id="limitRange" name="limit" value="{{limit}}" min=10 | |
| 132 max=500 step=5 onchange="update_limit_text(this.value);" | |
| 133 onmousemove="update_limit_text(this.value);" > | |
| 134 <input type="text" id="limitText" value="{{limit}}" maxlength="3" | |
| 135 onchange="update_limit_range(this.value);"> | |
| 136 <input type="submit" value="Set limit"> | |
| 137 <p> | |
| 138 <table class=layout_table title="Select order and filter"> | |
| 139 <thead> | |
| 140 <tr> | |
| 141 <td align=center>Sort</td> | |
| 142 <td></td> | |
| 143 <td>State (total last 24h)</td> | |
| 144 <td></td> | |
| 145 <td>Search by tag</td> | |
| 146 </tr> | |
| 147 </thead> | |
| 148 <tbody> | |
| 149 <tr> | |
| 150 <td> | |
| 151 {% for key, name, item_title in sort_choices %} | |
| 152 <label title="{{item_title}}"> | |
| 153 <input type="radio" name="sort" value="{{key}}" | |
| 154 onchange="update_sort()" | |
| 155 {% if sort == key %}checked{%endif%}> | |
| 156 {{name}} | |
| 157 </input> | |
| 158 </label> | |
| 159 <br> | |
| 160 {% endfor %} | |
| 161 </td> | |
| 162 {% for state_column in state_choices %} | |
| 163 <td> | |
| 164 {% for key, name, item_title in state_column %} | |
| 165 <label title="{{item_title}}"> | |
| 166 <input type="radio" name="state" value="{{key}}" | |
| 167 onchange="update_filter()" | |
| 168 {% if state == key %}checked{%endif%}> | |
| 169 {{name}} | |
| 170 </input> | |
| 171 </label> | |
| 172 <br> | |
| 173 {% endfor %} | |
| 174 </td> | |
| 175 {% endfor %} | |
| 176 <td> | |
| 177 <div title="Task tags uses whole tag search ONLY. Using it resets sort t
o 'Created' and the task state filter to 'All'."> | |
| 178 Task tags<br> | |
| 179 (whole tag only, 1 per line) | |
| 180 <br> | |
| 181 <textarea id="task_tag" name="task_tag" rows="3" cols="30">{{task_tag}
}</textarea> | |
| 182 <br> | |
| 183 <input type="submit" value="Search"> | |
| 184 </div> | |
| 185 </td> | |
| 186 </tr> | |
| 187 <tbody> | |
| 188 </table> | |
| 189 </form> | |
| 190 <br> | |
| 191 | |
| 192 | |
| 193 {% macro total_pending_star() %} | |
| 194 {% if has_pending %}*{% endif %} | |
| 195 {% endmacro %} | |
| 196 | |
| 197 | |
| 198 {% macro total_running_star() %} | |
| 199 {% if has_running %}*{% endif %} | |
| 200 {% endmacro %} | |
| 201 | |
| 202 | |
| 203 {% macro next_page_link() %} | |
| 204 {% if cursor %} | |
| 205 <p> | |
| 206 {% if task_tag %} | |
| 207 <a href="/user/tasks?limit={{limit}}&state={{state}}&task_tag={{task_tag|urlen
code}}&cursor={{cursor|urlencode}}">Next page</a> | |
| 208 {% else %} | |
| 209 <a href="/user/tasks?limit={{limit}}&state={{state}}&sort={{sort}}&cursor={{cu
rsor|urlencode}}">Next page</a> | |
| 210 {% endif %} | |
| 211 {% endif %} | |
| 212 {% endmacro %} | |
| 213 | |
| 214 | |
| 215 {% if tasks %} | |
| 216 <table id="request-table" class="alterning_background" | |
| 217 summary="This table lists all test requests"> | |
| 218 <thead> | |
| 219 <th>Name</th> | |
| 220 <th>Status</th> | |
| 221 <th>Requested</th> | |
| 222 <th>Pending</th> | |
| 223 <th>Duration</th> | |
| 224 <th>$USD</th> | |
| 225 <th>User</th> | |
| 226 <th>Bot</th> | |
| 227 <th>Priority</th> | |
| 228 </thead> | |
| 229 <tbody> | |
| 230 {% for task in tasks %} | |
| 231 <tr class="request {% if task.failure or task.internal_failure or task.i
s_exceptional %}failed_test{% endif%}"> | |
| 232 <td> | |
| 233 <a href="/user/task/{{task.task_id}}">{{task.name}}</a> | |
| 234 </td> | |
| 235 <td> | |
| 236 {{task.to_string()|safe}} | |
| 237 {% if task.request.has_access and task.can_be_canceled %} | |
| 238 <form id="cancel_{{task.task_id}}" method="POST" | |
| 239 action="/user/task/{{task.task_id}}/cancel" | |
| 240 style="display:inline"> | |
| 241 <input type="hidden" name="redirect_to" value="listing" /> | |
| 242 <input type="hidden" name="xsrf_token" value="{{xsrf_token}}" /> | |
| 243 <input type="submit" value="Cancel" style="display:inline"></inp
ut> | |
| 244 </form> | |
| 245 {% endif %} | |
| 246 </td> | |
| 247 <td>{{task.created_ts|succinctdatetimeformat}}</td> | |
| 248 <td> | |
| 249 {{bot_view.pending_star(task)}}{{task.pending_now(now)|timedeltaform
at}} | |
| 250 </td> | |
| 251 <td> | |
| 252 {{bot_view.running_star(task)}} | |
| 253 {% if task.deduped_from %} | |
| 254 <span title="Duration of the original task. This task wasn't actua
lly run as it was deduped." | |
| 255 style="color:green"> | |
| 256 {{task.duration_now(now)|timedeltaformat}} | |
| 257 </span> | |
| 258 {% else %} | |
| 259 {{task.duration_now(now)|timedeltaformat}} | |
| 260 {% endif %} | |
| 261 </td> | |
| 262 <td> | |
| 263 {% if task.cost_usd %} | |
| 264 {{task.cost_usd|round(4) }} $ | |
| 265 {% elif task.cost_saved_usd %} | |
| 266 <span style="color:green">-{{task.cost_saved_usd|round(4) }} $</sp
an> | |
| 267 {% else %} | |
| 268 ‑‑ | |
| 269 {% endif %} | |
| 270 </td> | |
| 271 <td> | |
| 272 {% if task.user %} | |
| 273 <a href="/user/tasks?task_tag=user:{{task.user}}&limit={{limit}}">
{{task.user}}</a> | |
| 274 {% else %} | |
| 275 ‑‑ | |
| 276 {% endif %} | |
| 277 </td> | |
| 278 <td>{{bot_view.bot_link(task.bot_id, is_privileged_user)}}</td> | |
| 279 <td>{{task.request.priority}}</td> | |
| 280 </tr> | |
| 281 {% endfor %} | |
| 282 {% if show_footer %} | |
| 283 <tr> | |
| 284 <td> </td> | |
| 285 <td></td> | |
| 286 <td></td> | |
| 287 <td></td> | |
| 288 <td></td> | |
| 289 <td></td> | |
| 290 <td></td> | |
| 291 <td></td> | |
| 292 </tr> | |
| 293 {% endif %} | |
| 294 </tbody> | |
| 295 {% if show_footer %} | |
| 296 <tfoot> | |
| 297 <tr> | |
| 298 <td>{{ next_page_link() }}</td> | |
| 299 <td></td> | |
| 300 <td><strong>Median</strong></td> | |
| 301 <td> | |
| 302 {{total_pending_star()}}{{pending_median|timedeltaformat}} | |
| 303 </td> | |
| 304 <td> | |
| 305 {{total_running_star()}}{{duration_median|timedeltaformat}} | |
| 306 </td> | |
| 307 <td></td> | |
| 308 <td></td> | |
| 309 </tr> | |
| 310 <tr> | |
| 311 <td></td> | |
| 312 <td><strong>Total: </strong>{{tasks|length}}</td> | |
| 313 <td><strong>Average</strong></td> | |
| 314 <td> | |
| 315 {{total_pending_star()}}{{pending_average|timedeltaformat}} | |
| 316 </td> | |
| 317 <td> | |
| 318 {{total_running_star()}}{{duration_average|timedeltaformat}} | |
| 319 </td> | |
| 320 <td></td> | |
| 321 <td></td> | |
| 322 <td></td> | |
| 323 </tr> | |
| 324 <tr> | |
| 325 <td></td> | |
| 326 <td></td> | |
| 327 <td><strong>Sum</strong></td> | |
| 328 <td> | |
| 329 {{total_pending_star()}}{{pending_sum|timedeltaformat}} | |
| 330 </td> | |
| 331 <td> | |
| 332 {{total_running_star()}}{{duration_sum|timedeltaformat}} | |
| 333 </td> | |
| 334 <td> | |
| 335 {% if total_cost_usd %} | |
| 336 {{total_cost_usd|round(4) }} $ | |
| 337 {% else %} | |
| 338 ‑‑ | |
| 339 {% endif %} | |
| 340 </td> | |
| 341 <td></td> | |
| 342 <td></td> | |
| 343 </tr> | |
| 344 <tr> | |
| 345 <td></td> | |
| 346 <td></td> | |
| 347 <td><strong>Saved by deduping</strong></td> | |
| 348 <td></td> | |
| 349 <td> | |
| 350 {{total_saved|timedeltaformat}} | |
| 351 </td> | |
| 352 <td> | |
| 353 {% if total_cost_saved_usd %} | |
| 354 <span style="color:green">{{total_cost_saved_usd|round(4) }} $</sp
an> | |
| 355 {% else %} | |
| 356 ‑‑ | |
| 357 {% endif %} | |
| 358 </td> | |
| 359 <td> | |
| 360 ({{'%1.1f' % total_saved_percent}}%) | |
| 361 </td> | |
| 362 <td></td> | |
| 363 <td></td> | |
| 364 </tr> | |
| 365 </tfoot> | |
| 366 {% else %} | |
| 367 {{ next_page_link() }} | |
| 368 {% endif %} | |
| 369 </table> | |
| 370 {% else %} | |
| 371 No data to show for this selection. | |
| 372 {% endif %} | |
| 373 | |
| 374 {% endblock %} | |
| OLD | NEW |