mirror of
https://github.com/moodle/moodle.git
synced 2025-04-13 12:32:08 +02:00
MDL-59365 enrol_manual: Rewrite the yui enrolment popup in amd
The add/roles thing was only converted to bootstrap 2/4 markup and the yui left in place. The modal for adding users to a course was unsavable so I rewrote it with an mform in a popup, still calling the same (barely) modified ajax script. The webservice for searching cohorts was taken from admin/tool/lp and moved into /cohort. I added a generic "cohort" mform element at the same time. The webservice for searching for users was taken from the original ajax script.
This commit is contained in:
parent
bdf31b0919
commit
a60e8ba51e
@ -920,119 +920,6 @@ class external extends external_api {
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the description of external function parameters.
|
||||
*
|
||||
* @return external_function_parameters
|
||||
*/
|
||||
public static function search_cohorts_parameters() {
|
||||
$query = new external_value(
|
||||
PARAM_RAW,
|
||||
'Query string'
|
||||
);
|
||||
$includes = new external_value(
|
||||
PARAM_ALPHA,
|
||||
'What other contexts to fetch the frameworks from. (all, parents, self)',
|
||||
VALUE_DEFAULT,
|
||||
'parents'
|
||||
);
|
||||
$limitfrom = new external_value(
|
||||
PARAM_INT,
|
||||
'limitfrom we are fetching the records from',
|
||||
VALUE_DEFAULT,
|
||||
0
|
||||
);
|
||||
$limitnum = new external_value(
|
||||
PARAM_INT,
|
||||
'Number of records to fetch',
|
||||
VALUE_DEFAULT,
|
||||
25
|
||||
);
|
||||
return new external_function_parameters(array(
|
||||
'query' => $query,
|
||||
'context' => self::get_context_parameters(),
|
||||
'includes' => $includes,
|
||||
'limitfrom' => $limitfrom,
|
||||
'limitnum' => $limitnum
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Search cohorts.
|
||||
* TODO: MDL-52243 Move this function to cohorts/externallib.php
|
||||
*
|
||||
* @param string $query
|
||||
* @param array $context
|
||||
* @param string $includes
|
||||
* @param int $limitfrom
|
||||
* @param int $limitnum
|
||||
* @return array
|
||||
*/
|
||||
public static function search_cohorts($query, $context, $includes = 'parents', $limitfrom = 0, $limitnum = 25) {
|
||||
global $DB, $CFG, $PAGE;
|
||||
require_once($CFG->dirroot . '/cohort/lib.php');
|
||||
|
||||
$params = self::validate_parameters(self::search_cohorts_parameters(), array(
|
||||
'query' => $query,
|
||||
'context' => $context,
|
||||
'includes' => $includes,
|
||||
'limitfrom' => $limitfrom,
|
||||
'limitnum' => $limitnum,
|
||||
));
|
||||
$query = $params['query'];
|
||||
$includes = $params['includes'];
|
||||
$context = self::get_context_from_params($params['context']);
|
||||
$limitfrom = $params['limitfrom'];
|
||||
$limitnum = $params['limitnum'];
|
||||
|
||||
self::validate_context($context);
|
||||
$output = $PAGE->get_renderer('tool_lp');
|
||||
|
||||
$manager = has_capability('moodle/cohort:manage', $context);
|
||||
if (!$manager) {
|
||||
require_capability('moodle/cohort:view', $context);
|
||||
}
|
||||
|
||||
// TODO Make this more efficient.
|
||||
if ($includes == 'self') {
|
||||
$results = cohort_get_cohorts($context->id, $limitfrom, $limitnum, $query);
|
||||
$results = $results['cohorts'];
|
||||
} else if ($includes == 'parents') {
|
||||
$results = cohort_get_cohorts($context->id, $limitfrom, $limitnum, $query);
|
||||
$results = $results['cohorts'];
|
||||
if (!$context instanceof context_system) {
|
||||
$results = array_merge($results, cohort_get_available_cohorts($context, COHORT_ALL, $limitfrom, $limitnum, $query));
|
||||
}
|
||||
} else if ($includes == 'all') {
|
||||
$results = cohort_get_all_cohorts($limitfrom, $limitnum, $query);
|
||||
$results = $results['cohorts'];
|
||||
} else {
|
||||
throw new coding_exception('Invalid parameter value for \'includes\'.');
|
||||
}
|
||||
|
||||
$cohorts = array();
|
||||
foreach ($results as $key => $cohort) {
|
||||
$cohortcontext = context::instance_by_id($cohort->contextid);
|
||||
$exporter = new cohort_summary_exporter($cohort, array('context' => $cohortcontext));
|
||||
$newcohort = $exporter->export($output);
|
||||
|
||||
$cohorts[$key] = $newcohort;
|
||||
}
|
||||
|
||||
return array('cohorts' => $cohorts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns description of external function result value.
|
||||
*
|
||||
* @return external_description
|
||||
*/
|
||||
public static function search_cohorts_returns() {
|
||||
return new external_single_structure(array(
|
||||
'cohorts' => new external_multiple_structure(cohort_summary_exporter::get_read_structure())
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns description of external function.
|
||||
*
|
||||
|
@ -131,10 +131,11 @@ $functions = array(
|
||||
'capabilities' => '',
|
||||
'ajax' => true,
|
||||
),
|
||||
// This function was originally in this plugin but has been moved to core.
|
||||
'tool_lp_search_cohorts' => array(
|
||||
'classname' => 'tool_lp\external',
|
||||
'classname' => 'core_cohort_external',
|
||||
'methodname' => 'search_cohorts',
|
||||
'classpath' => '',
|
||||
'classpath' => 'cohort/externallib.php',
|
||||
'description' => 'Search for cohorts.',
|
||||
'type' => 'read',
|
||||
'capabilities' => 'moodle/cohort:view',
|
||||
|
@ -461,76 +461,4 @@ class tool_lp_external_testcase extends externallib_advanced_testcase {
|
||||
$this->assertEquals('A', $summary->evidence[1]->gradename);
|
||||
}
|
||||
|
||||
/**
|
||||
* Search cohorts.
|
||||
*/
|
||||
public function test_search_cohorts() {
|
||||
$this->resetAfterTest(true);
|
||||
|
||||
$syscontext = array('contextid' => context_system::instance()->id);
|
||||
$catcontext = array('contextid' => context_coursecat::instance($this->category->id)->id);
|
||||
$othercatcontext = array('contextid' => context_coursecat::instance($this->othercategory->id)->id);
|
||||
|
||||
$cohort1 = $this->getDataGenerator()->create_cohort(array_merge($syscontext, array('name' => 'Cohortsearch 1')));
|
||||
$cohort2 = $this->getDataGenerator()->create_cohort(array_merge($catcontext, array('name' => 'Cohortsearch 2')));
|
||||
$cohort3 = $this->getDataGenerator()->create_cohort(array_merge($othercatcontext, array('name' => 'Cohortsearch 3')));
|
||||
|
||||
// Check for parameter $includes = 'parents'.
|
||||
|
||||
// A user without permission in the system.
|
||||
$this->setUser($this->user);
|
||||
try {
|
||||
$result = external::search_cohorts("Cohortsearch", $syscontext, 'parents');
|
||||
$this->fail('Invalid permissions in system');
|
||||
} catch (required_capability_exception $e) {
|
||||
// All good.
|
||||
}
|
||||
|
||||
// A user without permission in a category.
|
||||
$this->setUser($this->catuser);
|
||||
try {
|
||||
$result = external::search_cohorts("Cohortsearch", $catcontext, 'parents');
|
||||
$this->fail('Invalid permissions in category');
|
||||
} catch (required_capability_exception $e) {
|
||||
// All good.
|
||||
}
|
||||
|
||||
// A user with permissions in the system.
|
||||
$this->setUser($this->creator);
|
||||
$result = external::search_cohorts("Cohortsearch", $syscontext, 'parents');
|
||||
$this->assertEquals(1, count($result['cohorts']));
|
||||
$this->assertEquals('Cohortsearch 1', $result['cohorts'][$cohort1->id]->name);
|
||||
|
||||
// A user with permissions in the category.
|
||||
$this->setUser($this->catcreator);
|
||||
$result = external::search_cohorts("Cohortsearch", $catcontext, 'parents');
|
||||
$this->assertEquals(2, count($result['cohorts']));
|
||||
$cohorts = array();
|
||||
foreach ($result['cohorts'] as $cohort) {
|
||||
$cohorts[] = $cohort->name;
|
||||
}
|
||||
$this->assertTrue(in_array('Cohortsearch 1', $cohorts));
|
||||
$this->assertTrue(in_array('Cohortsearch 2', $cohorts));
|
||||
|
||||
// Check for parameter $includes = 'self'.
|
||||
$this->setUser($this->creator);
|
||||
$result = external::search_cohorts("Cohortsearch", $othercatcontext, 'self');
|
||||
$this->assertEquals(1, count($result['cohorts']));
|
||||
$this->assertEquals('Cohortsearch 3', $result['cohorts'][$cohort3->id]->name);
|
||||
|
||||
// Check for parameter $includes = 'all'.
|
||||
$this->setUser($this->creator);
|
||||
$result = external::search_cohorts("Cohortsearch", $syscontext, 'all');
|
||||
$this->assertEquals(3, count($result['cohorts']));
|
||||
|
||||
// Detect invalid parameter $includes.
|
||||
$this->setUser($this->creator);
|
||||
try {
|
||||
$result = external::search_cohorts("Cohortsearch", $syscontext, 'invalid');
|
||||
$this->fail('Invalid parameter includes');
|
||||
} catch (coding_exception $e) {
|
||||
// All good.
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -25,6 +25,6 @@
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
|
||||
$plugin->version = 2017051500; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->version = 2017062700; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2017050500; // Requires this Moodle version.
|
||||
$plugin->component = 'tool_lp'; // Full name of the plugin (used for diagnostics).
|
||||
|
@ -274,6 +274,137 @@ class core_cohort_external extends external_api {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the description of external function parameters.
|
||||
*
|
||||
* @return external_function_parameters
|
||||
*/
|
||||
public static function search_cohorts_parameters() {
|
||||
$query = new external_value(
|
||||
PARAM_RAW,
|
||||
'Query string'
|
||||
);
|
||||
$includes = new external_value(
|
||||
PARAM_ALPHA,
|
||||
'What other contexts to fetch the frameworks from. (all, parents, self)',
|
||||
VALUE_DEFAULT,
|
||||
'parents'
|
||||
);
|
||||
$limitfrom = new external_value(
|
||||
PARAM_INT,
|
||||
'limitfrom we are fetching the records from',
|
||||
VALUE_DEFAULT,
|
||||
0
|
||||
);
|
||||
$limitnum = new external_value(
|
||||
PARAM_INT,
|
||||
'Number of records to fetch',
|
||||
VALUE_DEFAULT,
|
||||
25
|
||||
);
|
||||
return new external_function_parameters(array(
|
||||
'query' => $query,
|
||||
'context' => self::get_context_parameters(),
|
||||
'includes' => $includes,
|
||||
'limitfrom' => $limitfrom,
|
||||
'limitnum' => $limitnum
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Search cohorts.
|
||||
*
|
||||
* @param string $query
|
||||
* @param array $context
|
||||
* @param string $includes
|
||||
* @param int $limitfrom
|
||||
* @param int $limitnum
|
||||
* @return array
|
||||
*/
|
||||
public static function search_cohorts($query, $context, $includes = 'parents', $limitfrom = 0, $limitnum = 25) {
|
||||
global $DB, $CFG, $PAGE;
|
||||
require_once($CFG->dirroot . '/cohort/lib.php');
|
||||
|
||||
$params = self::validate_parameters(self::search_cohorts_parameters(), array(
|
||||
'query' => $query,
|
||||
'context' => $context,
|
||||
'includes' => $includes,
|
||||
'limitfrom' => $limitfrom,
|
||||
'limitnum' => $limitnum,
|
||||
));
|
||||
$query = $params['query'];
|
||||
$includes = $params['includes'];
|
||||
$context = self::get_context_from_params($params['context']);
|
||||
$limitfrom = $params['limitfrom'];
|
||||
$limitnum = $params['limitnum'];
|
||||
|
||||
self::validate_context($context);
|
||||
$output = $PAGE->get_renderer('tool_lp');
|
||||
|
||||
$manager = has_capability('moodle/cohort:manage', $context);
|
||||
if (!$manager) {
|
||||
require_capability('moodle/cohort:view', $context);
|
||||
}
|
||||
|
||||
// TODO Make this more efficient.
|
||||
if ($includes == 'self') {
|
||||
$results = cohort_get_cohorts($context->id, $limitfrom, $limitnum, $query);
|
||||
$results = $results['cohorts'];
|
||||
} else if ($includes == 'parents') {
|
||||
$results = cohort_get_cohorts($context->id, $limitfrom, $limitnum, $query);
|
||||
$results = $results['cohorts'];
|
||||
if (!$context instanceof context_system) {
|
||||
$results = array_merge($results, cohort_get_available_cohorts($context, COHORT_ALL, $limitfrom, $limitnum, $query));
|
||||
}
|
||||
} else if ($includes == 'all') {
|
||||
$results = cohort_get_all_cohorts($limitfrom, $limitnum, $query);
|
||||
$results = $results['cohorts'];
|
||||
} else {
|
||||
throw new coding_exception('Invalid parameter value for \'includes\'.');
|
||||
}
|
||||
|
||||
$cohorts = array();
|
||||
foreach ($results as $key => $cohort) {
|
||||
$cohortcontext = context::instance_by_id($cohort->contextid);
|
||||
if (!isset($cohort->description)) {
|
||||
$cohort->description = '';
|
||||
}
|
||||
if (!isset($cohort->descriptionformat)) {
|
||||
$cohort->descriptionformat = FORMAT_PLAIN;
|
||||
}
|
||||
|
||||
list($cohort->description, $cohort->descriptionformat) =
|
||||
external_format_text($cohort->description, $cohort->descriptionformat,
|
||||
$cohortcontext->id, 'cohort', 'description', $cohort->id);
|
||||
|
||||
$cohorts[$key] = $cohort;
|
||||
}
|
||||
|
||||
return array('cohorts' => $cohorts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns description of external function result value.
|
||||
*
|
||||
* @return external_description
|
||||
*/
|
||||
public static function search_cohorts_returns() {
|
||||
return new external_single_structure(array(
|
||||
'cohorts' => new external_multiple_structure(
|
||||
new external_single_structure(array(
|
||||
'id' => new external_value(PARAM_INT, 'ID of the cohort'),
|
||||
'name' => new external_value(PARAM_RAW, 'cohort name'),
|
||||
'idnumber' => new external_value(PARAM_RAW, 'cohort idnumber'),
|
||||
'description' => new external_value(PARAM_RAW, 'cohort description'),
|
||||
'descriptionformat' => new external_format_value('description'),
|
||||
'visible' => new external_value(PARAM_BOOL, 'cohort visible'),
|
||||
))
|
||||
)
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns description of method parameters
|
||||
*
|
||||
|
@ -330,6 +330,33 @@ function cohort_can_view_cohort($cohortorid, $currentcontext) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a cohort by id. Also does a visibility check and returns false if the user cannot see this cohort.
|
||||
*
|
||||
* @param stdClass|int $cohortorid cohort object or id
|
||||
* @param context $currentcontext current context (course) where visibility is checked
|
||||
* @return stdClass|boolean
|
||||
*/
|
||||
function cohort_get_cohort($cohortorid, $currentcontext) {
|
||||
global $DB;
|
||||
if (is_numeric($cohortorid)) {
|
||||
$cohort = $DB->get_record('cohort', array('id' => $cohortorid), 'id, contextid, visible');
|
||||
} else {
|
||||
$cohort = $cohortorid;
|
||||
}
|
||||
|
||||
if ($cohort && in_array($cohort->contextid, $currentcontext->get_parent_context_ids())) {
|
||||
if ($cohort->visible) {
|
||||
return $cohort;
|
||||
}
|
||||
$cohortcontext = context::instance_by_id($cohort->contextid);
|
||||
if (has_capability('moodle/cohort:view', $cohortcontext)) {
|
||||
return $cohort;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Produces a part of SQL query to filter cohorts by the search string
|
||||
*
|
||||
|
@ -454,4 +454,102 @@ class core_cohort_externallib_testcase extends externallib_advanced_testcase {
|
||||
$this->unassignUserCapability('moodle/cohort:assign', $context->id, $roleid);
|
||||
core_cohort_external::delete_cohort_members(array($cohortdel1, $cohortdel2));
|
||||
}
|
||||
|
||||
/**
|
||||
* Search cohorts.
|
||||
*/
|
||||
public function test_search_cohorts() {
|
||||
$this->resetAfterTest(true);
|
||||
|
||||
$creator = $this->getDataGenerator()->create_user();
|
||||
$user = $this->getDataGenerator()->create_user();
|
||||
$catuser = $this->getDataGenerator()->create_user();
|
||||
$catcreator = $this->getDataGenerator()->create_user();
|
||||
$category = $this->getDataGenerator()->create_category();
|
||||
$othercategory = $this->getDataGenerator()->create_category();
|
||||
$syscontext = context_system::instance();
|
||||
$catcontext = context_coursecat::instance($category->id);
|
||||
|
||||
// Fetching default authenticated user role.
|
||||
$userroles = get_archetype_roles('user');
|
||||
$this->assertCount(1, $userroles);
|
||||
$authrole = array_pop($userroles);
|
||||
|
||||
// Reset all default authenticated users permissions.
|
||||
unassign_capability('moodle/cohort:manage', $authrole->id);
|
||||
|
||||
// Creating specific roles.
|
||||
$creatorrole = create_role('Creator role', 'creatorrole', 'creator role description');
|
||||
$userrole = create_role('User role', 'userrole', 'user role description');
|
||||
|
||||
assign_capability('moodle/cohort:manage', CAP_ALLOW, $creatorrole, $syscontext->id);
|
||||
|
||||
// Check for parameter $includes = 'parents'.
|
||||
role_assign($creatorrole, $creator->id, $syscontext->id);
|
||||
role_assign($creatorrole, $catcreator->id, $catcontext->id);
|
||||
role_assign($userrole, $user->id, $syscontext->id);
|
||||
role_assign($userrole, $catuser->id, $catcontext->id);
|
||||
|
||||
$syscontext = array('contextid' => context_system::instance()->id);
|
||||
$catcontext = array('contextid' => context_coursecat::instance($category->id)->id);
|
||||
$othercatcontext = array('contextid' => context_coursecat::instance($othercategory->id)->id);
|
||||
|
||||
$cohort1 = $this->getDataGenerator()->create_cohort(array_merge($syscontext, array('name' => 'Cohortsearch 1')));
|
||||
$cohort2 = $this->getDataGenerator()->create_cohort(array_merge($catcontext, array('name' => 'Cohortsearch 2')));
|
||||
$cohort3 = $this->getDataGenerator()->create_cohort(array_merge($othercatcontext, array('name' => 'Cohortsearch 3')));
|
||||
|
||||
// A user without permission in the system.
|
||||
$this->setUser($user);
|
||||
try {
|
||||
$result = core_cohort_external::search_cohorts("Cohortsearch", $syscontext, 'parents');
|
||||
$this->fail('Invalid permissions in system');
|
||||
} catch (required_capability_exception $e) {
|
||||
// All good.
|
||||
}
|
||||
|
||||
// A user without permission in a category.
|
||||
$this->setUser($catuser);
|
||||
try {
|
||||
$result = core_cohort_external::search_cohorts("Cohortsearch", $catcontext, 'parents');
|
||||
$this->fail('Invalid permissions in category');
|
||||
} catch (required_capability_exception $e) {
|
||||
// All good.
|
||||
}
|
||||
|
||||
// A user with permissions in the system.
|
||||
$this->setUser($creator);
|
||||
$result = core_cohort_external::search_cohorts("Cohortsearch", $syscontext, 'parents');
|
||||
$this->assertEquals(1, count($result['cohorts']));
|
||||
$this->assertEquals('Cohortsearch 1', $result['cohorts'][$cohort1->id]->name);
|
||||
|
||||
// A user with permissions in the category.
|
||||
$this->setUser($catcreator);
|
||||
$result = core_cohort_external::search_cohorts("Cohortsearch", $catcontext, 'parents');
|
||||
$this->assertEquals(2, count($result['cohorts']));
|
||||
$cohorts = array();
|
||||
foreach ($result['cohorts'] as $cohort) {
|
||||
$cohorts[] = $cohort->name;
|
||||
}
|
||||
$this->assertTrue(in_array('Cohortsearch 1', $cohorts));
|
||||
|
||||
// Check for parameter $includes = 'self'.
|
||||
$this->setUser($creator);
|
||||
$result = core_cohort_external::search_cohorts("Cohortsearch", $othercatcontext, 'self');
|
||||
$this->assertEquals(1, count($result['cohorts']));
|
||||
$this->assertEquals('Cohortsearch 3', $result['cohorts'][$cohort3->id]->name);
|
||||
|
||||
// Check for parameter $includes = 'all'.
|
||||
$this->setUser($creator);
|
||||
$result = core_cohort_external::search_cohorts("Cohortsearch", $syscontext, 'all');
|
||||
$this->assertEquals(3, count($result['cohorts']));
|
||||
|
||||
// Detect invalid parameter $includes.
|
||||
$this->setUser($creator);
|
||||
try {
|
||||
$result = core_cohort_external::search_cohorts("Cohortsearch", $syscontext, 'invalid');
|
||||
$this->fail('Invalid parameter includes');
|
||||
} catch (coding_exception $e) {
|
||||
// All good.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -385,6 +385,81 @@ class core_enrol_external extends external_api {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns description of method parameters value
|
||||
*
|
||||
* @return external_description
|
||||
*/
|
||||
public static function get_potential_users_parameters() {
|
||||
return new external_function_parameters(
|
||||
array(
|
||||
'courseid' => new external_value(PARAM_INT, 'course id'),
|
||||
'enrolid' => new external_value(PARAM_INT, 'enrolment id'),
|
||||
'search' => new external_value(PARAM_RAW, 'query'),
|
||||
'searchanywhere' => new external_value(PARAM_BOOL, 'find a match anywhere, or only at the beginning'),
|
||||
'page' => new external_value(PARAM_INT, 'Page number'),
|
||||
'perpage' => new external_value(PARAM_INT, 'Number per page'),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get potential users.
|
||||
*
|
||||
* @param int $courseid Course id
|
||||
* @param int $enrolid Enrolment id
|
||||
* @param string $search The query
|
||||
* @param boolean $searchanywhere Match anywhere in the string
|
||||
* @param int $page Page number
|
||||
* @param int $perpage Max per page
|
||||
* @return array An array of users
|
||||
*/
|
||||
public static function get_potential_users($courseid, $enrolid, $search, $searchanywhere, $page, $perpage) {
|
||||
global $PAGE;
|
||||
|
||||
$params = self::validate_parameters(
|
||||
self::get_potential_users_parameters(),
|
||||
array(
|
||||
'courseid' => $courseid,
|
||||
'enrolid' => $enrolid,
|
||||
'search' => $search,
|
||||
'searchanywhere' => $searchanywhere,
|
||||
'page' => $page,
|
||||
'perpage' => $perpage
|
||||
)
|
||||
);
|
||||
$context = context_course::instance($params['courseid']);
|
||||
require_capability('moodle/course:enrolreview', $context);
|
||||
|
||||
$course = $DB->get_record('course', array('id' => $params['courseid']));
|
||||
$manager = new course_enrolment_manager($PAGE, $course);
|
||||
|
||||
$users = $manager->get_potential_users($params['enrolid'],
|
||||
$params['search'],
|
||||
$params['searchanywhere'],
|
||||
$params['page'],
|
||||
$params['perpage']);
|
||||
|
||||
$results = array();
|
||||
foreach ($users as $id => $user) {
|
||||
if ($userdetails = user_get_user_details($user)) {
|
||||
$results[] = $userdetails;
|
||||
}
|
||||
}
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns description of method result value
|
||||
*
|
||||
* @return external_description
|
||||
*/
|
||||
public static function get_potential_users_returns() {
|
||||
global $CFG;
|
||||
require_once($CFG->dirroot . '/user/externallib.php');
|
||||
return new external_multiple_structure(core_user_external::user_description());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns description of method parameters
|
||||
*
|
||||
|
@ -61,62 +61,32 @@ $outcome->error = '';
|
||||
$searchanywhere = get_user_preferences('userselector_searchanywhere', false);
|
||||
|
||||
switch ($action) {
|
||||
case 'getassignable':
|
||||
$otheruserroles = optional_param('otherusers', false, PARAM_BOOL);
|
||||
$outcome->response = array_reverse($manager->get_assignable_roles($otheruserroles), true);
|
||||
break;
|
||||
case 'searchusers':
|
||||
$enrolid = required_param('enrolid', PARAM_INT);
|
||||
$search = optional_param('search', '', PARAM_RAW);
|
||||
$page = optional_param('page', 0, PARAM_INT);
|
||||
$addedenrollment = optional_param('enrolcount', 0, PARAM_INT);
|
||||
$perpage = optional_param('perpage', 25, PARAM_INT); // This value is hard-coded to 25 in quickenrolment.js
|
||||
$outcome->response = $manager->get_potential_users($enrolid, $search, $searchanywhere, $page, $perpage, $addedenrollment);
|
||||
$extrafields = get_extra_user_fields($context);
|
||||
$useroptions = array();
|
||||
// User is not enrolled yet, either link to site profile or do not link at all.
|
||||
if (has_capability('moodle/user:viewdetails', context_system::instance())) {
|
||||
$useroptions['courseid'] = SITEID;
|
||||
} else {
|
||||
$useroptions['link'] = false;
|
||||
}
|
||||
$viewfullnames = has_capability('moodle/site:viewfullnames', $context);
|
||||
foreach ($outcome->response['users'] as &$user) {
|
||||
$user->picture = $OUTPUT->user_picture($user, $useroptions);
|
||||
$user->fullname = fullname($user, $viewfullnames);
|
||||
$fieldvalues = array();
|
||||
foreach ($extrafields as $field) {
|
||||
$fieldvalues[] = s($user->{$field});
|
||||
unset($user->{$field});
|
||||
}
|
||||
$user->extrafields = implode(', ', $fieldvalues);
|
||||
}
|
||||
// Chrome will display users in the order of the array keys, so we need
|
||||
// to ensure that the results ordered array keys. Fortunately, the JavaScript
|
||||
// does not care what the array keys are. It uses user.id where necessary.
|
||||
$outcome->response['users'] = array_values($outcome->response['users']);
|
||||
$outcome->success = true;
|
||||
break;
|
||||
case 'searchcohorts':
|
||||
$enrolid = required_param('enrolid', PARAM_INT);
|
||||
$search = optional_param('search', '', PARAM_RAW);
|
||||
$page = optional_param('page', 0, PARAM_INT);
|
||||
$addedenrollment = optional_param('enrolcount', 0, PARAM_INT);
|
||||
$perpage = optional_param('perpage', 25, PARAM_INT); // This value is hard-coded to 25 in quickenrolment.js
|
||||
$outcome->response = enrol_manual_get_potential_cohorts($context, $enrolid, $search, $page, $perpage, $addedenrollment);
|
||||
$outcome->success = true;
|
||||
break;
|
||||
case 'enrol':
|
||||
$enrolid = required_param('enrolid', PARAM_INT);
|
||||
$cohort = $user = null;
|
||||
$cohorts = $users = [];
|
||||
|
||||
$userids = optional_param('userlist', [], PARAM_SEQUENCE);
|
||||
$userid = optional_param('userid', 0, PARAM_INT);
|
||||
if ($userid) {
|
||||
$userids[] = $userid;
|
||||
}
|
||||
if ($userids) {
|
||||
foreach ($userids as $userid) {
|
||||
$users[] = $DB->get_record('user', array('id' => $userid), '*', MUST_EXIST);
|
||||
}
|
||||
}
|
||||
$cohortids = optional_param('cohortlist', [], PARAM_SEQUENCE);
|
||||
$cohortid = optional_param('cohortid', 0, PARAM_INT);
|
||||
if (!$cohortid) {
|
||||
$userid = required_param('userid', PARAM_INT);
|
||||
$user = $DB->get_record('user', array('id' => $userid), '*', MUST_EXIST);
|
||||
} else {
|
||||
$cohort = $DB->get_record('cohort', array('id' => $cohortid), '*', MUST_EXIST);
|
||||
if (!cohort_can_view_cohort($cohort, $context)) {
|
||||
throw new enrol_ajax_exception('invalidenrolinstance'); // TODO error text!
|
||||
if ($cohortid) {
|
||||
$cohortids[] = $cohortid;
|
||||
}
|
||||
if ($cohortids) {
|
||||
foreach ($cohortids as $cohortid) {
|
||||
$cohort = $DB->get_record('cohort', array('id' => $cohortid), '*', MUST_EXIST);
|
||||
if (!cohort_can_view_cohort($cohort, $context)) {
|
||||
throw new enrol_ajax_exception('invalidenrolinstance'); // TODO error text!
|
||||
}
|
||||
$cohorts[] = $cohort;
|
||||
}
|
||||
}
|
||||
|
||||
@ -169,9 +139,10 @@ switch ($action) {
|
||||
}
|
||||
$plugin = $plugins[$instance->enrol];
|
||||
if ($plugin->allow_enrol($instance) && has_capability('enrol/'.$plugin->get_name().':enrol', $context)) {
|
||||
if ($user) {
|
||||
foreach ($users as $user) {
|
||||
$plugin->enrol_user($instance, $user->id, $roleid, $timestart, $timeend, null, $recovergrades);
|
||||
} else {
|
||||
}
|
||||
foreach ($cohorts as $cohort) {
|
||||
$plugin->enrol_cohort($instance, $cohort->id, $roleid, $timestart, $timeend, null, $recovergrades);
|
||||
}
|
||||
} else {
|
||||
|
1
enrol/manual/amd/build/form-potential-user-selector.min.js
vendored
Normal file
1
enrol/manual/amd/build/form-potential-user-selector.min.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
define(["jquery","core/ajax","core/templates"],function(a,b,c){return{processResults:function(b,c){var d=[];return a.each(c,function(a,b){d.push({value:b.id,label:b._label})}),d},transport:function(d,e,f,g){var h,i=a(d).data("courseid");"undefined"==typeof i&&(i="1");var j=a(d).data("enrolid");"undefined"==typeof j&&(j=""),h=b.call([{methodname:"core_enrol_get_potential_users",args:{courseid:i,enrolid:j,search:e,searchanywhere:!0,page:0,perpage:30}}]),h[0].then(function(b){var d=[],e=0;return a.each(b.users,function(b,e){var f=e,g=[];a.each(["idnumber","email","phone1","phone2","department","institution"],function(a,b){"undefined"!=typeof e[b]&&""!==e[b]&&(f.hasidentity=!0,g.push(e[b]))}),f.identity=g.join(", "),d.push(c.render("enrol_manual/form-user-selector-suggestion",f))}),a.when.apply(a.when,d).then(function(){var c=arguments;a.each(b.users,function(a,b){b._label=c[e],e++}),f(b.users)})},g)}}});
|
1
enrol/manual/amd/build/quickenrolment.min.js
vendored
Normal file
1
enrol/manual/amd/build/quickenrolment.min.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
define(["core/templates","jquery","core/str","core/config","core/notification","core/modal_factory","core/modal_events","core/fragment"],function(a,b,c,d,e,f,g,h){var i=function(a){this.contextid=a.contextid,this.initModal()};return i.prototype.courseid=0,i.prototype.modal=null,i.prototype.initModal=function(){var a=b('.enrolusersbutton.enrol_manual_plugin [type="submit"]');c.get_string("enrolusers","enrol_manual").then(function(b){return f.create({title:b,body:this.getBody(),footer:this.getFooter()},a).then(function(a){this.modal=a,this.modal.setLarge(),this.modal.getRoot().on(g.hidden,function(){this.modal.setBody(this.getBody())}.bind(this)),this.modal.getFooter().on("click",'[data-action="submit"]',this.submitForm.bind(this)),this.modal.getRoot().on("submit","form",this.submitFormAjax.bind(this))}.bind(this))}.bind(this)).fail(e.exception)},i.prototype.submitForm=function(a){a.preventDefault(),this.modal.getRoot().find("form").submit()},i.prototype.submitFormAjax=function(a){a.preventDefault();var c=this.modal.getRoot().find("form").serialize();this.modal.hide();var f={type:"GET",processData:!1,contentType:"application/json"},g=d.wwwroot+"/enrol/manual/ajax.php?"+c;b.ajax(g,f).then(function(a){a.error?e.addNotification({message:a.error,type:"error"}):("undefined"!=typeof window.M.core_formchangechecker&&window.M.core_formchangechecker.reset_form_dirty_state(),window.location.reload())}).fail(e.exception)},i.prototype.getBody=function(){return h.loadFragment("enrol_manual","enrol_users_form",this.contextid,{}).fail(e.exception)},i.prototype.getFooter=function(){return a.render("enrol_manual/enrol_modal_footer",{})},{init:function(a){new i(a)}}});
|
97
enrol/manual/amd/src/form-potential-user-selector.js
Normal file
97
enrol/manual/amd/src/form-potential-user-selector.js
Normal file
@ -0,0 +1,97 @@
|
||||
// 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/>.
|
||||
|
||||
/**
|
||||
* Potential user selector module.
|
||||
*
|
||||
* @module enrol_manual/form-potential-user-selector
|
||||
* @class form-potential-user-selector
|
||||
* @package enrol_manual
|
||||
* @copyright 2016 Damyon Wiese
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
define(['jquery', 'core/ajax', 'core/templates'], function($, Ajax, Templates) {
|
||||
|
||||
return /** @alias module:enrol_manual/form-potential-user-selector */ {
|
||||
|
||||
processResults: function(selector, results) {
|
||||
var users = [];
|
||||
$.each(results, function(index, user) {
|
||||
users.push({
|
||||
value: user.id,
|
||||
label: user._label
|
||||
});
|
||||
});
|
||||
return users;
|
||||
},
|
||||
|
||||
transport: function(selector, query, success, failure) {
|
||||
var promise;
|
||||
var courseid = $(selector).data('courseid');
|
||||
if (typeof courseid === "undefined") {
|
||||
courseid = '1';
|
||||
}
|
||||
var enrolid = $(selector).data('enrolid');
|
||||
if (typeof enrolid === "undefined") {
|
||||
enrolid = '';
|
||||
}
|
||||
|
||||
promise = Ajax.call([{
|
||||
methodname: 'core_enrol_get_potential_users',
|
||||
args: {
|
||||
courseid: courseid,
|
||||
enrolid: enrolid,
|
||||
search: query,
|
||||
searchanywhere: true,
|
||||
page: 0,
|
||||
perpage: 30
|
||||
}
|
||||
}]);
|
||||
|
||||
promise[0].then(function(results) {
|
||||
var promises = [],
|
||||
i = 0;
|
||||
|
||||
// Render the label.
|
||||
$.each(results.users, function(index, user) {
|
||||
var ctx = user,
|
||||
identity = [];
|
||||
$.each(['idnumber', 'email', 'phone1', 'phone2', 'department', 'institution'], function(i, k) {
|
||||
if (typeof user[k] !== 'undefined' && user[k] !== '') {
|
||||
ctx.hasidentity = true;
|
||||
identity.push(user[k]);
|
||||
}
|
||||
});
|
||||
ctx.identity = identity.join(', ');
|
||||
promises.push(Templates.render('enrol_manual/form-user-selector-suggestion', ctx));
|
||||
});
|
||||
|
||||
// Apply the label to the results.
|
||||
return $.when.apply($.when, promises).then(function() {
|
||||
var args = arguments;
|
||||
$.each(results.users, function(index, user) {
|
||||
user._label = args[i];
|
||||
i++;
|
||||
});
|
||||
success(results.users);
|
||||
});
|
||||
|
||||
}, failure);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
});
|
168
enrol/manual/amd/src/quickenrolment.js
Normal file
168
enrol/manual/amd/src/quickenrolment.js
Normal file
@ -0,0 +1,168 @@
|
||||
// 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/>.
|
||||
|
||||
/**
|
||||
* Quick enrolment AMD module.
|
||||
*
|
||||
* @module enrol_manual/quickenrolment
|
||||
* @copyright 2016 Damyon Wiese <damyon@moodle.com>
|
||||
* @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',
|
||||
],
|
||||
function(Template, $, Str, Config, Notification, ModalFactory, ModalEvents, Fragment) {
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* Each call to templates.render gets it's own instance of this class.
|
||||
*/
|
||||
var QuickEnrolment = function(options) {
|
||||
this.contextid = options.contextid;
|
||||
|
||||
this.initModal();
|
||||
};
|
||||
// Class variables and functions.
|
||||
|
||||
/** @var {number} courseid - */
|
||||
QuickEnrolment.prototype.courseid = 0;
|
||||
|
||||
/** @var {Modal} modal */
|
||||
QuickEnrolment.prototype.modal = null;
|
||||
|
||||
/**
|
||||
* Private method
|
||||
*
|
||||
* @method initModal
|
||||
* @private
|
||||
*/
|
||||
QuickEnrolment.prototype.initModal = function() {
|
||||
var triggerButtons = $('.enrolusersbutton.enrol_manual_plugin [type="submit"]');
|
||||
|
||||
Str.get_string('enrolusers', 'enrol_manual').then(function(modalTitle) {
|
||||
return ModalFactory.create({
|
||||
title: modalTitle,
|
||||
body: this.getBody(),
|
||||
footer: this.getFooter()
|
||||
}, triggerButtons).then(function(modal) {
|
||||
this.modal = modal;
|
||||
this.modal.setLarge();
|
||||
|
||||
// We want the reset the form every time it is opened.
|
||||
this.modal.getRoot().on(ModalEvents.hidden, function() {
|
||||
this.modal.setBody(this.getBody());
|
||||
}.bind(this));
|
||||
|
||||
this.modal.getFooter().on('click', '[data-action="submit"]', this.submitForm.bind(this));
|
||||
this.modal.getRoot().on('submit', 'form', this.submitFormAjax.bind(this));
|
||||
}.bind(this));
|
||||
}.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
|
||||
* @private
|
||||
*/
|
||||
QuickEnrolment.prototype.submitForm = function(e) {
|
||||
e.preventDefault();
|
||||
this.modal.getRoot().find('form').submit();
|
||||
};
|
||||
|
||||
/**
|
||||
* Private method
|
||||
*
|
||||
* @method submitForm
|
||||
* @private
|
||||
* @return Promise
|
||||
*/
|
||||
QuickEnrolment.prototype.submitFormAjax = function(e) {
|
||||
// We don't want to do a real form submission.
|
||||
e.preventDefault();
|
||||
|
||||
var formData = this.modal.getRoot().find('form').serialize();
|
||||
|
||||
this.modal.hide();
|
||||
|
||||
var settings = {
|
||||
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();
|
||||
}
|
||||
})
|
||||
.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));
|
||||
}
|
||||
};
|
||||
});
|
132
enrol/manual/classes/enrol_users_form.php
Normal file
132
enrol/manual/classes/enrol_users_form.php
Normal file
@ -0,0 +1,132 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Enrol users form.
|
||||
*
|
||||
* Simple form to search for users and add them using a manual enrolment to this course.
|
||||
*
|
||||
* @package enrol_manual
|
||||
* @copyright 2016 Damyon Wiese
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
require_once($CFG->libdir.'/formslib.php');
|
||||
|
||||
class enrol_manual_enrol_users_form extends moodleform {
|
||||
|
||||
/**
|
||||
* Form definition.
|
||||
* @return void
|
||||
*/
|
||||
public function definition() {
|
||||
global $PAGE, $DB, $CFG;
|
||||
|
||||
|
||||
require_once($CFG->dirroot . '/enrol/locallib.php');
|
||||
|
||||
$context = $this->_customdata->context;
|
||||
|
||||
// Get the course and enrolment instance.
|
||||
$coursecontext = $context->get_course_context();
|
||||
$course = $DB->get_record('course', ['id' => $coursecontext->instanceid]);
|
||||
$manager = new course_enrolment_manager($PAGE, $course);
|
||||
|
||||
$instance = null;
|
||||
foreach ($manager->get_enrolment_instances() as $tempinstance) {
|
||||
if ($tempinstance->enrol == 'manual') {
|
||||
if ($instance === null) {
|
||||
$instance = $tempinstance;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$mform = $this->_form;
|
||||
$mform->setDisableShortforms();
|
||||
$mform->disable_form_change_checker();
|
||||
// Build the list of options for the enrolment period dropdown.
|
||||
$unlimitedperiod = get_string('unlimited');
|
||||
$periodmenu = array();
|
||||
$periodmenu[''] = $unlimitedperiod;
|
||||
for ($i=1; $i<=365; $i++) {
|
||||
$seconds = $i * 86400;
|
||||
$periodmenu[$seconds] = get_string('numdays', '', $i);
|
||||
}
|
||||
// Work out the apropriate default settings.
|
||||
$defaultperiod = $instance->enrolperiod;
|
||||
if ($instance->enrolperiod > 0 && !isset($periodmenu[$instance->enrolperiod])) {
|
||||
$periodmenu[$instance->enrolperiod] = format_time($instance->enrolperiod);
|
||||
}
|
||||
if (empty($extendbase)) {
|
||||
if (!$extendbase = get_config('enrol_manual', 'enrolstart')) {
|
||||
// Default to now if there is no system setting.
|
||||
$extendbase = 4;
|
||||
}
|
||||
}
|
||||
|
||||
// Build the list of options for the starting from dropdown.
|
||||
$now = time();
|
||||
$today = make_timestamp(date('Y', $now), date('m', $now), date('d', $now), 0, 0, 0);
|
||||
$dateformat = get_string('strftimedatefullshort');
|
||||
|
||||
// Enrolment start.
|
||||
$basemenu = array();
|
||||
if ($course->startdate > 0) {
|
||||
$basemenu[2] = get_string('coursestart') . ' (' . userdate($course->startdate, $dateformat) . ')';
|
||||
}
|
||||
$basemenu[3] = get_string('today') . ' (' . userdate($today, $dateformat) . ')';
|
||||
$basemenu[4] = get_string('now', 'enrol_manual') . ' (' . userdate($now, get_string('strftimedatetimeshort')) . ')';
|
||||
|
||||
$mform->addElement('header', 'main', get_string('enrolmentoptions', 'enrol'));
|
||||
$roles = get_assignable_roles($context);
|
||||
$mform->addElement('select', 'role', get_string('assignrole', 'enrol_manual'), $roles);
|
||||
$keys = array_keys($roles);
|
||||
$defaultrole = end($keys);
|
||||
$mform->setDefault('role', $defaultrole);
|
||||
|
||||
$options = array(
|
||||
'ajax' => 'tool_lp/form-user-selector',
|
||||
'multiple' => true,
|
||||
'courseid' => $course->id,
|
||||
'enrolid' => $instance->id
|
||||
);
|
||||
$mform->addElement('autocomplete', 'userlist', get_string('selectusers', 'enrol_manual'), array(), $options);
|
||||
|
||||
$options = ['contextid' => $context->id, 'multiple' => true];
|
||||
$mform->addElement('cohort', 'cohortlist', get_string('selectcohorts', 'enrol_manual'), $options);
|
||||
|
||||
$mform->addAdvancedStatusElement('main');
|
||||
|
||||
$mform->addElement('checkbox', 'recovergrades', get_string('recovergrades', 'enrol'));
|
||||
$mform->setAdvanced('recovergrades');
|
||||
$mform->addElement('select', 'duration', get_string('defaultperiod', 'enrol_manual'), $periodmenu);
|
||||
$mform->setDefault('duration', $defaultperiod);
|
||||
$mform->setAdvanced('duration');
|
||||
$mform->addElement('select', 'startdate', get_string('startingfrom'), $basemenu);
|
||||
$mform->setDefault('startdate', $extendbase);
|
||||
$mform->setAdvanced('startdate');
|
||||
|
||||
$mform->addElement('hidden', 'id', $course->id);
|
||||
$mform->setType('id', PARAM_INT);
|
||||
$mform->addElement('hidden', 'action', 'enrol');
|
||||
$mform->setType('action', PARAM_ALPHA);
|
||||
$mform->addElement('hidden', 'enrolid', $instance->id);
|
||||
$mform->setType('enrolid', PARAM_INT);
|
||||
}
|
||||
}
|
@ -22,10 +22,12 @@
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
$string['advanced'] = 'Advanced';
|
||||
$string['alterstatus'] = 'Alter status';
|
||||
$string['altertimeend'] = 'Alter end time';
|
||||
$string['altertimestart'] = 'Alter start time';
|
||||
$string['assignrole'] = 'Assign role';
|
||||
$string['assignroles'] = 'Assign roles';
|
||||
$string['browseusers'] = 'Browse users';
|
||||
$string['browsecohorts'] = 'Browse cohorts';
|
||||
$string['confirmbulkdeleteenrolment'] = 'Are you sure you want to delete these users enrolments?';
|
||||
@ -37,6 +39,7 @@ $string['deleteselectedusers'] = 'Delete selected user enrolments';
|
||||
$string['editselectedusers'] = 'Edit selected user enrolments';
|
||||
$string['enrolledincourserole'] = 'Enrolled in "{$a->course}" as "{$a->role}"';
|
||||
$string['enrolusers'] = 'Enrol users';
|
||||
$string['enroluserscohorts'] = 'Enrol selected users and cohorts';
|
||||
$string['expiredaction'] = 'Enrolment expiry action';
|
||||
$string['expiredaction_help'] = 'Select action to carry out when user enrolment expires. Please note that some user data and settings are purged from course during course unenrolment.';
|
||||
$string['expirymessageenrollersubject'] = 'Enrolment expiry notification';
|
||||
@ -60,6 +63,9 @@ $string['messageprovider:expiry_notification'] = 'Manual enrolment expiry notifi
|
||||
$string['now'] = 'Now';
|
||||
$string['pluginname'] = 'Manual enrolments';
|
||||
$string['pluginname_desc'] = 'The manual enrolments plugin allows users to be enrolled manually via a link in the course administration settings, by a user with appropriate permissions such as a teacher. The plugin should normally be enabled, since certain other enrolment plugins, such as self enrolment, require it.';
|
||||
$string['selection'] = 'Selection';
|
||||
$string['selectusers'] = 'Select users';
|
||||
$string['selectcohorts'] = 'Select cohorts';
|
||||
$string['status'] = 'Enable manual enrolments';
|
||||
$string['status_desc'] = 'Allow course access of internally enrolled users. This should be kept enabled in most cases.';
|
||||
$string['status_help'] = 'This setting determines whether users can be enrolled manually, via a link in the course administration settings, by a user with appropriate permissions such as a teacher.';
|
||||
|
@ -194,7 +194,7 @@ class enrol_manual_plugin extends enrol_plugin {
|
||||
* @return enrol_user_button
|
||||
*/
|
||||
public function get_manual_enrol_button(course_enrolment_manager $manager) {
|
||||
global $CFG;
|
||||
global $CFG, $PAGE;
|
||||
require_once($CFG->dirroot.'/cohort/lib.php');
|
||||
|
||||
$instance = null;
|
||||
@ -211,72 +211,18 @@ class enrol_manual_plugin extends enrol_plugin {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$manuallink = $this->get_manual_enrol_link($instance)) {
|
||||
$link = $this->get_manual_enrol_link($instance);
|
||||
if (!$link) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$button = new enrol_user_button($manuallink, get_string('enrolusers', 'enrol_manual'), 'get');
|
||||
$button = new enrol_user_button($link, get_string('enrolusers', 'enrol_manual'), 'get');
|
||||
$button->class .= ' enrol_manual_plugin';
|
||||
|
||||
$startdate = $manager->get_course()->startdate;
|
||||
if (!$defaultstart = get_config('enrol_manual', 'enrolstart')) {
|
||||
// Default to now if there is no system setting.
|
||||
$defaultstart = 4;
|
||||
}
|
||||
$startdateoptions = array();
|
||||
$dateformat = get_string('strftimedatefullshort');
|
||||
if ($startdate > 0) {
|
||||
$startdateoptions[2] = get_string('coursestart') . ' (' . userdate($startdate, $dateformat) . ')';
|
||||
}
|
||||
$now = time();
|
||||
$today = make_timestamp(date('Y', $now), date('m', $now), date('d', $now), 0, 0, 0);
|
||||
$startdateoptions[3] = get_string('today') . ' (' . userdate($today, $dateformat) . ')';
|
||||
$startdateoptions[4] = get_string('now', 'enrol_manual') . ' (' . userdate($now, get_string('strftimedatetimeshort')) . ')';
|
||||
$defaultduration = $instance->enrolperiod > 0 ? $instance->enrolperiod / DAYSECS : '';
|
||||
$context = context_course::instance($instance->courseid);
|
||||
$arguments = array('contextid' => $context->id);
|
||||
|
||||
$modules = array('moodle-enrol_manual-quickenrolment', 'moodle-enrol_manual-quickenrolment-skin');
|
||||
$arguments = array(
|
||||
'instances' => $instances,
|
||||
'courseid' => $instance->courseid,
|
||||
'ajaxurl' => '/enrol/manual/ajax.php',
|
||||
'url' => $manager->get_moodlepage()->url->out(false),
|
||||
'optionsStartDate' => $startdateoptions,
|
||||
'defaultRole' => $instance->roleid,
|
||||
'defaultDuration' => $defaultduration,
|
||||
'defaultStartDate' => (int)$defaultstart,
|
||||
'disableGradeHistory' => $CFG->disablegradehistory,
|
||||
'recoverGradesDefault'=> '',
|
||||
'cohortsAvailable' => cohort_get_available_cohorts($manager->get_context(), COHORT_WITH_NOTENROLLED_MEMBERS_ONLY, 0, 1) ? true : false
|
||||
);
|
||||
|
||||
if ($CFG->recovergradesdefault) {
|
||||
$arguments['recoverGradesDefault'] = ' checked="checked"';
|
||||
}
|
||||
|
||||
$function = 'M.enrol_manual.quickenrolment.init';
|
||||
$button->require_yui_module($modules, $function, array($arguments));
|
||||
$button->strings_for_js(array(
|
||||
'ajaxoneuserfound',
|
||||
'ajaxxusersfound',
|
||||
'ajaxnext25',
|
||||
'enrol',
|
||||
'enrolmentoptions',
|
||||
'enrolusers',
|
||||
'enrolxusers',
|
||||
'errajaxfailedenrol',
|
||||
'errajaxsearch',
|
||||
'foundxcohorts',
|
||||
'none',
|
||||
'usersearch',
|
||||
'unlimitedduration',
|
||||
'startdatetoday',
|
||||
'durationdays',
|
||||
'enrolperiod',
|
||||
'finishenrollingusers',
|
||||
'recovergrades'), 'enrol');
|
||||
$button->strings_for_js(array('browseusers', 'browsecohorts'), 'enrol_manual');
|
||||
$button->strings_for_js('assignroles', 'role');
|
||||
$button->strings_for_js('startingfrom', 'moodle');
|
||||
$PAGE->requires->js_call_amd('enrol_manual/quickenrolment', 'init', array($arguments));
|
||||
|
||||
return $button;
|
||||
}
|
||||
@ -730,3 +676,25 @@ class enrol_manual_plugin extends enrol_plugin {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Serve the manual enrol users form as a fragment.
|
||||
*
|
||||
* @param array $args List of named arguments for the fragment loader.
|
||||
* @return string
|
||||
*/
|
||||
function enrol_manual_output_fragment_enrol_users_form($args) {
|
||||
$args = (object) $args;
|
||||
$context = $args->context;
|
||||
$o = '';
|
||||
|
||||
require_capability('enrol/manual:enrol', $context);
|
||||
$mform = new enrol_manual_enrol_users_form(null, $args);
|
||||
|
||||
ob_start();
|
||||
$mform->display();
|
||||
$o .= ob_get_contents();
|
||||
ob_end_clean();
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
2
enrol/manual/templates/enrol_modal_footer.mustache
Normal file
2
enrol/manual/templates/enrol_modal_footer.mustache
Normal file
@ -0,0 +1,2 @@
|
||||
<input type="button" class="btn btn-primary" data-action="submit" value="{{#str}}enroluserscohorts, enrol_manual{{/str}}">
|
||||
<input type="button" class="btn btn-secondary" data-action="hide" value="{{#str}}cancel{{/str}}">
|
@ -0,0 +1,57 @@
|
||||
{{!
|
||||
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 enrol_manual/form-user-selector-suggestion
|
||||
|
||||
Moodle template for the list of valid options in an autocomplate form element.
|
||||
|
||||
Classes required for JS:
|
||||
* none
|
||||
|
||||
Data attributes required for JS:
|
||||
* none
|
||||
|
||||
Context variables required for this template:
|
||||
* profileimageurlsmall Url to a small profile image.
|
||||
* profileimageurl Url to a profile image.
|
||||
* fullname Users full name
|
||||
* hasidentity boolean to say if there are identity fields to show
|
||||
* identity concatenated list of identity fields.
|
||||
* id user id field
|
||||
* email user email field
|
||||
* idnumber user idnumber field
|
||||
* phone1 user phone1 field
|
||||
* phone2 user phone2 field
|
||||
* department user department field
|
||||
* institution user institution field
|
||||
|
||||
Example context (json):
|
||||
{ "id": "1",
|
||||
"fullname": "Admin",
|
||||
"hasidentity": true,
|
||||
"identity": "Admin User, 0144114141",
|
||||
"profileimageurl": "invalid url",
|
||||
"profileimageurlsmall": "invalid url"
|
||||
}
|
||||
}}
|
||||
<span>
|
||||
<img height="18" src="{{profileimageurlsmall}}" alt="" role="presentation">
|
||||
<span>{{fullname}}</span>
|
||||
{{#hasidentity}}
|
||||
<span><small>{{identity}}</small></span>
|
||||
{{/hasidentity}}
|
||||
</span>
|
@ -1,197 +0,0 @@
|
||||
/* stylelint-disable unit-blacklist */
|
||||
/**************************************
|
||||
|
||||
Structure of the user enroller panel
|
||||
|
||||
.user-enroller-panel(.visible)
|
||||
.uep-wrap
|
||||
.uep-header
|
||||
.uep-content
|
||||
.uep-ajax-content
|
||||
.uep-search-results
|
||||
.totalusers
|
||||
.users
|
||||
.user.clearfix(.odd|.even)(.enrolled)
|
||||
.count
|
||||
.picture
|
||||
.details
|
||||
.fullname
|
||||
.extrafields
|
||||
.options
|
||||
.enrol
|
||||
.uep-more-results
|
||||
.uep-loading-lightbox(.hidden)
|
||||
.loading-icon
|
||||
.uep-footer
|
||||
.uep-search
|
||||
input
|
||||
.uep-searchoptions
|
||||
.collapsibleheading
|
||||
.collapsiblearea(.hidden)
|
||||
.uep-enrolment-option
|
||||
.role
|
||||
.startdate
|
||||
.duration
|
||||
|
||||
**************************************/
|
||||
|
||||
.user-enroller-panel {
|
||||
width: 400px;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.user-enroller-panel.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.user-enroller-panel .uep-wrap {
|
||||
height: inherit;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.user-enroller-panel .uep-search-results .user .count {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.user-enroller-panel .uep-search-results .cohort .count {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.user-enroller-panel .uep-content {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
max-height: 1000px;
|
||||
}
|
||||
|
||||
.user-enroller-panel .uep-ajax-content {
|
||||
height: 375px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.user-enroller-panel .uep-search-results .user .picture {
|
||||
width: 45px;
|
||||
float: left;
|
||||
margin: 3px;
|
||||
}
|
||||
/* Note this file isn't auto flipped, so we need dir-rtl rules*/
|
||||
.dir-rtl .user-enroller-panel .uep-search-results .user .picture {
|
||||
float: right;
|
||||
}
|
||||
.user-enroller-panel .uep-search-results .user .details {
|
||||
width: 180px;
|
||||
float: left;
|
||||
margin: 3px;
|
||||
}
|
||||
/* Note this file isn't auto flipped, so we need dir-rtl rules*/
|
||||
.dir-rtl .user-enroller-panel .uep-search-results .user .details {
|
||||
float: right;
|
||||
}
|
||||
.user-enroller-panel .uep-search-results .user .options {
|
||||
padding-right: 7px;
|
||||
margin: 3px;
|
||||
}
|
||||
|
||||
.user-enroller-panel .uep-search-results .user .options .enrol {
|
||||
margin: 3px;
|
||||
float: right;
|
||||
cursor: pointer;
|
||||
}
|
||||
/* Note this file isn't auto flipped, so we need dir-rtl rules*/
|
||||
.dir-rtl .user-enroller-panel .uep-search-results .user .options .enrol {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.user-enroller-panel .uep-search-results .cohort {
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.user-enroller-panel .uep-search-results .cohort .count {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.user-enroller-panel .uep-search-results .cohort .details {
|
||||
width: 180px;
|
||||
float: left;
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
.user-enroller-panel .uep-search-results .cohort .options .enrol {
|
||||
margin: 3px;
|
||||
float: right;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.user-enroller-panel .uep-search-results .cohort.enrolled .count {
|
||||
width: 40px;
|
||||
}
|
||||
|
||||
.user-enroller-panel .uep-loading-lightbox {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #ddd;
|
||||
top: 0;
|
||||
left: 0;
|
||||
min-width: 50px;
|
||||
min-height: 50px;
|
||||
}
|
||||
|
||||
.user-enroller-panel .uep-loading-lightbox.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.user-enroller-panel .uep-loading-lightbox .loading-icon {
|
||||
margin: auto;
|
||||
vertical-align: middle;
|
||||
margin-top: 125px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.user-enroller-panel .uep-footer {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.user-enroller-panel .uep-search {
|
||||
margin: 3px;
|
||||
}
|
||||
|
||||
.user-enroller-panel .uep-search label {
|
||||
padding-right: 8px;
|
||||
}
|
||||
|
||||
.user-enroller-panel .uep-search input {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.user-enroller-panel .uep-search input.uep-search-btn {
|
||||
width: 20%;
|
||||
}
|
||||
|
||||
.user-enroller-panel .uep-searchoptions {
|
||||
margin: 3px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.user-enroller-panel .uep-controls select {
|
||||
margin-left: 1em;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.user-enroller-panel .collapsibleheading img {
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.user-enroller-panel .collapsiblearea {
|
||||
border: 1px solid #ddd;
|
||||
padding: 0.5rem;
|
||||
}
|
||||
|
||||
.user-enroller-panel .collapsiblearea.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.user-enroller-panel .collapsiblearea .uep-enrolment-option {
|
||||
margin: 5px 1em;
|
||||
}
|
Binary file not shown.
Before Width: | Height: | Size: 930 B |
668
enrol/manual/yui/quickenrolment/quickenrolment.js
vendored
668
enrol/manual/yui/quickenrolment/quickenrolment.js
vendored
@ -1,668 +0,0 @@
|
||||
YUI.add('moodle-enrol_manual-quickenrolment', function(Y) {
|
||||
|
||||
var UEP = {
|
||||
NAME : 'Enrolment Manager',
|
||||
/** Properties **/
|
||||
BASE : 'base',
|
||||
SEARCH : 'search',
|
||||
SEARCHBTN : 'searchbtn',
|
||||
PARAMS : 'params',
|
||||
URL : 'url',
|
||||
AJAXURL : 'ajaxurl',
|
||||
MULTIPLE : 'multiple',
|
||||
PAGE : 'page',
|
||||
COURSEID : 'courseid',
|
||||
USERS : 'users',
|
||||
USERCOUNT : 'userCount',
|
||||
REQUIREREFRESH : 'requiresRefresh',
|
||||
LASTSEARCH : 'lastPreSearchValue',
|
||||
INSTANCES : 'instances',
|
||||
OPTIONSTARTDATE : 'optionsStartDate',
|
||||
DEFAULTROLE : 'defaultRole',
|
||||
DEFAULTSTARTDATE : 'defaultStartDate',
|
||||
DEFAULTDURATION : 'defaultDuration',
|
||||
ASSIGNABLEROLES : 'assignableRoles',
|
||||
DISABLEGRADEHISTORY : 'disableGradeHistory',
|
||||
RECOVERGRADESDEFAULT : 'recoverGradesDefault',
|
||||
ENROLCOUNT : 'enrolCount',
|
||||
PERPAGE : 'perPage',
|
||||
COHORTSAVAILABLE : 'cohortsAvailable',
|
||||
COHORTCOUNT : 'cohortCount'
|
||||
};
|
||||
/** CSS classes for nodes in structure **/
|
||||
var CSS = {
|
||||
PANEL : 'user-enroller-panel',
|
||||
WRAP : 'uep-wrap modal-dialog',
|
||||
HEADER : 'uep-header',
|
||||
CONTENT : 'uep-content',
|
||||
AJAXCONTENT : 'uep-ajax-content',
|
||||
SEARCHRESULTS : 'uep-search-results',
|
||||
TOTALUSERS : 'totalusers',
|
||||
USERS : 'users',
|
||||
USER : 'user',
|
||||
MORERESULTS : 'uep-more-results',
|
||||
LIGHTBOX : 'uep-loading-lightbox',
|
||||
LOADINGICON : 'loading-icon',
|
||||
FOOTER : 'uep-footer',
|
||||
ENROL : 'enrol',
|
||||
ENROLLED : 'enrolled',
|
||||
COUNT : 'count',
|
||||
PICTURE : 'picture',
|
||||
DETAILS : 'details',
|
||||
FULLNAME : 'fullname',
|
||||
EXTRAFIELDS : 'extrafields',
|
||||
OPTIONS : 'options',
|
||||
ODD : 'odd',
|
||||
EVEN : 'even',
|
||||
HIDDEN : 'hidden',
|
||||
RECOVERGRADES : 'recovergrades',
|
||||
RECOVERGRADESTITLE : 'recovergradestitle',
|
||||
SEARCHOPTIONS : 'uep-searchoptions',
|
||||
COLLAPSIBLEHEADING : 'collapsibleheading',
|
||||
COLLAPSIBLEAREA : 'collapsiblearea',
|
||||
ENROLMENTOPTION : 'uep-enrolment-option',
|
||||
SEARCHCONTROLS : 'uep-controls',
|
||||
ROLE : 'role',
|
||||
STARTDATE : 'startdate',
|
||||
DURATION : 'duration',
|
||||
ACTIVE : 'active',
|
||||
SEARCH : 'uep-search',
|
||||
SEARCHBTN : 'uep-search-btn',
|
||||
CLOSE : 'close',
|
||||
CLOSEBTN : 'close-button',
|
||||
ENTITYSELECTOR : 'uep-entity-selector',
|
||||
COHORTS : 'cohorts',
|
||||
COHORT : 'cohort',
|
||||
COHORTNAME : 'cohortname',
|
||||
TOTALCOHORTS : 'totalcohorts'
|
||||
};
|
||||
var create = Y.Node.create;
|
||||
|
||||
var USERENROLLER = function(config) {
|
||||
USERENROLLER.superclass.constructor.apply(this, arguments);
|
||||
};
|
||||
Y.extend(USERENROLLER, Y.Base, {
|
||||
_searchTimeout : null,
|
||||
_loadingNode : null,
|
||||
_escCloseEvent : null,
|
||||
initializer : function(config) {
|
||||
var recovergrades = null;
|
||||
if (this.get(UEP.DISABLEGRADEHISTORY) != true) {
|
||||
recovergrades = create('<div class="'+CSS.ENROLMENTOPTION+' '+CSS.RECOVERGRADES+'"></div>')
|
||||
.append(create('<label class="'+CSS.RECOVERGRADESTITLE+'" for="'+CSS.RECOVERGRADES+'">'+M.util.get_string('recovergrades', 'enrol')+'</label>'))
|
||||
.append(create('<input type="checkbox" class="m-x-1" id="'+CSS.RECOVERGRADES+'" name="'+CSS.RECOVERGRADES+'"'+ this.get(UEP.RECOVERGRADESDEFAULT) +' />'))
|
||||
}
|
||||
|
||||
this.set(UEP.BASE, create('<div class="'+CSS.PANEL+' '+CSS.HIDDEN+'"></div>')
|
||||
.append(create('<div class="'+CSS.WRAP+' modal show modal-dialog modal-content"></div>')
|
||||
.append(create('<div class="'+CSS.HEADER+' header modal-header"></div>')
|
||||
.append(create('<div class="'+CSS.CLOSE+'">×</div>'))
|
||||
.append(create('<h2 class="modal-title">'+M.util.get_string('enrolusers', 'enrol')+'</h2>')))
|
||||
.append(create('<div class="'+CSS.CONTENT+' modal-body"></div>')
|
||||
.append(create('<div class="'+CSS.SEARCHCONTROLS+' form-inline"></div>')
|
||||
.append(create('<div class="'+CSS.ENROLMENTOPTION+' '+CSS.ROLE+'"><label for="id_enrol_manual_assignable_roles">'+M.util.get_string('assignroles', 'role')+'</label></div>')
|
||||
.append(create('<select id="id_enrol_manual_assignable_roles" class="custom-select"><option value="">'+M.util.get_string('none', 'enrol')+'</option></select>'))
|
||||
)
|
||||
.append(create('<div class="'+CSS.ENTITYSELECTOR+' m-y-1"></div>'))
|
||||
.append(create('<div class="'+CSS.SEARCHOPTIONS+'"></div>')
|
||||
.append(create('<div class="'+CSS.COLLAPSIBLEHEADING+'"><img alt="" />'+M.util.get_string('enrolmentoptions', 'enrol')+'</div>'))
|
||||
.append(create('<div class="'+CSS.COLLAPSIBLEAREA+' '+CSS.HIDDEN+'"></div>')
|
||||
.append(recovergrades)
|
||||
.append(create('<div class="'+CSS.ENROLMENTOPTION+' '+CSS.STARTDATE+'">'+M.util.get_string('startingfrom', 'moodle')+'</div>')
|
||||
.append(create('<select class="custom-select"></select>')))
|
||||
.append(create('<div class="'+CSS.ENROLMENTOPTION+' '+CSS.DURATION+'">'+M.util.get_string('enrolperiod', 'enrol')+'</div>')
|
||||
.append(create('<select class="custom-select"><option value="0" selected="selected">'+M.util.get_string('unlimitedduration', 'enrol')+'</option></select>')))
|
||||
)
|
||||
)
|
||||
.append(create('<div class="'+CSS.SEARCH+'"><label for="enrolusersearch" class="accesshide">'+M.util.get_string('usersearch', 'enrol')+'</label></div>')
|
||||
.append(create('<input class="form-control" type="text" id="enrolusersearch" value="" />'))
|
||||
.append(create('<input type="button" id="searchbtn" class="'+CSS.SEARCHBTN+' btn btn-secondary m-l-1" value="'+M.util.get_string('usersearch', 'enrol')+'" />'))
|
||||
)
|
||||
)
|
||||
.append(create('<div class="'+CSS.AJAXCONTENT+'"></div>'))
|
||||
.append(create('<div class="'+CSS.LIGHTBOX+' '+CSS.HIDDEN+'"></div>')
|
||||
.append(create('<img alt="loading" class="'+CSS.LOADINGICON+'" />')
|
||||
.setAttribute('src', M.util.image_url('i/loading', 'moodle')))
|
||||
.setStyle('opacity', 0.5)))
|
||||
.append(create('<div class="'+CSS.FOOTER+' modal-footer"></div>')
|
||||
.append(create('<div class="'+CSS.CLOSEBTN+'"></div>')
|
||||
.append(create('<input type="button" class="btn btn-primary" value="'+M.util.get_string('finishenrollingusers', 'enrol')+'" />'))
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
this.set(UEP.SEARCH, this.get(UEP.BASE).one('#enrolusersearch'));
|
||||
this.set(UEP.SEARCHBTN, this.get(UEP.BASE).one('#searchbtn'));
|
||||
Y.all('.enrol_manual_plugin input').each(function(node){
|
||||
if (node.getAttribute('type', 'submit')) {
|
||||
node.on('click', this.show, this);
|
||||
}
|
||||
}, this);
|
||||
this.get(UEP.BASE).one('.'+CSS.HEADER+' .'+CSS.CLOSE).on('click', this.hide, this);
|
||||
this.get(UEP.BASE).one('.'+CSS.FOOTER+' .'+CSS.CLOSEBTN+' input').on('click', this.hide, this);
|
||||
this._loadingNode = this.get(UEP.BASE).one('.'+CSS.CONTENT+' .'+CSS.LIGHTBOX);
|
||||
var params = this.get(UEP.PARAMS);
|
||||
params['id'] = this.get(UEP.COURSEID);
|
||||
this.set(UEP.PARAMS, params);
|
||||
|
||||
Y.on('key', this.preSearch, this.get(UEP.SEARCH), 'down:13', this);
|
||||
this.get(UEP.SEARCHBTN).on('click', this.preSearch, this);
|
||||
|
||||
if (this.get(UEP.COHORTSAVAILABLE)) {
|
||||
this.get(UEP.BASE).one('.'+CSS.ENTITYSELECTOR)
|
||||
.append(create('<input type="radio" id="id_enrol_manual_entity_users" name="enrol_manual_entity" value="users" class="m-r-1" checked="checked"/>'))
|
||||
.append(create('<label for="id_enrol_manual_entity_users">'+ M.util.get_string('browseusers', 'enrol_manual')+'</label>'))
|
||||
.append(create('<input type="radio" id="id_enrol_manual_entity_cohorts" name="enrol_manual_entity" class="m-x-1" value="cohorts"/>'))
|
||||
.append(create('<label for="id_enrol_manual_entity_cohorts">'+M.util.get_string('browsecohorts', 'enrol_manual')+'</label>'));
|
||||
this.get(UEP.BASE).one('#id_enrol_manual_entity_cohorts').on('change', this.search, this);
|
||||
this.get(UEP.BASE).one('#id_enrol_manual_entity_users').on('change', this.search, this);
|
||||
} else {
|
||||
this.get(UEP.BASE).one('.'+CSS.ENTITYSELECTOR)
|
||||
.append(create('<input type="hidden" name="enrol_manual_entity" value="users"/>'));
|
||||
}
|
||||
|
||||
Y.one(document.body).append(this.get(UEP.BASE));
|
||||
|
||||
var base = this.get(UEP.BASE);
|
||||
base.plug(Y.Plugin.Drag);
|
||||
base.dd.addHandle('.'+CSS.HEADER+' h2');
|
||||
base.one('.'+CSS.HEADER+' h2').setStyle('cursor', 'move');
|
||||
|
||||
var collapsedimage = 't/collapsed'; // ltr mode
|
||||
if ( Y.one(document.body).hasClass('dir-rtl') ) {
|
||||
collapsedimage = 't/collapsed_rtl';
|
||||
} else {
|
||||
collapsedimage = 't/collapsed';
|
||||
}
|
||||
|
||||
this.get(UEP.BASE).one('.'+CSS.SEARCHOPTIONS+' .'+CSS.COLLAPSIBLEHEADING).one('img').setAttribute('src', M.util.image_url(collapsedimage, 'moodle'));
|
||||
this.populateStartDates();
|
||||
this.populateDuration();
|
||||
this.get(UEP.BASE).one('.'+CSS.SEARCHOPTIONS+' .'+CSS.COLLAPSIBLEHEADING).on('click', function(){
|
||||
this.get(UEP.BASE).one('.'+CSS.SEARCHOPTIONS+' .'+CSS.COLLAPSIBLEHEADING).toggleClass(CSS.ACTIVE);
|
||||
this.get(UEP.BASE).one('.'+CSS.SEARCHOPTIONS+' .'+CSS.COLLAPSIBLEAREA).toggleClass(CSS.HIDDEN);
|
||||
if (this.get(UEP.BASE).one('.'+CSS.SEARCHOPTIONS+' .'+CSS.COLLAPSIBLEAREA).hasClass(CSS.HIDDEN)) {
|
||||
this.get(UEP.BASE).one('.'+CSS.SEARCHOPTIONS+' .'+CSS.COLLAPSIBLEHEADING).one('img').setAttribute('src', M.util.image_url(collapsedimage, 'moodle'));
|
||||
} else {
|
||||
this.get(UEP.BASE).one('.'+CSS.SEARCHOPTIONS+' .'+CSS.COLLAPSIBLEHEADING).one('img').setAttribute('src', M.util.image_url('t/expanded', 'moodle'));
|
||||
}
|
||||
}, this);
|
||||
this.populateAssignableRoles();
|
||||
},
|
||||
populateAssignableRoles : function() {
|
||||
this.on('assignablerolesloaded', function(){
|
||||
var roles = this.get(UEP.ASSIGNABLEROLES);
|
||||
var s = this.get(UEP.BASE).one('.'+CSS.ENROLMENTOPTION+'.'+CSS.ROLE+' select');
|
||||
var v = this.get(UEP.DEFAULTROLE);
|
||||
var index = 0, count = 0;
|
||||
for (var i in roles) {
|
||||
count++;
|
||||
var option = create('<option value="' + roles[i].id + '">' + roles[i].name + '</option>');
|
||||
if (roles[i].id == v) {
|
||||
index = count;
|
||||
}
|
||||
s.append(option);
|
||||
}
|
||||
s.set('selectedIndex', index);
|
||||
Y.one('#id_enrol_manual_assignable_roles').focus();
|
||||
}, this);
|
||||
this.getAssignableRoles();
|
||||
},
|
||||
populateStartDates : function() {
|
||||
var select = this.get(UEP.BASE).one('.'+CSS.ENROLMENTOPTION+'.'+CSS.STARTDATE+' select');
|
||||
var defaultvalue = this.get(UEP.DEFAULTSTARTDATE);
|
||||
var options = this.get(UEP.OPTIONSTARTDATE);
|
||||
var index = 0, count = 0;
|
||||
for (var i in options) {
|
||||
var option = create('<option value="'+i+'">'+options[i]+'</option>');
|
||||
if (i == defaultvalue) {
|
||||
index = count;
|
||||
}
|
||||
select.append(option);
|
||||
count++;
|
||||
}
|
||||
select.set('selectedIndex', index);
|
||||
},
|
||||
populateDuration : function() {
|
||||
var select = this.get(UEP.BASE).one('.'+CSS.ENROLMENTOPTION+'.'+CSS.DURATION+' select');
|
||||
var defaultvalue = this.get(UEP.DEFAULTDURATION);
|
||||
var prefix = Math.round(defaultvalue) != defaultvalue ? '≈' : '';
|
||||
var index = 0, count = 0;
|
||||
var durationdays = M.util.get_string('durationdays', 'enrol', '{a}');
|
||||
for (var i = 1; i <= 365; i++) {
|
||||
count++;
|
||||
var option = create('<option value="'+i+'">'+durationdays.replace('{a}', i)+'</option>');
|
||||
if (i == defaultvalue) {
|
||||
index = count;
|
||||
}
|
||||
select.append(option);
|
||||
}
|
||||
if (!index && defaultvalue > 0) {
|
||||
select.append(create('<option value="'+defaultvalue+'">'+durationdays.replace('{a}',
|
||||
prefix + (Math.round(defaultvalue * 100) / 100))+'</option>'));
|
||||
index = ++count;
|
||||
}
|
||||
select.set('selectedIndex', index);
|
||||
},
|
||||
getAssignableRoles : function(){
|
||||
Y.io(M.cfg.wwwroot+'/enrol/ajax.php', {
|
||||
method:'POST',
|
||||
data:'id='+this.get(UEP.COURSEID)+'&action=getassignable&sesskey='+M.cfg.sesskey,
|
||||
on: {
|
||||
complete: function(tid, outcome, args) {
|
||||
try {
|
||||
var roles = Y.JSON.parse(outcome.responseText);
|
||||
this.set(UEP.ASSIGNABLEROLES, roles.response);
|
||||
} catch (e) {
|
||||
new M.core.exception(e);
|
||||
}
|
||||
this.getAssignableRoles = function() {
|
||||
this.fire('assignablerolesloaded');
|
||||
};
|
||||
this.getAssignableRoles();
|
||||
}
|
||||
},
|
||||
context:this
|
||||
});
|
||||
},
|
||||
preSearch : function(e) {
|
||||
this.search(e, false);
|
||||
/*
|
||||
var value = this.get(UEP.SEARCH).get('value');
|
||||
if (value.length < 3 || value == this.get(UEP.LASTSEARCH)) {
|
||||
return;
|
||||
}
|
||||
this.set(UEP.LASTSEARCH, value);
|
||||
if (this._searchTimeout) {
|
||||
clearTimeout(this._searchTimeout);
|
||||
this._searchTimeout = null;
|
||||
}
|
||||
var self = this;
|
||||
this._searchTimeout = setTimeout(function(){
|
||||
self._searchTimeout = null;
|
||||
self.search(null, false);
|
||||
}, 300);
|
||||
*/
|
||||
},
|
||||
show : function(e) {
|
||||
e.preventDefault();
|
||||
e.halt();
|
||||
|
||||
var base = this.get(UEP.BASE);
|
||||
base.removeClass(CSS.HIDDEN);
|
||||
var x = (base.get('winWidth') - 400)/2;
|
||||
var y = (parseInt(base.get('winHeight'))-base.get('offsetHeight'))/2 + parseInt(base.get('docScrollY'));
|
||||
if (y < parseInt(base.get('winHeight'))*0.1) {
|
||||
y = parseInt(base.get('winHeight'))*0.1;
|
||||
}
|
||||
base.setXY([x,y]);
|
||||
var zindex = 0;
|
||||
Y.all('.moodle-has-zindex').each(function() {
|
||||
if (parseInt(this.getComputedStyle('zIndex'), 10) > zindex) {
|
||||
zindex = parseInt(this.getComputedStyle('zIndex'), 10);
|
||||
}
|
||||
});
|
||||
base.setStyle('zIndex', zindex + 1);
|
||||
|
||||
if (this.get(UEP.USERS)===null) {
|
||||
this.search(e, false);
|
||||
}
|
||||
|
||||
this._escCloseEvent = Y.on('key', this.hide, document.body, 'down:27', this);
|
||||
var rolesselect = Y.one('#id_enrol_manual_assignable_roles');
|
||||
if (rolesselect) {
|
||||
rolesselect.focus();
|
||||
}
|
||||
},
|
||||
hide : function(e) {
|
||||
if (this._escCloseEvent) {
|
||||
this._escCloseEvent.detach();
|
||||
this._escCloseEvent = null;
|
||||
}
|
||||
this.get(UEP.BASE).addClass(CSS.HIDDEN);
|
||||
if (this.get(UEP.REQUIREREFRESH)) {
|
||||
window.location = this.get(UEP.URL);
|
||||
}
|
||||
},
|
||||
currentEntity : function() {
|
||||
var entity = CSS.USER;
|
||||
var cohortsinput = Y.one('#id_enrol_manual_entity_cohorts');
|
||||
if (cohortsinput && cohortsinput.get('checked')) {
|
||||
entity = CSS.COHORT;
|
||||
}
|
||||
return entity;
|
||||
},
|
||||
search : function(e, append) {
|
||||
var entity = this.currentEntity();
|
||||
|
||||
if (e) {
|
||||
e.halt();
|
||||
e.preventDefault();
|
||||
}
|
||||
var on, params;
|
||||
if (append) {
|
||||
this.set(UEP.PAGE, this.get(UEP.PAGE)+1);
|
||||
} else {
|
||||
this.set(UEP.USERCOUNT, 0);
|
||||
this.set(UEP.COHORTCOUNT, 0);
|
||||
this.set(UEP.PAGE, 0);
|
||||
}
|
||||
params = this.get(UEP.PARAMS);
|
||||
params['sesskey'] = M.cfg.sesskey;
|
||||
params['action'] = (entity === CSS.USER) ? 'searchusers' : 'searchcohorts';
|
||||
params['search'] = this.get(UEP.SEARCH).get('value');
|
||||
params['page'] = this.get(UEP.PAGE);
|
||||
params['enrolcount'] = this.get(UEP.ENROLCOUNT);
|
||||
params['perpage'] = this.get(UEP.PERPAGE);
|
||||
|
||||
if (this.get(UEP.MULTIPLE)) {
|
||||
alert('oh no there are multiple');
|
||||
} else {
|
||||
var instance = this.get(UEP.INSTANCES)[0];
|
||||
params['enrolid'] = instance.id;
|
||||
}
|
||||
Y.io(M.cfg.wwwroot+this.get(UEP.AJAXURL), {
|
||||
method:'POST',
|
||||
data:build_querystring(params),
|
||||
on : {
|
||||
start : this.displayLoading,
|
||||
complete: ((entity === CSS.USER) ? this.processSearchResults : this.processCohortsSearchResults),
|
||||
end : this.removeLoading
|
||||
},
|
||||
context:this,
|
||||
arguments:{
|
||||
append:append,
|
||||
enrolid:params['enrolid']
|
||||
}
|
||||
});
|
||||
},
|
||||
displayLoading : function() {
|
||||
this._loadingNode.removeClass(CSS.HIDDEN);
|
||||
},
|
||||
removeLoading : function() {
|
||||
this._loadingNode.addClass(CSS.HIDDEN);
|
||||
},
|
||||
processSearchResults : function(tid, outcome, args) {
|
||||
try {
|
||||
var result = Y.JSON.parse(outcome.responseText);
|
||||
if (result.error) {
|
||||
return new M.core.ajaxException(result);
|
||||
}
|
||||
} catch (e) {
|
||||
new M.core.exception(e);
|
||||
}
|
||||
if (!result.success) {
|
||||
this.setContent = M.util.get_string('errajaxsearch', 'enrol');
|
||||
}
|
||||
var users;
|
||||
if (!args.append) {
|
||||
users = create('<div class="'+CSS.USERS+' list-group"></div>');
|
||||
} else {
|
||||
users = this.get(UEP.BASE).one('.'+CSS.SEARCHRESULTS+' .'+CSS.USERS);
|
||||
}
|
||||
var count = this.get(UEP.USERCOUNT);
|
||||
for (var i in result.response.users) {
|
||||
count++;
|
||||
var user = result.response.users[i];
|
||||
users.append(create('<div class="'+CSS.USER+' clearfix list-group-item list-group-item-action" rel="'+user.id+'"></div>')
|
||||
.addClass((count%2)?CSS.ODD:CSS.EVEN)
|
||||
.append(create('<div class="'+CSS.COUNT+'">'+count+'</div>'))
|
||||
.append(create('<div class="'+CSS.PICTURE+'"></div>')
|
||||
.append(create(user.picture)))
|
||||
.append(create('<div class="'+CSS.DETAILS+'"></div>')
|
||||
.append(create('<div class="'+CSS.FULLNAME+'">'+user.fullname+'</div>'))
|
||||
.append(create('<div class="'+CSS.EXTRAFIELDS+'">'+user.extrafields+'</div>')))
|
||||
.append(create('<div class="'+CSS.OPTIONS+'"></div>')
|
||||
.append(create('<input type="button" class="'+CSS.ENROL+' btn btn-secondary" value="'+M.util.get_string('enrol', 'enrol')+'" />')))
|
||||
);
|
||||
}
|
||||
this.set(UEP.USERCOUNT, count);
|
||||
if (!args.append) {
|
||||
var usersstr = (result.response.totalusers == '1')?M.util.get_string('ajaxoneuserfound', 'enrol'):M.util.get_string('ajaxxusersfound','enrol', result.response.totalusers);
|
||||
var content = create('<div class="'+CSS.SEARCHRESULTS+'"></div>')
|
||||
.append(create('<div class="'+CSS.TOTALUSERS+'">'+usersstr+'</div>'))
|
||||
.append(users);
|
||||
if (result.response.totalusers > (this.get(UEP.PAGE)+1)*this.get(UEP.PERPAGE)) {
|
||||
var fetchmore = create('<div class="'+CSS.MORERESULTS+'"><a href="#">'+M.util.get_string('ajaxnext25', 'enrol')+'</a></div>');
|
||||
fetchmore.on('click', this.search, this, true);
|
||||
content.append(fetchmore)
|
||||
}
|
||||
this.setContent(content);
|
||||
Y.delegate("click", this.enrolUser, users, '.'+CSS.USER+' .'+CSS.ENROL, this, args);
|
||||
} else {
|
||||
if (result.response.totalusers <= (this.get(UEP.PAGE)+1)*this.get(UEP.PERPAGE)) {
|
||||
this.get(UEP.BASE).one('.'+CSS.MORERESULTS).remove();
|
||||
}
|
||||
}
|
||||
},
|
||||
processCohortsSearchResults : function(tid, outcome, args) {
|
||||
try {
|
||||
var result = Y.JSON.parse(outcome.responseText);
|
||||
if (result.error) {
|
||||
return new M.core.ajaxException(result);
|
||||
}
|
||||
} catch (e) {
|
||||
new M.core.exception(e);
|
||||
}
|
||||
if (!result.success) {
|
||||
this.setContent = M.util.get_string('errajaxsearch', 'enrol');
|
||||
}
|
||||
var cohorts;
|
||||
if (!args.append) {
|
||||
cohorts = create('<div class="'+CSS.COHORTS+'"></div>');
|
||||
} else {
|
||||
cohorts = this.get(UEP.BASE).one('.'+CSS.SEARCHRESULTS+' .'+CSS.COHORTS);
|
||||
}
|
||||
var count = this.get(UEP.COHORTCOUNT);
|
||||
for (var i in result.response.cohorts) {
|
||||
count++;
|
||||
var cohort = result.response.cohorts[i];
|
||||
cohorts.append(create('<div class="'+CSS.COHORT+' clearfix" rel="'+cohort.id+'"></div>')
|
||||
.addClass((count%2)?CSS.ODD:CSS.EVEN)
|
||||
.append(create('<div class="'+CSS.COUNT+'">'+count+'</div>'))
|
||||
.append(create('<div class="'+CSS.DETAILS+'"></div>')
|
||||
.append(create('<div class="'+CSS.COHORTNAME+'">'+cohort.name+'</div>')))
|
||||
.append(create('<div class="'+CSS.OPTIONS+'"></div>')
|
||||
.append(create('<input type="button" class="' + CSS.ENROL + ' btn btn-secondary" value="' + M.util.get_string('enrolxusers', 'enrol', cohort.cnt) + '" />')))
|
||||
);
|
||||
}
|
||||
this.set(UEP.COHORTCOUNT, count);
|
||||
if (!args.append) {
|
||||
//var usersstr = (result.response.totalusers == '1')?M.util.get_string('ajaxoneuserfound', 'enrol'):M.util.get_string('ajaxxusersfound','enrol', result.response.totalusers);
|
||||
var cohortsstr = M.util.get_string('foundxcohorts', 'enrol', result.response.totalcohorts);
|
||||
var content = create('<div class="'+CSS.SEARCHRESULTS+'"></div>')
|
||||
.append(create('<div class="'+CSS.TOTALCOHORTS+'">'+cohortsstr+'</div>'))
|
||||
.append(cohorts);
|
||||
if (result.response.totalcohorts > (this.get(UEP.PAGE)+1)*this.get(UEP.PERPAGE)) {
|
||||
var fetchmore = create('<div class="'+CSS.MORERESULTS+'"><a href="#">'+M.util.get_string('ajaxnext25', 'enrol')+'</a></div>');
|
||||
fetchmore.on('click', this.search, this, true);
|
||||
content.append(fetchmore)
|
||||
}
|
||||
this.setContent(content);
|
||||
Y.delegate("click", this.enrolUser, cohorts, '.'+CSS.COHORT+' .'+CSS.ENROL, this, args);
|
||||
} else {
|
||||
if (result.response.totalcohorts <= (this.get(UEP.PAGE)+1)*this.get(UEP.PERPAGE)) {
|
||||
this.get(UEP.BASE).one('.'+CSS.MORERESULTS).remove();
|
||||
}
|
||||
}
|
||||
},
|
||||
enrolUser : function(e, args) {
|
||||
var entityname = this.currentEntity();
|
||||
|
||||
var entity = e.currentTarget.ancestor('.'+entityname);
|
||||
var params = [];
|
||||
params['id'] = this.get(UEP.COURSEID);
|
||||
if (entityname === CSS.USER) {
|
||||
params['userid'] = entity.getAttribute("rel");
|
||||
} else {
|
||||
params['cohortid'] = entity.getAttribute("rel");
|
||||
}
|
||||
params['enrolid'] = args.enrolid;
|
||||
params['sesskey'] = M.cfg.sesskey;
|
||||
params['action'] = 'enrol';
|
||||
params['role'] = this.get(UEP.BASE).one('.'+CSS.ENROLMENTOPTION+'.'+CSS.ROLE+' select').get('value');
|
||||
params['startdate'] = this.get(UEP.BASE).one('.'+CSS.ENROLMENTOPTION+'.'+CSS.STARTDATE+' select').get('value');
|
||||
params['duration'] = this.get(UEP.BASE).one('.'+CSS.ENROLMENTOPTION+'.'+CSS.DURATION+' select').get('value');
|
||||
if (this.get(UEP.DISABLEGRADEHISTORY) != true) {
|
||||
params['recovergrades'] = this.get(UEP.BASE).one('#'+CSS.RECOVERGRADES).get('checked')?1:0;
|
||||
} else {
|
||||
params['recovergrades'] = 0;
|
||||
}
|
||||
|
||||
Y.io(M.cfg.wwwroot+this.get(UEP.AJAXURL), {
|
||||
method:'POST',
|
||||
data:build_querystring(params),
|
||||
on: {
|
||||
start : this.displayLoading,
|
||||
complete : function(tid, outcome, args) {
|
||||
try {
|
||||
var result = Y.JSON.parse(outcome.responseText);
|
||||
if (result.error) {
|
||||
return new M.core.ajaxException(result);
|
||||
} else {
|
||||
args.entityNode.addClass(CSS.ENROLLED);
|
||||
args.entityNode.one('.'+CSS.ENROL).remove();
|
||||
this.set(UEP.REQUIREREFRESH, true);
|
||||
var countenrol = this.get(UEP.ENROLCOUNT)+1;
|
||||
this.set(UEP.ENROLCOUNT, countenrol);
|
||||
}
|
||||
} catch (e) {
|
||||
new M.core.exception(e);
|
||||
}
|
||||
},
|
||||
end : this.removeLoading
|
||||
},
|
||||
context:this,
|
||||
arguments:{
|
||||
params : params,
|
||||
entityNode : entity
|
||||
}
|
||||
});
|
||||
|
||||
},
|
||||
setContent: function(content) {
|
||||
this.get(UEP.BASE).one('.'+CSS.CONTENT+' .'+CSS.AJAXCONTENT).setContent(content);
|
||||
}
|
||||
}, {
|
||||
NAME : UEP.NAME,
|
||||
ATTRS : {
|
||||
url : {
|
||||
validator : Y.Lang.isString
|
||||
},
|
||||
ajaxurl : {
|
||||
validator : Y.Lang.isString
|
||||
},
|
||||
base : {
|
||||
setter : function(node) {
|
||||
var n = Y.one(node);
|
||||
if (!n) {
|
||||
Y.fail(UEP.NAME+': invalid base node set');
|
||||
}
|
||||
return n;
|
||||
}
|
||||
},
|
||||
users : {
|
||||
validator : Y.Lang.isArray,
|
||||
value : null
|
||||
},
|
||||
courseid : {
|
||||
value : null
|
||||
},
|
||||
params : {
|
||||
validator : Y.Lang.isArray,
|
||||
value : []
|
||||
},
|
||||
instances : {
|
||||
validator : Y.Lang.isArray,
|
||||
setter : function(instances) {
|
||||
var i,ia = [], count=0;
|
||||
for (i in instances) {
|
||||
ia.push(instances[i]);
|
||||
count++;
|
||||
}
|
||||
this.set(UEP.MULTIPLE, (count>1));
|
||||
}
|
||||
},
|
||||
multiple : {
|
||||
validator : Y.Lang.isBool,
|
||||
value : false
|
||||
},
|
||||
page : {
|
||||
validator : Y.Lang.isNumber,
|
||||
value : 0
|
||||
},
|
||||
userCount : {
|
||||
value : 0,
|
||||
validator : Y.Lang.isNumber
|
||||
},
|
||||
requiresRefresh : {
|
||||
value : false,
|
||||
validator : Y.Lang.isBool
|
||||
},
|
||||
search : {
|
||||
setter : function(node) {
|
||||
var n = Y.one(node);
|
||||
if (!n) {
|
||||
Y.fail(UEP.NAME+': invalid search node set');
|
||||
}
|
||||
return n;
|
||||
}
|
||||
},
|
||||
lastPreSearchValue : {
|
||||
value : '',
|
||||
validator : Y.Lang.isString
|
||||
},
|
||||
strings : {
|
||||
value : {},
|
||||
validator : Y.Lang.isObject
|
||||
},
|
||||
defaultRole : {
|
||||
value : 0
|
||||
},
|
||||
defaultStartDate : {
|
||||
value : 4,
|
||||
validator : Y.Lang.isNumber
|
||||
},
|
||||
defaultDuration : {
|
||||
value : ''
|
||||
},
|
||||
assignableRoles : {
|
||||
value : []
|
||||
},
|
||||
optionsStartDate : {
|
||||
value : []
|
||||
},
|
||||
disableGradeHistory : {
|
||||
value : 0
|
||||
},
|
||||
recoverGradesDefault : {
|
||||
value : ''
|
||||
},
|
||||
enrolCount : {
|
||||
value : 0,
|
||||
validator : Y.Lang.isNumber
|
||||
},
|
||||
perPage : {
|
||||
value: 25,
|
||||
Validator: Y.Lang.isNumber
|
||||
},
|
||||
cohortCount : {
|
||||
value : 0,
|
||||
validator : Y.Lang.isNumber
|
||||
},
|
||||
cohortsAvailable : {
|
||||
value : null
|
||||
}
|
||||
}
|
||||
});
|
||||
Y.augment(USERENROLLER, Y.EventTarget);
|
||||
|
||||
M.enrol_manual = M.enrol_manual || {};
|
||||
M.enrol_manual.quickenrolment = {
|
||||
init : function(cfg) {
|
||||
new USERENROLLER(cfg);
|
||||
}
|
||||
}
|
||||
|
||||
}, '@VERSION@', {requires:['base','node', 'overlay', 'io-base', 'test', 'json-parse', 'event-delegate', 'dd-plugin', 'event-key', 'moodle-core-notification']});
|
@ -95,16 +95,12 @@ class behat_enrol extends behat_base {
|
||||
$this->execute("behat_forms::press_button", get_string('enrolusers', 'enrol'));
|
||||
|
||||
if ($this->running_javascript()) {
|
||||
$this->execute('behat_forms::i_set_the_field_to', array(get_string('assignroles', 'role'), $rolename));
|
||||
$this->execute('behat_forms::i_set_the_field_to', array(get_string('assignroles', 'enrol_manual'), $rolename));
|
||||
|
||||
// We have a div here, not a tr.
|
||||
$userliteral = behat_context_helper::escape($userfullname);
|
||||
$userrowxpath = "//div[contains(concat(' ',normalize-space(@class),' '),' user ')][contains(., $userliteral)]";
|
||||
$this->execute('behat_forms::i_set_the_field_to', array(get_string('selectusers', 'enrol_manual'), $userfullname));
|
||||
|
||||
$this->execute('behat_general::i_click_on_in_the',
|
||||
array(get_string('enrol', 'enrol'), "button", $userrowxpath, "xpath_element")
|
||||
);
|
||||
$this->execute("behat_forms::press_button", get_string('finishenrollingusers', 'enrol'));
|
||||
$this->execute("behat_forms::press_button", get_string('enroluserscohorts', 'enrol_manual'));
|
||||
|
||||
} else {
|
||||
$this->execute('behat_forms::i_set_the_field_to', array(get_string('assignrole', 'role'), $rolename));
|
||||
|
@ -1,47 +0,0 @@
|
||||
.enrolpanel {
|
||||
display: none;
|
||||
position: absolute;
|
||||
background-color: #666;
|
||||
padding: 0 5px;
|
||||
min-width: 200px;
|
||||
}
|
||||
|
||||
.enrolpanel.visible {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.enrolpanel .container {
|
||||
position: relative;
|
||||
background-color: #fff;
|
||||
border: 1px solid #999;
|
||||
top: -5px;
|
||||
}
|
||||
|
||||
.enrolpanel .container .header {
|
||||
border-bottom: 1px solid #999;
|
||||
}
|
||||
|
||||
.enrolpanel .container .header h2 {
|
||||
font-size: 90%;
|
||||
text-align: center;
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
.enrolpanel .container .header .close {
|
||||
width: 25px;
|
||||
height: 15px;
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
right: 1em;
|
||||
cursor: pointer;
|
||||
background: url("sprite.png") no-repeat scroll 0 0 transparent;
|
||||
}
|
||||
|
||||
.enrolpanel .container .content input {
|
||||
margin: 5px;
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.enrolpanel.roleassign.visible .container {
|
||||
width: auto;
|
||||
}
|
Binary file not shown.
Before Width: | Height: | Size: 930 B |
1
lib/amd/build/form-cohort-selector.min.js
vendored
Normal file
1
lib/amd/build/form-cohort-selector.min.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
define(["core/ajax","jquery"],function(a,b){return{processResults:function(a,c){var d=[],e=0,f=String(b(a).data("exclude")).split(",");for(e=0;e<c.cohorts.length;e++)f.indexOf(String(c.cohorts[e].id))===-1&&d.push({value:c.cohorts[e].id,label:c.cohorts[e].name});return d},transport:function(c,d,e,f){var g=b(c),h=null;"undefined"==typeof d&&(d="");var i=g.data("contextid"),j={query:d,includes:"parents",limitfrom:0,limitnum:100,context:{contextid:i}},k=[{methodname:"core_cohort_search_cohorts",args:j}];h=a.call(k),b.when.apply(b.when,h).done(function(a){e(a)}).fail(f)}}});
|
76
lib/amd/src/form-cohort-selector.js
Normal file
76
lib/amd/src/form-cohort-selector.js
Normal file
@ -0,0 +1,76 @@
|
||||
// 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/>.
|
||||
|
||||
/**
|
||||
* Course selector adaptor for auto-complete form element.
|
||||
*
|
||||
* @module core/form-cohort-selector
|
||||
* @class form-cohort-selector
|
||||
* @package core
|
||||
* @copyright 2016 Damyon Wiese <damyon@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
* @since 3.1
|
||||
*/
|
||||
define(['core/ajax', 'jquery'], function(ajax, $) {
|
||||
|
||||
return /** @alias module:core/form-cohort-selector */ {
|
||||
// Public variables and functions.
|
||||
processResults: function(selector, data) {
|
||||
// Mangle the results into an array of objects.
|
||||
var results = [];
|
||||
var i = 0;
|
||||
var excludelist = String($(selector).data('exclude')).split(',');
|
||||
|
||||
for (i = 0; i < data.cohorts.length; i++) {
|
||||
if (excludelist.indexOf(String(data.cohorts[i].id)) === -1) {
|
||||
results.push({value: data.cohorts[i].id, label: data.cohorts[i].name});
|
||||
}
|
||||
}
|
||||
return results;
|
||||
},
|
||||
|
||||
transport: function(selector, query, success, failure) {
|
||||
var el = $(selector);
|
||||
|
||||
// Parse some data-attributes from the form element.
|
||||
|
||||
// Build the query.
|
||||
var promises = null;
|
||||
|
||||
if (typeof query === "undefined") {
|
||||
query = '';
|
||||
}
|
||||
var contextid = el.data('contextid');
|
||||
|
||||
var searchargs = {
|
||||
query: query,
|
||||
includes: 'parents',
|
||||
limitfrom: 0,
|
||||
limitnum: 100,
|
||||
context: { contextid: contextid }
|
||||
};
|
||||
|
||||
var calls = [{
|
||||
methodname: 'core_cohort_search_cohorts', args: searchargs
|
||||
}];
|
||||
|
||||
// Go go go!
|
||||
promises = ajax.call(calls);
|
||||
$.when.apply($.when, promises).done(function(data) {
|
||||
success(data);
|
||||
}).fail(failure);
|
||||
}
|
||||
};
|
||||
});
|
@ -165,6 +165,15 @@ $functions = array(
|
||||
'type' => 'read',
|
||||
'capabilities' => 'moodle/cohort:view'
|
||||
),
|
||||
'core_cohort_search_cohorts' => array(
|
||||
'classname' => 'core_cohort_external',
|
||||
'methodname' => 'search_cohorts',
|
||||
'classpath' => 'cohort/externallib.php',
|
||||
'description' => 'Search for cohorts.',
|
||||
'type' => 'read',
|
||||
'ajax' => true,
|
||||
'capabilities' => 'moodle/cohort:view'
|
||||
),
|
||||
'core_cohort_get_cohorts' => array(
|
||||
'classname' => 'core_cohort_external',
|
||||
'methodname' => 'get_cohorts',
|
||||
@ -454,6 +463,14 @@ $functions = array(
|
||||
and have that capability',
|
||||
'type' => 'read',
|
||||
),
|
||||
'core_enrol_get_potential_users' => array(
|
||||
'classname' => 'core_enrol_external',
|
||||
'methodname' => 'get_potential_users',
|
||||
'classpath' => 'enrol/externallib.php',
|
||||
'description' => 'Get the list of potential users to enrol',
|
||||
'type' => 'read',
|
||||
'capabilities' => 'moodle/course:enrolreview'
|
||||
),
|
||||
'core_enrol_get_users_courses' => array(
|
||||
'classname' => 'core_enrol_external',
|
||||
'methodname' => 'get_users_courses',
|
||||
|
@ -508,6 +508,37 @@ class external_api {
|
||||
throw new invalid_parameter_exception('Missing parameters, please provide either context level with instance id or contextid');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a prepared structure to use a context parameters.
|
||||
* @return external_single_structure
|
||||
*/
|
||||
protected static function get_context_parameters() {
|
||||
$id = new external_value(
|
||||
PARAM_INT,
|
||||
'Context ID. Either use this value, or level and instanceid.',
|
||||
VALUE_DEFAULT,
|
||||
0
|
||||
);
|
||||
$level = new external_value(
|
||||
PARAM_ALPHA,
|
||||
'Context level. To be used with instanceid.',
|
||||
VALUE_DEFAULT,
|
||||
''
|
||||
);
|
||||
$instanceid = new external_value(
|
||||
PARAM_INT,
|
||||
'Context instance ID. To be used with level',
|
||||
VALUE_DEFAULT,
|
||||
0
|
||||
);
|
||||
return new external_single_structure(array(
|
||||
'contextid' => $id,
|
||||
'contextlevel' => $level,
|
||||
'instanceid' => $instanceid,
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
150
lib/form/cohort.php
Normal file
150
lib/form/cohort.php
Normal file
@ -0,0 +1,150 @@
|
||||
<?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/>.
|
||||
|
||||
|
||||
/**
|
||||
* Course selector field.
|
||||
*
|
||||
* Allows auto-complete ajax searching for cohort.
|
||||
*
|
||||
* @package core_form
|
||||
* @copyright 2015 Damyon Wiese <damyon@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
global $CFG;
|
||||
require_once($CFG->libdir . '/form/autocomplete.php');
|
||||
|
||||
/**
|
||||
* Form field type for choosing a cohort.
|
||||
*
|
||||
* Allows auto-complete ajax searching for cohort.
|
||||
*
|
||||
* @package core_form
|
||||
* @copyright 2016 Damyon Wiese <damyon@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class MoodleQuickForm_cohort extends MoodleQuickForm_autocomplete {
|
||||
|
||||
/**
|
||||
* @var array $exclude Exclude a list of cohorts from the list (e.g. the current cohort).
|
||||
*/
|
||||
protected $exclude = array();
|
||||
|
||||
/**
|
||||
* @var int $contextid The context id to fetch cohorts in.
|
||||
*/
|
||||
protected $contextid = 0;
|
||||
|
||||
/**
|
||||
* @var boolean $allowmultiple Allow selecting more than one cohort.
|
||||
*/
|
||||
protected $multiple = false;
|
||||
|
||||
/**
|
||||
* @var array $requiredcapabilities Array of extra capabilities to check at the cohort context.
|
||||
*/
|
||||
protected $requiredcapabilities = array();
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param string $elementname Element name
|
||||
* @param mixed $elementlabel Label(s) for an element
|
||||
* @param array $options Options to control the element's display
|
||||
* Valid options are:
|
||||
* 'multiple' - boolean multi select
|
||||
* 'exclude' - array or int, list of course ids to never show
|
||||
* 'requiredcapabilities' - array of capabilities. Uses ANY to combine them.
|
||||
*/
|
||||
public function __construct($elementname = null, $elementlabel = null, $options = array()) {
|
||||
if (isset($options['multiple'])) {
|
||||
$this->multiple = $options['multiple'];
|
||||
}
|
||||
if (isset($options['contextid'])) {
|
||||
$this->contextid = $options['contextid'];
|
||||
} else {
|
||||
$this->contextid = context_system::instance()->id;
|
||||
}
|
||||
if (isset($options['exclude'])) {
|
||||
$this->exclude = $options['exclude'];
|
||||
if (!is_array($this->exclude)) {
|
||||
$this->exclude = array($this->exclude);
|
||||
}
|
||||
}
|
||||
if (isset($options['requiredcapabilities'])) {
|
||||
$this->requiredcapabilities = $options['requiredcapabilities'];
|
||||
}
|
||||
|
||||
$validattributes = array(
|
||||
'ajax' => 'core/form-cohort-selector',
|
||||
'data-exclude' => implode(',', $this->exclude),
|
||||
'data-contextid' => (int)$this->contextid
|
||||
);
|
||||
if ($this->multiple) {
|
||||
$validattributes['multiple'] = 'multiple';
|
||||
}
|
||||
if (isset($options['noselectionstring'])) {
|
||||
$validattributes['noselectionstring'] = $options['noselectionstring'];
|
||||
}
|
||||
if (isset($options['placeholder'])) {
|
||||
$validattributes['placeholder'] = $options['placeholder'];
|
||||
}
|
||||
|
||||
parent::__construct($elementname, $elementlabel, array(), $validattributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of this element. If values can be added or are unknown, we will
|
||||
* make sure they exist in the options array.
|
||||
* @param string|array $value The value to set.
|
||||
* @return boolean
|
||||
*/
|
||||
public function setValue($value) {
|
||||
global $DB;
|
||||
$values = (array) $value;
|
||||
$cohortstofetch = array();
|
||||
|
||||
foreach ($values as $onevalue) {
|
||||
if ((!$this->optionExists($onevalue)) &&
|
||||
($onevalue !== '_qf__force_multiselect_submission')) {
|
||||
array_push($cohortstofetch, $onevalue);
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($cohortstofetch)) {
|
||||
$this->setSelected($values);
|
||||
return true;
|
||||
}
|
||||
|
||||
list($whereclause, $params) = $DB->get_in_or_equal($cohortstofetch, SQL_PARAMS_NAMED, 'id');
|
||||
|
||||
$list = $DB->get_records_select('cohort', 'id ' . $whereclause, $params, 'name');
|
||||
|
||||
$currentcontext = context_helper::instance_by_id($this->contextid);
|
||||
foreach ($list as $cohort) {
|
||||
// Make sure we can see the cohort.
|
||||
if (!cohort_can_view_cohort($cohort, $currentcontext)) {
|
||||
continue;
|
||||
}
|
||||
$label = format_string($cohort->name, true, $currentcontext);
|
||||
$this->addOption($label, $cohort->id);
|
||||
}
|
||||
|
||||
$this->setSelected($values);
|
||||
return true;
|
||||
}
|
||||
}
|
@ -3111,6 +3111,7 @@ MoodleQuickForm::registerElementType('autocomplete', "$CFG->libdir/form/autocomp
|
||||
MoodleQuickForm::registerElementType('button', "$CFG->libdir/form/button.php", 'MoodleQuickForm_button');
|
||||
MoodleQuickForm::registerElementType('cancel', "$CFG->libdir/form/cancel.php", 'MoodleQuickForm_cancel');
|
||||
MoodleQuickForm::registerElementType('course', "$CFG->libdir/form/course.php", 'MoodleQuickForm_course');
|
||||
MoodleQuickForm::registerElementType('cohort', "$CFG->libdir/form/cohort.php", 'MoodleQuickForm_cohort');
|
||||
MoodleQuickForm::registerElementType('searchableselector', "$CFG->libdir/form/searchableselector.php", 'MoodleQuickForm_searchableselector');
|
||||
MoodleQuickForm::registerElementType('checkbox', "$CFG->libdir/form/checkbox.php", 'MoodleQuickForm_checkbox');
|
||||
MoodleQuickForm::registerElementType('date_selector', "$CFG->libdir/form/dateselector.php", 'MoodleQuickForm_date_selector');
|
||||
|
@ -40,7 +40,7 @@
|
||||
<div class="form-autocomplete-selection {{#multiple}}form-autocomplete-multiple{{/multiple}}" id="{{selectionId}}" role="list" aria-atomic="true" {{#multiple}}tabindex="0" aria-multiselectable="true"{{/multiple}}>
|
||||
<span class="accesshide">{{#str}}selecteditems, form{{/str}}</span>
|
||||
{{#items}}
|
||||
<span role="listitem" data-value="{{value}}" aria-selected="true" class="label label-info">
|
||||
<span role="listitem" data-value="{{value}}" aria-selected="true" class="label label-info" style="font-size: larger; margin-bottom: 0.5rem;">
|
||||
{{#multiple}}<span aria-hidden="true">× </span>{{/multiple}}{{{label}}}
|
||||
</span>
|
||||
{{/items}}
|
||||
|
@ -40,7 +40,7 @@
|
||||
<div class="form-autocomplete-selection {{#multiple}}form-autocomplete-multiple{{/multiple}}" id="{{selectionId}}" role="list" aria-atomic="true" {{#multiple}}tabindex="0" aria-multiselectable="true"{{/multiple}}>
|
||||
<span class="accesshide">{{#str}}selecteditems, form{{/str}}</span>
|
||||
{{#items}}
|
||||
<span role="listitem" data-value="{{value}}" aria-selected="true" class="tag tag-info">
|
||||
<span role="listitem" data-value="{{value}}" aria-selected="true" class="tag tag-info m-b-1 m-r-1" style="font-size: larger">
|
||||
{{#multiple}}<span aria-hidden="true">× </span>{{/multiple}}{{{label}}}
|
||||
</span>
|
||||
{{/items}}
|
||||
|
@ -29,7 +29,7 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$version = 2017071100.00; // YYYYMMDD = weekly release date of this DEV branch.
|
||||
$version = 2017071101.00; // YYYYMMDD = weekly release date of this DEV branch.
|
||||
// RR = release increments - 00 in DEV branches.
|
||||
// .XX = incremental changes.
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user