Timo Tijhof | 51516cd | 2013-04-09 01:32:29 +0200 | [diff] [blame] | 1 | // Client script for Zuul status page |
| 2 | // |
| 3 | // Copyright 2012 OpenStack Foundation |
| 4 | // Copyright 2013 Timo Tijhof |
| 5 | // Copyright 2013 Wikimedia Foundation |
Joshua Hesketh | 6b1a218 | 2014-03-21 14:40:04 +1100 | [diff] [blame] | 6 | // Copyright 2014 Rackspace Australia |
Timo Tijhof | 51516cd | 2013-04-09 01:32:29 +0200 | [diff] [blame] | 7 | // |
| 8 | // Licensed under the Apache License, Version 2.0 (the "License"); you may |
| 9 | // not use this file except in compliance with the License. You may obtain |
| 10 | // a copy of the License at |
| 11 | // |
| 12 | // http://www.apache.org/licenses/LICENSE-2.0 |
| 13 | // |
| 14 | // Unless required by applicable law or agreed to in writing, software |
| 15 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| 16 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| 17 | // License for the specific language governing permissions and limitations |
| 18 | // under the License. |
| 19 | |
| 20 | (function ($) { |
Joshua Hesketh | 4863b60 | 2014-03-21 14:19:06 +1100 | [diff] [blame] | 21 | var $container, $msg, $indicator, $queueInfo, $queueEventsNum, |
Joshua Hesketh | cbdcca1 | 2014-03-20 16:06:25 +1100 | [diff] [blame] | 22 | $queueResultsNum, $pipelines, $jq; |
Joshua Hesketh | 298c491 | 2014-03-20 16:06:25 +1100 | [diff] [blame] | 23 | var xhr, zuul, |
Joshua Hesketh | ace4889 | 2014-03-22 17:18:31 +1100 | [diff] [blame] | 24 | current_filter = '', |
Timo Tijhof | 51516cd | 2013-04-09 01:32:29 +0200 | [diff] [blame] | 25 | demo = location.search.match(/[?&]demo=([^?&]*)/), |
Joshua Hesketh | 668700b | 2014-03-21 14:25:53 +1100 | [diff] [blame] | 26 | source_url = location.search.match(/[?&]source_url=([^?&]*)/), |
Timo Tijhof | 51516cd | 2013-04-09 01:32:29 +0200 | [diff] [blame] | 27 | source = demo ? |
| 28 | './status-' + (demo[1] || 'basic') + '.json-sample' : |
James E. Blair | 7c7ed7a | 2013-05-15 13:13:26 -0700 | [diff] [blame] | 29 | 'status.json'; |
Joshua Hesketh | 668700b | 2014-03-21 14:25:53 +1100 | [diff] [blame] | 30 | source = source_url ? source_url[1] : source; |
Timo Tijhof | 51516cd | 2013-04-09 01:32:29 +0200 | [diff] [blame] | 31 | |
Joshua Hesketh | ace4889 | 2014-03-22 17:18:31 +1100 | [diff] [blame] | 32 | function set_cookie(name, value) { |
| 33 | document.cookie = name + "=" + value + "; path=/"; |
| 34 | } |
| 35 | |
| 36 | function read_cookie(name, default_value) { |
| 37 | var nameEQ = name + "="; |
| 38 | var ca = document.cookie.split(';'); |
| 39 | for(var i=0;i < ca.length;i++) { |
| 40 | var c = ca[i]; |
| 41 | while (c.charAt(0) == ' ') c = c.substring(1, c.length); |
| 42 | if (c.indexOf(nameEQ) == 0) { |
| 43 | return c.substring(nameEQ.length, c.length); |
| 44 | } |
| 45 | } |
| 46 | return default_value; |
| 47 | } |
| 48 | |
| 49 | |
Timo Tijhof | 51516cd | 2013-04-09 01:32:29 +0200 | [diff] [blame] | 50 | zuul = { |
| 51 | enabled: true, |
Joshua Hesketh | db8046e | 2014-03-21 18:42:25 +1100 | [diff] [blame] | 52 | collapsed_exceptions: [], |
Timo Tijhof | 51516cd | 2013-04-09 01:32:29 +0200 | [diff] [blame] | 53 | |
| 54 | schedule: function () { |
| 55 | if (!zuul.enabled) { |
| 56 | setTimeout(zuul.schedule, 5000); |
| 57 | return; |
| 58 | } |
| 59 | zuul.update().complete(function () { |
| 60 | setTimeout(zuul.schedule, 5000); |
| 61 | }); |
| 62 | }, |
| 63 | |
| 64 | /** @return {jQuery.Promise} */ |
| 65 | update: function () { |
| 66 | // Cancel the previous update if it hasn't completed yet. |
| 67 | if (xhr) { |
| 68 | xhr.abort(); |
| 69 | } |
| 70 | |
| 71 | zuul.emit('update-start'); |
| 72 | |
Joshua Hesketh | 298c491 | 2014-03-20 16:06:25 +1100 | [diff] [blame] | 73 | xhr = $.getJSON(source) |
| 74 | .done(function (data) { |
| 75 | if ('message' in data) { |
Joshua Hesketh | 4863b60 | 2014-03-21 14:19:06 +1100 | [diff] [blame] | 76 | $msg.removeClass('alert-danger').addClass('alert-info'); |
Joshua Hesketh | 298c491 | 2014-03-20 16:06:25 +1100 | [diff] [blame] | 77 | $msg.text(data.message); |
Joshua Hesketh | 4863b60 | 2014-03-21 14:19:06 +1100 | [diff] [blame] | 78 | $msg.show(); |
Joshua Hesketh | 298c491 | 2014-03-20 16:06:25 +1100 | [diff] [blame] | 79 | } else { |
| 80 | $msg.empty(); |
Joshua Hesketh | 4863b60 | 2014-03-21 14:19:06 +1100 | [diff] [blame] | 81 | $msg.hide(); |
Joshua Hesketh | 298c491 | 2014-03-20 16:06:25 +1100 | [diff] [blame] | 82 | } |
Timo Tijhof | 51516cd | 2013-04-09 01:32:29 +0200 | [diff] [blame] | 83 | |
Joshua Hesketh | 298c491 | 2014-03-20 16:06:25 +1100 | [diff] [blame] | 84 | if ('zuul_version' in data) { |
| 85 | $('#zuul-version-span').text(data['zuul_version']); |
| 86 | } |
| 87 | if ('last_reconfigured' in data) { |
| 88 | var last_reconfigured = |
| 89 | new Date(data['last_reconfigured']); |
| 90 | $('#last-reconfigured-span').text( |
| 91 | last_reconfigured.toString()); |
| 92 | } |
| 93 | |
| 94 | $pipelines.html(''); |
| 95 | $.each(data.pipelines, function (i, pipeline) { |
| 96 | $pipelines.append(zuul.format.pipeline(pipeline)); |
| 97 | }); |
| 98 | |
| 99 | $queueEventsNum.text( |
| 100 | data.trigger_event_queue ? |
| 101 | data.trigger_event_queue.length : '0' |
| 102 | ); |
| 103 | $queueResultsNum.text( |
| 104 | data.result_event_queue ? |
| 105 | data.result_event_queue.length : '0' |
| 106 | ); |
| 107 | }) |
| 108 | .fail(function (err, jqXHR, errMsg) { |
| 109 | $msg.text(source + ': ' + errMsg).show(); |
Timo Tijhof | 51516cd | 2013-04-09 01:32:29 +0200 | [diff] [blame] | 110 | $msgWrap.removeClass('zuul-msg-wrap-off'); |
Joshua Hesketh | 298c491 | 2014-03-20 16:06:25 +1100 | [diff] [blame] | 111 | }) |
| 112 | .complete(function () { |
| 113 | xhr = undefined; |
| 114 | zuul.emit('update-end'); |
Timo Tijhof | 51516cd | 2013-04-09 01:32:29 +0200 | [diff] [blame] | 115 | }); |
| 116 | |
Timo Tijhof | 51516cd | 2013-04-09 01:32:29 +0200 | [diff] [blame] | 117 | return xhr; |
| 118 | }, |
| 119 | |
| 120 | format: { |
Joshua Hesketh | 6b1a218 | 2014-03-21 14:40:04 +1100 | [diff] [blame] | 121 | job: function(job) { |
| 122 | if (job.url !== null) { |
| 123 | $job_line = $('<a href="' + job.url + '" />'); |
| 124 | } |
| 125 | else{ |
| 126 | $job_line = $('<span />'); |
| 127 | } |
| 128 | $job_line.text(job.name) |
| 129 | .append(zuul.format.job_status(job)); |
| 130 | |
| 131 | if (job.voting === false) { |
| 132 | $job_line.append( |
| 133 | $(' <small />').text(' (non-voting)') |
| 134 | ); |
| 135 | } |
| 136 | return $job_line; |
| 137 | }, |
| 138 | |
| 139 | job_status: function(job) { |
| 140 | var result = job.result ? job.result.toLowerCase() : null; |
| 141 | if (result === null) { |
| 142 | result = job.url ? 'in progress' : 'queued'; |
| 143 | } |
| 144 | |
| 145 | if (result == 'in progress') { |
Joshua Hesketh | f1b06ca | 2014-03-21 17:01:12 +1100 | [diff] [blame] | 146 | return zuul.format.job_progress_bar(job.elapsed_time, |
| 147 | job.remaining_time); |
Joshua Hesketh | 6b1a218 | 2014-03-21 14:40:04 +1100 | [diff] [blame] | 148 | } |
| 149 | else { |
| 150 | return zuul.format.status_label(result); |
| 151 | } |
| 152 | }, |
| 153 | |
| 154 | status_label: function(result) { |
| 155 | $status = $('<span />'); |
Joshua Hesketh | f1b06ca | 2014-03-21 17:01:12 +1100 | [diff] [blame] | 156 | $status.addClass('zuul-job-result label'); |
Joshua Hesketh | 6b1a218 | 2014-03-21 14:40:04 +1100 | [diff] [blame] | 157 | |
| 158 | switch (result) { |
| 159 | case 'success': |
| 160 | $status.addClass('label-success'); |
| 161 | break; |
| 162 | case 'failure': |
| 163 | $status.addClass('label-danger'); |
| 164 | break; |
| 165 | case 'unstable': |
| 166 | $status.addClass('label-warning'); |
| 167 | break; |
| 168 | case 'in progress': |
| 169 | case 'queued': |
| 170 | case 'lost': |
| 171 | $status.addClass('label-default'); |
| 172 | break; |
| 173 | } |
| 174 | $status.text(result); |
| 175 | return $status; |
| 176 | }, |
| 177 | |
Joshua Hesketh | f1b06ca | 2014-03-21 17:01:12 +1100 | [diff] [blame] | 178 | job_progress_bar: function(elapsed_time, remaining_time) { |
Joshua Hesketh | 6b1a218 | 2014-03-21 14:40:04 +1100 | [diff] [blame] | 179 | var progress_percent = 100 * (elapsed_time / (elapsed_time + |
| 180 | remaining_time)); |
| 181 | var $bar_inner = $('<div />') |
| 182 | .addClass('progress-bar') |
| 183 | .attr('role', 'progressbar') |
| 184 | .attr('aria-valuenow', 'progressbar') |
| 185 | .attr('aria-valuemin', progress_percent) |
| 186 | .attr('aria-valuemin', '0') |
| 187 | .attr('aria-valuemax', '100') |
| 188 | .css('width', progress_percent + '%'); |
| 189 | |
| 190 | var $bar_outter = $('<div />') |
Joshua Hesketh | f1b06ca | 2014-03-21 17:01:12 +1100 | [diff] [blame] | 191 | .addClass('progress zuul-job-result') |
Joshua Hesketh | 6b1a218 | 2014-03-21 14:40:04 +1100 | [diff] [blame] | 192 | .append($bar_inner); |
| 193 | |
| 194 | return $bar_outter; |
| 195 | }, |
| 196 | |
Joshua Hesketh | 0ca1e2e | 2014-03-21 16:49:05 +1100 | [diff] [blame] | 197 | enqueue_time: function(ms) { |
| 198 | // Special format case for enqueue time to add style |
| 199 | var hours = 60 * 60 * 1000; |
| 200 | var now = Date.now(); |
| 201 | var delta = now - ms; |
| 202 | var status = "text-success"; |
| 203 | var text = zuul.format.time(delta, true); |
| 204 | if (delta > (4 * hours)) { |
| 205 | status = "text-danger"; |
| 206 | } else if (delta > (2 * hours)) { |
| 207 | status = "text-warning"; |
| 208 | } |
| 209 | return '<span class="' + status + '">' + text + '</span>'; |
| 210 | }, |
| 211 | |
Joshua Hesketh | 6b1a218 | 2014-03-21 14:40:04 +1100 | [diff] [blame] | 212 | time: function(ms, words) { |
| 213 | if (typeof(words) === 'undefined') words = false; |
| 214 | var seconds = (+ms)/1000; |
| 215 | var minutes = Math.floor(seconds/60); |
| 216 | var hours = Math.floor(minutes/60); |
| 217 | seconds = Math.floor(seconds % 60); |
| 218 | minutes = Math.floor(minutes % 60); |
| 219 | r = ''; |
| 220 | if (words) { |
| 221 | if (hours) { |
| 222 | r += hours; |
| 223 | r += ' hr '; |
| 224 | } |
| 225 | r += minutes + ' min'; |
| 226 | } else { |
| 227 | if (hours < 10) r += '0'; |
| 228 | r += hours + ':'; |
| 229 | if (minutes < 10) r += '0'; |
| 230 | r += minutes + ':'; |
| 231 | if (seconds < 10) r += '0'; |
| 232 | r += seconds; |
| 233 | } |
| 234 | return r; |
| 235 | }, |
| 236 | |
Joshua Hesketh | f1b06ca | 2014-03-21 17:01:12 +1100 | [diff] [blame] | 237 | change_total_progress_bar: function(change) { |
| 238 | job_percent = Math.floor(100 / change.jobs.length); |
| 239 | var $bar_outter = $('<div />') |
| 240 | .addClass('progress zuul-change-total-result'); |
| 241 | |
| 242 | $.each(change.jobs, function (i, job) { |
| 243 | var result = job.result ? job.result.toLowerCase() : null; |
| 244 | if (result === null) { |
| 245 | result = job.url ? 'in progress' : 'queued'; |
| 246 | } |
| 247 | |
| 248 | if (result != 'queued') { |
| 249 | var $bar_inner = $('<div />') |
| 250 | .addClass('progress-bar'); |
| 251 | |
| 252 | switch (result) { |
| 253 | case 'success': |
| 254 | $bar_inner.addClass('progress-bar-success'); |
| 255 | break; |
| 256 | case 'lost': |
| 257 | case 'failure': |
| 258 | $bar_inner.addClass('progress-bar-danger'); |
| 259 | break; |
| 260 | case 'unstable': |
| 261 | $bar_inner.addClass('progress-bar-warning'); |
| 262 | break; |
| 263 | case 'in progress': |
| 264 | case 'queued': |
| 265 | break; |
| 266 | } |
| 267 | $bar_inner.attr('title', job.name) |
| 268 | .css('width', job_percent + '%'); |
| 269 | $bar_outter.append($bar_inner); |
| 270 | } |
| 271 | }); |
| 272 | return $bar_outter; |
| 273 | }, |
| 274 | |
Joshua Hesketh | 0ca1e2e | 2014-03-21 16:49:05 +1100 | [diff] [blame] | 275 | change_header: function(change) { |
| 276 | change_id = change.id || 'NA'; |
| 277 | if (change_id.length === 40) { |
| 278 | change_id = change_id.substr(0, 7); |
Joshua Hesketh | 298c491 | 2014-03-20 16:06:25 +1100 | [diff] [blame] | 279 | } |
Timo Tijhof | 51516cd | 2013-04-09 01:32:29 +0200 | [diff] [blame] | 280 | |
Joshua Hesketh | 0ca1e2e | 2014-03-21 16:49:05 +1100 | [diff] [blame] | 281 | $change_link = $('<small />'); |
Joshua Hesketh | 298c491 | 2014-03-20 16:06:25 +1100 | [diff] [blame] | 282 | if (change.url !== null) { |
Joshua Hesketh | 0ca1e2e | 2014-03-21 16:49:05 +1100 | [diff] [blame] | 283 | $change_link.append( |
Joshua Hesketh | 298c491 | 2014-03-20 16:06:25 +1100 | [diff] [blame] | 284 | $("<a />").attr("href", change.url).text(change.id) |
| 285 | ); |
Timo Tijhof | 51516cd | 2013-04-09 01:32:29 +0200 | [diff] [blame] | 286 | } |
Joshua Hesketh | 298c491 | 2014-03-20 16:06:25 +1100 | [diff] [blame] | 287 | else { |
Joshua Hesketh | 0ca1e2e | 2014-03-21 16:49:05 +1100 | [diff] [blame] | 288 | $change_link.text(change_id); |
Timo Tijhof | 51516cd | 2013-04-09 01:32:29 +0200 | [diff] [blame] | 289 | } |
Timo Tijhof | 51516cd | 2013-04-09 01:32:29 +0200 | [diff] [blame] | 290 | |
Joshua Hesketh | f1b06ca | 2014-03-21 17:01:12 +1100 | [diff] [blame] | 291 | $change_progress_row_left = $('<div />') |
| 292 | .addClass('col-xs-3') |
| 293 | .append($change_link); |
| 294 | $change_progress_row_right = $('<div />') |
| 295 | .addClass('col-xs-9') |
| 296 | .append(zuul.format.change_total_progress_bar(change)) |
| 297 | |
| 298 | $change_progress_row = $('<div />') |
| 299 | .addClass('row') |
| 300 | .append($change_progress_row_left) |
| 301 | .append($change_progress_row_right) |
| 302 | |
Joshua Hesketh | ace4889 | 2014-03-22 17:18:31 +1100 | [diff] [blame] | 303 | $project_span = $('<span />') |
| 304 | .addClass('change_project') |
| 305 | .text(change.project); |
| 306 | |
Joshua Hesketh | 0ca1e2e | 2014-03-21 16:49:05 +1100 | [diff] [blame] | 307 | $left = $('<div />') |
| 308 | .addClass('col-xs-8') |
Joshua Hesketh | ace4889 | 2014-03-22 17:18:31 +1100 | [diff] [blame] | 309 | .append($project_span, $('<br />'), $change_progress_row); |
Joshua Hesketh | 0ca1e2e | 2014-03-21 16:49:05 +1100 | [diff] [blame] | 310 | |
| 311 | remaining_time = zuul.format.time(change.remaining_time, true); |
| 312 | enqueue_time = zuul.format.enqueue_time(change.enqueue_time); |
| 313 | $remaining_time = $('<small />').addClass('time') |
| 314 | .attr('title', 'Remaining Time').html(remaining_time); |
| 315 | $enqueue_time = $('<small />').addClass('time') |
| 316 | .attr('title', 'Elapsed Time').html(enqueue_time); |
| 317 | |
| 318 | $right = $('<div />') |
| 319 | .addClass('col-xs-4 text-right') |
| 320 | .append($remaining_time, $('<br />'), $enqueue_time); |
| 321 | |
| 322 | $header = $('<div />') |
| 323 | .addClass('row') |
| 324 | .append($left, $right); |
| 325 | return $header; |
| 326 | }, |
| 327 | |
| 328 | change_list: function(jobs) { |
Joshua Hesketh | 6b1a218 | 2014-03-21 14:40:04 +1100 | [diff] [blame] | 329 | var $list = $('<ul />') |
| 330 | .addClass('list-group'); |
| 331 | |
Joshua Hesketh | 0ca1e2e | 2014-03-21 16:49:05 +1100 | [diff] [blame] | 332 | $.each(jobs, function (i, job) { |
Joshua Hesketh | 6b1a218 | 2014-03-21 14:40:04 +1100 | [diff] [blame] | 333 | var $item = $('<li />') |
| 334 | .addClass('list-group-item') |
| 335 | .addClass('zuul-change-job') |
| 336 | .append(zuul.format.job(job)); |
Joshua Hesketh | 298c491 | 2014-03-20 16:06:25 +1100 | [diff] [blame] | 337 | $list.append($item); |
Timo Tijhof | 51516cd | 2013-04-09 01:32:29 +0200 | [diff] [blame] | 338 | }); |
| 339 | |
Joshua Hesketh | 0ca1e2e | 2014-03-21 16:49:05 +1100 | [diff] [blame] | 340 | return $list; |
| 341 | }, |
| 342 | |
| 343 | change_panel: function (change) { |
| 344 | var $header = $('<div />') |
Joshua Hesketh | db8046e | 2014-03-21 18:42:25 +1100 | [diff] [blame] | 345 | .addClass('panel-heading patchset-header') |
Joshua Hesketh | 0ca1e2e | 2014-03-21 16:49:05 +1100 | [diff] [blame] | 346 | .append(zuul.format.change_header(change)); |
| 347 | |
Joshua Hesketh | db8046e | 2014-03-21 18:42:25 +1100 | [diff] [blame] | 348 | var panel_id = change.id ? change.id.replace(',', '_') |
| 349 | : change.project.replace('/', '_') + |
| 350 | '-' + change.enqueue_time |
| 351 | var $panel = $('<div />') |
| 352 | .attr("id", panel_id) |
Joshua Hesketh | 0ca1e2e | 2014-03-21 16:49:05 +1100 | [diff] [blame] | 353 | .addClass('panel panel-default zuul-change') |
| 354 | .append($header) |
| 355 | .append(zuul.format.change_list(change.jobs)); |
Joshua Hesketh | db8046e | 2014-03-21 18:42:25 +1100 | [diff] [blame] | 356 | |
| 357 | $header.click(zuul.toggle_patchset); |
Joshua Hesketh | db8046e | 2014-03-21 18:42:25 +1100 | [diff] [blame] | 358 | return $panel; |
Timo Tijhof | 51516cd | 2013-04-09 01:32:29 +0200 | [diff] [blame] | 359 | }, |
| 360 | |
| 361 | pipeline: function (pipeline) { |
Joshua Hesketh | 298c491 | 2014-03-20 16:06:25 +1100 | [diff] [blame] | 362 | var $html = $('<div />') |
Joshua Hesketh | 4863b60 | 2014-03-21 14:19:06 +1100 | [diff] [blame] | 363 | .addClass('zuul-pipeline col-md-4') |
Joshua Hesketh | 298c491 | 2014-03-20 16:06:25 +1100 | [diff] [blame] | 364 | .append($('<h3 />').text(pipeline.name)); |
| 365 | |
Timo Tijhof | 51516cd | 2013-04-09 01:32:29 +0200 | [diff] [blame] | 366 | if (typeof pipeline.description === 'string') { |
Joshua Hesketh | 298c491 | 2014-03-20 16:06:25 +1100 | [diff] [blame] | 367 | $html.append( |
| 368 | $('<p />').append( |
| 369 | $('<small />').text(pipeline.description) |
| 370 | ) |
| 371 | ); |
Timo Tijhof | 51516cd | 2013-04-09 01:32:29 +0200 | [diff] [blame] | 372 | } |
| 373 | |
Joshua Hesketh | cbdcca1 | 2014-03-20 16:06:25 +1100 | [diff] [blame] | 374 | $.each(pipeline.change_queues, |
| 375 | function (queueNum, changeQueue) { |
Timo Tijhof | 51516cd | 2013-04-09 01:32:29 +0200 | [diff] [blame] | 376 | $.each(changeQueue.heads, function (headNum, changes) { |
Joshua Hesketh | cbdcca1 | 2014-03-20 16:06:25 +1100 | [diff] [blame] | 377 | if (pipeline.change_queues.length > 1 && |
| 378 | headNum === 0) { |
Timo Tijhof | 51516cd | 2013-04-09 01:32:29 +0200 | [diff] [blame] | 379 | var name = changeQueue.name; |
Joshua Hesketh | 6b1a218 | 2014-03-21 14:40:04 +1100 | [diff] [blame] | 380 | var short_name = name; |
| 381 | if (short_name.length > 32) { |
| 382 | short_name = short_name.substr(0, 32) + '...'; |
Timo Tijhof | 51516cd | 2013-04-09 01:32:29 +0200 | [diff] [blame] | 383 | } |
Joshua Hesketh | 298c491 | 2014-03-20 16:06:25 +1100 | [diff] [blame] | 384 | $html.append( |
| 385 | $('<p />') |
| 386 | .text('Queue: ') |
| 387 | .append( |
| 388 | $('<abbr />') |
| 389 | .attr('title', name) |
| 390 | .text(short_name) |
| 391 | ) |
| 392 | ); |
Timo Tijhof | 51516cd | 2013-04-09 01:32:29 +0200 | [diff] [blame] | 393 | } |
| 394 | $.each(changes, function (changeNum, change) { |
Joshua Hesketh | ace4889 | 2014-03-22 17:18:31 +1100 | [diff] [blame] | 395 | var $panel = zuul.format.change_panel(change); |
| 396 | $html.append($panel) |
| 397 | zuul.display_patchset($panel); |
Timo Tijhof | 51516cd | 2013-04-09 01:32:29 +0200 | [diff] [blame] | 398 | }); |
| 399 | }); |
| 400 | }); |
Joshua Hesketh | 298c491 | 2014-03-20 16:06:25 +1100 | [diff] [blame] | 401 | return $html; |
Joshua Hesketh | ace4889 | 2014-03-22 17:18:31 +1100 | [diff] [blame] | 402 | }, |
| 403 | |
| 404 | filter_form_group: function(default_text) { |
| 405 | // Update the filter form with a clear button if required |
| 406 | |
| 407 | var $label = $('<label />') |
| 408 | .addClass('control-label') |
| 409 | .attr('for', 'filter_string') |
| 410 | .text('Filters') |
| 411 | .css('padding-right', '0.5em'); |
| 412 | |
| 413 | var $input = $('<input />') |
| 414 | .attr('type', 'text') |
| 415 | .attr('id', 'filter_string') |
| 416 | .addClass('form-control') |
| 417 | .attr('title', |
| 418 | 'project(s), pipeline(s) or review(s) comma ' + |
| 419 | 'separated') |
| 420 | .attr('value', default_text); |
| 421 | |
| 422 | $input.change(zuul.handle_filter_change); |
| 423 | |
| 424 | var $clear_icon = $('<span />') |
| 425 | .addClass('form-control-feedback') |
| 426 | .addClass('glyphicon glyphicon-remove-circle') |
| 427 | .attr('id', 'filter_form_clear_box') |
| 428 | .attr('title', 'clear filter') |
| 429 | .css('cursor', 'pointer'); |
| 430 | |
| 431 | $clear_icon.click(function() { |
| 432 | $('#filter_string').val('').change(); |
| 433 | }); |
| 434 | |
| 435 | if (default_text == '') { |
| 436 | $clear_icon.hide(); |
| 437 | } |
| 438 | |
| 439 | var $form_group = $('<div />') |
| 440 | .addClass('form-group has-feedback') |
| 441 | .append($label, $input, $clear_icon); |
| 442 | return $form_group; |
| 443 | }, |
| 444 | |
Joshua Hesketh | ae230f6 | 2014-03-22 22:14:44 +1100 | [diff] [blame^] | 445 | expand_form_group: function() { |
| 446 | expand_by_default = ( |
| 447 | read_cookie('zuul_expand_by_default', false) === 'true'); |
| 448 | |
| 449 | $checkbox = $('<input />') |
| 450 | .attr('type', 'checkbox') |
| 451 | .attr('id', 'expand_by_default') |
| 452 | .prop('checked', expand_by_default) |
| 453 | .change(zuul.handle_expand_by_default); |
| 454 | |
| 455 | $label = $('<label />') |
| 456 | .css('padding-left', '1em') |
| 457 | .html('Expand by default: ') |
| 458 | .append($checkbox); |
| 459 | |
| 460 | var $form_group = $('<div />') |
| 461 | .addClass('checkbox') |
| 462 | .append($label); |
| 463 | return $form_group; |
| 464 | }, |
| 465 | |
| 466 | control_form: function() { |
Joshua Hesketh | ace4889 | 2014-03-22 17:18:31 +1100 | [diff] [blame] | 467 | // Build the filter form filling anything from cookies |
| 468 | |
Joshua Hesketh | ae230f6 | 2014-03-22 22:14:44 +1100 | [diff] [blame^] | 469 | $control_form = $('<form />') |
Joshua Hesketh | ace4889 | 2014-03-22 17:18:31 +1100 | [diff] [blame] | 470 | .attr('role', 'form') |
| 471 | .addClass('form-inline') |
| 472 | .submit(zuul.handle_filter_change); |
| 473 | |
Joshua Hesketh | ae230f6 | 2014-03-22 22:14:44 +1100 | [diff] [blame^] | 474 | $control_form |
| 475 | .append(zuul.format.filter_form_group(current_filter)) |
| 476 | .append(zuul.format.expand_form_group()); |
| 477 | |
| 478 | return $control_form; |
Joshua Hesketh | ace4889 | 2014-03-22 17:18:31 +1100 | [diff] [blame] | 479 | }, |
Timo Tijhof | 51516cd | 2013-04-09 01:32:29 +0200 | [diff] [blame] | 480 | }, |
| 481 | |
| 482 | emit: function () { |
| 483 | $jq.trigger.apply($jq, arguments); |
| 484 | return this; |
| 485 | }, |
| 486 | on: function () { |
| 487 | $jq.on.apply($jq, arguments); |
| 488 | return this; |
| 489 | }, |
| 490 | one: function () { |
| 491 | $jq.one.apply($jq, arguments); |
| 492 | return this; |
Joshua Hesketh | db8046e | 2014-03-21 18:42:25 +1100 | [diff] [blame] | 493 | }, |
| 494 | |
| 495 | toggle_patchset: function(e) { |
| 496 | // Toggle showing/hiding the patchset when the header is clicked |
| 497 | // Grab the patchset panel |
| 498 | var $panel = $(e.target).parents('.zuul-change'); |
| 499 | var $body = $panel.children(':not(.patchset-header)'); |
| 500 | $body.toggle(200); |
| 501 | var collapsed_index = zuul.collapsed_exceptions.indexOf( |
| 502 | $panel.attr('id')); |
| 503 | if (collapsed_index == -1 ) { |
| 504 | // Currently not an exception, add it to list |
| 505 | zuul.collapsed_exceptions.push($panel.attr('id')); |
| 506 | } |
| 507 | else { |
| 508 | // Currently an except, remove from exceptions |
| 509 | zuul.collapsed_exceptions.splice(collapsed_index, 1); |
| 510 | } |
| 511 | }, |
| 512 | |
Joshua Hesketh | ace4889 | 2014-03-22 17:18:31 +1100 | [diff] [blame] | 513 | display_patchset: function($panel, animate) { |
| 514 | // Determine if to show or hide the patchset and/or the results |
| 515 | // when loaded |
| 516 | |
| 517 | // See if we should hide the body/results |
Joshua Hesketh | db8046e | 2014-03-21 18:42:25 +1100 | [diff] [blame] | 518 | var $body = $panel.children(':not(.patchset-header)'); |
Joshua Hesketh | ae230f6 | 2014-03-22 22:14:44 +1100 | [diff] [blame^] | 519 | var expand_by_default = $('#expand_by_default').prop('checked'); |
Joshua Hesketh | db8046e | 2014-03-21 18:42:25 +1100 | [diff] [blame] | 520 | var collapsed_index = zuul.collapsed_exceptions.indexOf( |
| 521 | $panel.attr('id')); |
Joshua Hesketh | ae230f6 | 2014-03-22 22:14:44 +1100 | [diff] [blame^] | 522 | if (expand_by_default && collapsed_index == -1 || |
| 523 | !expand_by_default && collapsed_index != -1) { |
| 524 | // Expand by default, or is an exception |
| 525 | $body.show(animate); |
Joshua Hesketh | db8046e | 2014-03-21 18:42:25 +1100 | [diff] [blame] | 526 | } |
| 527 | else { |
Joshua Hesketh | ae230f6 | 2014-03-22 22:14:44 +1100 | [diff] [blame^] | 528 | $body.hide(animate); |
Joshua Hesketh | db8046e | 2014-03-21 18:42:25 +1100 | [diff] [blame] | 529 | } |
Joshua Hesketh | ace4889 | 2014-03-22 17:18:31 +1100 | [diff] [blame] | 530 | |
| 531 | // Check if we should hide the whole panel |
| 532 | var panel_project = $panel.find('.change_project').text() |
| 533 | .toLowerCase(); |
| 534 | var panel_pipeline = $panel.parents('.zuul-pipeline') |
| 535 | .children('h3').text().toLowerCase(); |
| 536 | var panel_change = $panel.attr('id'); |
| 537 | if (current_filter != '') { |
| 538 | show_panel = false; |
| 539 | filter = current_filter.trim().split(/[\s,]+/); |
| 540 | $.each(filter, function(index, f_val) { |
| 541 | if (f_val != '') { |
| 542 | f_val = f_val.toLowerCase(); |
| 543 | if (panel_project.indexOf(f_val) != '-1' || |
| 544 | panel_pipeline.indexOf(f_val) != '-1' || |
| 545 | panel_change.indexOf(f_val) != '-1') { |
| 546 | show_panel = true; |
| 547 | } |
| 548 | } |
| 549 | }); |
| 550 | if (show_panel == true) { |
| 551 | $panel.show(animate); |
| 552 | } |
| 553 | else { |
| 554 | $panel.hide(animate); |
| 555 | } |
| 556 | } |
| 557 | else { |
| 558 | $panel.show(animate); |
| 559 | } |
| 560 | }, |
| 561 | |
| 562 | handle_filter_change: function(e) { |
| 563 | // Update the filter and save it to a cookie |
| 564 | current_filter = $('#filter_string').val(); |
| 565 | set_cookie('zuul_filter_string', current_filter); |
| 566 | if (current_filter == '') { |
| 567 | $('#filter_form_clear_box').hide(); |
| 568 | } |
| 569 | else { |
| 570 | $('#filter_form_clear_box').show(); |
| 571 | } |
| 572 | |
| 573 | $('.zuul-change').each(function(index, obj) { |
| 574 | $panel = $(obj); |
| 575 | zuul.display_patchset($panel, 200); |
| 576 | }) |
| 577 | return false; |
Joshua Hesketh | db8046e | 2014-03-21 18:42:25 +1100 | [diff] [blame] | 578 | }, |
Joshua Hesketh | ae230f6 | 2014-03-22 22:14:44 +1100 | [diff] [blame^] | 579 | |
| 580 | handle_expand_by_default: function(e) { |
| 581 | // Handle toggling expand by default |
| 582 | set_cookie('zuul_expand_by_default', e.target.checked); |
| 583 | zuul.collapsed_exceptions = []; |
| 584 | $('.zuul-change').each(function(index, obj) { |
| 585 | $panel = $(obj); |
| 586 | zuul.display_patchset($panel, 200); |
| 587 | }) |
| 588 | }, |
Timo Tijhof | 51516cd | 2013-04-09 01:32:29 +0200 | [diff] [blame] | 589 | }; |
| 590 | |
Joshua Hesketh | ace4889 | 2014-03-22 17:18:31 +1100 | [diff] [blame] | 591 | current_filter = read_cookie('zuul_filter_string', current_filter); |
| 592 | |
Timo Tijhof | 51516cd | 2013-04-09 01:32:29 +0200 | [diff] [blame] | 593 | $jq = $(zuul); |
| 594 | |
| 595 | $jq.on('update-start', function () { |
| 596 | $container.addClass('zuul-container-loading'); |
| 597 | $indicator.addClass('zuul-spinner-on'); |
| 598 | }); |
| 599 | |
| 600 | $jq.on('update-end', function () { |
| 601 | $container.removeClass('zuul-container-loading'); |
| 602 | setTimeout(function () { |
| 603 | $indicator.removeClass('zuul-spinner-on'); |
Joshua Hesketh | 876ca51 | 2014-03-21 18:44:22 +1100 | [diff] [blame] | 604 | }, 500); |
Timo Tijhof | 51516cd | 2013-04-09 01:32:29 +0200 | [diff] [blame] | 605 | }); |
| 606 | |
| 607 | $jq.one('update-end', function () { |
Joshua Hesketh | cbdcca1 | 2014-03-20 16:06:25 +1100 | [diff] [blame] | 608 | // Do this asynchronous so that if the first update adds a message, it |
| 609 | // will not animate while we fade in the content. Instead it simply |
| 610 | // appears with the rest of the content. |
Timo Tijhof | 51516cd | 2013-04-09 01:32:29 +0200 | [diff] [blame] | 611 | setTimeout(function () { |
Joshua Hesketh | cbdcca1 | 2014-03-20 16:06:25 +1100 | [diff] [blame] | 612 | // Fade in the content |
| 613 | $container.addClass('zuul-container-ready'); |
Timo Tijhof | 51516cd | 2013-04-09 01:32:29 +0200 | [diff] [blame] | 614 | }); |
| 615 | }); |
| 616 | |
| 617 | $(function ($) { |
Joshua Hesketh | 4863b60 | 2014-03-21 14:19:06 +1100 | [diff] [blame] | 618 | $msg = $('<div />').addClass('alert').hide(); |
| 619 | $indicator = $('<button class="btn pull-right zuul-spinner">updating ' |
| 620 | + '<span class="glyphicon glyphicon-refresh"></span>' |
| 621 | + '</button>'); |
Joshua Hesketh | cbdcca1 | 2014-03-20 16:06:25 +1100 | [diff] [blame] | 622 | $queueInfo = $('<p>Queue lengths: <span>0</span> events, ' + |
| 623 | '<span>0</span> results.</p>'); |
Joshua Hesketh | 298c491 | 2014-03-20 16:06:25 +1100 | [diff] [blame] | 624 | $queueEventsNum = $queueInfo.find('span').eq(0); |
| 625 | $queueResultsNum = $queueEventsNum.next(); |
Joshua Hesketh | ace4889 | 2014-03-22 17:18:31 +1100 | [diff] [blame] | 626 | |
Joshua Hesketh | ae230f6 | 2014-03-22 22:14:44 +1100 | [diff] [blame^] | 627 | $control_form = zuul.format.control_form(); |
Joshua Hesketh | ace4889 | 2014-03-22 17:18:31 +1100 | [diff] [blame] | 628 | |
Timo Tijhof | 51516cd | 2013-04-09 01:32:29 +0200 | [diff] [blame] | 629 | $pipelines = $('<div class="row"></div>'); |
Joshua Hesketh | cbdcca1 | 2014-03-20 16:06:25 +1100 | [diff] [blame] | 630 | $zuulVersion = $('<p>Zuul version: <span id="zuul-version-span">' + |
| 631 | '</span></p>'); |
| 632 | $lastReconf = $('<p>Last reconfigured: ' + |
| 633 | '<span id="last-reconfigured-span"></span></p>'); |
Timo Tijhof | 51516cd | 2013-04-09 01:32:29 +0200 | [diff] [blame] | 634 | |
Joshua Hesketh | 4863b60 | 2014-03-21 14:19:06 +1100 | [diff] [blame] | 635 | $container = $('#zuul-container').append($msg, $indicator, |
Joshua Hesketh | ae230f6 | 2014-03-22 22:14:44 +1100 | [diff] [blame^] | 636 | $queueInfo, $control_form, |
Joshua Hesketh | ace4889 | 2014-03-22 17:18:31 +1100 | [diff] [blame] | 637 | $pipelines, $zuulVersion, |
| 638 | $lastReconf); |
Timo Tijhof | 51516cd | 2013-04-09 01:32:29 +0200 | [diff] [blame] | 639 | |
| 640 | zuul.schedule(); |
| 641 | |
| 642 | $(document).on({ |
| 643 | 'show.visibility': function () { |
| 644 | zuul.enabled = true; |
| 645 | zuul.update(); |
| 646 | }, |
| 647 | 'hide.visibility': function () { |
| 648 | zuul.enabled = false; |
| 649 | } |
| 650 | }); |
| 651 | }); |
| 652 | }(jQuery)); |