xref: /dragonfly/usr.bin/dsynth/progress.js (revision b81e76a3785f67a811dad5e50f4f3027034c6eff)
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