Skip to content

Commit 7112b80

Browse files
author
Ondřej Holeček
committed
Merge pull request os-autoinst#308 from os-autoinst/add_more_restart_buttons
add a restart icon to all test related views
2 parents 7dfa8e1 + f83545f commit 7112b80

File tree

14 files changed

+469
-448
lines changed

14 files changed

+469
-448
lines changed

Diff for: lib/OpenQA/Controller/API/V1/Job.pm

+3-2
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ sub done {
194194

195195
# Used for both apiv1_restart and apiv1_restart_jobs
196196
sub restart {
197-
my $self = shift;
197+
my ($self) = @_;
198198
my $target = $self->param('name');
199199
if ($target) {
200200
$self->app->log->debug("Restarting job $target");
@@ -206,7 +206,8 @@ sub restart {
206206
}
207207

208208
my @res = OpenQA::Scheduler::job_restart($target);
209-
$self->render(json => {result => \@res});
209+
my @urls = map { $self->url_for('test', testid => $_) } @res;
210+
$self->render(json => {result => \@res, test_url => \@urls});
210211
}
211212

212213
sub cancel {

Diff for: lib/OpenQA/Controller/Test.pm

+3
Original file line numberDiff line numberDiff line change
@@ -256,8 +256,11 @@ sub show {
256256
return;
257257
}
258258

259+
my $clone_of = $self->app->schema->resultset("Jobs")->find({ clone_id => $job->id });
260+
259261
my $modlist = read_test_modules($job);
260262
$self->stash(job => $job);
263+
$self->stash(clone_of => $clone_of);
261264
$self->stash(modlist => $modlist);
262265

263266
my $rd = $job->result_dir();

Diff for: public/images/b1-systems.png

-3.75 KB
Binary file not shown.

Diff for: public/images/back.png

-1005 Bytes
Binary file not shown.

Diff for: public/images/log.png

-476 Bytes
Binary file not shown.

Diff for: public/javascripts/openqa.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ function scrollModuleThumbnails() {
2626
var area = $("#module-thumbnails");
2727
var current = $('#module-thumbnails .current');
2828

29-
if (!current)
29+
if (!current || !area.offset())
3030
return;
3131
var offset = current.offset().left - area.offset().left;
3232
area.scrollLeft(40 + offset - area.width()/2);

Diff for: public/javascripts/tests.js

+126-116
Original file line numberDiff line numberDiff line change
@@ -26,19 +26,19 @@ function highlightJobsHtml (children, parents) {
2626

2727
function renderTestName ( data, type, row ) {
2828
if (type === 'display') {
29-
var html = '<span class="result_' + row['result'] + '">';
30-
html += '<a href="/tests/' + row['id'] + '">';
31-
html += '<i class="status fa fa-circle" title="Done: ' + row['result'] + '"></i>';
32-
if (is_operator && !row['clone']) {
33-
var url = restart_url.replace('REPLACEIT', row['id']);
29+
var html = '<span class="result_' + row['result'] + '">';
30+
html += '<a href="/tests/' + row['id'] + '">';
31+
html += '<i class="status fa fa-circle" title="Done: ' + row['result'] + '"></i>';
32+
if (is_operator && !row['clone']) {
33+
var url = restart_url.replace('REPLACEIT', row['id']);
3434
html += ' <a data-method="POST" data-remote="true" class="restart"';
35-
html += ' href="' + url + '">';
35+
html += ' href="' + url + '">';
3636
html += '<i class="action fa fa-repeat" title="Restart Job"></i></a>';
37-
}
37+
}
3838
html += '</a> ';
39-
// the name
40-
html += '<a href="/tests/' + row['id'] + '" class="name">' + data + '</a>';
41-
html += '</span>';
39+
// the name
40+
html += '<a href="/tests/' + row['id'] + '" class="name">' + data + '</a>';
41+
html += '</span>';
4242

4343
var deps = '';
4444
if (row['deps']['parents']['Chained'].length) {
@@ -85,133 +85,143 @@ function renderTestName ( data, type, row ) {
8585
'><i class="fa fa-code-fork"></i></a>';
8686
}
8787

88-
if (row['clone'])
88+
if (row['clone'])
8989
html += ' <a href="/tests/' + row['clone'] + '">(restarted)</a>';
9090

9191
return html;
9292
} else {
93-
return data;
93+
return data;
9494
}
9595
}
9696

9797
function renderTestResult( data, type, row ) {
9898
if (type === 'display') {
99-
var html = '';
100-
if (row['state'] === 'done') {
101-
html += data['passed'] + "<i class='fa module_passed fa-star' title='modules passed'></i>";
102-
if (data['dents']) {
103-
html += " " + data['dents'] + "<i class='fa module_softfail fa-star-half-empty' title='modules with warnings'></i> ";
104-
}
105-
if (data['failed']) {
106-
html += " " + data['failed'] + "<i class='fa module_failed fa-star-o' title='modules failed'></i> ";
107-
}
108-
if (data['none']) {
109-
html += " " + data['none'] + "<i class='fa module_none fa-ban' title='modules skipped'></i> ";
110-
}
111-
}
112-
if (row['state'] === 'cancelled') {
113-
html += "<i class='fa fa-times' title='canceled'></i>";
114-
}
115-
if (row['deps']['parents']['Parallel'].length + row['deps']['parents']['Chained'].length > 0) {
116-
if (row['result'] === 'skipped' ||
117-
row['result'] === 'parallel_failed') {
118-
html += "<i class='fa fa-chain-broken' title='dependency failed'></i>";
119-
}
120-
else {
121-
html += "<i class='fa fa-link' title='dependency passed'></i>";
122-
}
123-
}
99+
var html = '';
100+
if (row['state'] === 'done') {
101+
html += data['passed'] + "<i class='fa module_passed fa-star' title='modules passed'></i>";
102+
if (data['dents']) {
103+
html += " " + data['dents'] + "<i class='fa module_softfail fa-star-half-empty' title='modules with warnings'></i> ";
104+
}
105+
if (data['failed']) {
106+
html += " " + data['failed'] + "<i class='fa module_failed fa-star-o' title='modules failed'></i> ";
107+
}
108+
if (data['none']) {
109+
html += " " + data['none'] + "<i class='fa module_none fa-ban' title='modules skipped'></i> ";
110+
}
111+
}
112+
if (row['state'] === 'cancelled') {
113+
html += "<i class='fa fa-times' title='canceled'></i>";
114+
}
115+
if (row['deps']['parents']['Parallel'].length + row['deps']['parents']['Chained'].length > 0) {
116+
if (row['result'] === 'skipped' ||
117+
row['result'] === 'parallel_failed') {
118+
html += "<i class='fa fa-chain-broken' title='dependency failed'></i>";
119+
}
120+
else {
121+
html += "<i class='fa fa-link' title='dependency passed'></i>";
122+
}
123+
}
124124
return '<a href="/tests/' + row['id'] + '">' + html + '</a>';
125125
} else {
126-
return (parseInt(data['passed']) * 10000) + (parseInt(data['dents']) * 100) + parseInt(data['failed']);
126+
return (parseInt(data['passed']) * 10000) + (parseInt(data['dents']) * 100) + parseInt(data['failed']);
127127
}
128128
}
129129

130130
function renderTestsList(jobs) {
131131

132132
var table = $('#results').DataTable( {
133-
"dom": 'l<"#toolbar">frtip',
134-
"lengthMenu": [[10, 25, 50], [10, 25, 50]],
135-
"ajax": {
136-
"url": "/tests/list_ajax",
137-
"type": "POST", // we use POST as the URLs can get long
138-
"data": function(d) {
139-
var ret = {
140-
"relevant": $('#relevantfilter').prop('checked')
141-
};
142-
if (jobs != null) {
143-
ret['jobs'] = jobs;
144-
ret['initial'] = 1;
145-
}
146-
// reset for reload
147-
jobs = null;
148-
return ret;
149-
}
150-
},
151-
// no initial resorting
152-
"order": [],
153-
"columns": [
154-
{ "data": "name" },
155-
{ "data": "test" },
156-
{ "data": "result_stats" },
157-
{ "data": "testtime" },
158-
],
159-
"columnDefs": [
160-
{ targets: 0,
161-
className: "name",
162-
"render": function ( data, type, row ) {
163-
var link = '/tests/overview?build=' + row['build'];
164-
if (row['group'])
165-
link += '&groupid=' + row['group'];
166-
else
167-
link += '&distri=' + row['distri'] + '&version=' + row['version'];
168-
169-
var name = "<a href='" + link + "'>" + 'Build' + row['build'] + '</a>';
170-
name += " of ";
171-
return name + row['distri'] + "-" + row['version'] + "-" + row['flavor'] + "." + row['arch'];
172-
}
173-
},
174-
{ targets: 1,
175-
className: "test",
176-
"render": renderTestName
177-
},
178-
{ targets: 3,
179-
"render": function ( data, type, row ) {
180-
if (type === 'display')
181-
return jQuery.timeago(data + " UTC");
182-
else
183-
return data;
184-
}
185-
},
186-
{ targets: 2,
187-
"render": renderTestResult
188-
}
189-
],
133+
"dom": 'l<"#toolbar">frtip',
134+
"lengthMenu": [[10, 25, 50], [10, 25, 50]],
135+
"ajax": {
136+
"url": "/tests/list_ajax",
137+
"type": "POST", // we use POST as the URLs can get long
138+
"data": function(d) {
139+
var ret = {
140+
"relevant": $('#relevantfilter').prop('checked')
141+
};
142+
if (jobs != null) {
143+
ret['jobs'] = jobs;
144+
ret['initial'] = 1;
145+
}
146+
// reset for reload
147+
jobs = null;
148+
return ret;
149+
}
150+
},
151+
// no initial resorting
152+
"order": [],
153+
"columns": [
154+
{ "data": "name" },
155+
{ "data": "test" },
156+
{ "data": "result_stats" },
157+
{ "data": "testtime" },
158+
],
159+
"columnDefs": [
160+
{ targets: 0,
161+
className: "name",
162+
"render": function ( data, type, row ) {
163+
var link = '/tests/overview?build=' + row['build'];
164+
if (row['group'])
165+
link += '&groupid=' + row['group'];
166+
else
167+
link += '&distri=' + row['distri'] + '&version=' + row['version'];
168+
169+
var name = "<a href='" + link + "'>" + 'Build' + row['build'] + '</a>';
170+
name += " of ";
171+
return name + row['distri'] + "-" + row['version'] + "-" + row['flavor'] + "." + row['arch'];
172+
}
173+
},
174+
{ targets: 1,
175+
className: "test",
176+
"render": renderTestName
177+
},
178+
{ targets: 3,
179+
"render": function ( data, type, row ) {
180+
if (type === 'display')
181+
return jQuery.timeago(data + " UTC");
182+
else
183+
return data;
184+
}
185+
},
186+
{ targets: 2,
187+
"render": renderTestResult
188+
}
189+
]
190190
} );
191191
$("#relevantbox").detach().appendTo('#toolbar');
192192
$('#relevantbox').css('display', 'inherit');
193193
// Event listener to the two range filtering inputs to redraw on input
194194
$('#relevantfilter').change( function() {
195-
$('#relevantbox').css('color', 'cyan');
195+
$('#relevantbox').css('color', 'cyan');
196196
table.ajax.reload(function() {
197-
$('#relevantbox').css('color', 'inherit');
198-
} );
197+
$('#relevantbox').css('color', 'inherit');
198+
} );
199199
} );
200-
};
201-
202-
$(document).on("click", '.restart', function() {
203-
var restart_link = $(this);
204-
var link = $(this).parent('span').find('.name');
205-
$.post(restart_link.attr("href")).done( function( data ) { $(link).append(' (restarted)'); });
206-
$(this).html('');
207-
});
208-
209-
$(document).on('click', '.cancel', function() {
210-
var cancel_link = $(this);
211-
var test = $(this).parent('td');
212-
$.post(cancel_link.attr("href")).done( function( data ) { $(test).append(' (cancelled)'); });
213-
$(this).html('');
214-
});
215-
216-
$(document).on('mouseover', '.parent_child', highlightJobs);
217-
$(document).on('mouseout', '.parent_child', unhighlightJobs);
200+
201+
$(document).on('mouseover', '.parent_child', highlightJobs);
202+
$(document).on('mouseout', '.parent_child', unhighlightJobs);
203+
204+
205+
$(document).on("click", '.restart', function() {
206+
var restart_link = $(this);
207+
var link = $(this).parent('span').find('.name');
208+
$.post(restart_link.attr("href")).done( function( data ) { $(link).append(' (restarted)'); });
209+
$(this).html('');
210+
});
211+
212+
$(document).on('click', '.cancel', function() {
213+
var cancel_link = $(this);
214+
var test = $(this).parent('td');
215+
$.post(cancel_link.attr("href")).done( function( data ) { $(test).append(' (cancelled)'); });
216+
$(this).html('');
217+
});
218+
}
219+
220+
function setupResultButtons() {
221+
$( '#restart-result' ).click( function(event) {
222+
event.preventDefault();
223+
$.post($(this).attr("href")).done( function( data, res, xhr ) {
224+
window.location.replace(xhr.responseJSON.test_url);
225+
});
226+
});
227+
}

Diff for: templates/session/new.html.ep

+14-15
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,18 @@
55
% end
66

77
<div class="grid_6 box box-shadow omega">
8-
%= t h1 => 'Login to ' . $appname
9-
%= form_for login => (method => 'POST') => begin
10-
% if (my $err = validation->error('name')) {
11-
% if ( $err->[0] eq 'required' ) {
12-
<blockquote class="ui-state-error" style="margin-bottom: 0.6em;">User Name is required</blockquote>
13-
% }
14-
% if ( $err->[0] eq 'like' ) {
15-
<blockquote class="ui-state-error" style="margin-bottom: 0.6em;">User Name needs to be alphanumeric ASCII</blockquote>
16-
% }
17-
% }
18-
%= label_for name => 'User Name'
19-
%= text_field 'name', id => 'input-name', autofocus => 'true'
20-
%= submit_button 'Log in'
21-
%= end
8+
%= t h1 => 'Login to ' . $appname
9+
%= form_for login => (method => 'POST') => begin
10+
% if (my $err = validation->error('name')) {
11+
% if ( $err->[0] eq 'required' ) {
12+
<blockquote class="ui-state-error" style="margin-bottom: 0.6em;">User Name is required</blockquote>
13+
% }
14+
% if ( $err->[0] eq 'like' ) {
15+
<blockquote class="ui-state-error" style="margin-bottom: 0.6em;">User Name needs to be alphanumeric ASCII</blockquote>
16+
% }
17+
% }
18+
%= label_for name => 'User Name'
19+
%= text_field 'name', id => 'input-name', autofocus => 'true'
20+
%= submit_button 'Log in'
21+
%= end
2222
</div>
23-

0 commit comments

Comments
 (0)