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