diff --git a/export.php b/export.php index 76de1b4..d6a5253 100644 --- a/export.php +++ b/export.php @@ -50,8 +50,7 @@ $PAGE->navbar->add(get_string('export', 'attendance')); $formparams = array('course' => $course, 'cm' => $cm, 'modcontext' => $PAGE->context); $mform = new mod_attendance_export_form($att->url_export(), $formparams); -if ($mform->is_submitted()) { - $formdata = $mform->get_data(); +if ($formdata = $mform->get_data()) { $pageparams = new att_page_with_filter_controls(); $pageparams->init($cm); @@ -70,6 +69,9 @@ if ($mform->is_submitted()) { $pageparams->startdate = $formdata->sessionstartdate; $pageparams->enddate = $formdata->sessionenddate; } + if ($formdata->selectedusers) { + $pageparams->userids = $formdata->users; + } $att->pageparams = $pageparams; $reportdata = new attendance_report_data($att); diff --git a/export_form.php b/export_form.php index 8d6990c..b07b8ad 100644 --- a/export_form.php +++ b/export_form.php @@ -39,7 +39,7 @@ class mod_attendance_export_form extends moodleform { */ public function definition() { - global $USER; + global $USER, $DB, $PAGE; $mform =& $this->_form; $course = $this->_customdata['course']; @@ -60,6 +60,43 @@ class mod_attendance_export_form extends moodleform { } $mform->addElement('select', 'group', get_string('group'), $grouplist); + + // Restrict the export to the selected users. + $namefields = get_all_user_name_fields(true, 'u'); + $allusers = get_enrolled_users($modcontext, 'mod/attendance:canbelisted', 0, 'u.id,'.$namefields); + $userlist = array(); + foreach ($allusers as $user) { + $userlist[$user->id] = fullname($user); + } + unset($allusers); + $tempusers = $DB->get_records('attendance_tempusers', array('courseid' => $course->id), 'studentid, fullname'); + foreach ($tempusers as $user) { + $userlist[$user->studentid] = $user->fullname; + } + list($gsql, $gparams) = $DB->get_in_or_equal(array_keys($grouplist), SQL_PARAMS_NAMED); + list($usql, $uparams) = $DB->get_in_or_equal(array_keys($userlist), SQL_PARAMS_NAMED); + $params = array_merge($gparams, $uparams); + $groupmembers = $DB->get_recordset_select('groups_members', "groupid {$gsql} AND userid {$usql}", $params, + '', 'groupid, userid'); + $groupmappings = array(); + foreach ($groupmembers as $groupmember) { + if (!isset($groupmappings[$groupmember->groupid])) { + $groupmappings[$groupmember->groupid] = array(); + } + $groupmappings[$groupmember->groupid][$groupmember->userid] = $userlist[$groupmember->userid]; + } + if (isset($grouplist[0])) { + $groupmappings[0] = $userlist; + } + + $mform->addElement('selectyesno', 'selectedusers', get_string('onlyselectedusers', 'mod_attendance')); + $sel = $mform->addElement('select', 'users', get_string('users', 'mod_attendance'), $userlist, array('size' => 12)); + $sel->setMultiple(true); + $mform->disabledIf('users', 'selectedusers', 'eq', 0); + + $opts = array('groupmappings' => $groupmappings); + $PAGE->requires->yui_module('moodle-mod_attendance-groupfilter', 'M.mod_attendance.groupfilter.init', array($opts)); + $ident = array(); $ident[] =& $mform->createElement('checkbox', 'id', '', get_string('studentid', 'attendance')); $ident[] =& $mform->createElement('checkbox', 'uname', '', get_string('username')); @@ -96,5 +133,16 @@ class mod_attendance_export_form extends moodleform { $mform->addElement('hidden', 'id', $cm->id); } + + function validation($data, $files) { + $errors = parent::validation($data, $files); + + // Validate the 'users' field. + if ($data['selectedusers'] && empty($data['users'])) { + $errors['users'] = get_string('mustselectusers', 'mod_attendance'); + } + + return $errors; + } } diff --git a/lang/en/attendance.php b/lang/en/attendance.php index 6bf3481..540760d 100644 --- a/lang/en/attendance.php +++ b/lang/en/attendance.php @@ -140,6 +140,7 @@ Reports are available for the entire class or individual students.'; $string['modulenameplural'] = 'Attendances'; $string['months'] = 'Months'; $string['moreattendance'] = 'Attendance has been successfully taken for this page'; +$string['mustselectusers'] = 'Must select users to export'; $string['myvariables'] = 'My Variables'; $string['newdate'] = 'New date'; $string['newduration'] = 'New duration'; @@ -158,7 +159,9 @@ $string['nosessionsselected'] = 'No sessions selected'; $string['notfound'] = 'Attendance activity not found in this course!'; $string['noupgradefromthisversion'] = 'The Attendance module cannot upgrade from the version of attforblock you have installed. - please delete attforblock or upgrade it to the latest version before isntalling the new attendance module'; $string['olddate'] = 'Old date'; +$string['onlyselectedusers'] = 'Export specific users'; $string['participant'] = 'Participant'; +$string['percentage'] = 'Percentage'; $string['period'] = 'Frequency'; $string['pluginname'] = 'Attendance'; $string['pluginadministration'] = 'Attendance administration'; @@ -267,6 +270,7 @@ $string['tusername'] = 'Full name'; $string['update'] = 'Update'; $string['usestatusset'] = 'Use status set'; $string['userexists'] = 'There is already a real user with this email address'; +$string['users'] = 'Users to export'; $string['variable'] = 'variable'; $string['variablesupdated'] = 'Variables successfully updated'; $string['versionforprinting'] = 'version for printing'; diff --git a/renderables.php b/renderables.php index 047a461..8b04082 100644 --- a/renderables.php +++ b/renderables.php @@ -478,6 +478,14 @@ class attendance_report_data implements renderable { $this->users = $att->get_users($att->pageparams->group, $att->pageparams->page); + if (isset($att->pageparams->userids)) { + foreach ($this->users as $key => $user) { + if (!in_array($user->id, $att->pageparams->userids)) { + unset($this->users[$key]); + } + } + } + $this->groups = groups_get_all_groups($att->course->id); $this->sessions = $att->get_filtered_sessions(); diff --git a/tests/behat/extra_features.feature b/tests/behat/extra_features.feature index ffab425..991bdfa 100644 --- a/tests/behat/extra_features.feature +++ b/tests/behat/extra_features.feature @@ -111,6 +111,40 @@ Feature: Test the various new features in the attendance module And "A" "text" should exist in the "Student 3" "table_row" And I should not see "Temporary user 2" + Scenario: A teacher can select a subset of users for export + Given the following "groups" exist: + | course | name | idnumber | + | C1 | Group1 | Group1 | + | C1 | Group2 | Group2 | + And the following "group members" exist: + | group | user | + | Group1 | student1 | + | Group1 | student2 | + | Group2 | student2 | + | Group2 | student3 | + + And I log in as "teacher1" + And I follow "Course 1" + And I follow "Test attendance" + And I follow "Add" + And I set the following fields to these values: + | Create multiple sessions | 0 | + And I click on "submitbutton" "button" + + And I follow "Export" + + When I set the field "Export specific users" to "Yes" + And I set the field "Group" to "Group1" + Then the "Users to export" select box should contain "Student 1" + And the "Users to export" select box should contain "Student 2" + And the "Users to export" select box should not contain "Student 3" + + When I set the field "Group" to "Group2" + Then the "Users to export" select box should contain "Student 2" + And the "Users to export" select box should contain "Student 3" + And the "Users to export" select box should not contain "Student 1" + # Ideally the download would be tested here, but that is difficult to configure. + Scenario: A teacher can create and use multiple status lists Given I log in as "teacher1" And I follow "Course 1" diff --git a/yui/build/moodle-mod_attendance-groupfilter/moodle-mod_attendance-groupfilter-debug.js b/yui/build/moodle-mod_attendance-groupfilter/moodle-mod_attendance-groupfilter-debug.js new file mode 100644 index 0000000..8cc126f --- /dev/null +++ b/yui/build/moodle-mod_attendance-groupfilter/moodle-mod_attendance-groupfilter-debug.js @@ -0,0 +1,45 @@ +YUI.add('moodle-mod_attendance-groupfilter', function (Y, NAME) { + +/*global M*/ +M.mod_attendance = M.mod_attendance || {}; +M.mod_attendance.groupfilter = { + groupmappings: null, + + init: function(opts) { + "use strict"; + + this.groupmappings = opts.groupmappings; + Y.one('#id_group').after('change', this.update_user_list, this); + }, + + /** + * Update the user list with those found in the selected group. + */ + update_user_list: function() { + "use strict"; + var groupid, userlist, users, userid, opt; + + // Get the list of users in the current group. + groupid = Y.one('#id_group').get('value'); + users = this.groupmappings[groupid]; + + // Remove the options from the users select. + userlist = Y.one('#id_users'); + userlist.get('options').remove(); + + // Repopulate the users select with those users in the selected group (if any). + if (users !== undefined) { + for (userid in users) { + if (users.hasOwnProperty(userid)) { + opt = Y.Node.create(''); + opt.set('value', userid); + opt.set('text', users[userid]); + userlist.appendChild(opt); + } + } + } + } +}; + + +}, '@VERSION@', {"requires": ["base", "node"]}); diff --git a/yui/build/moodle-mod_attendance-groupfilter/moodle-mod_attendance-groupfilter-min.js b/yui/build/moodle-mod_attendance-groupfilter/moodle-mod_attendance-groupfilter-min.js new file mode 100644 index 0000000..6e5da57 --- /dev/null +++ b/yui/build/moodle-mod_attendance-groupfilter/moodle-mod_attendance-groupfilter-min.js @@ -0,0 +1 @@ +YUI.add("moodle-mod_attendance-groupfilter",function(e,t){M.mod_attendance=M.mod_attendance||{},M.mod_attendance.groupfilter={groupmappings:null,init:function(t){"use strict";this.groupmappings=t.groupmappings,e.one("#id_group").after("change",this.update_user_list,this)},update_user_list:function(){"use strict";var t,n,r,i,s;t=e.one("#id_group").get("value"),r=this.groupmappings[t],n=e.one("#id_users"),n.get("options").remove();if(r!==undefined)for(i in r)r.hasOwnProperty(i)&&(s=e.Node.create(""),s.set("value",i),s.set("text",r[i]),n.appendChild(s))}}},"@VERSION@",{requires:["base","node"]}); diff --git a/yui/build/moodle-mod_attendance-groupfilter/moodle-mod_attendance-groupfilter.js b/yui/build/moodle-mod_attendance-groupfilter/moodle-mod_attendance-groupfilter.js new file mode 100644 index 0000000..8cc126f --- /dev/null +++ b/yui/build/moodle-mod_attendance-groupfilter/moodle-mod_attendance-groupfilter.js @@ -0,0 +1,45 @@ +YUI.add('moodle-mod_attendance-groupfilter', function (Y, NAME) { + +/*global M*/ +M.mod_attendance = M.mod_attendance || {}; +M.mod_attendance.groupfilter = { + groupmappings: null, + + init: function(opts) { + "use strict"; + + this.groupmappings = opts.groupmappings; + Y.one('#id_group').after('change', this.update_user_list, this); + }, + + /** + * Update the user list with those found in the selected group. + */ + update_user_list: function() { + "use strict"; + var groupid, userlist, users, userid, opt; + + // Get the list of users in the current group. + groupid = Y.one('#id_group').get('value'); + users = this.groupmappings[groupid]; + + // Remove the options from the users select. + userlist = Y.one('#id_users'); + userlist.get('options').remove(); + + // Repopulate the users select with those users in the selected group (if any). + if (users !== undefined) { + for (userid in users) { + if (users.hasOwnProperty(userid)) { + opt = Y.Node.create(''); + opt.set('value', userid); + opt.set('text', users[userid]); + userlist.appendChild(opt); + } + } + } + } +}; + + +}, '@VERSION@', {"requires": ["base", "node"]}); diff --git a/yui/src/groupfilter/build.json b/yui/src/groupfilter/build.json new file mode 100644 index 0000000..9545400 --- /dev/null +++ b/yui/src/groupfilter/build.json @@ -0,0 +1,10 @@ +{ + "name": "moodle-mod_attendance-groupfilter", + "builds": { + "moodle-mod_attendance-groupfilter": { + "jsfiles": [ + "groupfilter.js" + ] + } + } +} \ No newline at end of file diff --git a/yui/src/groupfilter/js/groupfilter.js b/yui/src/groupfilter/js/groupfilter.js new file mode 100644 index 0000000..5bda295 --- /dev/null +++ b/yui/src/groupfilter/js/groupfilter.js @@ -0,0 +1,40 @@ +/*global M*/ +M.mod_attendance = M.mod_attendance || {}; +M.mod_attendance.groupfilter = { + groupmappings: null, + + init: function(opts) { + "use strict"; + + this.groupmappings = opts.groupmappings; + Y.one('#id_group').after('change', this.update_user_list, this); + }, + + /** + * Update the user list with those found in the selected group. + */ + update_user_list: function() { + "use strict"; + var groupid, userlist, users, userid, opt; + + // Get the list of users in the current group. + groupid = Y.one('#id_group').get('value'); + users = this.groupmappings[groupid]; + + // Remove the options from the users select. + userlist = Y.one('#id_users'); + userlist.get('options').remove(); + + // Repopulate the users select with those users in the selected group (if any). + if (users !== undefined) { + for (userid in users) { + if (users.hasOwnProperty(userid)) { + opt = Y.Node.create(''); + opt.set('value', userid); + opt.set('text', users[userid]); + userlist.appendChild(opt); + } + } + } + } +}; diff --git a/yui/src/groupfilter/meta/groupfilter.json b/yui/src/groupfilter/meta/groupfilter.json new file mode 100644 index 0000000..5308751 --- /dev/null +++ b/yui/src/groupfilter/meta/groupfilter.json @@ -0,0 +1,8 @@ +{ + "moodle-mod_attendance-groupfilter": { + "requires": [ + "base", + "node" + ] + } +} \ No newline at end of file