Merge branch 'MDL-68464-master-final' of git://github.com/andrewnicols/moodle
This commit is contained in:
@@ -58,6 +58,7 @@ $outcome = new stdClass();
|
||||
$outcome->success = true;
|
||||
$outcome->response = new stdClass();
|
||||
$outcome->error = '';
|
||||
$outcome->count = 0;
|
||||
|
||||
$searchanywhere = get_user_preferences('userselector_searchanywhere', false);
|
||||
|
||||
@@ -157,14 +158,10 @@ switch ($action) {
|
||||
foreach ($users as $user) {
|
||||
$plugin->enrol_user($instance, $user->id, $roleid, $timestart, $timeend, null, $recovergrades);
|
||||
}
|
||||
$counter = count($users);
|
||||
$outcome->count += count($users);
|
||||
foreach ($cohorts as $cohort) {
|
||||
$totalenrolledusers = $plugin->enrol_cohort($instance, $cohort->id, $roleid, $timestart, $timeend, null, $recovergrades);
|
||||
$counter += $totalenrolledusers;
|
||||
}
|
||||
// Display a notification message after the bulk user enrollment.
|
||||
if ($counter > 0) {
|
||||
\core\notification::info(get_string('totalenrolledusers', 'enrol', $counter));
|
||||
$outcome->count += $totalenrolledusers;
|
||||
}
|
||||
} else {
|
||||
throw new enrol_ajax_exception('enrolnotpermitted');
|
||||
|
||||
+1
-1
@@ -1,2 +1,2 @@
|
||||
define ("enrol_manual/quickenrolment",["core/templates","jquery","core/str","core/config","core/notification","core/modal_factory","core/modal_events","core/fragment","core/pending"],function(a,b,c,d,f,g,h,i,j){var k={COHORTSELECT:"#id_cohortlist",TRIGGERBUTTONS:".enrolusersbutton.enrol_manual_plugin [type='submit']",UNWANTEDHIDDENFIELDS:":input[value='_qf__force_multiselect_submission']"},l=function(a){this.contextid=a.contextid;this.initModal()};l.prototype.courseid=0;l.prototype.modal=null;l.prototype.initModal=function(){var a=b(k.TRIGGERBUTTONS);b.when(c.get_strings([{key:"enroluserscohorts",component:"enrol_manual"},{key:"enrolusers",component:"enrol_manual"}]),g.create({type:g.types.SAVE_CANCEL,large:!0},a)).then(function(a,c){this.modal=c;c.setTitle(a[1]);c.setSaveButtonText(a[1]);c.getRoot().on(h.save,this.submitForm.bind(this));c.getRoot().on("submit","form",this.submitFormAjax.bind(this));c.getRoot().on(h.hidden,function(){c.setBody("")});c.getRoot().on(h.shown,function(){var d=new j("enrol_manual/quickenrolment:initModal:shown"),e=this.getBody();e.then(function(d){var e=b(d).find(k.COHORTSELECT).length?0:1;c.setSaveButtonText(a[e])}).then(d.resolve).catch(f.exception);c.setBody(e)}.bind(this))}.bind(this)).fail(f.exception)};l.prototype.submitForm=function(a){a.preventDefault();this.modal.getRoot().find("form").submit()};l.prototype.submitFormAjax=function(a){a.preventDefault();var c=this.modal.getRoot().find("form"),e=c.find(k.UNWANTEDHIDDENFIELDS);e.each(function(){b(this).remove()});var g=c.serialize();this.modal.hide();var h=d.wwwroot+"/enrol/manual/ajax.php?"+g;b.ajax(h,{type:"GET",processData:!1,contentType:"application/json"}).then(function(a){if(a.error){f.addNotification({message:a.error,type:"error"})}else{if("undefined"!=typeof window.M.core_formchangechecker){window.M.core_formchangechecker.reset_form_dirty_state()}window.location.reload()}}).fail(f.exception)};l.prototype.getBody=function(){return i.loadFragment("enrol_manual","enrol_users_form",this.contextid,{}).fail(f.exception)};l.prototype.getFooter=function(){return a.render("enrol_manual/enrol_modal_footer",{})};return{init:function init(a){new l(a)}}});
|
||||
function _typeof(a){"@babel/helpers - typeof";if("function"==typeof Symbol&&"symbol"==typeof Symbol.iterator){_typeof=function(a){return typeof a}}else{_typeof=function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a}}return _typeof(a)}define ("enrol_manual/quickenrolment",["exports","core_table/dynamic","core/str","core/toast","core/config","core/fragment","core/modal_events","core/modal_factory","core/notification","jquery","core/prefetch"],function(a,b,c,d,e,f,g,h,i,j,k){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.init=void 0;b=n(b);c=n(c);d=n(d);e=l(e);f=l(f);g=l(g);h=l(h);i=l(i);j=l(j);k=l(k);function l(a){return a&&a.__esModule?a:{default:a}}function m(){if("function"!=typeof WeakMap)return null;var a=new WeakMap;m=function(){return a};return a}function n(a){if(a&&a.__esModule){return a}if(null===a||"object"!==_typeof(a)&&"function"!=typeof a){return{default:a}}var b=m();if(b&&b.has(a)){return b.get(a)}var c={},d=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var e in a){if(Object.prototype.hasOwnProperty.call(a,e)){var f=d?Object.getOwnPropertyDescriptor(a,e):null;if(f&&(f.get||f.set)){Object.defineProperty(c,e,f)}else{c[e]=a[e]}}}c.default=a;if(b){b.set(a,c)}return c}var o={cohortSelector:"#id_cohortlist",triggerButtons:".enrolusersbutton.enrol_manual_plugin [type='submit']",unwantedHiddenFields:"input[value='_qf__force_multiselect_submission']",buttonWrapper:"[data-region=\"wrapper\"]"},p=function(a){return f.default.loadFragment("enrol_manual","enrol_users_form",a,{})},q=function(a){var c=a.closest(o.buttonWrapper);return b.getTableFromId(c.dataset.tableUniqueid)},r=function(a){document.addEventListener("click",function(b){if(b.target.closest(o.triggerButtons)){b.preventDefault();s(q(b.target),a)}})},s=function(a,b){return h.default.create({type:h.default.types.SAVE_CANCEL,large:!0,title:c.get_string("enrolusers","enrol_manual"),body:p(b)}).then(function(b){b.getRoot().on(g.default.save,function(a){a.preventDefault();b.getRoot().find("form").submit()});b.getRoot().on("submit","form",function(c){c.preventDefault();t(a,b)});b.getRoot().on(g.default.hidden,function(){b.destroy()});return b}).then(function(a){a.show();return a}).then(function(a){a.setSaveButtonText(c.get_string("enrolusers","enrol_manual"));a.getBodyPromise().then(function(b){if(b.get(0).querySelector(o.cohortSelector)){a.setSaveButtonText(c.get_string("enroluserscohorts","enrol_manual"))}return b}).catch();return a}).catch(i.default.exception)},t=function(a,f){var g=f.getRoot().find("form");g.get(0).querySelectorAll(o.unwantedHiddenFields).forEach(function(a){return a.remove()});f.hide();f.destroy();j.default.ajax("".concat(e.default.wwwroot,"/enrol/manual/ajax.php?").concat(g.serialize()),{type:"GET",processData:!1,contentType:"application/json"}).then(function(d){if(d.error){throw new Error(d.error)}b.refreshTableContent(a);return c.get_string("totalenrolledusers","enrol",d.count)}).then(function(a){return d.add(a)}).catch(function(a){i.default.addNotification({message:a.message,type:"error"})})},u=function(a){var b=a.contextid;r(b);k.default.prefetchStrings("enrol_manual",["enrolusers","enroluserscohorts"]);k.default.prefetchString("enrol","totalenrolledusers")};a.init=u});
|
||||
//# sourceMappingURL=quickenrolment.min.js.map
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -20,193 +20,175 @@
|
||||
* @copyright 2016 Damyon Wiese <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
define(['core/templates',
|
||||
'jquery',
|
||||
'core/str',
|
||||
'core/config',
|
||||
'core/notification',
|
||||
'core/modal_factory',
|
||||
'core/modal_events',
|
||||
'core/fragment',
|
||||
'core/pending',
|
||||
],
|
||||
function(Template, $, Str, Config, Notification, ModalFactory, ModalEvents, Fragment, Pending) {
|
||||
import * as DynamicTable from 'core_table/dynamic';
|
||||
import * as Str from 'core/str';
|
||||
import * as Toast from 'core/toast';
|
||||
import Config from 'core/config';
|
||||
import Fragment from 'core/fragment';
|
||||
import ModalEvents from 'core/modal_events';
|
||||
import ModalFactory from 'core/modal_factory';
|
||||
import Notification from 'core/notification';
|
||||
import jQuery from 'jquery';
|
||||
import Prefetch from 'core/prefetch';
|
||||
|
||||
/** @type {Object} The list of selectors for the quick enrolment modal. */
|
||||
var SELECTORS = {
|
||||
COHORTSELECT: "#id_cohortlist",
|
||||
TRIGGERBUTTONS: ".enrolusersbutton.enrol_manual_plugin [type='submit']",
|
||||
UNWANTEDHIDDENFIELDS: ":input[value='_qf__force_multiselect_submission']"
|
||||
};
|
||||
const Selectors = {
|
||||
cohortSelector: "#id_cohortlist",
|
||||
triggerButtons: ".enrolusersbutton.enrol_manual_plugin [type='submit']",
|
||||
unwantedHiddenFields: "input[value='_qf__force_multiselect_submission']",
|
||||
buttonWrapper: '[data-region="wrapper"]',
|
||||
};
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param {Object} options Object containing options. The only valid option at this time is contextid.
|
||||
* Each call to templates.render gets it's own instance of this class.
|
||||
*/
|
||||
var QuickEnrolment = function(options) {
|
||||
this.contextid = options.contextid;
|
||||
/**
|
||||
* Get the content of the body for the specified context.
|
||||
*
|
||||
* @param {Number} contextId
|
||||
* @returns {Promise}
|
||||
*/
|
||||
const getBodyForContext = contextId => {
|
||||
return Fragment.loadFragment('enrol_manual', 'enrol_users_form', contextId, {});
|
||||
};
|
||||
|
||||
this.initModal();
|
||||
};
|
||||
// Class variables and functions.
|
||||
/**
|
||||
* Get the dynamic table for the button.
|
||||
*
|
||||
* @param {HTMLElement} element
|
||||
* @returns {HTMLElement}
|
||||
*/
|
||||
const getDynamicTableForElement = element => {
|
||||
const wrapper = element.closest(Selectors.buttonWrapper);
|
||||
|
||||
/** @var {number} courseid - */
|
||||
QuickEnrolment.prototype.courseid = 0;
|
||||
return DynamicTable.getTableFromId(wrapper.dataset.tableUniqueid);
|
||||
};
|
||||
|
||||
/** @var {Modal} modal */
|
||||
QuickEnrolment.prototype.modal = null;
|
||||
/**
|
||||
* Register the event listeners for this contextid.
|
||||
*
|
||||
* @param {Number} contextId
|
||||
*/
|
||||
const registerEventListeners = contextId => {
|
||||
document.addEventListener('click', e => {
|
||||
if (e.target.closest(Selectors.triggerButtons)) {
|
||||
e.preventDefault();
|
||||
|
||||
/**
|
||||
* Private method
|
||||
*
|
||||
* @method initModal
|
||||
* @private
|
||||
*/
|
||||
QuickEnrolment.prototype.initModal = function() {
|
||||
var triggerButtons = $(SELECTORS.TRIGGERBUTTONS);
|
||||
|
||||
$.when(
|
||||
Str.get_strings([
|
||||
{key: 'enroluserscohorts', component: 'enrol_manual'},
|
||||
{key: 'enrolusers', component: 'enrol_manual'},
|
||||
]),
|
||||
ModalFactory.create({
|
||||
type: ModalFactory.types.SAVE_CANCEL,
|
||||
large: true,
|
||||
}, triggerButtons)
|
||||
)
|
||||
.then(function(strings, modal) {
|
||||
this.modal = modal;
|
||||
|
||||
modal.setTitle(strings[1]);
|
||||
modal.setSaveButtonText(strings[1]);
|
||||
|
||||
modal.getRoot().on(ModalEvents.save, this.submitForm.bind(this));
|
||||
modal.getRoot().on('submit', 'form', this.submitFormAjax.bind(this));
|
||||
|
||||
// We want the reset the form every time it is opened.
|
||||
modal.getRoot().on(ModalEvents.hidden, function() {
|
||||
modal.setBody('');
|
||||
});
|
||||
|
||||
modal.getRoot().on(ModalEvents.shown, function() {
|
||||
var pendingPromise = new Pending('enrol_manual/quickenrolment:initModal:shown');
|
||||
var bodyPromise = this.getBody();
|
||||
bodyPromise.then(function(html) {
|
||||
var stringIndex = $(html).find(SELECTORS.COHORTSELECT).length ? 0 : 1;
|
||||
modal.setSaveButtonText(strings[stringIndex]);
|
||||
|
||||
return;
|
||||
})
|
||||
.then(pendingPromise.resolve)
|
||||
.catch(Notification.exception);
|
||||
|
||||
modal.setBody(bodyPromise);
|
||||
}.bind(this));
|
||||
showModal(getDynamicTableForElement(e.target), contextId);
|
||||
|
||||
return;
|
||||
}.bind(this))
|
||||
.fail(Notification.exception);
|
||||
};
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* This triggers a form submission, so that any mform elements can do final tricks before the form submission is processed.
|
||||
*
|
||||
* @method submitForm
|
||||
* @param {Event} e Form submission event.
|
||||
* @private
|
||||
*/
|
||||
QuickEnrolment.prototype.submitForm = function(e) {
|
||||
e.preventDefault();
|
||||
this.modal.getRoot().find('form').submit();
|
||||
};
|
||||
/**
|
||||
* Display the modal for this contextId.
|
||||
*
|
||||
* @param {HTMLElement} dynamicTable The table to beb refreshed when changes are made
|
||||
* @param {Number} contextId
|
||||
* @returns {Promise}
|
||||
*/
|
||||
const showModal = (dynamicTable, contextId) => {
|
||||
return ModalFactory.create({
|
||||
type: ModalFactory.types.SAVE_CANCEL,
|
||||
large: true,
|
||||
title: Str.get_string('enrolusers', 'enrol_manual'),
|
||||
body: getBodyForContext(contextId),
|
||||
})
|
||||
.then(modal => {
|
||||
modal.getRoot().on(ModalEvents.save, e => {
|
||||
// Trigger a form submission, so that any mform elements can do final tricks before the form submission
|
||||
// is processed.
|
||||
// The actual submit even tis captured in the next handler.
|
||||
|
||||
/**
|
||||
* Private method
|
||||
*
|
||||
* @method submitForm
|
||||
* @private
|
||||
* @param {Event} e Form submission event.
|
||||
*/
|
||||
QuickEnrolment.prototype.submitFormAjax = function(e) {
|
||||
// We don't want to do a real form submission.
|
||||
e.preventDefault();
|
||||
|
||||
var form = this.modal.getRoot().find('form');
|
||||
|
||||
// Before send the data through AJAX, we need to parse and remove some unwanted hidden fields.
|
||||
// This hidden fields are added automatically by mforms and when it reaches the AJAX we get an error.
|
||||
var hidden = form.find(SELECTORS.UNWANTEDHIDDENFIELDS);
|
||||
hidden.each(function() {
|
||||
$(this).remove();
|
||||
e.preventDefault();
|
||||
modal.getRoot().find('form').submit();
|
||||
});
|
||||
|
||||
var formData = form.serialize();
|
||||
modal.getRoot().on('submit', 'form', e => {
|
||||
e.preventDefault();
|
||||
|
||||
this.modal.hide();
|
||||
submitFormAjax(dynamicTable, modal);
|
||||
});
|
||||
|
||||
var settings = {
|
||||
modal.getRoot().on(ModalEvents.hidden, () => {
|
||||
modal.destroy();
|
||||
});
|
||||
|
||||
return modal;
|
||||
})
|
||||
.then(modal => {
|
||||
modal.show();
|
||||
|
||||
return modal;
|
||||
})
|
||||
.then(modal => {
|
||||
modal.setSaveButtonText(Str.get_string('enrolusers', 'enrol_manual'));
|
||||
|
||||
modal.getBodyPromise().then(body => {
|
||||
if (body.get(0).querySelector(Selectors.cohortSelector)) {
|
||||
modal.setSaveButtonText(Str.get_string('enroluserscohorts', 'enrol_manual'));
|
||||
}
|
||||
|
||||
return body;
|
||||
})
|
||||
.catch();
|
||||
|
||||
return modal;
|
||||
})
|
||||
.catch(Notification.exception);
|
||||
};
|
||||
|
||||
/**
|
||||
* Submit the form via ajax.
|
||||
*
|
||||
* @param {HTMLElement} dynamicTable
|
||||
* @param {Object} modal
|
||||
*/
|
||||
const submitFormAjax = (dynamicTable, modal) => {
|
||||
// Note: We use a jQuery object here so that we can use its serialize functionality.
|
||||
const form = modal.getRoot().find('form');
|
||||
|
||||
// Before send the data through AJAX, we need to parse and remove some unwanted hidden fields.
|
||||
// This hidden fields are added automatically by mforms and when it reaches the AJAX we get an error.
|
||||
form.get(0).querySelectorAll(Selectors.unwantedHiddenFields).forEach(hiddenField => hiddenField.remove());
|
||||
|
||||
modal.hide();
|
||||
modal.destroy();
|
||||
|
||||
jQuery.ajax(
|
||||
`${Config.wwwroot}/enrol/manual/ajax.php?${form.serialize()}`,
|
||||
{
|
||||
type: 'GET',
|
||||
processData: false,
|
||||
contentType: "application/json"
|
||||
};
|
||||
|
||||
var script = Config.wwwroot + '/enrol/manual/ajax.php?' + formData;
|
||||
$.ajax(script, settings)
|
||||
.then(function(response) {
|
||||
|
||||
if (response.error) {
|
||||
Notification.addNotification({
|
||||
message: response.error,
|
||||
type: "error"
|
||||
});
|
||||
} else {
|
||||
// Reload the page, don't show changed data warnings.
|
||||
if (typeof window.M.core_formchangechecker !== "undefined") {
|
||||
window.M.core_formchangechecker.reset_form_dirty_state();
|
||||
}
|
||||
window.location.reload();
|
||||
}
|
||||
return;
|
||||
})
|
||||
.fail(Notification.exception);
|
||||
};
|
||||
|
||||
/**
|
||||
* Private method
|
||||
*
|
||||
* @method getBody
|
||||
* @private
|
||||
* @return {Promise}
|
||||
*/
|
||||
QuickEnrolment.prototype.getBody = function() {
|
||||
return Fragment.loadFragment('enrol_manual', 'enrol_users_form', this.contextid, {}).fail(Notification.exception);
|
||||
};
|
||||
|
||||
/**
|
||||
* Private method
|
||||
*
|
||||
* @method getFooter
|
||||
* @private
|
||||
* @return {Promise}
|
||||
*/
|
||||
QuickEnrolment.prototype.getFooter = function() {
|
||||
return Template.render('enrol_manual/enrol_modal_footer', {});
|
||||
};
|
||||
|
||||
return /** @alias module:enrol_manual/quickenrolment */ {
|
||||
// Public variables and functions.
|
||||
/**
|
||||
* Every call to init creates a new instance of the class with it's own event listeners etc.
|
||||
*
|
||||
* @method init
|
||||
* @public
|
||||
* @param {object} config - config variables for the module.
|
||||
*/
|
||||
init: function(config) {
|
||||
(new QuickEnrolment(config));
|
||||
contentType: "application/json",
|
||||
}
|
||||
};
|
||||
});
|
||||
)
|
||||
.then(response => {
|
||||
if (response.error) {
|
||||
throw new Error(response.error);
|
||||
}
|
||||
|
||||
DynamicTable.refreshTableContent(dynamicTable);
|
||||
return Str.get_string('totalenrolledusers', 'enrol', response.count);
|
||||
})
|
||||
.then(notificationBody => Toast.add(notificationBody))
|
||||
.catch(error => {
|
||||
Notification.addNotification({
|
||||
message: error.message,
|
||||
type: 'error',
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Set up quick enrolment for the manual enrolment plugin.
|
||||
*
|
||||
* @param {Number} contextid The context id to setup for
|
||||
*/
|
||||
export const init = ({contextid}) => {
|
||||
registerEventListeners(contextid);
|
||||
|
||||
Prefetch.prefetchStrings('enrol_manual', [
|
||||
'enrolusers',
|
||||
'enroluserscohorts',
|
||||
]);
|
||||
|
||||
Prefetch.prefetchString('enrol', 'totalenrolledusers');
|
||||
};
|
||||
|
||||
@@ -124,7 +124,9 @@ Feature: Teacher can search and enrol users one by one into the course
|
||||
And I should see "Student 001"
|
||||
And I click on "Enrol users" "button" in the "Enrol users" "dialogue"
|
||||
Then I should see "Active" in the "Student 001" "table_row"
|
||||
And I should see "1 enrolled users"
|
||||
# The following line is commented out as auto-hidden toasts fire events in the wrong place.
|
||||
# TODO Uncomment this when we upgrade Bootstrap. This issue is fixed in v4.4.0 - see MDL-67386.
|
||||
#And I should see "1 enrolled users"
|
||||
|
||||
@javascript
|
||||
Scenario: Searching for a non-existing user
|
||||
|
||||
+15
-11
@@ -223,6 +223,16 @@ if ($groupid > 0 && ($course->groupmode != SEPARATEGROUPS || $canaccessallgroups
|
||||
echo $grouprenderer->group_details($groupdetailpage);
|
||||
}
|
||||
|
||||
// Should use this variable so that we don't break stuff every time a variable is added or changed.
|
||||
$baseurl = new moodle_url('/user/index.php', array(
|
||||
'contextid' => $context->id,
|
||||
'id' => $course->id,
|
||||
'perpage' => $perpage));
|
||||
|
||||
$participanttable = new \core_user\table\participants("user-index-participants-{$course->id}");
|
||||
$participanttable->set_selectall($selectall);
|
||||
$participanttable->define_baseurl($baseurl);
|
||||
|
||||
// Manage enrolments.
|
||||
$manager = new course_enrolment_manager($PAGE, $course);
|
||||
$enrolbuttons = $manager->get_manual_enrol_buttons();
|
||||
@@ -231,13 +241,10 @@ $enrolbuttonsout = '';
|
||||
foreach ($enrolbuttons as $enrolbutton) {
|
||||
$enrolbuttonsout .= $enrolrenderer->render($enrolbutton);
|
||||
}
|
||||
echo html_writer::div($enrolbuttonsout, 'float-right');
|
||||
|
||||
// Should use this variable so that we don't break stuff every time a variable is added or changed.
|
||||
$baseurl = new moodle_url('/user/index.php', array(
|
||||
'contextid' => $context->id,
|
||||
'id' => $course->id,
|
||||
'perpage' => $perpage));
|
||||
echo html_writer::div($enrolbuttonsout, 'float-right', [
|
||||
'data-region' => 'wrapper',
|
||||
'data-table-uniqueid' => $participanttable->uniqueid,
|
||||
]);
|
||||
|
||||
// Render the unified filter.
|
||||
$renderer = $PAGE->get_renderer('core_user');
|
||||
@@ -274,12 +281,9 @@ if (count($keywordfilter)) {
|
||||
$filterset->add_filter($keywordfilter);
|
||||
}
|
||||
|
||||
$participanttable = new \core_user\table\participants("user-index-participants-{$course->id}");
|
||||
$participanttable->set_filterset($filterset);
|
||||
$participanttable->define_baseurl($baseurl);
|
||||
|
||||
// Do this so we can get the total number of rows.
|
||||
ob_start();
|
||||
$participanttable->set_filterset($filterset);
|
||||
$participanttable->out($perpage, true);
|
||||
$participanttablehtml = ob_get_contents();
|
||||
ob_end_clean();
|
||||
|
||||
Reference in New Issue
Block a user