diff --git a/assets/javascripts/audit_log.js b/assets/javascripts/audit_log.js index 6713ab475d9..e425f317b4d 100644 --- a/assets/javascripts/audit_log.js +++ b/assets/javascripts/audit_log.js @@ -186,27 +186,26 @@ function showScheduledProductResults(link) { } } -function rescheduleProduct(link) { - const rowData = dataForLink(link); - if (rowData === undefined) { - return; +function rescheduleProductForActionLink(link) { + const id = dataForLink(link)?.id; + if (id && window.confirm('Do you really want to reschedule all jobs for the product ' + id + '?')) { + rescheduleProduct(scheduledProductsTable.rescheduleUrlTemplate.replace('XXXXX', id)); } - const id = rowData.id; - if (!id || !window.confirm('Do you really want to reschedule all jobs for the product ' + id + '?')) { - return; - } - const url = scheduledProductsTable.rescheduleUrlTemplate.replace('XXXXX', id); - $.post(url, undefined, function () { - addFlash( - 'info', - 'Re-scheduling the product has been triggered. A new scheduled product should appear when refreshing the page.' - ); - }).fail(function (response) { - const responseText = response.responseText; - if (responseText) { - addFlash('danger', 'Unable to trigger re-scheduling: ' + responseText); - } else { - addFlash('danger', 'Unable to trigger re-scheduling.'); +} + +function rescheduleProduct(url) { + $.post({ + url: url, + success: (data, textStatus, jqXHR) => { + const id = jqXHR.responseJSON?.scheduled_product_id; + const msg = + typeof id === 'number' + ? `The product has been re-triggered as ${id}.` + : 'Re-scheduling the product has been triggered.'; + addFlash('info', msg); + }, + error: (jqXHR, textStatus, errorThrown) => { + addFlash('danger', 'Unable to trigger re-scheduling: ' + getXhrError(jqXHR, textStatus, errorThrown)); } }); } @@ -288,7 +287,7 @@ function loadProductLogTable(dataTableUrl, rescheduleUrlTemplate, showActions) { } if (showActions) { html += - '\ + '\ '; } return html; diff --git a/assets/javascripts/comments.js b/assets/javascripts/comments.js index b072dd4e18e..8121045f8f3 100644 --- a/assets/javascripts/comments.js +++ b/assets/javascripts/comments.js @@ -34,14 +34,6 @@ function renderCommentHeading(comment, commentId) { return heading; } -function getXhrError(jqXHR, textStatus, errorThrown) { - try { - return JSON.parse(jqXHR.responseText).error || errorThrown || textStatus; - } catch { - return errorThrown || textStatus; - } -} - function showXhrError(context, jqXHR, textStatus, errorThrown) { window.alert(context + getXhrError(jqXHR, textStatus, errorThrown)); } diff --git a/assets/javascripts/openqa.js b/assets/javascripts/openqa.js index 2cff57af29a..635649c5f18 100644 --- a/assets/javascripts/openqa.js +++ b/assets/javascripts/openqa.js @@ -550,3 +550,7 @@ function renderHttpUrlAsLink(value) { span.appendChild(document.createTextNode(value)); return span; } + +function getXhrError(jqXHR, textStatus, errorThrown) { + return jqXHR.responseJSON?.error || jqXHR.responseText || errorThrown || textStatus; +} diff --git a/t/ui/17-product-log.t b/t/ui/17-product-log.t index 994fe754086..0b9063f6905 100644 --- a/t/ui/17-product-log.t +++ b/t/ui/17-product-log.t @@ -123,12 +123,8 @@ subtest 'trigger actions' => sub { 'confirmation prompt shown' ); $driver->accept_alert; - wait_for_ajax; - is( - $driver->find_element('#flash-messages span')->get_text(), - 'Re-scheduling the product has been triggered. A new scheduled product should appear when refreshing the page.', - 'flash with info message occurs' - ); + wait_for_ajax msg => 'info message for rescheduling'; + $driver->element_text_is('#flash-messages span', 'The product has been re-triggered as 2.', 'info message shown'),; }; subtest 'rescheduled ISO shown after refreshing page' => sub { diff --git a/t/ui/18-tests-details.t b/t/ui/18-tests-details.t index 788fcec5c5b..c5e7297df5b 100644 --- a/t/ui/18-tests-details.t +++ b/t/ui/18-tests-details.t @@ -240,7 +240,7 @@ subtest 'bug reporting' => sub { subtest 'scheduled product shown' => sub { # still on test 99937 - my $scheduled_product_link = $driver->find_element('#scheduled-product-info a'); + my $scheduled_product_link = $driver->find_element('#scheduled-product-info > a'); my $expected_scheduled_product_id = $schema->resultset('Jobs')->find(99937)->scheduled_product_id; is($scheduled_product_link->get_text(), 'distri-dvd-1234', 'scheduled product name'); like( @@ -248,6 +248,13 @@ subtest 'scheduled product shown' => sub { qr/\/admin\/productlog\?id=$expected_scheduled_product_id/, 'scheduled product href' ); + my $reschedule_link = $driver->find_element('#scheduled-product-info div > a'); + my $expected_params = qr/scheduled_product_clone_id=$expected_scheduled_product_id&TEST=kde/; + like $reschedule_link->get_attribute('data-url'), $expected_params, 'reschedule link shown'; + $reschedule_link->click; + wait_for_ajax msg => 'message for rescheduling'; + element_visible '#flash-messages .alert > span', qr/Scheduled product to clone settings from misses DISTRI/, undef, + 'error shown'; $driver->get('/tests/99963'); like( $driver->find_element_by_id('scheduled-product-info')->get_text(), diff --git a/templates/webapi/test/infopanel.html.ep b/templates/webapi/test/infopanel.html.ep index 411327ede57..063069a17a1 100644 --- a/templates/webapi/test/infopanel.html.ep +++ b/templates/webapi/test/infopanel.html.ep @@ -134,7 +134,23 @@
Scheduled product:\ % if (my $scheduled_product = $job->scheduled_product) { - %= link_to $scheduled_product->to_string, url_for('admin_product_log')->query(id => $scheduled_product->id) + % my $sp_id = $scheduled_product->id; + %= link_to $scheduled_product->to_string, url_for('admin_product_log')->query(id => $sp_id) + % if (is_operator) { +
+ \ + + +
+ <%= help_popover('Partial product re-scheduling' => " +

Schedules the product again using the current job as starting point. That means chained parents of + the current job will not be scheduled again but all its children will be.

", + undef, undef, 'bottom'); + %> + % } % } else { job has not been created by posting an ISO % if ($clone_of) {