1/* 2 * Copyright (c) 2015-2017, John R. Marino <draco@marino.st> 3 * 4 * Permission to use, copy, modify, and/or distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16var SbInterval = 10; 17var progwidth = 950; 18var progheight = 14; 19var progtop = 2; 20var run_active; 21var kfiles = 0; 22var last_kfile = 1; 23var history = [[]]; 24 25/* Disabling jQuery caching */ 26$.ajaxSetup({ 27 cache: false 28}); 29 30function catwidth (variable, queued) { 31 if (variable == 0) 32 return 0; 33 var width = variable * progwidth / queued; 34 return (width < 1) ? 1 : Math.round (width); 35} 36 37function maxcatwidth(A, B, C, D, queued) { 38 var cat = new Array(); 39 cat[0] = catwidth (A, queued); 40 cat[1] = catwidth (B, queued); 41 cat[2] = catwidth (C, queued); 42 cat[3] = catwidth (D, queued); 43 cat.sort(function(a,b){return a-b}); 44 return (progwidth - cat[0] - cat[1] - cat[2]); 45} 46 47function minidraw(x, context, color, queued, variable, mcw) { 48 var width = catwidth (variable, queued); 49 if (width == 0) 50 return (0); 51 if (width > mcw) 52 width = mcw; 53 context.fillStyle = color; 54 context.fillRect(x, progtop + 1, width, progheight + 2); 55 return (width); 56} 57 58function update_canvas(stats) { 59 var queued = stats.queued; 60 var built = stats.built; 61 var meta = stats.meta; 62 var failed = stats.failed; 63 var skipped = stats.skipped; 64 var ignored = stats.ignored; 65 66 var canvas = document.getElementById('progressbar'); 67 if (canvas.getContext === undefined) { 68 /* Not supported */ 69 return; 70 } 71 72 var context = canvas.getContext('2d'); 73 74 context.fillStyle = '#D8D8D8'; 75 context.fillRect(0, progtop + 1, progwidth, progheight + 2); 76 var x = 0; 77 var mcw = maxcatwidth (built, meta, failed, ignored, skipped, queued); 78 x += minidraw(x, context, "#339966", queued, built, mcw); 79 x += minidraw(x, context, "#A577E1", queued, meta, mcw); 80 x += minidraw(x, context, "#CC0033", queued, failed, mcw); 81 x += minidraw(x, context, "#FFCC33", queued, ignored, mcw); 82 x += minidraw(x, context, "#CC6633", queued, skipped, mcw); 83} 84 85function filter (txt) { 86 $('#report input').val (txt).trigger('search'); 87} 88 89function process_summary(data) { 90 var html; 91 var RB = '<tr>'; 92 var RE = '</tr>'; 93 var B = '<td>'; 94 var E = '</td>'; 95 96 kfiles = parseInt (data.kfiles); 97 run_active = parseInt (data.active); 98 $('#profile').html(data.profile); 99 $('#kickoff').html(data.kickoff); 100 $('#polling').html(run_active ? "Active" : "Complete"); 101 if (data.stats) { 102 $.each(data.stats, function(status, count) { 103 html = count; 104 $('#stats_' + status).html(html); 105 }); 106 update_canvas (data.stats); 107 } 108 109 $('#builders_body tbody').empty(); 110 for (n = 0; n < data.builders.length; n++) { 111 var trow = RB + '<td class="b' + data.builders[n].ID + 112 '" onclick="filter(\'[' + data.builders[n].ID + 113 ']\')" title="Click to filter for work done by builder ' + 114 data.builders[n].ID + '">' 115 + data.builders[n].ID + E + 116 B + data.builders[n].elapsed + E + 117 B + data.builders[n].phase + E + 118 B + data.builders[n].origin + E + 119 B + data.builders[n].lines + E + 120 RE; 121 $('#builders_body tbody').append (trow); 122 } 123} 124 125function digit2(n){ 126 return n > 9 ? "" + n: "0" + n; 127} 128 129function logfile (origin) { 130 var parts = origin.split('/'); 131 return '../' + parts[0] + '___' + parts[1] + '.log'; 132} 133 134function format_result (result) { 135 return '<div class="' + result + ' result">' + result + '<div>'; 136} 137 138function format_entry (entry, origin) { 139 return '<span class="entry" onclick="filter(\'' + origin+ '\')">' + 140 entry + '</span>'; 141} 142 143function information (result, origin, info) { 144 var parts; 145 if (result == "meta") { 146 return 'meta-node complete.'; 147 } else if (result == "built") { 148 return '<a href="' + logfile (origin) + '">logfile</a>'; 149 } else if (result == "failed") { 150 parts = info.split(':'); 151 return 'Failed ' + parts[0] + ' phase (<a href="' + logfile (origin) + 152 '">logfile</a>)'; 153 } else if (result == "skipped") { 154 return 'Issue with ' + info; 155 } else if (result == "ignored") { 156 parts = info.split(':|:'); 157 return parts[0]; 158 } else { 159 return "??"; 160 } 161} 162 163function skip_info (result, info) { 164 var parts; 165 if (result == "failed") { 166 parts = info.split(':'); 167 return parts[1]; 168 } else if (result == "ignored") { 169 parts = info.split(':|:'); 170 return parts[1]; 171 } else { 172 return ""; 173 } 174} 175 176function portsmon (origin) { 177 var portparts = origin.split('/'); 178 var nameparts = portparts[1].split('@'); 179 var FPClink = '<a title="portsmon for "' + origin + '" href="https://www.freshports.org/' + portparts[0] + '/' + nameparts[0] + '">' + origin + '</a>'; 180 var NPSlink = '<a title="pkgsrc.se overview" href="http://pkgsrc.se/' + origin + '">' + origin + '</a>'; 181 return FPClink; 182} 183 184function process_history_file(data, k) { 185 history [k] = []; 186 for (n = 0; n < data.length; n++) { 187 var trow = []; 188 trow.push(format_entry (data[n].entry, data[n].origin)); 189 trow.push(data[n].elapsed); 190 trow.push('[' + data[n].ID + ']'); 191 trow.push(format_result (data[n].result)); 192 trow.push(portsmon (data[n].origin)); 193 trow.push(information (data[n].result, data[n].origin, data[n].info)); 194 trow.push(skip_info (data[n].result, data[n].info)); 195 trow.push(data[n].duration); 196 history [k].push (trow); 197 } 198} 199 200function cycle () { 201 if (run_active) { 202 setTimeout(update_summary_and_builders, SbInterval * 1000); 203 } else { 204 $('#builders_zone_2').fadeOut(2500); 205 $('#main').css('border-top', '1px solid #404066'); 206 } 207} 208 209function update_history_success(kfile) { 210 if (kfile == kfiles) { 211 var full_history = []; 212 for (var k = 1; k <= kfiles; k++) { 213 full_history = full_history.concat (history[k]); 214 } 215 $('#report_table').dataTable().fnClearTable(); 216 $('#report_table').dataTable().fnAddData(full_history); 217 cycle(); 218 } else { 219 last_kfile = kfile + 1; 220 update_history(); 221 } 222} 223 224function update_history() { 225 if (kfiles == 0) { 226 cycle(); 227 return; 228 } 229 clearInterval(update_history); 230 $.ajax({ 231 url: digit2(last_kfile) + '_history.json', 232 dataType: 'json', 233 success: function(data) { 234 process_history_file(data, last_kfile); 235 update_history_success (last_kfile); 236 }, 237 error: function(data) { 238 /* May not be there yet, try again shortly */ 239 setTimeout(update_history, SbInterval * 500); 240 } 241 }) 242} 243 244function update_summary_and_builders() { 245 $.ajax({ 246 url: 'summary.json', 247 dataType: 'json', 248 success: function(data) { 249 process_summary(data); 250 clearInterval(update_summary_and_builders); 251 update_history(); 252 }, 253 error: function(data) { 254 /* May not be there yet, try again shortly */ 255 setTimeout(update_summary_and_builders, SbInterval * 500); 256 } 257 }); 258} 259 260$(document).ready(function() { 261 262 $('#report_table').dataTable({ 263 "aaSorting": [[ 0, 'desc' ]], 264 "bProcessing": true, // Show processing icon 265 "bDeferRender": true, // Defer creating TR/TD until needed 266 "aoColumnDefs": [ 267 {"bSortable": false, "aTargets": [1,2,3,5]}, 268 {"bSearchable": false, "aTargets": [0,1,6,7]}, 269 ], 270 "bStateSave": true, // Enable cookie for keeping state 271 "aLengthMenu":[10,20,50, 100, 200], 272 "iDisplayLength": 20, 273 }); 274 275 update_summary_and_builders(); 276}) 277 278$(document).bind("keydown", function(e) { 279 /* Disable F5 refreshing since this is AJAX driven. */ 280 if (e.which == 116) { 281 e.preventDefault(); 282 } 283}); 284