MDL-86066 reportbuilder: hook up front end elements to new schedules.

This commit is contained in:
Paul Holden
2025-08-29 16:02:18 +01:00
parent ce09276d3e
commit 513a32f94a
14 changed files with 186 additions and 96 deletions
@@ -5,6 +5,6 @@ define("core_reportbuilder/local/repository/modals",["exports","core_form/modalf
* @module core_reportbuilder/local/repository/modals
* @copyright 2021 David Matamoros <davidmc@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.createScheduleModal=_exports.createReportModal=_exports.createDuplicateReportModal=void 0,_modalform=(obj=_modalform)&&obj.__esModule?obj:{default:obj};const createModalForm=(triggerElement,modalTitle,formClass,formArgs)=>new _modalform.default({modalConfig:{title:modalTitle},formClass:formClass,args:formArgs,saveButtonText:(0,_str.getString)("save","moodle"),returnFocus:triggerElement});_exports.createReportModal=function(triggerElement,modalTitle){let reportId=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0;return createModalForm(triggerElement,modalTitle,"core_reportbuilder\\form\\report",{id:reportId})};_exports.createDuplicateReportModal=(triggerElement,modalTitle,reportId,reportName)=>createModalForm(triggerElement,modalTitle,"core_reportbuilder\\form\\duplicate_report",{id:reportId,name:reportName});_exports.createScheduleModal=function(triggerElement,modalTitle,reportId){let scheduleId=arguments.length>3&&void 0!==arguments[3]?arguments[3]:0;return createModalForm(triggerElement,modalTitle,"core_reportbuilder\\form\\schedule",{reportid:reportId,id:scheduleId})}}));
*/Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.createScheduleModal=_exports.createReportModal=_exports.createDuplicateReportModal=void 0,_modalform=(obj=_modalform)&&obj.__esModule?obj:{default:obj};const createModalForm=(triggerElement,modalTitle,formClass,formArgs)=>new _modalform.default({modalConfig:{title:modalTitle},formClass:formClass,args:formArgs,saveButtonText:(0,_str.getString)("save","moodle"),returnFocus:triggerElement});_exports.createReportModal=function(triggerElement,modalTitle){let reportId=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0;return createModalForm(triggerElement,modalTitle,"core_reportbuilder\\form\\report",{id:reportId})};_exports.createDuplicateReportModal=(triggerElement,modalTitle,reportId,reportName)=>createModalForm(triggerElement,modalTitle,"core_reportbuilder\\form\\duplicate_report",{id:reportId,name:reportName});_exports.createScheduleModal=function(triggerElement,modalTitle,reportId){let scheduleId=arguments.length>3&&void 0!==arguments[3]?arguments[3]:0,scheduleClass=arguments.length>4&&void 0!==arguments[4]?arguments[4]:"";return createModalForm(triggerElement,modalTitle,"core_reportbuilder\\form\\schedule",{reportid:reportId,id:scheduleId,classname:scheduleClass})}}));
//# sourceMappingURL=modals.min.js.map
@@ -1 +1 @@
{"version":3,"file":"modals.min.js","sources":["../../../src/local/repository/modals.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * Module to handle modal form requests\n *\n * @module core_reportbuilder/local/repository/modals\n * @copyright 2021 David Matamoros <[email protected]>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport ModalForm from 'core_form/modalform';\nimport {getString} from 'core/str';\n\n/**\n * Return modal instance\n *\n * @param {EventTarget} triggerElement\n * @param {Promise} modalTitle\n * @param {String} formClass\n * @param {Object} formArgs\n * @return {ModalForm}\n */\nconst createModalForm = (triggerElement, modalTitle, formClass, formArgs) => {\n return new ModalForm({\n modalConfig: {\n title: modalTitle,\n },\n formClass: formClass,\n args: formArgs,\n saveButtonText: getString('save', 'moodle'),\n returnFocus: triggerElement,\n });\n};\n\n/**\n * Return report modal instance\n *\n * @param {EventTarget} triggerElement\n * @param {Promise} modalTitle\n * @param {Number} reportId\n * @return {ModalForm}\n */\nexport const createReportModal = (triggerElement, modalTitle, reportId = 0) => {\n return createModalForm(triggerElement, modalTitle, 'core_reportbuilder\\\\form\\\\report', {\n id: reportId,\n });\n};\n\n/**\n * Return duplicate report modal instance\n *\n * @param {EventTarget} triggerElement\n * @param {Promise} modalTitle\n * @param {Number} reportId\n * @param {String} reportName\n * @return {ModalForm}\n */\nexport const createDuplicateReportModal = (triggerElement, modalTitle, reportId, reportName) => {\n return createModalForm(triggerElement, modalTitle, 'core_reportbuilder\\\\form\\\\duplicate_report', {\n id: reportId,\n name: reportName,\n });\n};\n\n/**\n * Return schedule modal instance\n *\n * @param {EventTarget} triggerElement\n * @param {Promise} modalTitle\n * @param {Number} reportId\n * @param {Number} scheduleId\n * @return {ModalForm}\n */\nexport const createScheduleModal = (triggerElement, modalTitle, reportId, scheduleId = 0) => {\n return createModalForm(triggerElement, modalTitle, 'core_reportbuilder\\\\form\\\\schedule', {\n reportid: reportId,\n id: scheduleId,\n });\n};\n"],"names":["createModalForm","triggerElement","modalTitle","formClass","formArgs","ModalForm","modalConfig","title","args","saveButtonText","returnFocus","reportId","id","reportName","name","scheduleId","reportid"],"mappings":";;;;;;;oOAmCMA,gBAAkB,CAACC,eAAgBC,WAAYC,UAAWC,WACrD,IAAIC,mBAAU,CACjBC,YAAa,CACTC,MAAOL,YAEXC,UAAWA,UACXK,KAAMJ,SACNK,gBAAgB,kBAAU,OAAQ,UAClCC,YAAaT,4CAYY,SAACA,eAAgBC,gBAAYS,gEAAW,SAC9DX,gBAAgBC,eAAgBC,WAAY,mCAAoC,CACnFU,GAAID,gDAa8B,CAACV,eAAgBC,WAAYS,SAAUE,aACtEb,gBAAgBC,eAAgBC,WAAY,6CAA8C,CAC7FU,GAAID,SACJG,KAAMD,0CAaqB,SAACZ,eAAgBC,WAAYS,cAAUI,kEAAa,SAC5Ef,gBAAgBC,eAAgBC,WAAY,qCAAsC,CACrFc,SAAUL,SACVC,GAAIG"}
{"version":3,"file":"modals.min.js","sources":["../../../src/local/repository/modals.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * Module to handle modal form requests\n *\n * @module core_reportbuilder/local/repository/modals\n * @copyright 2021 David Matamoros <[email protected]>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport ModalForm from 'core_form/modalform';\nimport {getString} from 'core/str';\n\n/**\n * Return modal instance\n *\n * @param {EventTarget} triggerElement\n * @param {Promise} modalTitle\n * @param {String} formClass\n * @param {Object} formArgs\n * @return {ModalForm}\n */\nconst createModalForm = (triggerElement, modalTitle, formClass, formArgs) => {\n return new ModalForm({\n modalConfig: {\n title: modalTitle,\n },\n formClass: formClass,\n args: formArgs,\n saveButtonText: getString('save', 'moodle'),\n returnFocus: triggerElement,\n });\n};\n\n/**\n * Return report modal instance\n *\n * @param {EventTarget} triggerElement\n * @param {Promise} modalTitle\n * @param {Number} reportId\n * @return {ModalForm}\n */\nexport const createReportModal = (triggerElement, modalTitle, reportId = 0) => {\n return createModalForm(triggerElement, modalTitle, 'core_reportbuilder\\\\form\\\\report', {\n id: reportId,\n });\n};\n\n/**\n * Return duplicate report modal instance\n *\n * @param {EventTarget} triggerElement\n * @param {Promise} modalTitle\n * @param {Number} reportId\n * @param {String} reportName\n * @return {ModalForm}\n */\nexport const createDuplicateReportModal = (triggerElement, modalTitle, reportId, reportName) => {\n return createModalForm(triggerElement, modalTitle, 'core_reportbuilder\\\\form\\\\duplicate_report', {\n id: reportId,\n name: reportName,\n });\n};\n\n/**\n * Return schedule modal instance\n *\n * @param {EventTarget} triggerElement\n * @param {Promise} modalTitle\n * @param {Number} reportId\n * @param {Number} scheduleId\n * @param {String} scheduleClass\n * @return {ModalForm}\n */\nexport const createScheduleModal = (triggerElement, modalTitle, reportId, scheduleId = 0, scheduleClass = '') => {\n return createModalForm(triggerElement, modalTitle, 'core_reportbuilder\\\\form\\\\schedule', {\n reportid: reportId,\n id: scheduleId,\n classname: scheduleClass,\n });\n};\n"],"names":["createModalForm","triggerElement","modalTitle","formClass","formArgs","ModalForm","modalConfig","title","args","saveButtonText","returnFocus","reportId","id","reportName","name","scheduleId","scheduleClass","reportid","classname"],"mappings":";;;;;;;oOAmCMA,gBAAkB,CAACC,eAAgBC,WAAYC,UAAWC,WACrD,IAAIC,mBAAU,CACjBC,YAAa,CACTC,MAAOL,YAEXC,UAAWA,UACXK,KAAMJ,SACNK,gBAAgB,kBAAU,OAAQ,UAClCC,YAAaT,4CAYY,SAACA,eAAgBC,gBAAYS,gEAAW,SAC9DX,gBAAgBC,eAAgBC,WAAY,mCAAoC,CACnFU,GAAID,gDAa8B,CAACV,eAAgBC,WAAYS,SAAUE,aACtEb,gBAAgBC,eAAgBC,WAAY,6CAA8C,CAC7FU,GAAID,SACJG,KAAMD,0CAcqB,SAACZ,eAAgBC,WAAYS,cAAUI,kEAAa,EAAGC,qEAAgB,UAC/FhB,gBAAgBC,eAAgBC,WAAY,qCAAsC,CACrFe,SAAUN,SACVC,GAAIG,WACJG,UAAWF"}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -82,11 +82,13 @@ export const createDuplicateReportModal = (triggerElement, modalTitle, reportId,
* @param {Promise} modalTitle
* @param {Number} reportId
* @param {Number} scheduleId
* @param {String} scheduleClass
* @return {ModalForm}
*/
export const createScheduleModal = (triggerElement, modalTitle, reportId, scheduleId = 0) => {
export const createScheduleModal = (triggerElement, modalTitle, reportId, scheduleId = 0, scheduleClass = '') => {
return createModalForm(triggerElement, modalTitle, 'core_reportbuilder\\form\\schedule', {
reportid: reportId,
id: scheduleId,
classname: scheduleClass,
});
};
+4 -1
View File
@@ -75,7 +75,10 @@ export const init = reportId => {
if (scheduleCreate) {
event.preventDefault();
const scheduleModal = createScheduleModal(event.target, getString('newschedule', 'core_reportbuilder'), reportId);
const {scheduleClass} = scheduleCreate.dataset;
const scheduleModal = createScheduleModal(event.target, getString('newschedule', 'core_reportbuilder'), reportId, 0,
scheduleClass);
scheduleModal.addEventListener(scheduleModal.events.FORM_SUBMITTED, () => {
getString('schedulecreated', 'core_reportbuilder')
.then(addToast)
+80 -63
View File
@@ -26,10 +26,10 @@ use core\output\notification;
use core_form\dynamic_form;
use core_reportbuilder\manager;
use core_reportbuilder\permission;
use core_reportbuilder\local\helpers\audience;
use core_reportbuilder\local\helpers\schedule as helper;
use core_reportbuilder\local\helpers\{audience, schedule as helper};
use core_reportbuilder\local\models\schedule as model;
use core_reportbuilder\local\report\base;
use core_reportbuilder\local\schedules\base;
use core_reportbuilder\local\report\base as report_base;
/**
* Schedule form
@@ -41,11 +41,30 @@ use core_reportbuilder\local\report\base;
class schedule extends dynamic_form {
/**
* Return instance of the system report using the filter form
* Return schedule instance
*
* @return base
*/
private function get_report(): base {
private function get_schedule(): base {
$reportid = $this->optional_param('reportid', 0, PARAM_INT);
$scheduleid = $this->optional_param('id', 0, PARAM_INT);
if ($scheduleid > 0) {
$schedule = model::get_record(['id' => $scheduleid, 'reportid' => $reportid], MUST_EXIST);
return base::from_persistent($schedule);
} else {
/** @var base $scheduleclass */
$scheduleclass = $this->optional_param('classname', '', PARAM_RAW);
return $scheduleclass::instance();
}
}
/**
* Return instance of the system report using the filter form
*
* @return report_base
*/
private function get_report(): report_base {
$reportid = $this->optional_param('reportid', 0, PARAM_INT);
return manager::get_report_from_id($reportid);
}
@@ -83,6 +102,9 @@ class schedule extends dynamic_form {
$mform->addElement('hidden', 'id');
$mform->setType('id', PARAM_INT);
$mform->addElement('hidden', 'classname');
$mform->setType('id', PARAM_RAW);
// General fields.
$mform->addElement('header', 'headergeneral', get_string('general'));
@@ -121,63 +143,47 @@ class schedule extends dynamic_form {
}
// Audience fields.
$mform->addElement('header', 'headeraudience', get_string('audience', 'core_reportbuilder'));
$mform->setExpanded('headeraudience', true);
$schedule = $this->get_schedule();
if ($schedule->requires_audience()) {
$mform->addElement('header', 'headeraudience', get_string('audience', 'core_reportbuilder'));
$mform->setExpanded('headeraudience', true);
$audiences = audience::get_base_records($this->optional_param('reportid', 0, PARAM_INT));
if (empty($audiences)) {
$notification = new notification(get_string('noaudiences', 'core_reportbuilder'), notification::NOTIFY_INFO, false);
$mform->addElement('static', 'noaudiences', '', $OUTPUT->render($notification));
}
$audiencecheckboxes = [];
foreach ($audiences as $audience) {
$persistent = $audience->get_persistent();
// Check for a custom name, otherwise fall back to default.
if ('' === $audiencelabel = $persistent->get_formatted_heading($context)) {
$audiencelabel = get_string('audiencelabel', 'core_reportbuilder', (object) [
'name' => $audience->get_name(),
'description' => $audience->get_description(),
]);
$audiences = audience::get_base_records($this->optional_param('reportid', 0, PARAM_INT));
if (empty($audiences)) {
$notification = new notification(get_string('noaudiences', 'core_reportbuilder'), notification::NOTIFY_INFO, false);
$mform->addElement('static', 'noaudiences', '', $OUTPUT->render($notification));
}
$audiencecheckboxes[] = $mform->createElement('checkbox', $persistent->get('id'), $audiencelabel);
$audiencecheckboxes = [];
foreach ($audiences as $audience) {
$persistent = $audience->get_persistent();
// Check for a custom name, otherwise fall back to default.
if ('' === $audiencelabel = $persistent->get_formatted_heading($context)) {
$audiencelabel = get_string('audiencelabel', 'core_reportbuilder', (object) [
'name' => $audience->get_name(),
'description' => $audience->get_description(),
]);
}
$audiencecheckboxes[] = $mform->createElement('checkbox', $persistent->get('id'), $audiencelabel);
}
$mform->addElement('group', 'audiences', '', $audiencecheckboxes, html_writer::div('', 'w-100 mb-2'));
}
$mform->addElement('group', 'audiences', '', $audiencecheckboxes, html_writer::div('', 'w-100 mb-2'));
// Message fields.
$mform->addElement('header', 'headermessage', get_string('messagecontent', 'core_reportbuilder'));
$mform->addElement('text', 'subject', get_string('messagesubject', 'core_reportbuilder'));
$mform->setType('subject', PARAM_TEXT);
$mform->addRule('subject', null, 'required', null, 'client');
$mform->addRule('subject', get_string('maximumchars', '', 255), 'maxlength', 255);
$mform->addElement('editor', 'message', get_string('messagebody', 'core_reportbuilder'), null, ['autosave' => false]);
$mform->setType('message', PARAM_RAW);
$mform->addRule('message', null, 'required', null, 'client');
// Advanced.
$mform->addElement('header', 'headeradvanced', get_string('advanced'));
$mform->addElement('select', 'reportempty', get_string('scheduleempty', 'core_reportbuilder'),
helper::get_report_empty_options());
$mform->setType('reportempty', PARAM_INT);
// Load schedule type form definition.
$schedule->definition($mform);
}
/**
* Load form data if we are editing an existing schedule
*/
public function set_data_for_dynamic_submission(): void {
$reportid = $this->optional_param('reportid', 0, PARAM_INT);
$scheduleid = $this->optional_param('id', 0, PARAM_INT);
$schedule = $this->get_schedule();
if ($scheduleid > 0) {
$schedule = model::get_record(['id' => $scheduleid, 'reportid' => $reportid]);
$data = (array) $schedule->to_record();
if ($schedule->get_persistent()->get('id') > 0) {
$data = (array) $schedule->get_persistent()->to_record();
// Pre-process some of the form fields.
if (!in_array($data['userviewas'], [model::REPORT_VIEWAS_CREATOR, model::REPORT_VIEWAS_RECIPIENT])) {
@@ -185,17 +191,18 @@ class schedule extends dynamic_form {
$data['userviewas'] = model::REPORT_VIEWAS_USER;
}
$audiences = json_decode($data['audiences']);
$data['audiences'] = array_fill_keys($audiences, 1);
if ($schedule->requires_audience()) {
$audiences = (array) json_decode((string) $data['audiences']);
$data['audiences'] = array_fill_keys($audiences, 1);
}
$data['message'] = [
'text' => $data['message'],
'format' => $data['messageformat'],
];
// Load schedule type form definition data.
$data['configdata'] = $schedule->get_configdata();
$this->set_data($data);
} else {
$this->set_data(['reportid' => $reportid]);
$reportid = $this->optional_param('reportid', 0, PARAM_INT);
$this->set_data(['reportid' => $reportid, 'classname' => $schedule::class]);
}
}
@@ -220,11 +227,13 @@ class schedule extends dynamic_form {
$errors['user'] = get_string('required');
}
if (empty($data['audiences'])) {
// Load schedule type form validation.
$schedule = $this->get_schedule();
if ($schedule->requires_audience() && empty($data['audiences'])) {
$errors['audiences'] = get_string('required');
}
return $errors;
return array_merge($errors, $schedule->validate($data, $files));
}
/**
@@ -238,13 +247,21 @@ class schedule extends dynamic_form {
$data->userviewas = (int) $data->user;
}
$data->audiences = json_encode(array_keys($data->audiences));
['text' => $data->message, 'format' => $data->messageformat] = $data->message;
$schedule = $this->get_schedule();
if ($data->id) {
if ($schedule->requires_audience()) {
$data->audiences = json_encode(array_keys($data->audiences));
} else {
$data->audiences = null;
}
$data->configdata = json_encode((array) $data->configdata);
if ($schedule->get_persistent()->get('id') > 0) {
helper::update_schedule($data);
} else {
helper::create_schedule($data);
unset($data->id);
$schedule::create($data);
}
}
@@ -19,7 +19,7 @@ declare(strict_types=1);
namespace core_reportbuilder\local\helpers;
use context_user;
use core\{clock, di};
use core\{component, clock, di};
use core\exception\{coding_exception, invalid_parameter_exception};
use core_user;
use stdClass;
@@ -50,6 +50,17 @@ class schedule {
return class_exists($scheduleclass) && is_subclass_of($scheduleclass, base::class);
}
/**
* Return list of all available/valid schedule types
*
* @return base[]
*/
public static function get_schedules(): array {
$classes = component::get_component_classes_in_namespace(null, 'reportbuilder\\schedule');
return array_filter(array_keys($classes), [static::class, 'valid']);
}
/**
* Create report schedule, calculate when it should be next sent
*
@@ -327,8 +338,13 @@ class schedule {
* @param stdClass $user
* @param stored_file $attachment
* @return bool
*
* @deprecated since Moodle 5.1 - please do not use this function any more
*/
#[\core\attribute\deprecated(reason: 'It is no longer used', since: '5.1', mdl: 'MDL-86066')]
public static function send_schedule_message(model $schedule, stdClass $user, stored_file $attachment): bool {
\core\deprecation::emit_deprecation([self::class, __FUNCTION__]);
$message = new message();
$message->component = 'moodle';
$message->name = 'reportbuilderschedule';
@@ -412,12 +428,17 @@ class schedule {
* Return list of options for when report is empty
*
* @return string[]
*
* @deprecated since Moodle 5.1 - please do not use this function any more
*/
#[\core\attribute\deprecated(reason: 'It is no longer used', since: '5.1', mdl: 'MDL-86066')]
public static function get_report_empty_options(): array {
\core\deprecation::emit_deprecation([self::class, __FUNCTION__]);
return [
model::REPORT_EMPTY_SEND_EMPTY => get_string('scheduleemptysendwithattachment', 'core_reportbuilder'),
model::REPORT_EMPTY_SEND_WITHOUT => get_string('scheduleemptysendwithoutattachment', 'core_reportbuilder'),
model::REPORT_EMPTY_DONT_SEND => get_string('scheduleemptydontsend', 'core_reportbuilder'),
0 => get_string('scheduleemptysendwithattachment', 'core_reportbuilder'),
1 => get_string('scheduleemptysendwithoutattachment', 'core_reportbuilder'),
2 => get_string('scheduleemptydontsend', 'core_reportbuilder'),
];
}
}
@@ -67,15 +67,6 @@ class schedule extends persistent {
/** @var int Annual recurrence */
public const RECURRENCE_ANNUALLY = 5;
/** @var int Send schedule with empty report */
public const REPORT_EMPTY_SEND_EMPTY = 0;
/** @var int Send schedule without report */
public const REPORT_EMPTY_SEND_WITHOUT = 1;
/** @var int Don't send schedule if report is empty */
public const REPORT_EMPTY_DONT_SEND = 2;
/**
* Return the definition of the properties of this model.
*
@@ -30,6 +30,7 @@ use core_reportbuilder\local\filters\{boolean_select, date, text};
use core_reportbuilder\local\helpers\format;
use core_reportbuilder\local\models\{report, schedule};
use core_reportbuilder\local\report\{action, column, filter};
use core_reportbuilder\local\schedules\base;
use core_reportbuilder\output\schedule_name_editable;
/**
@@ -60,7 +61,7 @@ class report_schedules extends system_report {
$this->add_base_condition_simple('sc.reportid', $this->get_parameter('reportid', 0, PARAM_INT));
// Select fields required for actions, permission checks, and row class callbacks.
$this->add_base_fields('sc.id, sc.name, sc.enabled, rb.contextid');
$this->add_base_fields('sc.id, sc.name, sc.enabled, sc.classname, rb.contextid');
// Join user entity for "User modified" column.
$entityuser = new user();
@@ -310,31 +311,38 @@ class report_schedules extends system_report {
*/
protected function add_actions(): void {
// Edit action.
$this->add_action(new action(
$this->add_action((new action(
new moodle_url('#'),
new pix_icon('t/edit', ''),
['data-action' => 'schedule-edit', 'data-schedule-id' => ':id'],
false,
new lang_string('editscheduledetails', 'core_reportbuilder')
));
))
->add_callback(static function (stdClass $row): bool {
$instance = base::instance(0, $row);
return $instance !== null && $instance->user_can_add();
}));
// Send now action.
$this->add_action((new action(
new moodle_url('#'),
new pix_icon('t/email', ''),
new pix_icon('t/play', ''),
['data-action' => 'schedule-send', 'data-schedule-id' => ':id', 'data-schedule-name' => ':name'],
false,
new lang_string('sendschedule', 'core_reportbuilder')
))
->add_callback(function(stdClass $row): bool {
$instance = base::instance(0, $row);
if ($instance === null || !$instance->user_can_add()) {
return false;
}
// Ensure data name attribute is properly formatted.
$row->name = (new schedule(0, $row))->get_formatted_name(
$row->name = $instance->get_persistent()->get_formatted_name(
context::instance_by_id($row->contextid));
return true;
})
);
}));
// Delete action.
$this->add_action((new action(
@@ -350,13 +358,16 @@ class report_schedules extends system_report {
new lang_string('deleteschedule', 'core_reportbuilder')
))
->add_callback(function(stdClass $row): bool {
$instance = base::instance(0, $row);
if ($instance !== null && !$instance->user_can_add()) {
return false;
}
// Ensure data name attribute is properly formatted.
$row->name = (new schedule(0, $row))->get_formatted_name(
context::instance_by_id($row->contextid));
return true;
})
);
}));
}
}
@@ -19,13 +19,14 @@ declare(strict_types=1);
namespace core_reportbuilder\output\dynamictabs;
use context_system;
use renderer_base;
use core\output\{choicelist, renderer_base};
use core\output\local\dropdown\{dialog, status};
use core\output\dynamic_tabs\base;
use core_reportbuilder\permission;
use core_reportbuilder\system_report_factory;
use core_reportbuilder\local\helpers\schedule;
use core_reportbuilder\local\models\report;
use core_reportbuilder\local\systemreports\report_schedules;
use core_reportbuilder\output\report_action;
/**
* Schedules dynamic tab
@@ -45,12 +46,38 @@ class schedules extends base {
public function export_for_template(renderer_base $output): array {
$report = system_report_factory::create(report_schedules::class, context_system::instance(), '', '', 0,
['reportid' => $this->data['reportid']]);
$report->set_report_action(new report_action(
// Schedule type menu.
$choicelist = new choicelist();
$choicelist->set_allow_empty(true);
// Include those schedule types the user can add.
foreach (schedule::get_schedules() as $schedule) {
$instance = $schedule::instance();
if ($instance->user_can_add()) {
$choicelist->add_option(
$instance::class,
$instance->get_name(),
[
'description' => $instance->get_description(),
'extras' => ['data-action' => 'schedule-create', 'data-schedule-class' => $instance::class],
]
);
}
}
$dialog = new status(
get_string('newschedule', 'core_reportbuilder'),
['class' => 'btn btn-primary ms-auto', 'data-action' => 'schedule-create'],
));
$choicelist,
[
'classes' => 'd-flex justify-content-end mb-2',
'buttonclasses' => 'btn btn-primary dropdown-toggle',
],
);
$dialog->set_dialog_width(dialog::WIDTH['small']);
return [
'menu' => $dialog->export_for_template($output),
'reportid' => $this->data['reportid'],
'report' => $report->output(),
];
@@ -21,12 +21,16 @@
Example context (json):
{
"menu": {},
"report": "The report content",
"reportid": 10
}
}}
<h2 class="visually-hidden">{{#str}} schedules, core_reportbuilder {{/str}}</h2>
<div class="reportbuilder-schedules-container">
{{#menu}}
{{> core/local/dropdown/status}}
{{/menu}}
{{{ report }}}
</div>
@@ -204,6 +204,7 @@ Feature: Configure access to reports based on intended audience
And I am on the "My report" "reportbuilder > Editor" page logged in as "admin"
And I click on the "Schedules" dynamic tab
And I press "New schedule"
And I click on "Schedule an email" "link" in the ".dropdown" "css_element"
And I set the following fields in the "New schedule" "dialogue" to these values:
| Name | My schedule |
| Starting from | ##tomorrow 11:00## |
@@ -30,6 +30,7 @@ Feature: Manage custom report schedules
And I press "Save changes"
When I click on the "Schedules" dynamic tab
And I press "New schedule"
And I click on "Schedule an email" "link" in the ".dropdown" "css_element"
And I set the following fields in the "New schedule" "dialogue" to these values:
| Name | My schedule |
| Starting from | ##tomorrow 11:00## |
@@ -52,6 +53,7 @@ Feature: Manage custom report schedules
And I set the field "Rename audience 'All users'" to "<span class=\"multilang\" lang=\"en\">English</span><span class=\"multilang\" lang=\"es\">Spanish</span>"
When I click on the "Schedules" dynamic tab
And I press "New schedule"
And I click on "Schedule an email" "link" in the ".dropdown" "css_element"
Then I should see "English" in the "New schedule" "dialogue"
And I should not see "Spanish" in the "New schedule" "dialogue"
And I click on "Cancel" "button" in the "New schedule" "dialogue"
@@ -147,11 +149,22 @@ Feature: Manage custom report schedules
| Name | My updated schedule |
| Starting from | ##tomorrow 11:00## |
| All users: All site users | 1 |
| Subject | Tell me how to win your heart |
| Body | For I haven't got a clue |
| If the report is empty | Don't send message |
And I click on "Save" "button" in the "Edit schedule details" "dialogue"
Then I should see "Schedule updated"
And the following should exist in the "Report schedules" table:
| Name | Time last sent | Time next send | Modified by |
| My updated schedule | Never | ##tomorrow 11:00##%A, %d %B %Y, %H:%M## | Admin User |
And I press "Edit schedule details" action in the "My updated schedule" report row
And the following fields in the "Edit schedule details" "dialogue" match these values:
| Name | My updated schedule |
# | Starting from | ##tomorrow 11:00## | Nope, can't: MDL-86255.
| All users: All site users | 1 |
| Subject | Tell me how to win your heart |
| Body | For I haven't got a clue |
| If the report is empty | Don't send message |
Scenario: Send report schedule
Given the following "core_reportbuilder > Schedules" exist: