Skip to content

Commit

Permalink
MDL-81714 grades: Display "Run now" button for admins in task indicator
Browse files Browse the repository at this point in the history
  • Loading branch information
marxjohnson committed Sep 10, 2024
1 parent 3c94972 commit 5efb352
Show file tree
Hide file tree
Showing 7 changed files with 97 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -91,3 +91,29 @@ if ($taskindicator->has_task_record()) {

If the optional `redirecturl` parameter is set when creating the indicator, the page will automatically reload or redirect to
this URL when the progress bar completes.

While the task is still queued, admins will see a "Run now" button below the progress bar. This is designed for convenience if
a user is blocked on a job and needs the task run immediately. It will run the specific instance of the task tracked by the
indicator.

{{< mustache template="core/task_indicator" >}}
{
"heading": "Regrade in progress",
"icon": {
"attributes": [
{"name": "src", "value": "/pix/i/timer.svg"},
{"name": "alt", "value": ""}
]
},
"message": "Grades are being recalculated due to recent changes.",
"progress": {
"id": "progressbar_test",
"message": "Task pending",
"idnumber": "progressbar_test",
"width": "500",
"value": "0"
},
"runurl": "http://example.com/runtask.php?id=1",
"runlabel": "Run now"
}
{{< /mustache >}}
16 changes: 16 additions & 0 deletions grade/tests/behat/grade_async_regrade.feature
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ Feature: Asynchronous regrade on a large course
And I set the field "Maximum grade" to "50"
And I press "Save and return to course"
And I log out
And I change the viewport size to "medium"

Scenario Outline: Task indicator displays on all grade reports when a calculation is pending
Given I am on the "Test course 2" "<report>" page logged in as "teacher1"
Expand Down Expand Up @@ -87,6 +88,7 @@ Feature: Asynchronous regrade on a large course
When I am on the "Test course 1" "grades > Grader report > View" page logged in as teacher1
And I should see "Grades are being recalculated due to recent changes."
And I should see "Task pending"
And I should not see "Run now"
And I should see "0.0%"
And "user-grades" "table" should not exist
When I run all adhoc tasks
Expand All @@ -100,3 +102,17 @@ Feature: Asynchronous regrade on a large course
And I set the field "Search users" to "Student 1"
And "user-grades" "table" should exist
And "40.00" "text" should exist in the "[email protected]" "table_row"

Scenario: Admin should see a "Run now" button that disappears once the task starts running
When I am on the "Test course 1" "grades > Grader report > View" page logged in as admin
And I should see "Grades are being recalculated due to recent changes."
And I should see "Task pending"
And I should see "Run now"
And I should see "0.0%"
And "user-grades" "table" should not exist
When I run all adhoc tasks
# Progress bar should update.
Then I should see "Recalculating grades" in the ".progressbar_container" "css_element"
And I should not see "Task pending"
And I should not see "Run now"
And I should see "100%"
2 changes: 1 addition & 1 deletion lib/amd/build/task_indicator.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion lib/amd/build/task_indicator.min.js.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 7 additions & 1 deletion lib/amd/src/task_indicator.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,13 @@ export default class {
*/
static init(id, redirectUrl) {
document.getElementById(id).addEventListener('update', (event) => {
if (event.detail.percent === 100) {
// Once progress has started, remove the run link.
const runlink = document.querySelector(`.runlink[data-idnumber=${id}]`);
if (runlink && event.detail.percent > 0) {
runlink.remove();
}
// Once the progress bar completes, redirect the page.
if (redirectUrl !== '' && event.detail.percent === 100) {
window.setTimeout(() => window.location.assign(redirectUrl), 2000);
}
});
Expand Down
27 changes: 26 additions & 1 deletion lib/classes/output/task_indicator.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,21 @@

namespace core\output;

use core\plugin_manager;
use core\task\adhoc_task;
use core\task\stored_progress_task_trait;
use core\url;
use core\context\system;
use stdClass;

/**
* Indicator for displaying status and progress of a background task
*
* This will display a section containing an icon, heading and message describing the background task being performed,
* as well as a progress bar that is updated as the task progresses. Optionally, it will redirect to a given URL (or reload
* the current one) when the task completes. If the task is still waiting in the queue, an admin viewing the indicator
* will also see a "Run now" button.
*
* @package core
* @copyright 2024 onwards Catalyst IT EU {@link https://catalyst-eu.net}
* @author Mark Johnson <[email protected]>
Expand All @@ -36,6 +43,12 @@ class task_indicator implements renderable, templatable {
/** @var ?stored_progress_bar $progressbar */
protected ?stored_progress_bar $progressbar;

/** @var ?url $runurl The URL to manually run the task. */
protected ?url $runurl = null;

/** @var string $runlabel Label for the link to run the task. */
protected string $runlabel = '';

/**
* Find the task record, and get the progress bar object.
*
Expand Down Expand Up @@ -80,6 +93,16 @@ protected function setup_task_data(): void {
$this->task->set_id($this->taskrecord->id);
$idnumber = stored_progress_bar::convert_to_idnumber($this->task::class, $this->task->get_id());
$this->progressbar = stored_progress_bar::get_by_idnumber($idnumber);
// As long as the tool_task plugin hasn't been removed,
// allow admins to trigger the task manually if it's not running yet.
if (
array_key_exists('task', plugin_manager::instance()->get_present_plugins('tool'))
&& is_null($this->taskrecord->timestarted)
&& has_capability('moodle/site:config', system::instance())
) {
$this->runurl = new url('/admin/tool/task/run_adhoctasks.php', ['id' => $this->taskrecord->id]);
$this->runlabel = get_string('runnow', 'tool_task');
}
}
}

Expand All @@ -103,8 +126,10 @@ public function export_for_template(renderer_base $output): array {
$export['message'] = $this->message;
$export['progress'] = $this->progressbar->export_for_template($output);
$export['icon'] = $this->icon ? $this->icon->export_for_template($output) : '';
$export['redirecturl'] = $this->redirecturl->out();
$export['redirecturl'] = $this->redirecturl?->out();
$export['extraclasses'] = implode(' ', $this->extraclasses);
$export['runurl'] = $this->runurl?->out();
$export['runlabel'] = $this->runlabel;
$this->progressbar->init_js();
}
return $export;
Expand Down
35 changes: 20 additions & 15 deletions lib/templates/task_indicator.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -39,23 +39,28 @@
}
}}
<div class="task-indicator {{extraclasses}}">
{{#icon}}
<div class="text-center">
{{>core/pix_icon}}
</div>
{{/icon}}
<h3 class="text-center">{{heading}}</h3>
<p class="text-center">{{message}}</p>
<div class="text-center">
{{#icon}}
<div>
{{>core/pix_icon}}
</div>
{{/icon}}
<h3>{{heading}}</h3>
<p>{{message}}</p>
</div>
{{#progress}}
{{>core/progress_bar}}
{{/progress}}
</div>
{{#runurl}}
<p class="text-center">
<a class="runlink btn btn-primary" href="{{runurl}}" data-idnumber="{{progress.idnumber}}">{{runlabel}}</a>
</p>
{{/runurl}}

{{#redirecturl}}
{{#js}}
require(['core/task_indicator'], function(TaskIndicator) {
TaskIndicator.init('{{progress.idnumber}}', '{{redirecturl}}');
});
{{/js}}
{{/redirecturl}}
</div>

{{#js}}
require(['core/task_indicator'], function(TaskIndicator) {
TaskIndicator.init('{{progress.idnumber}}', '{{redirecturl}}');
});
{{/js}}

0 comments on commit 5efb352

Please sign in to comment.