Merge branch 'MDL-75337-master' of https://github.com/laurentdavid/moodle

This commit is contained in:
Sara Arjona
2023-01-24 16:07:35 +01:00
70 changed files with 675 additions and 153 deletions
+1 -1
View File
@@ -213,7 +213,7 @@ class core_admin_renderer extends plugin_renderer_base {
$output .= $this->container_end();
}
$button = new single_button($continueurl, get_string('upgradestart', 'admin'), 'get', true);
$button = new single_button($continueurl, get_string('upgradestart', 'admin'), 'get', single_button::BUTTON_PRIMARY);
$button->class = 'continuebutton';
$output .= $this->render($button);
$output .= $this->footer();
+1 -1
View File
@@ -77,7 +77,7 @@ if ($action) {
$cancelurl = new moodle_url('/admin/searchareas.php');
echo $OUTPUT->header();
echo $OUTPUT->confirm(get_string('confirm_' . $action, 'search', $a),
new single_button($actionurl, get_string('continue'), 'post', true),
new single_button($actionurl, get_string('continue'), 'post', single_button::BUTTON_PRIMARY),
new single_button($cancelurl, get_string('cancel'), 'get'));
echo $OUTPUT->footer();
exit;
+1 -1
View File
@@ -83,7 +83,7 @@ if (optional_param('sesskey', '', PARAM_ALPHANUM)) {
// Display confirmation prompt.
echo $OUTPUT->confirm(get_string('gradualreindex_confirm', 'search', html_writer::tag('strong', $areaname)),
new single_button(new moodle_url('/admin/searchreindex.php', ['areaid' => $areaid,
'sesskey' => sesskey()]), get_string('continue'), 'post', true),
'sesskey' => sesskey()]), get_string('continue'), 'post', single_button::BUTTON_PRIMARY),
new single_button(new moodle_url('/admin/searchareas.php'), get_string('cancel'), 'get'));
}
@@ -170,7 +170,7 @@ class renderer extends plugin_renderer_base {
$link,
get_string('schedule:requestanalysis', manager::PLUGINNAME),
'post',
true,
\single_button::BUTTON_PRIMARY,
['class' => $classname]
);
@@ -62,7 +62,7 @@ Outline buttons are used for buttons that controll part of the user interface, l
### Using the single_select renderer
The ```single_select()``` renderer allows you to quickly add a button with an action to a page without having to write a template for the page. Single select buttons are added as miniature forms that can pass custom form data.
The ```single_button()``` renderer allows you to quickly add a button with an action to a page without having to write a template for the page. Single select buttons are added as miniature forms that can pass custom form data.
{{< php >}}
$url = new moodle_url("$CFG->wwwroot/my/index.php", $params);
@@ -70,6 +70,8 @@ The ```single_select()``` renderer allows you to quickly add a button with an ac
$PAGE->set_button($resetbutton . $button);
{{< / php >}}
<iframe src="../../../../examples/singlebuttons.php" style="overflow:hidden;height:50px;width:100%;border:0" title="Single button examples"></iframe>
### Button links
Links can be style to look like buttons, the action for this button is to simply navigate to some other page
@@ -16,7 +16,7 @@ to the element that will trigger the confirmation modal.
## Source files
* `lib/amd/src/confirm.js` ({{< jsdoc module="core/confirm" >}})
* `lib/amd/src/utility.js` ({{< jsdoc module="core/utility" >}})
* `lib/templates/modal.mustache`
## Usage
@@ -82,23 +82,33 @@ echo $OUTPUT->single_button('#', get_string('delete'), 'get', [
### Basic confirmation modal
#### Simple Modal
{{< example >}}
<button type="button" class="btn btn-primary" data-confirmation="modal" data-confirmation-title-str='["delete", "core"]'
data-confirmation-question-str='["areyousure"]' data-confirmation-yes-button-str='["delete", "core"]'>Show confirmation modal</button>
<button type="button" class="btn btn-primary" data-confirmation="modal" data-confirmation-title-str='["ok", "core"]'
data-confirmation-question-str='["areyousure"]' data-confirmation-yes-button-str='["ok", "core"]'>Show confirmation modal</button>
{{< /example >}}
#### Delete Modal
{{< example >}}
<button type="button" class="btn btn-primary" data-confirmation="modal" data-confirmation-type="delete" data-confirmation-title-str='["delete", "core"]'
data-confirmation-question-str='["areyousure"]' data-confirmation-yes-button-str='["delete", "core"]'>Show delete modal</button>
{{< /example >}}
### Confirmation modal with a toast
{{< example >}}
<button type="button" class="btn btn-primary" data-confirmation="modal" data-confirmation-title-str='["delete", "core"]'
data-confirmation-question-str='["areyousure"]' data-confirmation-yes-button-str='["delete", "core"]' data-confirmation-toast="true"
data-confirmation-toast-confirmation-str='["deleteblockinprogress", "block", "Online users"]'>Show confirmation modal</button>
<button type="button" class="btn btn-primary" data-confirmation="modal" data-confirmation-title-str='["save", "core"]'
data-confirmation-question-str='["areyousure"]' data-confirmation-yes-button-str='["save", "core"]' data-confirmation-toast="true"
data-confirmation-toast-confirmation-str='["saved", "core_question", "My question"]'>Show confirmation modal</button>
{{< /example >}}
### Confirmation modal with redirect
{{< example >}}
<button type="button" class="btn btn-primary" data-confirmation="modal" data-confirmation-title-str='["delete", "core"]'
data-confirmation-question-str='["areyousure"]' data-confirmation-yes-button-str='["delete", "core"]'
<button type="button" class="btn btn-primary" data-confirmation="modal" data-confirmation-title-str='["save", "core"]'
data-confirmation-question-str='["areyousure"]' data-confirmation-yes-button-str='["save", "core"]'
data-confirmation-destination="http://moodle.com">Show confirmation modal</button>
{{< /example >}}
@@ -0,0 +1,59 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Moodle Component Library
*
* A sample of different singlebuttons
*
* @package tool_componentlibrary
* @copyright 2022 Laurent David <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
require_once(__DIR__ . '/../../../../config.php');
require_once($CFG->dirroot . '/lib/formslib.php');
require_login();
require_capability('moodle/site:configview', context_system::instance());
$repeatcount = optional_param('test_repeat', 1, PARAM_INT);
$PAGE->set_pagelayout('embedded');
$url = new moodle_url('/admin/tool/componentlibrary/examples/singlebuttons.php');
$PAGE->set_url($url);
$PAGE->set_context(context_system::instance());
$PAGE->set_heading('Moodle single buttons');
$PAGE->set_title('Moodle single buttons');
$buttondefinitions = [
['label' => 'Standard'],
['label' => 'Primary', 'type' => single_button::BUTTON_PRIMARY],
['label' => 'Danger', 'type' => single_button::BUTTON_DANGER],
['label' => 'Warning', 'type' => single_button::BUTTON_WARNING],
['label' => 'Success', 'type' => single_button::BUTTON_SUCCESS],
['label' => 'Info', 'type' => single_button::BUTTON_INFO],
];
echo $OUTPUT->header();
foreach ($buttondefinitions as $def) {
$button = new single_button($url, $def['label'], 'post', $def['type'] ??
single_button::BUTTON_SECONDARY, $def['attributes'] ?? []);
echo $OUTPUT->render($button);
}
echo $OUTPUT->footer();
+1 -1
View File
@@ -148,7 +148,7 @@ echo $OUTPUT->header();
echo $OUTPUT->heading(get_string('managetokens', 'core_webservice'));
echo html_writer::div($OUTPUT->render(new single_button(new moodle_url($PAGE->url, ['action' => 'create']),
get_string('createtoken', 'core_webservice'), 'get', true)), 'my-3');
get_string('createtoken', 'core_webservice'), 'get', single_button::BUTTON_PRIMARY)), 'my-3');
$filter->display();
+4 -1
View File
@@ -60,6 +60,9 @@ class bulk_action extends action {
$this->url = new \moodle_url('/report/insights/action.php', $params);
$label = $OUTPUT->render($icon) . $this->text;
$this->actionlink = new \single_button($this->url, $label, 'get', $primary, $attributes);
$this->actionlink = new \single_button($this->url, $label,
'get',
$primary ? \single_button::BUTTON_PRIMARY : \single_button::BUTTON_SECONDARY,
$attributes);
}
}
+1 -1
View File
@@ -567,7 +567,7 @@ class core_backup_renderer extends plugin_renderer_base {
if ($method != 'post') {
$method = 'get';
}
$button = new single_button($url, get_string('continue'), $method, true);
$button = new single_button($url, get_string('continue'), $method, single_button::BUTTON_PRIMARY);
$button->class = 'continuebutton';
return $this->render($button);
}
@@ -50,7 +50,7 @@ class recipients_action_bar extends manage_badge_action_bar {
if ($this->badge->has_manual_award_criteria()
&& has_capability('moodle/badges:awardbadge', $this->page->context) && $this->badge->is_active()) {
$url = new moodle_url('/badges/award.php', ['id' => $this->badge->id]);
$button = new single_button($url, get_string('award', 'badges'), 'post', true);
$button = new single_button($url, get_string('award', 'badges'), 'post', single_button::BUTTON_PRIMARY);
$elements['awardbutton'] = $button->export_for_template($output);
}
$thirdpartynav = $this->get_third_party_nav_action($output);
@@ -89,7 +89,7 @@ class standard_action_bar extends base_action_bar {
if ($this->showaddbadge && has_capability('moodle/badges:createbadge', $this->page->context)) {
$buttons[] = new single_button(new moodle_url('/badges/newbadge.php', $params),
get_string('newbadge', 'core_badges'), 'post', true);
get_string('newbadge', 'core_badges'), 'post', single_button::BUTTON_PRIMARY);
}
foreach ($buttons as $key => $button) {
+1 -1
View File
@@ -155,7 +155,7 @@ class block_accessreview extends block_base {
$button = new single_button(
new moodle_url(accessibility::get_plugin_url(), ['action' => 'requestanalysis', 'courseid' => $COURSE->id]),
get_string('schedule:requestanalysis', manager::PLUGINNAME), 'post', true,
get_string('schedule:requestanalysis', manager::PLUGINNAME), 'post', single_button::BUTTON_PRIMARY,
['class' => 'block_accessreview_analysisbutton']);
$this->content->text .= html_writer::tag('div', $OUTPUT->render($button),
['class' => 'block_accessreview_analysisbutton']);
+3 -3
View File
@@ -502,7 +502,7 @@ class main implements renderable, templatable {
new \moodle_url('/course/request.php', ['category' => $category->id]),
get_string('requestcourse'),
'post',
true
\single_button::BUTTON_PRIMARY
);
return $this->generate_zero_state_data($nocoursesimg, [$button], 'request');
}
@@ -523,7 +523,7 @@ class main implements renderable, templatable {
new \moodle_url('/course/edit.php', ['category' => $category->id]),
get_string('createcourse', 'block_myoverview'),
'post',
true
\single_button::BUTTON_PRIMARY
);
$buttons[] = $createbutton->export_for_template($output);
return $this->generate_zero_state_data($nocoursesimg, $buttons, 'nocourses');
@@ -534,7 +534,7 @@ class main implements renderable, templatable {
new \moodle_url('/course/edit.php', ['category' => $categorytocreate->id]),
get_string('createcourse', 'block_myoverview'),
'post',
true
\single_button::BUTTON_PRIMARY
);
$buttons = [$createbutton->export_for_template($output)];
if ($categorytomanage = \core_course_category::get_nearest_editable_subcategory($coursecat, ['manage'])) {
+2 -2
View File
@@ -325,10 +325,10 @@ class core_calendar_renderer extends plugin_renderer_base {
*/
public function render_subscriptions_header(): string {
$importcalendarbutton = new single_button(new moodle_url('/calendar/import.php', calendar_get_export_import_link_params()),
get_string('importcalendar', 'calendar'), 'get', true);
get_string('importcalendar', 'calendar'), 'get', single_button::BUTTON_PRIMARY);
$importcalendarbutton->class .= ' float-sm-right float-right';
$exportcalendarbutton = new single_button(new moodle_url('/calendar/export.php', calendar_get_export_import_link_params()),
get_string('exportcalendar', 'calendar'), 'get', true);
get_string('exportcalendar', 'calendar'), 'get', single_button::BUTTON_PRIMARY);
$exportcalendarbutton->class .= ' float-sm-right float-right';
$output = $this->output->heading(get_string('managesubscriptions', 'calendar'));
$output .= html_writer::start_div('header d-flex flex-wrap mt-5');
+1 -1
View File
@@ -218,7 +218,7 @@ class enrol_manual_plugin extends enrol_plugin {
$button = new enrol_user_button($link, get_string('enrolusers', 'enrol_manual'), 'get');
$button->class .= ' enrol_manual_plugin';
$button->primary = true;
$button->type = single_button::BUTTON_PRIMARY;
$context = context_course::instance($instance->courseid);
$arguments = array('contextid' => $context->id);
+1 -1
View File
@@ -98,7 +98,7 @@ echo $OUTPUT->header();
// Check we have a search button to render.
$searchbuttonrender = null;
if ($searchbutton = $table->get_user_search_button()) {
$searchbutton->primary = true;
$searchbutton->type = single_button::BUTTON_PRIMARY;
$searchbuttonrender = $OUTPUT->render($searchbutton);
}
+8 -5
View File
@@ -37,12 +37,15 @@ class core_enrol_renderer extends plugin_renderer_base {
* @return string XHTML
*/
protected function render_enrol_user_button(enrol_user_button $button) {
$attributes = array('type' => 'submit',
'value' => $button->label,
'disabled' => $button->disabled ? 'disabled' : null,
'title' => $button->tooltip,
'class' => 'btn ' . ($button->primary ? 'btn-primary' : 'btn-secondary'));
$buttoninfo = $button->export_for_template($this->output);
$attributes = [
'type' => 'submit',
'value' => $buttoninfo->label,
'disabled' => $buttoninfo->disabled ? 'disabled' : null,
'title' => $buttoninfo->tooltip,
'class' => 'btn ' . "btn-{$buttoninfo->type}",
];
if ($button->actions) {
$id = html_writer::random_id('single_button');
$attributes['id'] = $id;
@@ -56,7 +56,7 @@ class course_outcomes_action_bar extends action_bar {
// Add a button to the action bar with a link to the 'manage outcomes' page.
$manageoutcomeslink = new moodle_url('/grade/edit/outcome/index.php', ['id' => $courseid]);
$manageoutcomesbutton = new \single_button($manageoutcomeslink, get_string('manageoutcomes', 'grades'),
'get', true);
'get', \single_button::BUTTON_PRIMARY);
$data['manageoutcomesbutton'] = $manageoutcomesbutton->export_for_template($output);
}
@@ -54,7 +54,7 @@ class export_key_manager_action_bar extends action_bar {
// Add a button to the action bar with a link to the 'add user key' page.
$adduserkeylink = new moodle_url('/grade/export/key.php', ['courseid' => $courseid]);
$adduserkeybutton = new \single_button($adduserkeylink, get_string('adduserkey', 'userkey'),
'get', true);
'get', \single_button::BUTTON_PRIMARY);
$data['adduserkeybutton'] = $adduserkeybutton->export_for_template($output);
return $data;
@@ -53,7 +53,7 @@ class grade_letters_action_bar extends action_bar {
}
// Add a button to the action bar with a link to the 'edit grade letters' page.
$editbuttonlink = new moodle_url('/grade/edit/letter/index.php', ['id' => $this->context->id, 'edit' => 1]);
$editbutton = new \single_button($editbuttonlink, get_string('edit'), 'get', true);
$editbutton = new \single_button($editbuttonlink, get_string('edit'), 'get', \single_button::BUTTON_PRIMARY);
$data['editbutton'] = $editbutton->export_for_template($output);
return $data;
@@ -54,7 +54,7 @@ class import_key_manager_action_bar extends action_bar {
// Add a button to the action bar with a link to the 'add user key' page.
$adduserkeylink = new moodle_url('/grade/import/key.php', ['courseid' => $courseid]);
$adduserkeybutton = new \single_button($adduserkeylink, get_string('adduserkey', 'userkey'),
'get', true);
'get', \single_button::BUTTON_PRIMARY);
$data['adduserkeybutton'] = $adduserkeybutton->export_for_template($output);
return $data;
@@ -78,7 +78,7 @@ class manage_outcomes_action_bar extends action_bar {
// Add a button to the action bar with a link to the 'add new outcome' page.
$addoutcomelink = new moodle_url('/grade/edit/outcome/edit.php', ['courseid' => $courseid]);
$addoutcomebutton = new \single_button($addoutcomelink, get_string('outcomecreate', 'grades'),
'get', true);
'get', \single_button::BUTTON_PRIMARY);
$data['addoutcomebutton'] = $addoutcomebutton->export_for_template($output);
if ($this->hasoutcomes) {
+1 -1
View File
@@ -56,7 +56,7 @@ class scales_action_bar extends action_bar {
// Add a button to the action bar with a link to the 'add new scale' page.
$addnewscalelink = new moodle_url('/grade/edit/scale/edit.php', ['courseid' => $courseid]);
$addnewscalebutton = new \single_button($addnewscalelink, get_string('scalescustomcreate'),
'get', true);
'get', \single_button::BUTTON_PRIMARY);
$data['addnewscalebutton'] = $addnewscalebutton->export_for_template($output);
return $data;
+1 -1
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+10
View File
@@ -0,0 +1,10 @@
define("core/modal_delete_cancel",["exports","core/modal","core/notification"],(function(_exports,_modal,_notification){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}
/**
* Contain the logic for the delete/cancel modal.
*
* @module core/modal_delete_cancel
* @copyright 2022 Laurent David <laurent.david@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_modal=_interopRequireDefault(_modal),_notification=_interopRequireDefault(_notification);class _default extends _modal.default{constructor(root){super(root),this.getFooter().find(this.getActionSelector("delete")).length||_notification.default.exception({message:"No delete button found"}),this.getFooter().find(this.getActionSelector("cancel")).length||_notification.default.exception({message:"No cancel button found"})}registerEventListeners(){super.registerEventListeners(),this.registerCloseOnDelete(),this.registerCloseOnCancel()}setFooter(){_notification.default.exception({message:"Can not change the footer of a delete cancel modal"})}setDeleteButtonText(value){return this.setButtonText("delete",value)}}return _exports.default=_default,_exports.default}));
//# sourceMappingURL=modal_delete_cancel.min.js.map
@@ -0,0 +1 @@
{"version":3,"file":"modal_delete_cancel.min.js","sources":["../src/modal_delete_cancel.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 * Contain the logic for the delete/cancel modal.\n *\n * @module core/modal_delete_cancel\n * @copyright 2022 Laurent David <[email protected]>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport Modal from 'core/modal';\nimport Notification from 'core/notification';\n\n/**\n * The Delete/Cancel Modal.\n *\n * @class\n * @extends module:core/modal\n */\nexport default class extends Modal {\n constructor(root) {\n super(root);\n\n if (!this.getFooter().find(this.getActionSelector('delete')).length) {\n Notification.exception({message: 'No delete button found'});\n }\n\n if (!this.getFooter().find(this.getActionSelector('cancel')).length) {\n Notification.exception({message: 'No cancel button found'});\n }\n }\n\n /**\n * Register all event listeners.\n */\n registerEventListeners() {\n // Call the parent registration.\n super.registerEventListeners();\n\n // Register to close on delete/cancel.\n this.registerCloseOnDelete();\n this.registerCloseOnCancel();\n }\n\n /**\n * Override parent implementation to prevent changing the footer content.\n */\n setFooter() {\n Notification.exception({message: 'Can not change the footer of a delete cancel modal'});\n }\n\n /**\n * Set the title of the delete button.\n *\n * @param {String|Promise} value The button text, or a Promise which will resolve it\n * @returns{Promise}\n */\n setDeleteButtonText(value) {\n return this.setButtonText('delete', value);\n }\n}\n"],"names":["Modal","constructor","root","this","getFooter","find","getActionSelector","length","exception","message","registerEventListeners","registerCloseOnDelete","registerCloseOnCancel","setFooter","setDeleteButtonText","value","setButtonText"],"mappings":";;;;;;;sMA+B6BA,eACzBC,YAAYC,YACFA,MAEDC,KAAKC,YAAYC,KAAKF,KAAKG,kBAAkB,WAAWC,8BAC5CC,UAAU,CAACC,QAAS,2BAGhCN,KAAKC,YAAYC,KAAKF,KAAKG,kBAAkB,WAAWC,8BAC5CC,UAAU,CAACC,QAAS,2BAOzCC,+BAEUA,8BAGDC,6BACAC,wBAMTC,kCACiBL,UAAU,CAACC,QAAS,uDASrCK,oBAAoBC,cACTZ,KAAKa,cAAc,SAAUD"}
+1 -1
View File
@@ -6,6 +6,6 @@
* @copyright 2016 Ryan Wyllie <ryan@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
define("core/modal_events",[],(function(){return{shown:"modal:shown",hidden:"modal:hidden",destroyed:"modal:destroyed",bodyRendered:"modal:bodyRendered",outsideClick:"modal:outsideClick",save:"modal-save-cancel:save",cancel:"modal-save-cancel:cancel"}}));
define("core/modal_events",[],(function(){return{shown:"modal:shown",hidden:"modal:hidden",destroyed:"modal:destroyed",bodyRendered:"modal:bodyRendered",outsideClick:"modal:outsideClick",save:"modal-save-cancel:save",delete:"modal-delete-cancel:delete",cancel:"modal-save-cancel:cancel"}}));
//# sourceMappingURL=modal_events.min.js.map
+1 -1
View File
@@ -1 +1 @@
{"version":3,"file":"modal_events.min.js","sources":["../src/modal_events.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 * Contain the events a modal can fire.\n *\n * @module core/modal_events\n * @class modal_events\n * @copyright 2016 Ryan Wyllie <[email protected]>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([], function() {\n return {\n // Default events.\n shown: 'modal:shown',\n hidden: 'modal:hidden',\n destroyed: 'modal:destroyed',\n bodyRendered: 'modal:bodyRendered',\n outsideClick: 'modal:outsideClick',\n // ModalSaveCancel events.\n save: 'modal-save-cancel:save',\n cancel: 'modal-save-cancel:cancel',\n };\n});\n"],"names":["define","shown","hidden","destroyed","bodyRendered","outsideClick","save","cancel"],"mappings":";;;;;;;;AAuBAA,2BAAO,IAAI,iBACA,CAEHC,MAAO,cACPC,OAAQ,eACRC,UAAW,kBACXC,aAAc,qBACdC,aAAc,qBAEdC,KAAM,yBACNC,OAAQ"}
{"version":3,"file":"modal_events.min.js","sources":["../src/modal_events.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 * Contain the events a modal can fire.\n *\n * @module core/modal_events\n * @class modal_events\n * @copyright 2016 Ryan Wyllie <[email protected]>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([], function() {\n return {\n // Default events.\n shown: 'modal:shown',\n hidden: 'modal:hidden',\n destroyed: 'modal:destroyed',\n bodyRendered: 'modal:bodyRendered',\n outsideClick: 'modal:outsideClick',\n // ModalSaveCancel events.\n save: 'modal-save-cancel:save',\n 'delete': 'modal-delete-cancel:delete', // Delete is a reserved word.\n cancel: 'modal-save-cancel:cancel',\n };\n});\n"],"names":["define","shown","hidden","destroyed","bodyRendered","outsideClick","save","cancel"],"mappings":";;;;;;;;AAuBAA,2BAAO,IAAI,iBACA,CAEHC,MAAO,cACPC,OAAQ,eACRC,UAAW,kBACXC,aAAc,qBACdC,aAAc,qBAEdC,KAAM,gCACI,6BACVC,OAAQ"}
+1 -1
View File
@@ -5,6 +5,6 @@
* @copyright 2016 Ryan Wyllie <ryan@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
define("core/modal_factory",["jquery","core/modal_events","core/modal_registry","core/modal","core/modal_save_cancel","core/modal_cancel","core/local/modal/alert","core/templates","core/notification","core/custom_interaction_events","core/pending"],(function($,ModalEvents,ModalRegistry,Modal,ModalSaveCancel,ModalCancel,ModalAlert,Templates,Notification,CustomEvents,Pending){var TEMPLATES_DEFAULT="core/modal",TEMPLATES_SAVE_CANCEL="core/modal_save_cancel",TEMPLATES_CANCEL="core/modal_cancel",TEMPLATES_ALERT="core/local/modal/alert",TYPES={DEFAULT:"DEFAULT",SAVE_CANCEL:"SAVE_CANCEL",CANCEL:"CANCEL",ALERT:"ALERT"};ModalRegistry.register(TYPES.DEFAULT,Modal,TEMPLATES_DEFAULT),ModalRegistry.register(TYPES.SAVE_CANCEL,ModalSaveCancel,TEMPLATES_SAVE_CANCEL),ModalRegistry.register(TYPES.CANCEL,ModalCancel,TEMPLATES_CANCEL),ModalRegistry.register(TYPES.ALERT,ModalAlert,TEMPLATES_ALERT);var createFromType=function(registryConf,templateContext){var templateName=registryConf.template,modalPromise=Templates.render(templateName,templateContext).then((function(html){var modalElement=$(html);return function(registryConf,modalElement){return modalElement=$(modalElement),new(0,registryConf.module)(modalElement)}(registryConf,modalElement)})).fail(Notification.exception);return modalPromise};return{create:function(modalConfig,triggerElement){var registryConf,type=modalConfig.type||TYPES.DEFAULT,isLarge=!!modalConfig.large,isScrollable=!modalConfig.hasOwnProperty("scrollable")||modalConfig.scrollable,templateContext={};(registryConf=ModalRegistry.get(type))||Notification.exception({message:"Unable to find modal of type: "+type}),void 0!==modalConfig.templateContext&&(templateContext=modalConfig.templateContext);var modalPromise=createFromType(registryConf,templateContext).then((function(modal){return void 0!==modalConfig.title&&modal.setTitle(modalConfig.title),void 0!==modalConfig.body&&modal.setBody(modalConfig.body),void 0!==modalConfig.footer&&modal.setFooter(modalConfig.footer),modalConfig.buttons&&Object.entries(modalConfig.buttons).forEach((function(_ref){let[key,value]=_ref;modal.setButtonText(key,value)})),isLarge&&modal.setLarge(),void 0!==modalConfig.removeOnClose&&modal.setRemoveOnClose(modalConfig.removeOnClose),modal.setScrollable(isScrollable),modal}));return void 0!==triggerElement&&function(modalPromise,triggerElement,modalConfig){var actualTriggerElement=null,hasPreShowCallback="function"==typeof modalConfig.preShowCallback,triggeredCallback=function(e,data){var pendingPromise=new Pending("core/modal_factory:setUpTrigger:triggeredCallback");actualTriggerElement=$(e.currentTarget),modalPromise.then((function(modal){return hasPreShowCallback&&modalConfig.preShowCallback(actualTriggerElement,modal),modal.show(),modal})).then(pendingPromise.resolve),data.originalEvent.preventDefault()};if(Array.isArray(triggerElement)){var selector=triggerElement[1];triggerElement=triggerElement[0],CustomEvents.define(triggerElement,[CustomEvents.events.activate]),triggerElement.on(CustomEvents.events.activate,selector,triggeredCallback)}else CustomEvents.define(triggerElement,[CustomEvents.events.activate]),triggerElement.on(CustomEvents.events.activate,triggeredCallback);modalPromise.then((function(modal){return modal.getRoot().on(ModalEvents.hidden,(function(){null!==actualTriggerElement&&actualTriggerElement.focus()})),modal}))}(modalPromise,triggerElement,modalConfig),modalPromise},types:TYPES}}));
define("core/modal_factory",["jquery","core/modal_events","core/modal_registry","core/modal","core/modal_save_cancel","core/modal_delete_cancel","core/modal_cancel","core/local/modal/alert","core/templates","core/notification","core/custom_interaction_events","core/pending"],(function($,ModalEvents,ModalRegistry,Modal,ModalSaveCancel,ModalDeleteCancel,ModalCancel,ModalAlert,Templates,Notification,CustomEvents,Pending){var TEMPLATES_DEFAULT="core/modal",TEMPLATES_SAVE_CANCEL="core/modal_save_cancel",TEMPLATES_DELETE_CANCEL="core/modal_delete_cancel",TEMPLATES_CANCEL="core/modal_cancel",TEMPLATES_ALERT="core/local/modal/alert",TYPES={DEFAULT:"DEFAULT",SAVE_CANCEL:"SAVE_CANCEL",DELETE_CANCEL:"DELETE_CANCEL",CANCEL:"CANCEL",ALERT:"ALERT"};ModalRegistry.register(TYPES.DEFAULT,Modal,TEMPLATES_DEFAULT),ModalRegistry.register(TYPES.SAVE_CANCEL,ModalSaveCancel,TEMPLATES_SAVE_CANCEL),ModalRegistry.register(TYPES.DELETE_CANCEL,ModalDeleteCancel,TEMPLATES_DELETE_CANCEL),ModalRegistry.register(TYPES.CANCEL,ModalCancel,TEMPLATES_CANCEL),ModalRegistry.register(TYPES.ALERT,ModalAlert,TEMPLATES_ALERT);var createFromType=function(registryConf,templateContext){var templateName=registryConf.template,modalPromise=Templates.render(templateName,templateContext).then((function(html){var modalElement=$(html);return function(registryConf,modalElement){return modalElement=$(modalElement),new(0,registryConf.module)(modalElement)}(registryConf,modalElement)})).fail(Notification.exception);return modalPromise};return{create:function(modalConfig,triggerElement){var registryConf,type=modalConfig.type||TYPES.DEFAULT,isLarge=!!modalConfig.large,isScrollable=!modalConfig.hasOwnProperty("scrollable")||modalConfig.scrollable,templateContext={};(registryConf=ModalRegistry.get(type))||Notification.exception({message:"Unable to find modal of type: "+type}),void 0!==modalConfig.templateContext&&(templateContext=modalConfig.templateContext);var modalPromise=createFromType(registryConf,templateContext).then((function(modal){return void 0!==modalConfig.title&&modal.setTitle(modalConfig.title),void 0!==modalConfig.body&&modal.setBody(modalConfig.body),void 0!==modalConfig.footer&&modal.setFooter(modalConfig.footer),modalConfig.buttons&&Object.entries(modalConfig.buttons).forEach((function(_ref){let[key,value]=_ref;modal.setButtonText(key,value)})),isLarge&&modal.setLarge(),void 0!==modalConfig.removeOnClose&&modal.setRemoveOnClose(modalConfig.removeOnClose),modal.setScrollable(isScrollable),modal}));return void 0!==triggerElement&&function(modalPromise,triggerElement,modalConfig){var actualTriggerElement=null,hasPreShowCallback="function"==typeof modalConfig.preShowCallback,triggeredCallback=function(e,data){var pendingPromise=new Pending("core/modal_factory:setUpTrigger:triggeredCallback");actualTriggerElement=$(e.currentTarget),modalPromise.then((function(modal){return hasPreShowCallback&&modalConfig.preShowCallback(actualTriggerElement,modal),modal.show(),modal})).then(pendingPromise.resolve),data.originalEvent.preventDefault()};if(Array.isArray(triggerElement)){var selector=triggerElement[1];triggerElement=triggerElement[0],CustomEvents.define(triggerElement,[CustomEvents.events.activate]),triggerElement.on(CustomEvents.events.activate,selector,triggeredCallback)}else CustomEvents.define(triggerElement,[CustomEvents.events.activate]),triggerElement.on(CustomEvents.events.activate,triggeredCallback);modalPromise.then((function(modal){return modal.getRoot().on(ModalEvents.hidden,(function(){null!==actualTriggerElement&&actualTriggerElement.focus()})),modal}))}(modalPromise,triggerElement,modalConfig),modalPromise},types:TYPES}}));
//# sourceMappingURL=modal_factory.min.js.map
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -1,3 +1,3 @@
define("core/utility",["core/str","core/pending","core/toast","core/notification"],(function(Str,_pending,_toast,_notification){var obj;Str=function(obj,nodeInterop){if(!nodeInterop&&obj&&obj.__esModule)return obj;if(null===obj||"object"!=typeof obj&&"function"!=typeof obj)return{default:obj};var cache=_getRequireWildcardCache(nodeInterop);if(cache&&cache.has(obj))return cache.get(obj);var newObj={},hasPropertyDescriptor=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var key in obj)if("default"!==key&&Object.prototype.hasOwnProperty.call(obj,key)){var desc=hasPropertyDescriptor?Object.getOwnPropertyDescriptor(obj,key):null;desc&&(desc.get||desc.set)?Object.defineProperty(newObj,key,desc):newObj[key]=obj[key]}newObj.default=obj,cache&&cache.set(obj,newObj);return newObj}(Str),_pending=(obj=_pending)&&obj.__esModule?obj:{default:obj};var _systemImportTransformerGlobalIdentifier="undefined"!=typeof window?window:"undefined"!=typeof self?self:"undefined"!=typeof global?global:{};function _getRequireWildcardCache(nodeInterop){if("function"!=typeof WeakMap)return null;var cacheBabelInterop=new WeakMap,cacheNodeInterop=new WeakMap;return(_getRequireWildcardCache=function(nodeInterop){return nodeInterop?cacheNodeInterop:cacheBabelInterop})(nodeInterop)}let registered=!1;const getModalString=(dataset,type,field)=>dataset["".concat(type).concat(field,"Str")]?Str.get_string.apply(null,JSON.parse(dataset["".concat(type).concat(field,"Str")])):Promise.resolve(dataset["".concat(type).concat(field)]),displayConfirmation=(source,type)=>(0,_notification.saveCancelPromise)(getModalString(source.dataset,type,"Title"),getModalString(source.dataset,type,"Content"),getModalString(source.dataset,type,"YesButton")).then((()=>{if("true"===source.dataset["".concat(type,"Toast")]){const stringForToast=getModalString(source.dataset,type,"ToastConfirmation");"string"==typeof stringForToast?(0,_toast.add)(stringForToast):stringForToast.then((str=>(0,_toast.add)(str))).catch((e=>(0,_notification.exception)(e)))}window.location.href=source.dataset["".concat(type,"Destination")]})).catch((()=>{}));registered||((()=>{document.addEventListener("click",(e=>{const confirmRequest=e.target.closest('[data-confirmation="modal"]');confirmRequest&&(e.preventDefault(),displayConfirmation(confirmRequest,"confirmation"));const modalConfirmation=e.target.closest('[data-modal="confirmation"]');modalConfirmation&&(e.preventDefault(),displayConfirmation(modalConfirmation,"modal"));const alertRequest=e.target.closest('[data-modal="alert"]');alertRequest&&(e.preventDefault(),(async(title,content)=>{const pendingPromise=new _pending.default("core/confirm:alert"),ModalFactory=await("function"==typeof _systemImportTransformerGlobalIdentifier.define&&_systemImportTransformerGlobalIdentifier.define.amd?new Promise((function(resolve,reject){_systemImportTransformerGlobalIdentifier.require(["core/modal_factory"],resolve,reject)})):"undefined"!=typeof module&&module.exports&&"undefined"!=typeof require||"undefined"!=typeof module&&module.component&&_systemImportTransformerGlobalIdentifier.require&&"component"===_systemImportTransformerGlobalIdentifier.require.loader?Promise.resolve(require("core/modal_factory")):Promise.resolve(_systemImportTransformerGlobalIdentifier["core/modal_factory"]));ModalFactory.create({type:ModalFactory.types.ALERT,title:title,body:content,removeOnClose:!0}).then((function(modal){return modal.show(),pendingPromise.resolve(),modal}))})(getModalString(alertRequest.dataset,"modal","Title"),getModalString(alertRequest.dataset,"modal","Content")))}))})(),registered=!0)}));
define("core/utility",["core/str","core/pending","core/toast","core/notification"],(function(Str,_pending,_toast,_notification){var obj;Str=function(obj,nodeInterop){if(!nodeInterop&&obj&&obj.__esModule)return obj;if(null===obj||"object"!=typeof obj&&"function"!=typeof obj)return{default:obj};var cache=_getRequireWildcardCache(nodeInterop);if(cache&&cache.has(obj))return cache.get(obj);var newObj={},hasPropertyDescriptor=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var key in obj)if("default"!==key&&Object.prototype.hasOwnProperty.call(obj,key)){var desc=hasPropertyDescriptor?Object.getOwnPropertyDescriptor(obj,key):null;desc&&(desc.get||desc.set)?Object.defineProperty(newObj,key,desc):newObj[key]=obj[key]}newObj.default=obj,cache&&cache.set(obj,newObj);return newObj}(Str),_pending=(obj=_pending)&&obj.__esModule?obj:{default:obj};var _systemImportTransformerGlobalIdentifier="undefined"!=typeof window?window:"undefined"!=typeof self?self:"undefined"!=typeof global?global:{};function _getRequireWildcardCache(nodeInterop){if("function"!=typeof WeakMap)return null;var cacheBabelInterop=new WeakMap,cacheNodeInterop=new WeakMap;return(_getRequireWildcardCache=function(nodeInterop){return nodeInterop?cacheNodeInterop:cacheBabelInterop})(nodeInterop)}let registered=!1;const getModalString=(dataset,type,field)=>dataset["".concat(type).concat(field,"Str")]?Str.get_string.apply(null,JSON.parse(dataset["".concat(type).concat(field,"Str")])):Promise.resolve(dataset["".concat(type).concat(field)]),displayConfirmation=(source,type)=>{let confirmationPromise=null;return confirmationPromise="".concat(type,"Type")in source.dataset&&"delete"===source.dataset["".concat(type,"Type")]?(0,_notification.deleteCancelPromise)(getModalString(source.dataset,type,"Title"),getModalString(source.dataset,type,"Content"),getModalString(source.dataset,type,"YesButton")):(0,_notification.saveCancelPromise)(getModalString(source.dataset,type,"Title"),getModalString(source.dataset,type,"Content"),getModalString(source.dataset,type,"YesButton")),confirmationPromise.then((()=>{if("true"===source.dataset["".concat(type,"Toast")]){const stringForToast=getModalString(source.dataset,type,"ToastConfirmation");"string"==typeof stringForToast?(0,_toast.add)(stringForToast):stringForToast.then((str=>(0,_toast.add)(str))).catch((e=>(0,_notification.exception)(e)))}window.location.href=source.dataset["".concat(type,"Destination")]})).catch((()=>{}))};registered||((()=>{document.addEventListener("click",(e=>{const confirmRequest=e.target.closest('[data-confirmation="modal"]');confirmRequest&&(e.preventDefault(),displayConfirmation(confirmRequest,"confirmation"));const modalConfirmation=e.target.closest('[data-modal="confirmation"]');modalConfirmation&&(e.preventDefault(),displayConfirmation(modalConfirmation,"modal"));const alertRequest=e.target.closest('[data-modal="alert"]');alertRequest&&(e.preventDefault(),(async(title,content)=>{const pendingPromise=new _pending.default("core/confirm:alert"),ModalFactory=await("function"==typeof _systemImportTransformerGlobalIdentifier.define&&_systemImportTransformerGlobalIdentifier.define.amd?new Promise((function(resolve,reject){_systemImportTransformerGlobalIdentifier.require(["core/modal_factory"],resolve,reject)})):"undefined"!=typeof module&&module.exports&&"undefined"!=typeof require||"undefined"!=typeof module&&module.component&&_systemImportTransformerGlobalIdentifier.require&&"component"===_systemImportTransformerGlobalIdentifier.require.loader?Promise.resolve(require("core/modal_factory")):Promise.resolve(_systemImportTransformerGlobalIdentifier["core/modal_factory"]));ModalFactory.create({type:ModalFactory.types.ALERT,title:title,body:content,removeOnClose:!0}).then((function(modal){return modal.show(),pendingPromise.resolve(),modal}))})(getModalString(alertRequest.dataset,"modal","Title"),getModalString(alertRequest.dataset,"modal","Content")))}))})(),registered=!0)}));
//# sourceMappingURL=utility.min.js.map
File diff suppressed because one or more lines are too long
+24
View File
@@ -911,6 +911,30 @@ define([
}.bind(this));
};
/**
* Register a listener to close the dialogue when the delete button is pressed.
*
* @method registerCloseOnDelete
*/
Modal.prototype.registerCloseOnDelete = function() {
// Handle the clicking of the Cancel button.
this.getModal().on(CustomEvents.events.activate, this.getActionSelector('delete'), function(e, data) {
var deleteEvent = $.Event(ModalEvents.delete);
this.getRoot().trigger(deleteEvent, this);
if (!deleteEvent.isDefaultPrevented()) {
data.originalEvent.preventDefault();
if (this.removeOnClose) {
this.destroy();
} else {
this.hide();
}
}
}.bind(this));
};
/**
* Set or resolve and set the value using the function.
*
+73
View File
@@ -0,0 +1,73 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Contain the logic for the delete/cancel modal.
*
* @module core/modal_delete_cancel
* @copyright 2022 Laurent David <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
import Modal from 'core/modal';
import Notification from 'core/notification';
/**
* The Delete/Cancel Modal.
*
* @class
* @extends module:core/modal
*/
export default class extends Modal {
constructor(root) {
super(root);
if (!this.getFooter().find(this.getActionSelector('delete')).length) {
Notification.exception({message: 'No delete button found'});
}
if (!this.getFooter().find(this.getActionSelector('cancel')).length) {
Notification.exception({message: 'No cancel button found'});
}
}
/**
* Register all event listeners.
*/
registerEventListeners() {
// Call the parent registration.
super.registerEventListeners();
// Register to close on delete/cancel.
this.registerCloseOnDelete();
this.registerCloseOnCancel();
}
/**
* Override parent implementation to prevent changing the footer content.
*/
setFooter() {
Notification.exception({message: 'Can not change the footer of a delete cancel modal'});
}
/**
* Set the title of the delete button.
*
* @param {String|Promise} value The button text, or a Promise which will resolve it
* @returns{Promise}
*/
setDeleteButtonText(value) {
return this.setButtonText('delete', value);
}
}
+1
View File
@@ -31,6 +31,7 @@ define([], function() {
outsideClick: 'modal:outsideClick',
// ModalSaveCancel events.
save: 'modal-save-cancel:save',
'delete': 'modal-delete-cancel:delete', // Delete is a reserved word.
cancel: 'modal-save-cancel:cancel',
};
});
+6 -2
View File
@@ -21,16 +21,17 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
define(['jquery', 'core/modal_events', 'core/modal_registry', 'core/modal',
'core/modal_save_cancel', 'core/modal_cancel', 'core/local/modal/alert',
'core/modal_save_cancel', 'core/modal_delete_cancel', 'core/modal_cancel', 'core/local/modal/alert',
'core/templates', 'core/notification', 'core/custom_interaction_events',
'core/pending'],
function($, ModalEvents, ModalRegistry, Modal, ModalSaveCancel,
function($, ModalEvents, ModalRegistry, Modal, ModalSaveCancel, ModalDeleteCancel,
ModalCancel, ModalAlert, Templates, Notification, CustomEvents, Pending) {
// The templates for each type of modal.
var TEMPLATES = {
DEFAULT: 'core/modal',
SAVE_CANCEL: 'core/modal_save_cancel',
DELETE_CANCEL: 'core/modal_delete_cancel',
CANCEL: 'core/modal_cancel',
ALERT: 'core/local/modal/alert',
};
@@ -43,12 +44,14 @@ define(['jquery', 'core/modal_events', 'core/modal_registry', 'core/modal',
* @public
* @property {String} DEFAULT The default modal
* @property {String} SAVE_CANCEL A modal which can be used to either save, or cancel.
* @property {String} DELETE_CANCEL A modal which can be used to either delete, or cancel.
* @property {String} CANCEL A modal which displayed a cancel button
* @property {String} ALERT An information modal which only displays information.
*/
var TYPES = {
DEFAULT: 'DEFAULT',
SAVE_CANCEL: 'SAVE_CANCEL',
DELETE_CANCEL: 'DELETE_CANCEL',
CANCEL: 'CANCEL',
ALERT: 'ALERT',
};
@@ -56,6 +59,7 @@ define(['jquery', 'core/modal_events', 'core/modal_registry', 'core/modal',
// Register the common set of modals.
ModalRegistry.register(TYPES.DEFAULT, Modal, TEMPLATES.DEFAULT);
ModalRegistry.register(TYPES.SAVE_CANCEL, ModalSaveCancel, TEMPLATES.SAVE_CANCEL);
ModalRegistry.register(TYPES.DELETE_CANCEL, ModalDeleteCancel, TEMPLATES.DELETE_CANCEL);
ModalRegistry.register(TYPES.CANCEL, ModalCancel, TEMPLATES.CANCEL);
ModalRegistry.register(TYPES.ALERT, ModalAlert, TEMPLATES.ALERT);
+66 -1
View File
@@ -261,6 +261,54 @@ export const saveCancel = async(title, question, saveLabel, saveCallback, cancel
});
};
/**
* The Delete and Cancel dialogue helper.
*
* @method
* @param {String|Promise} title
* @param {String|Promise} question
* @param {String|Promise} deleteLabel
* @param {String|Promise} deleteCallback
* @param {String|Promise} cancelCallback
* @param {Object} options
* @param {HTMLElement} [options.triggerElement=null] The element that triggered the modal (will receive the focus after hidden)
* @returns {Promise}
*/
export const deleteCancel = async(title, question, deleteLabel, deleteCallback, cancelCallback, {
triggerElement = null,
} = {}) => {
const pendingPromise = new Pending('core/notification:confirm');
const [
ModalFactory,
ModalEvents,
] = await Promise.all([
import('core/modal_factory'),
import('core/modal_events'),
]);
return ModalFactory.create({
type: ModalFactory.types.DELETE_CANCEL,
title: title,
body: question,
buttons: {
'delete': deleteLabel
},
removeOnClose: true,
})
.then(function(modal) {
modal.show();
modal.getRoot().on(ModalEvents.delete, deleteCallback);
modal.getRoot().on(ModalEvents.cancel, cancelCallback);
modal.getRoot().on(ModalEvents.hidden, () => triggerElement?.focus());
pendingPromise.resolve();
return modal;
});
};
/**
* Add all of the supplied notifications.
*
@@ -277,6 +325,22 @@ export const saveCancelPromise = (title, question, saveLabel, {
saveCancel(title, question, saveLabel, resolve, reject, {triggerElement});
});
/**
* Add all of the supplied notifications.
*
* @param {Promise|String} title The header of the modal
* @param {Promise|String} question What do we want the user to confirm
* @param {Promise|String} deleteLabel The modal action link text
* @param {Object} options
* @param {HTMLElement} [options.triggerElement=null] The element that triggered the modal (will receive the focus after hidden)
* @return {Promise}
*/
export const deleteCancelPromise = (title, question, deleteLabel, {
triggerElement = null,
} = {}) => new Promise((resolve, reject) => {
deleteCancel(title, question, deleteLabel, resolve, reject, {triggerElement});
});
/**
* Wrap M.core.exception.
*
@@ -338,7 +402,7 @@ export const exception = async ex => {
export const init = (contextId, notificationList) => {
currentContextId = contextId;
// Setup the message target region if it isn't setup already
// Setup the message target region if it isn't setup already.
setupTargetRegion();
// Add provided notifications.
@@ -354,5 +418,6 @@ export default {
confirm,
saveCancel,
saveCancelPromise,
deleteCancelPromise,
exception,
};
+16 -7
View File
@@ -48,7 +48,7 @@
import * as Str from 'core/str';
import Pending from 'core/pending';
import {add as addToast} from 'core/toast';
import {saveCancelPromise, exception} from 'core/notification';
import {saveCancelPromise, deleteCancelPromise, exception} from 'core/notification';
// We want to ensure that we only initialize the listeners only once.
let registered = false;
@@ -80,12 +80,21 @@ const getModalString = (dataset, type, field) => {
* @returns {Promise}
*/
const displayConfirmation = (source, type) => {
return saveCancelPromise(
getModalString(source.dataset, type, 'Title'),
getModalString(source.dataset, type, 'Content'),
getModalString(source.dataset, type, 'YesButton'),
)
.then(() => {
let confirmationPromise = null;
if (`${type}Type` in source.dataset && source.dataset[`${type}Type`] === 'delete') {
confirmationPromise = deleteCancelPromise(
getModalString(source.dataset, type, 'Title'),
getModalString(source.dataset, type, 'Content'),
getModalString(source.dataset, type, 'YesButton'),
);
} else {
confirmationPromise = saveCancelPromise(
getModalString(source.dataset, type, 'Title'),
getModalString(source.dataset, type, 'Content'),
getModalString(source.dataset, type, 'YesButton'),
);
}
return confirmationPromise.then(() => {
if (source.dataset[`${type}Toast`] === 'true') {
const stringForToast = getModalString(source.dataset, type, 'ToastConfirmation');
if (typeof stringForToast === "string") {
+130 -38
View File
@@ -223,14 +223,14 @@ class user_picture implements renderable {
if (!property_exists($user, $field)) {
$needrec = true;
debugging('Missing '.$field.' property in $user object, this is a performance problem that needs to be fixed by a developer. '
.'Please use the \core_user\fields API to get the full list of required fields.', DEBUG_DEVELOPER);
.'Please use the \core_user\fields API to get the full list of required fields.', DEBUG_DEVELOPER);
break;
}
}
if ($needrec) {
$this->user = $DB->get_record('user', array('id' => $user->id),
implode(',', \core_user\fields::get_picture_fields()), MUST_EXIST);
implode(',', \core_user\fields::get_picture_fields()), MUST_EXIST);
} else {
$this->user = clone($user);
}
@@ -387,7 +387,7 @@ class user_picture implements renderable {
}
// Set the image URL to the URL for the uploaded file and return.
$url = moodle_url::make_pluginfile_url(
$contextid, 'user', 'icon', null, $path, $filename, false, $this->includetoken);
$contextid, 'user', 'icon', null, $path, $filename, false, $this->includetoken);
$url->param('rev', $this->user->picture);
return $url;
}
@@ -789,6 +789,43 @@ class pix_emoticon extends pix_icon implements renderable {
*/
class single_button implements renderable {
/**
* Possible button types. From boostrap.
*/
const BUTTON_TYPES = [
self::BUTTON_PRIMARY,
self::BUTTON_SECONDARY,
self::BUTTON_SUCCESS,
self::BUTTON_DANGER,
self::BUTTON_WARNING,
self::BUTTON_INFO
];
/**
* Possible button types - Primary.
*/
const BUTTON_PRIMARY = 'primary';
/**
* Possible button types - Secondary.
*/
const BUTTON_SECONDARY = 'secondary';
/**
* Possible button types - Danger.
*/
const BUTTON_DANGER = 'danger';
/**
* Possible button types - Success.
*/
const BUTTON_SUCCESS = 'success';
/**
* Possible button types - Warning.
*/
const BUTTON_WARNING = 'warning';
/**
* Possible button types - Info.
*/
const BUTTON_INFO = 'info';
/**
* @var moodle_url Target url
*/
@@ -810,9 +847,15 @@ class single_button implements renderable {
public $class = 'singlebutton';
/**
* @var bool True if button is primary button. Used for styling.
* @var string Type of button (from defined types). Used for styling.
*/
public $primary = false;
protected $type;
/**
* @var bool True if button is primary button. Used for styling.
* @deprecated since Moodle 4.2
*/
private $primary = false;
/**
* @var bool True if button disabled, false if normal
@@ -851,17 +894,24 @@ class single_button implements renderable {
/**
* Constructor
*
* @param moodle_url $url
* @param string $label button text
* @param string $method get or post submit method
* @param bool $primary whether this is a primary button, used for styling
* @param string $type whether this is a primary button or another type, used for styling
* @param array $attributes Attributes for the HTML button tag
*/
public function __construct(moodle_url $url, $label, $method='post', $primary=false, $attributes = []) {
$this->url = clone($url);
$this->label = $label;
public function __construct(moodle_url $url, $label, $method = 'post', $type = self::BUTTON_SECONDARY,
$attributes = []) {
if (is_bool($type)) {
debugging('The boolean $primary is deprecated and replaced by $type,
use single_button::BUTTON_PRIMARY or self::BUTTON_SECONDARY instead');
$type = $type ? self::BUTTON_PRIMARY : self::BUTTON_SECONDARY;
}
$this->url = clone($url);
$this->label = $label;
$this->method = $method;
$this->primary = $primary;
$this->type = $type;
$this->attributes = $attributes;
}
@@ -894,6 +944,49 @@ class single_button implements renderable {
$this->attributes[$name] = $value;
}
/**
* Magic setter method.
*
* This method manages access to some properties and will display deprecation message when accessing 'primary' property.
*
* @param string $name
* @param mixed $value
*/
public function __set($name, $value) {
switch ($name) {
case 'primary':
debugging('The primary field is deprecated, use the type field instead');
// Here just in case we modified the primary field from outside {@see \mod_quiz_renderer::summary_page_controls}.
$this->type = $value ? self::BUTTON_PRIMARY : self::BUTTON_SECONDARY;
break;
case 'type':
$this->type = in_array($value, self::BUTTON_TYPES) ? $value : self::BUTTON_SECONDARY;
break;
default:
$this->$name = $value;
}
}
/**
* Magic method getter.
*
* This method manages access to some properties and will display deprecation message when accessing 'primary' property.
*
* @param string $name
* @return mixed
*/
public function __get($name) {
switch ($name) {
case 'primary':
debugging('The primary field is deprecated, use type field instead');
return $this->type == self::BUTTON_PRIMARY;
case 'type':
return $this->type;
default:
return $this->$name;
}
}
/**
* Export data.
*
@@ -912,8 +1005,7 @@ class single_button implements renderable {
$data->classes = $this->class;
$data->disabled = $this->disabled;
$data->tooltip = $this->tooltip;
$data->primary = $this->primary;
$data->type = $this->type;
$data->attributes = [];
foreach ($this->attributes as $key => $value) {
$data->attributes[] = ['name' => $key, 'value' => $value];
@@ -1401,8 +1493,8 @@ class url_select implements renderable, templatable {
$value = key($nothing);
$name = reset($nothing);
$flattened = [
$value => ['name' => $name, 'value' => $value, 'selected' => $this->selected == $value]
] + $flattened;
$value => ['name' => $name, 'value' => $value, 'selected' => $this->selected == $value]
] + $flattened;
}
// Make non-associative array.
@@ -1525,10 +1617,10 @@ class action_link implements renderable {
* @param pix_icon $icon optional pix_icon to render with the link text
*/
public function __construct(moodle_url $url,
$text,
component_action $action=null,
array $attributes=null,
pix_icon $icon=null) {
$text,
component_action $action=null,
array $attributes=null,
pix_icon $icon=null) {
$this->url = clone($url);
$this->text = $text;
if (empty($attributes['id'])) {
@@ -1790,7 +1882,7 @@ class html_writer {
* @return string html fragment
*/
public static function checkbox($name, $value, $checked = true, $label = '',
array $attributes = null, array $labelattributes = null) {
array $attributes = null, array $labelattributes = null) {
$attributes = (array) $attributes;
$output = '';
@@ -2143,12 +2235,12 @@ class html_writer {
// explicitly assigned properties override those defined via $table->attributes
$table->attributes['class'] = trim($table->attributes['class']);
$attributes = array_merge($table->attributes, array(
'id' => $table->id,
'width' => $table->width,
'summary' => $table->summary,
'cellpadding' => $table->cellpadding,
'cellspacing' => $table->cellspacing,
));
'id' => $table->id,
'width' => $table->width,
'summary' => $table->summary,
'cellpadding' => $table->cellpadding,
'cellspacing' => $table->cellspacing,
));
$output = html_writer::start_tag('table', $attributes) . "\n";
$countcols = 0;
@@ -2261,9 +2353,9 @@ class html_writer {
// Explicitly assigned properties should override those defined in the attributes.
$row->attributes['class'] = trim($row->attributes['class']);
$trattributes = array_merge($row->attributes, array(
'id' => $row->id,
'style' => $row->style,
));
'id' => $row->id,
'style' => $row->style,
));
$output .= html_writer::start_tag('tr', $trattributes) . "\n";
$keys2 = array_keys($row->cells);
$lastkey = end($keys2);
@@ -2300,13 +2392,13 @@ class html_writer {
$tdstyle .= isset($table->wrap[$key]) ? $table->wrap[$key] : '';
$cell->attributes['class'] = trim($cell->attributes['class']);
$tdattributes = array_merge($cell->attributes, array(
'style' => $tdstyle . $cell->style,
'colspan' => $cell->colspan,
'rowspan' => $cell->rowspan,
'id' => $cell->id,
'abbr' => $cell->abbr,
'scope' => $cell->scope,
));
'style' => $tdstyle . $cell->style,
'colspan' => $cell->colspan,
'rowspan' => $cell->rowspan,
'id' => $cell->id,
'abbr' => $cell->abbr,
'scope' => $cell->scope,
));
$tagtype = 'td';
if ($cell->header === true) {
$tagtype = 'th';
@@ -3516,7 +3608,7 @@ class custom_menu_item implements renderable, templatable {
* @param array $attributes Array of other HTML attributes for the custom menu item.
*/
public function __construct($text, moodle_url $url = null, $title = null, $sort = null, custom_menu_item $parent = null,
array $attributes = []) {
array $attributes = []) {
$this->text = $text;
$this->url = $url;
$this->title = $title;
@@ -4069,7 +4161,7 @@ class context_header implements renderable {
}
// Add the bootstrap 'btn' class for formatting.
$this->additionalbuttons[$buttontype]['linkattributes'] = array_merge($button['linkattributes'],
array('class' => $class));
array('class' => $class));
}
}
}
@@ -5042,7 +5134,7 @@ class progress_bar implements renderable, templatable {
if (empty($this->time_start)) {
throw new coding_exception('You must call create() (or use the $autostart ' .
'argument to the constructor) before you try updating the progress bar.');
'argument to the constructor) before you try updating the progress bar.');
}
$estimate = $this->estimate($percent);
+14 -8
View File
@@ -2051,12 +2051,16 @@ class core_renderer extends renderer_base {
$displayoptions['cancelstr'] = $displayoptions['cancelstr'] ?? get_string('cancel');
if ($continue instanceof single_button) {
// ok
$continue->primary = true;
// Continue button should be primary if set to secondary type as it is the fefault.
if ($continue->type === single_button::BUTTON_SECONDARY) {
$continue->type = single_button::BUTTON_PRIMARY;
}
} else if (is_string($continue)) {
$continue = new single_button(new moodle_url($continue), $displayoptions['continuestr'], 'post', true);
$continue = new single_button(new moodle_url($continue), $displayoptions['continuestr'], 'post',
$displayoptions['type'] ?? single_button::BUTTON_PRIMARY);
} else if ($continue instanceof moodle_url) {
$continue = new single_button($continue, $displayoptions['continuestr'], 'post', true);
$continue = new single_button($continue, $displayoptions['continuestr'], 'post',
$displayoptions['type'] ?? single_button::BUTTON_PRIMARY);
} else {
throw new coding_exception('The continue param to $OUTPUT->confirm() must be either a URL (string/moodle_url) or a single_button instance.');
}
@@ -3120,7 +3124,7 @@ EOD;
if (!($url instanceof moodle_url)) {
$url = new moodle_url($url);
}
$button = new single_button($url, get_string('continue'), 'get', true);
$button = new single_button($url, get_string('continue'), 'get', single_button::BUTTON_PRIMARY);
$button->class = 'continuebutton';
return $this->render($button);
@@ -5567,11 +5571,13 @@ class core_renderer_maintenance extends core_renderer {
// We need plain styling of confirm boxes on upgrade because we don't know which stylesheet we have (it could be
// from any previous version of Moodle).
if ($continue instanceof single_button) {
$continue->primary = true;
$continue->type = single_button::BUTTON_PRIMARY;
} else if (is_string($continue)) {
$continue = new single_button(new moodle_url($continue), get_string('continue'), 'post', true);
$continue = new single_button(new moodle_url($continue), get_string('continue'), 'post',
$displayoptions['type'] ?? single_button::BUTTON_PRIMARY);
} else if ($continue instanceof moodle_url) {
$continue = new single_button($continue, get_string('continue'), 'post', true);
$continue = new single_button($continue, get_string('continue'), 'post',
$displayoptions['type'] ?? single_button::BUTTON_PRIMARY);
} else {
throw new coding_exception('The continue param to $OUTPUT->confirm() must be either a URL' .
' (string/moodle_url) or a single_button instance.');
@@ -0,0 +1,46 @@
{{!
This file is part of Moodle - http://moodle.org/
Moodle is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Moodle is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Moodle. If not, see <http://www.gnu.org/licenses/>.
}}
{{!
@template core/modal_delete_cancel
Moodle modal template with delete and cancel buttons.
The purpose of this template is to render a modal.
Classes required for JS:
* none
Data attributes required for JS:
* none
Context variables required for this template:
* title A cleaned string (use clean_text()) to display.
* body HTML content for the boday
Example context (json):
{
"title": "Example delete cancel modal",
"body": "Some example content for the body"
}
}}
{{< core/modal }}
{{$footer}}
<button type="button" class="btn btn-secondary" data-action="cancel">{{#str}} cancel {{/str}}</button>
<button type="button" class="btn btn-danger" data-action="delete">{{#str}} delete {{/str}}</button>
{{/footer}}
{{/ core/modal }}
+6 -4
View File
@@ -31,16 +31,18 @@
* url - the action url to submit to
* formid - optional id value for the form
* params - array of params with name and value attributes
* primary - true if this is a primary action button
* id - id for the element
* type - type for the element
* tooltip - tooltip text for the button
* disabled - true if this element is disabled
* label - text to show on the button
Example context (json):
{ "method" : "get",
{
"method" : "get",
"id": "buttonid-123",
"type": "primary",
"url" : "#",
"primary" : true,
"tooltip" : "This is a tooltip",
"label" : "This is a the button text",
"attributes": [
@@ -56,7 +58,7 @@
{{#params}}
<input type="hidden" name="{{name}}" value="{{value}}">
{{/params}}
<button type="submit" class="btn {{#primary}}btn-primary{{/primary}}{{^primary}}btn-secondary{{/primary}}"
<button type="submit" class="btn btn-{{type}}"
id="{{id}}"
{{#tooltip}}title="{{tooltip}}"{{/tooltip}}
{{#disabled}}disabled{{/disabled}}
+93 -13
View File
@@ -21,6 +21,7 @@ use custom_menu;
use custom_menu_item;
use paging_bar;
use renderer_base;
use single_button;
use single_select;
use theme_config;
use url_select;
@@ -453,20 +454,20 @@ EOF;
public function test_prepare() {
$expecteda = array('<span class="current-page">1</span>',
'<a href="index.php?page=1">2</a>',
'<a href="index.php?page=2">3</a>',
'<a href="index.php?page=3">4</a>',
'<a href="index.php?page=4">5</a>',
'<a href="index.php?page=5">6</a>',
'<a href="index.php?page=6">7</a>',
'<a href="index.php?page=7">8</a>',
);
'<a href="index.php?page=1">2</a>',
'<a href="index.php?page=2">3</a>',
'<a href="index.php?page=3">4</a>',
'<a href="index.php?page=4">5</a>',
'<a href="index.php?page=5">6</a>',
'<a href="index.php?page=6">7</a>',
'<a href="index.php?page=7">8</a>',
);
$expectedb = array('<a href="page?page=3">4</a>',
'<a href="page?page=4">5</a>',
'<span class="current-page">6</span>',
'<a href="page?page=6">7</a>',
'<a href="page?page=7">8</a>',
);
'<a href="page?page=4">5</a>',
'<span class="current-page">6</span>',
'<a href="page?page=6">7</a>',
'<a href="page?page=7">8</a>',
);
$mpage = new \moodle_page();
$rbase = new renderer_base($mpage, "/");
@@ -588,6 +589,85 @@ EOF;
$this->assertTrue(in_array(['name' => 'class', 'value' => $labelclass], $data->labelattributes));
$this->assertTrue(in_array(['name' => 'style', 'value' => $labelstyle], $data->labelattributes));
}
/**
* Test for checking the template context data for the single_select element.
* @covers \single_button
*/
public function test_single_button() {
global $PAGE;
$url = new \moodle_url('/');
$realname = 'realname';
$attributes = [
'data-dummy' => 'dummy',
];
$singlebutton = new single_button($url, $realname, 'post', single_button::BUTTON_SECONDARY, $attributes);
$renderer = $PAGE->get_renderer('core');
$data = $singlebutton->export_for_template($renderer);
$this->assertEquals($realname, $data->label);
$this->assertEquals('post', $data->method);
$this->assertEquals('singlebutton', $data->classes);
$this->assertEquals('secondary', $data->type);
$this->assertEquals($attributes['data-dummy'], $data->attributes[0]['value']);
$singlebutton = new single_button($url, $realname, 'post', single_button::BUTTON_PRIMARY, $attributes);
$renderer = $PAGE->get_renderer('core');
$data = $singlebutton->export_for_template($renderer);
$this->assertEquals($realname, $data->label);
$this->assertEquals('post', $data->method);
$this->assertEquals('singlebutton', $data->classes);
$this->assertEquals('primary', $data->type);
$this->assertEquals($attributes['data-dummy'], $data->attributes[0]['value']);
}
/**
* Test for checking the template context data for the single_select element legacy API.
* @covers \single_button
*/
public function test_single_button_deprecated() {
global $PAGE;
$url = new \moodle_url('/');
$realname = 'realname';
$attributes = [
'data-dummy' => 'dummy',
];
// Test that when we use a true boolean value for the 4th parameter this is set as primary type.
$singlebutton = new single_button($url, $realname, 'post', single_button::BUTTON_PRIMARY, $attributes);
$renderer = $PAGE->get_renderer('core');
$data = $singlebutton->export_for_template($renderer);
$this->assertEquals($realname, $data->label);
$this->assertEquals('post', $data->method);
$this->assertEquals('singlebutton', $data->classes);
$this->assertEquals('primary', $data->type);
$this->assertEquals($attributes['data-dummy'], $data->attributes[0]['value']);
// Test that when we use a false boolean value for the 4th parameter this is set as secondary type.
$singlebutton = new single_button($url, $realname, 'post', false, $attributes);
$this->assertDebuggingCalled();
$renderer = $PAGE->get_renderer('core');
$data = $singlebutton->export_for_template($renderer);
$this->assertEquals($realname, $data->label);
$this->assertEquals('post', $data->method);
$this->assertEquals('singlebutton', $data->classes);
$this->assertEquals('secondary', $data->type);
$this->assertEquals($attributes['data-dummy'], $data->attributes[0]['value']);
// Test that when we set the primary value, then this is reflected in the type.
$singlebutton->primary = false;
$this->assertDebuggingCalled();
$this->assertEquals(single_button::BUTTON_SECONDARY, $singlebutton->type);
$singlebutton->primary = true;
$this->assertDebuggingCalled();
$this->assertEquals(single_button::BUTTON_PRIMARY, $singlebutton->type);
// Then set the type directly.
$singlebutton->type = single_button::BUTTON_DANGER;
$data = $singlebutton->export_for_template($renderer);
$this->assertEquals('danger', $data->type);
}
/**
* Test for checking the template context data for the url_select element.
+4
View File
@@ -3,6 +3,10 @@ information provided here is intended especially for developers.
=== 4.2 ===
* \single_button constructor signature has been changed to manage more types than just primary buttons.
The boolean "primary" parameter has been deprecated and replaced by a more generic type allowing to use
Bootstrap styles of buttons (danger, warning...). The constructor will still manage the boolean primary
parameter but will display a debugging message.
* In enrollib.php, the methods get_enrolled_with_capabilities_join, get_enrolled_sql, get_enrolled_users and
count_enrolled_users used to only be able to accept a single group id, even though internally, they used
groups_get_members_join which could also accept an array of groups, or the constant USERSWITHOUTGROUP.
@@ -150,7 +150,7 @@ class override_actionmenu implements templatable, renderable {
} else if ($action === 'adduser' && !$this->show_useroverride()) {
$options = ['disabled' => 'true'];
}
$overridebutton = new single_button($url, $text, 'post', true, $options);
$overridebutton = new single_button($url, $text, 'post', single_button::BUTTON_PRIMARY, $options);
$urlselect = $this->get_select_menu();
return [
@@ -119,7 +119,12 @@ class user_submission_actionmenu implements templatable, renderable {
'help' => $help->export_for_template($output)
];
$url = new moodle_url('/mod/assign/view.php', ['id' => $this->cmid, 'action' => 'editsubmission']);
$newattemptbutton = new single_button($url, get_string('addnewattempt', 'mod_assign'), 'get', true);
$newattemptbutton = new single_button(
$url,
get_string('addnewattempt', 'mod_assign'),
'get',
single_button::BUTTON_PRIMARY
);
$newattempthelp = new help_icon('addnewattempt', 'mod_assign');
$data['edit']['button'] = $newattemptbutton->export_for_template($output);
$data['edit']['help'] = $newattempthelp->export_for_template($output);
@@ -143,7 +148,12 @@ class user_submission_actionmenu implements templatable, renderable {
$data['edit']['begin'] = true;
$data['edit']['help'] = '';
} else {
$newattemptbutton = new single_button($url, get_string('addsubmission', 'mod_assign'), 'get', true);
$newattemptbutton = new single_button(
$url,
get_string('addsubmission', 'mod_assign'),
'get',
single_button::BUTTON_PRIMARY
);
$data['edit']['button'] = $newattemptbutton->export_for_template($output);
$data['edit']['help'] = '';
}
@@ -151,7 +161,7 @@ class user_submission_actionmenu implements templatable, renderable {
}
if ($this->showsubmit) {
$url = new moodle_url('/mod/assign/view.php', ['id' => $this->cmid, 'action' => 'submit']);
$button = new single_button($url, get_string('submitassignment', 'mod_assign'), 'get', true);
$button = new single_button($url, get_string('submitassignment', 'mod_assign'), 'get', single_button::BUTTON_PRIMARY);
$help = new help_icon('submitassignment', 'mod_assign');
$data['submit'] = [
'button' => $button->export_for_template($output),
+1 -1
View File
@@ -587,7 +587,7 @@ class mod_bigbluebuttonbn_mod_form extends moodleform_mod {
$action = new single_button(new moodle_url(qualified_me()),
get_string('mod_form_field_participant_list_action_add', 'bigbluebuttonbn'),
'post',
false,
single_button::BUTTON_SECONDARY,
['name' => 'bigbluebuttonbn_participant_selection_add']
);
$pformcontext = [
+1 -1
View File
@@ -5,6 +5,6 @@ define("mod_data/deletepreset",["exports","core/notification","core/prefetch","c
* @module mod_data/deletepreset
* @copyright 2022 Amaia Anabitarte <amaia@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_notification=_interopRequireDefault(_notification),_ajax=_interopRequireDefault(_ajax),_url=_interopRequireDefault(_url);const selectors_deletePresetButton='[data-action="deletepreset"]';_exports.init=()=>{(0,_prefetch.prefetchStrings)("mod_data",["deleteconfirm","deletewarning"]),(0,_prefetch.prefetchStrings)("core",["delete"]),registerEventListeners()};const registerEventListeners=()=>{document.addEventListener("click",(event=>{const deleteOption=event.target.closest(selectors_deletePresetButton);deleteOption&&(event.preventDefault(),deletePresetConfirm(deleteOption))}))},deletePresetConfirm=deleteOption=>{const presetName=deleteOption.getAttribute("data-presetname"),dataId=deleteOption.getAttribute("data-dataid");_notification.default.saveCancelPromise((0,_str.get_string)("deleteconfirm","mod_data",presetName),(0,_str.get_string)("deletewarning","mod_data"),(0,_str.get_string)("delete","core")).then((()=>async function(dataId,presetName){var request={methodname:"mod_data_delete_saved_preset",args:{dataid:dataId,presetnames:{presetname:presetName}}};try{await _ajax.default.call([request])[0],window.location.href=_url.default.relativeUrl("mod/data/preset.php",{d:dataId},!1)}catch(error){_notification.default.exception(error)}}(dataId,presetName))).catch((()=>{}))}}));
*/Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_notification=_interopRequireDefault(_notification),_ajax=_interopRequireDefault(_ajax),_url=_interopRequireDefault(_url);const selectors_deletePresetButton='[data-action="deletepreset"]';_exports.init=()=>{(0,_prefetch.prefetchStrings)("mod_data",["deleteconfirm","deletewarning"]),(0,_prefetch.prefetchStrings)("core",["delete"]),registerEventListeners()};const registerEventListeners=()=>{document.addEventListener("click",(event=>{const deleteOption=event.target.closest(selectors_deletePresetButton);deleteOption&&(event.preventDefault(),deletePresetConfirm(deleteOption))}))},deletePresetConfirm=deleteOption=>{const presetName=deleteOption.getAttribute("data-presetname"),dataId=deleteOption.getAttribute("data-dataid");_notification.default.deleteCancelPromise((0,_str.get_string)("deleteconfirm","mod_data",presetName),(0,_str.get_string)("deletewarning","mod_data")).then((()=>async function(dataId,presetName){var request={methodname:"mod_data_delete_saved_preset",args:{dataid:dataId,presetnames:{presetname:presetName}}};try{await _ajax.default.call([request])[0],window.location.href=_url.default.relativeUrl("mod/data/preset.php",{d:dataId},!1)}catch(error){_notification.default.exception(error)}}(dataId,presetName))).catch((()=>{}))}}));
//# sourceMappingURL=deletepreset.min.js.map
+1 -1
View File
@@ -1 +1 @@
{"version":3,"file":"deletepreset.min.js","sources":["../src/deletepreset.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 * Javascript module for deleting a database as a preset.\n *\n * @module mod_data/deletepreset\n * @copyright 2022 Amaia Anabitarte <[email protected]>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Notification from 'core/notification';\nimport {prefetchStrings} from 'core/prefetch';\nimport {get_string as getString} from 'core/str';\nimport Ajax from 'core/ajax';\nimport Url from 'core/url';\n\nconst selectors = {\n deletePresetButton: '[data-action=\"deletepreset\"]',\n};\n\n/**\n * Initialize module\n */\nexport const init = () => {\n prefetchStrings('mod_data', [\n 'deleteconfirm',\n 'deletewarning',\n ]);\n prefetchStrings('core', [\n 'delete',\n ]);\n\n registerEventListeners();\n};\n\n/**\n * Register events for delete preset option in action menu.\n */\nconst registerEventListeners = () => {\n document.addEventListener('click', (event) => {\n const deleteOption = event.target.closest(selectors.deletePresetButton);\n if (deleteOption) {\n event.preventDefault();\n deletePresetConfirm(deleteOption);\n }\n });\n};\n\n/**\n * Show the confirmation modal to delete the preset.\n *\n * @param {HTMLElement} deleteOption the element to delete.\n */\nconst deletePresetConfirm = (deleteOption) => {\n const presetName = deleteOption.getAttribute('data-presetname');\n const dataId = deleteOption.getAttribute('data-dataid');\n\n Notification.saveCancelPromise(\n getString('deleteconfirm', 'mod_data', presetName),\n getString('deletewarning', 'mod_data'),\n getString('delete', 'core'),\n ).then(() => {\n return deletePreset(dataId, presetName);\n }).catch(() => {\n return;\n });\n};\n\n/**\n * Delete site user preset.\n *\n * @param {int} dataId The id of the current database activity.\n * @param {string} presetName The preset name to delete.\n * @return {promise} Resolved with the result and warnings of deleting a preset.\n */\nasync function deletePreset(dataId, presetName) {\n var request = {\n methodname: 'mod_data_delete_saved_preset',\n args: {\n dataid: dataId,\n presetnames: {presetname: presetName},\n }\n };\n try {\n await Ajax.call([request])[0];\n window.location.href = Url.relativeUrl(\n 'mod/data/preset.php',\n {\n d: dataId,\n },\n false\n );\n } catch (error) {\n Notification.exception(error);\n }\n}\n"],"names":["selectors","registerEventListeners","document","addEventListener","event","deleteOption","target","closest","preventDefault","deletePresetConfirm","presetName","getAttribute","dataId","saveCancelPromise","then","request","methodname","args","dataid","presetnames","presetname","Ajax","call","window","location","href","Url","relativeUrl","d","error","exception","deletePreset","catch"],"mappings":";;;;;;;kNA6BMA,6BACkB,6CAMJ,mCACA,WAAY,CACxB,gBACA,gDAEY,OAAQ,CACpB,WAGJC,gCAMEA,uBAAyB,KAC3BC,SAASC,iBAAiB,SAAUC,cAC1BC,aAAeD,MAAME,OAAOC,QAAQP,8BACtCK,eACAD,MAAMI,iBACNC,oBAAoBJ,mBAU1BI,oBAAuBJ,qBACnBK,WAAaL,aAAaM,aAAa,mBACvCC,OAASP,aAAaM,aAAa,qCAE5BE,mBACT,mBAAU,gBAAiB,WAAYH,aACvC,mBAAU,gBAAiB,aAC3B,mBAAU,SAAU,SACtBI,MAAK,mBAciBF,OAAQF,gBAC5BK,QAAU,CACVC,WAAY,+BACZC,KAAM,CACFC,OAAQN,OACRO,YAAa,CAACC,WAAYV,wBAIxBW,cAAKC,KAAK,CAACP,UAAU,GAC3BQ,OAAOC,SAASC,KAAOC,aAAIC,YACvB,sBACA,CACIC,EAAGhB,SAEP,GAEN,MAAOiB,6BACQC,UAAUD,QA/BhBE,CAAanB,OAAQF,cAC7BsB,OAAM"}
{"version":3,"file":"deletepreset.min.js","sources":["../src/deletepreset.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 * Javascript module for deleting a database as a preset.\n *\n * @module mod_data/deletepreset\n * @copyright 2022 Amaia Anabitarte <[email protected]>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Notification from 'core/notification';\nimport {prefetchStrings} from 'core/prefetch';\nimport {get_string as getString} from 'core/str';\nimport Ajax from 'core/ajax';\nimport Url from 'core/url';\n\nconst selectors = {\n deletePresetButton: '[data-action=\"deletepreset\"]',\n};\n\n/**\n * Initialize module\n */\nexport const init = () => {\n prefetchStrings('mod_data', [\n 'deleteconfirm',\n 'deletewarning',\n ]);\n prefetchStrings('core', [\n 'delete',\n ]);\n\n registerEventListeners();\n};\n\n/**\n * Register events for delete preset option in action menu.\n */\nconst registerEventListeners = () => {\n document.addEventListener('click', (event) => {\n const deleteOption = event.target.closest(selectors.deletePresetButton);\n if (deleteOption) {\n event.preventDefault();\n deletePresetConfirm(deleteOption);\n }\n });\n};\n\n/**\n * Show the confirmation modal to delete the preset.\n *\n * @param {HTMLElement} deleteOption the element to delete.\n */\nconst deletePresetConfirm = (deleteOption) => {\n const presetName = deleteOption.getAttribute('data-presetname');\n const dataId = deleteOption.getAttribute('data-dataid');\n\n Notification.deleteCancelPromise(\n getString('deleteconfirm', 'mod_data', presetName),\n getString('deletewarning', 'mod_data'),\n ).then(() => {\n return deletePreset(dataId, presetName);\n }).catch(() => {\n return;\n });\n};\n\n/**\n * Delete site user preset.\n *\n * @param {int} dataId The id of the current database activity.\n * @param {string} presetName The preset name to delete.\n * @return {promise} Resolved with the result and warnings of deleting a preset.\n */\nasync function deletePreset(dataId, presetName) {\n var request = {\n methodname: 'mod_data_delete_saved_preset',\n args: {\n dataid: dataId,\n presetnames: {presetname: presetName},\n }\n };\n try {\n await Ajax.call([request])[0];\n window.location.href = Url.relativeUrl(\n 'mod/data/preset.php',\n {\n d: dataId,\n },\n false\n );\n } catch (error) {\n Notification.exception(error);\n }\n}\n"],"names":["selectors","registerEventListeners","document","addEventListener","event","deleteOption","target","closest","preventDefault","deletePresetConfirm","presetName","getAttribute","dataId","deleteCancelPromise","then","request","methodname","args","dataid","presetnames","presetname","Ajax","call","window","location","href","Url","relativeUrl","d","error","exception","deletePreset","catch"],"mappings":";;;;;;;kNA6BMA,6BACkB,6CAMJ,mCACA,WAAY,CACxB,gBACA,gDAEY,OAAQ,CACpB,WAGJC,gCAMEA,uBAAyB,KAC3BC,SAASC,iBAAiB,SAAUC,cAC1BC,aAAeD,MAAME,OAAOC,QAAQP,8BACtCK,eACAD,MAAMI,iBACNC,oBAAoBJ,mBAU1BI,oBAAuBJ,qBACnBK,WAAaL,aAAaM,aAAa,mBACvCC,OAASP,aAAaM,aAAa,qCAE5BE,qBACT,mBAAU,gBAAiB,WAAYH,aACvC,mBAAU,gBAAiB,aAC7BI,MAAK,mBAciBF,OAAQF,gBAC5BK,QAAU,CACVC,WAAY,+BACZC,KAAM,CACFC,OAAQN,OACRO,YAAa,CAACC,WAAYV,wBAIxBW,cAAKC,KAAK,CAACP,UAAU,GAC3BQ,OAAOC,SAASC,KAAOC,aAAIC,YACvB,sBACA,CACIC,EAAGhB,SAEP,GAEN,MAAOiB,6BACQC,UAAUD,QA/BhBE,CAAanB,OAAQF,cAC7BsB,OAAM"}
+1 -2
View File
@@ -68,10 +68,9 @@ const deletePresetConfirm = (deleteOption) => {
const presetName = deleteOption.getAttribute('data-presetname');
const dataId = deleteOption.getAttribute('data-dataid');
Notification.saveCancelPromise(
Notification.deleteCancelPromise(
getString('deleteconfirm', 'mod_data', presetName),
getString('deletewarning', 'mod_data'),
getString('delete', 'core'),
).then(() => {
return deletePreset(dataId, presetName);
}).catch(() => {
@@ -58,7 +58,7 @@ class add_entries_action implements templatable, renderable {
if (data_user_can_add_entry($database, $currentgroup, $groupmode, $PAGE->context)) {
$addentrylink = new moodle_url('/mod/data/edit.php', ['d' => $this->id, 'backto' => $PAGE->url->out(false)]);
$button = new \single_button($addentrylink, get_string('add', 'mod_data'), 'get', true);
$button = new \single_button($addentrylink, get_string('add', 'mod_data'), 'get', \single_button::BUTTON_PRIMARY);
return $button->export_for_template($output);
}
@@ -60,7 +60,7 @@ class empty_database_action_bar implements templatable, renderable {
$importentrieslink = new moodle_url('/mod/data/import.php', $params);
$importentriesbutton = new \single_button($importentrieslink,
get_string('importentries', 'mod_data'), 'get', false);
get_string('importentries', 'mod_data'), 'get');
$data['importentriesbutton'] = $importentriesbutton->export_for_template($output);
}
@@ -59,7 +59,7 @@ class zero_state_action_bar implements templatable, renderable {
$usepresetlink = new moodle_url('/mod/data/preset.php', $params);
$usepresetbutton = new \single_button($usepresetlink,
get_string('usestandard', 'mod_data'), 'get', true);
get_string('usestandard', 'mod_data'), 'get', \single_button::BUTTON_PRIMARY);
$data['usepresetbutton'] = $usepresetbutton->export_for_template($output);
$actionbar = new \mod_data\output\action_bar($instance->id, $PAGE->url);
@@ -68,7 +68,7 @@ class zero_state_action_bar implements templatable, renderable {
$importpresetlink = new moodle_url('/mod/data/preset.php', $params);
$importpresetbutton = new \single_button($importpresetlink,
get_string('importapreset', 'mod_data'), 'get', false, [
get_string('importapreset', 'mod_data'), 'get', \single_button::BUTTON_SECONDARY, [
'data-action' => 'importpresets',
'data-dataid' => $cm->id,
]);
+5 -4
View File
@@ -236,10 +236,11 @@ switch ($mode) {
} else {
$fieldtypename = $field->name();
}
echo $OUTPUT->confirm('<strong>'.$fieldtypename.': '.$field->field->name.'</strong><br /><br />'.
get_string('confirmdeletefield', 'data'),
'field.php?d='.$data->id.'&mode=delete&fid='.$fid.'&confirm=1',
'field.php?d='.$data->id);
echo $OUTPUT->confirm('<strong>' . $fieldtypename . ': ' . $field->field->name . '</strong><br /><br />' .
get_string('confirmdeletefield', 'data'),
'field.php?d=' . $data->id . '&mode=delete&fid=' . $fid . '&confirm=1',
'field.php?d=' . $data->id,
['type' => single_button::BUTTON_DANGER]);
echo $OUTPUT->footer();
exit;
+6 -2
View File
@@ -285,7 +285,11 @@ if ($delete && confirm_sesskey() && (data_user_can_manage_entry($delete, $data,
WHERE dr.id = ?", $dbparams, MUST_EXIST)) { // Need to check this is valid.
if ($deleterecord->dataid == $data->id) { // Must be from this database
echo $OUTPUT->heading(get_string('deleteentry', 'mod_data'), 2, 'mb-4');
$deletebutton = new single_button(new moodle_url('/mod/data/view.php?d='.$data->id.'&delete='.$delete.'&confirm=1'), get_string('delete'), 'post');
$deletebutton = new single_button(
new moodle_url('/mod/data/view.php?d=' . $data->id . '&delete=' . $delete . '&confirm=1'),
get_string('delete'), 'post',
single_button::BUTTON_DANGER
);
echo $OUTPUT->confirm(get_string('confirmdeleterecord','data'),
$deletebutton, 'view.php?d='.$data->id);
@@ -332,7 +336,7 @@ if ($multidelete && confirm_sesskey() && $canmanageentries) {
$submitactions = array('d' => $data->id, 'sesskey' => sesskey(), 'confirm' => '1', 'serialdelete' => $serialiseddata);
$action = new moodle_url('/mod/data/view.php', $submitactions);
$cancelurl = new moodle_url('/mod/data/view.php', array('d' => $data->id));
$deletebutton = new single_button($action, get_string('delete'));
$deletebutton = new single_button($action, get_string('delete'), 'post', single_button::BUTTON_DANGER);
echo $OUTPUT->confirm(get_string('confirmdeleterecords', 'data'), $deletebutton, $cancelurl);
$parser = $manager->get_template('listtemplate');
echo $parser->parse_entries($validrecords);
+1 -1
View File
@@ -60,7 +60,7 @@ class mod_folder_renderer extends plugin_renderer_base {
$canmanagecourseactivities = has_capability('moodle/course:manageactivities', $context);
if ($canmanagefolderfiles && ($folder->display != FOLDER_DISPLAY_INLINE || !$canmanagecourseactivities)) {
$editbutton = new single_button(new moodle_url('/mod/folder/edit.php', ['id' => $cm->id]),
get_string('edit'), 'post', true);
get_string('edit'), 'post', single_button::BUTTON_PRIMARY);
$editbutton->class = 'navitem';
$buttons .= $this->render($editbutton);
}
@@ -160,7 +160,7 @@ class standard_action_bar implements renderable, templatable {
return null;
}
$btn = new single_button(new moodle_url('/mod/glossary/edit.php', ['cmid' => $this->cm->id]),
get_string('addsingleentry', 'glossary'), 'post', true);
get_string('addsingleentry', 'glossary'), 'post', single_button::BUTTON_PRIMARY);
return $btn->export_for_template($output);
}
@@ -90,7 +90,7 @@ class edit_action_buttons implements templatable, renderable {
if ($this->lesson->can_manage()) {
$url = new moodle_url('/mod/lesson/edit.php', ['id' => $this->lesson->get_cm()->id]);
$editbutton = new single_button($url, get_string('editlesson', 'mod_lesson'), 'get', true);
$editbutton = new single_button($url, get_string('editlesson', 'mod_lesson'), 'get', single_button::BUTTON_PRIMARY);
$url = new moodle_url('/mod/lesson/essay.php', ['id' => $this->lesson->get_cm()->id]);
$essaybutton = new single_button($url, get_string('manualgrading', 'mod_lesson'), 'get');
$data += [
@@ -77,7 +77,7 @@ class overrides_actions implements renderable, templatable {
$label = get_string('addnewuseroverride', 'quiz');
}
$addoverridebutton = new \single_button($addoverrideurl, $label, 'get', true);
$addoverridebutton = new \single_button($addoverrideurl, $label, 'get', \single_button::BUTTON_PRIMARY);
if (!$this->addenabled) {
$addoverridebutton->disabled = true;
}
+2 -2
View File
@@ -828,7 +828,7 @@ class renderer extends plugin_renderer_base {
}
$this->page->requires->js_call_amd('mod_quiz/submission_confirmation', 'init', [$totalunanswered]);
}
$button->primary = true;
$button->type = \single_button::BUTTON_PRIMARY;
$duedate = $attemptobj->get_due_date();
$message = '';
@@ -940,7 +940,7 @@ class renderer extends plugin_renderer_base {
preflight_check_form $preflightcheckform = null,
$popuprequired = false, $popupoptions = null) {
$button = new single_button($url, $buttontext, 'post', true);
$button = new single_button($url, $buttontext, 'post', single_button::BUTTON_PRIMARY);
$button->class .= ' quizstartbuttondiv';
if ($popuprequired) {
$button->class .= ' quizsecuremoderequired';
+2 -2
View File
@@ -1225,7 +1225,7 @@ class mod_workshop_renderer extends plugin_renderer_base {
if (!$workshop->get_submission_by_author($USER->id)) {
$btnurl = new moodle_url($workshop->submission_url(), ['edit' => 'on']);
$btntxt = get_string('createsubmission', 'workshop');
$output .= $this->single_button($btnurl, $btntxt, 'get', ['primary' => true]);
$output .= $this->single_button($btnurl, $btntxt, 'get', ['type' => single_button::BUTTON_PRIMARY]);
}
}
break;
@@ -1236,7 +1236,7 @@ class mod_workshop_renderer extends plugin_renderer_base {
if ($workshop->creating_submission_allowed($USER->id)) {
$btnurl = new moodle_url($workshop->submission_url(), ['edit' => 'on']);
$btntxt = get_string('createsubmission', 'workshop');
$output .= $this->single_button($btnurl, $btntxt, 'get', ['primary' => true]);
$output .= $this->single_button($btnurl, $btntxt, 'get', ['type' => single_button::BUTTON_PRIMARY]);
}
}
}
+5 -1
View File
@@ -65,7 +65,11 @@ $PAGE->set_secondary_active_tab("modulepage");
//
echo $OUTPUT->header();
$continuebtn = new single_button(
new moodle_url($PAGE->url, array('confirm' => 1)), get_string('continue'), 'post', true);
new moodle_url($PAGE->url, array('confirm' => 1)),
get_string('continue'),
'post',
single_button::BUTTON_PRIMARY
);
$continuebtn->class .= ' mr-3';
echo $OUTPUT->confirm(get_string('switchphase' . $phase . 'info', 'workshop'),
$continuebtn, $workshop->view_url());
@@ -243,7 +243,7 @@ class infectedfiles_table extends \table_sql implements \renderable {
// Delete All.
$deleteallparams = ['action' => 'deleteall', 'sesskey' => sesskey()];
$deleteallurl = new \moodle_url($managefilepage, $deleteallparams);
$deletebutton = new \single_button($deleteallurl, get_string('deleteall'), 'post', true);
$deletebutton = new \single_button($deleteallurl, get_string('deleteall'), 'post', \single_button::BUTTON_PRIMARY);
$deletebutton->add_confirm_action(get_string('confirmdeleteall', 'report_infectedfiles'));
echo $OUTPUT->render($deletebutton);
@@ -252,7 +252,7 @@ class infectedfiles_table extends \table_sql implements \renderable {
// Download All.
$downloadallparams = ['action' => 'downloadall', 'sesskey' => sesskey()];
$downloadallurl = new \moodle_url($managefilepage, $downloadallparams);
$downloadbutton = new \single_button($downloadallurl, get_string('downloadall'), 'post', true);
$downloadbutton = new \single_button($downloadallurl, get_string('downloadall'), 'post', \single_button::BUTTON_PRIMARY);
$downloadbutton->add_confirm_action(get_string('confirmdownloadall', 'report_infectedfiles'));
echo $OUTPUT->render($downloadbutton);
}
+6 -1
View File
@@ -164,7 +164,12 @@ class repository_googledocs extends repository {
$repositoryname = get_string('pluginname', 'repository_googledocs');
$button = new single_button($url, get_string('logintoaccount', 'repository', $repositoryname), 'post', true);
$button = new single_button(
$url,
get_string('logintoaccount', 'repository', $repositoryname),
'post',
single_button::BUTTON_PRIMARY
);
$button->add_action(new popup_action('click', $url, 'Login'));
$button->class = 'mdl-align';
$button = $OUTPUT->render($button);
+1 -1
View File
@@ -857,7 +857,7 @@ class repository_nextcloud extends repository {
echo $OUTPUT->header();
$button = new single_button($url, get_string('logintoaccount', 'repository', $this->get_name()),
'post', true);
'post', single_button::BUTTON_PRIMARY);
$button->add_action(new popup_action('click', $url, 'Login'));
$button->class = 'mdl-align';
$button = $OUTPUT->render($button);
+6 -1
View File
@@ -145,7 +145,12 @@ class repository_onedrive extends repository {
$repositoryname = get_string('pluginname', 'repository_onedrive');
$button = new single_button($url, get_string('logintoaccount', 'repository', $repositoryname), 'post', true);
$button = new single_button(
$url,
get_string('logintoaccount', 'repository', $repositoryname),
'post',
single_button::BUTTON_PRIMARY
);
$button->add_action(new popup_action('click', $url, 'Login'));
$button->class = 'mdl-align';
$button = $OUTPUT->render($button);