From db0ed29c435ad048664e8f6b8a00485c27939829 Mon Sep 17 00:00:00 2001 From: antonio-c-mariani Date: Mon, 19 Dec 2016 19:50:16 -0200 Subject: [PATCH] Move hide session details (#238) * Fixing missing fields in backup * Fixing behat test due to changes in Moodle 3.2 * Add users taken sessions by acronym columns to the export report * Fixing user name sort order links * Adding buttons to hide/show session details and move them left/rigth * Fixing errors and warnings reported by travis * Fixing failures in behat tests because of enrol start date --- backup/moodle2/backup_attendance_stepslib.php | 9 +- classes/report_page_params.php | 10 + classes/structure.php | 17 +- db/install.xml | 2 + db/upgrade.php | 15 +- export.php | 19 + lang/en/attendance.php | 27 +- renderer.php | 588 +++++++++++++----- report.php | 3 + styles.css | 22 +- tests/behat/attendance_mod.feature | 14 +- tests/behat/calendar_features.feature | 13 +- tests/behat/extra_features.feature | 15 +- tests/behat/preferences.feature | 11 +- tests/behat/report.feature | 34 +- version.php | 4 +- 16 files changed, 605 insertions(+), 198 deletions(-) diff --git a/backup/moodle2/backup_attendance_stepslib.php b/backup/moodle2/backup_attendance_stepslib.php index 275903b..a53760f 100644 --- a/backup/moodle2/backup_attendance_stepslib.php +++ b/backup/moodle2/backup_attendance_stepslib.php @@ -44,22 +44,21 @@ class backup_attendance_activity_structure_step extends backup_activity_structur // XML nodes declaration - non-user data. $attendance = new backup_nested_element('attendance', array('id'), array( - 'name', 'grade')); + 'name', 'grade', 'showsessiondetails', 'sessiondetailspos')); $statuses = new backup_nested_element('statuses'); $status = new backup_nested_element('status', array('id'), array( - 'acronym', 'description', 'grade', 'visible', 'deleted')); + 'acronym', 'description', 'grade', 'visible', 'deleted', 'setnumber')); $sessions = new backup_nested_element('sessions'); $session = new backup_nested_element('session', array('id'), array( 'groupid', 'sessdate', 'duration', 'lasttaken', 'lasttakenby', - 'timemodified', 'description', 'descriptionformat', 'caleventid')); + 'timemodified', 'description', 'descriptionformat', 'studentscanmark', 'statusset', 'caleventid')); // XML nodes declaration - user data. $logs = new backup_nested_element('logs'); $log = new backup_nested_element('log', array('id'), array( - 'sessionid', 'studentid', 'statusid', 'lasttaken', 'statusset', - 'timetaken', 'takenby', 'remarks')); + 'sessionid', 'studentid', 'statusid', 'statusset', 'timetaken', 'takenby', 'remarks')); // Build the tree in the order needed for restore. $attendance->add_child($statuses); diff --git a/classes/report_page_params.php b/classes/report_page_params.php index b40ac43..9a7c2d6 100644 --- a/classes/report_page_params.php +++ b/classes/report_page_params.php @@ -32,6 +32,8 @@ defined('MOODLE_INTERNAL') || die(); class mod_attendance_report_page_params extends mod_attendance_page_with_filter_controls { public $group; public $sort; + public $showsessiondetails; + public $sessiondetailspos; public function __construct() { $this->selectortype = self::SELECTOR_GROUP; @@ -55,6 +57,14 @@ class mod_attendance_report_page_params extends mod_attendance_page_with_filter_ $params['sort'] = $this->sort; } + if (empty($this->showsessiondetails)) { + $params['showsessiondetails'] = 0; + } + + if ($this->sessiondetailspos != 'left') { + $params['sessiondetailspos'] = $this->sessiondetailspos; + } + return $params; } } diff --git a/classes/structure.php b/classes/structure.php index df7d823..b5381de 100644 --- a/classes/structure.php +++ b/classes/structure.php @@ -61,6 +61,12 @@ class mod_attendance_structure { public $subnet; + /** Define if session details should be shown in reports */ + public $showsessiondetails; + + /** Position for the session detail columns related to summary columns.*/ + public $sessiondetailspos; + private $groupmode; private $statuses; @@ -81,6 +87,8 @@ class mod_attendance_structure { * @param stdClass $context The context of the workshop instance */ public function __construct(stdclass $dbrecord, stdclass $cm, stdclass $course, stdclass $context=null, $pageparams=null) { + global $DB; + foreach ($dbrecord as $field => $value) { if (property_exists('mod_attendance_structure', $field)) { $this->{$field} = $value; @@ -97,6 +105,13 @@ class mod_attendance_structure { } $this->pageparams = $pageparams; + + if (isset($pageparams->showsessiondetails) && $pageparams->showsessiondetails != $this->showsessiondetails) { + $DB->set_field('attendance', 'showsessiondetails', $pageparams->showsessiondetails, array('id' => $this->id)); + } + if (isset($pageparams->sessiondetailspos) && $pageparams->sessiondetailspos != $this->sessiondetailspos) { + $DB->set_field('attendance', 'sessiondetailspos', $pageparams->sessiondetailspos, array('id' => $this->id)); + } } public function get_group_mode() { @@ -1065,4 +1080,4 @@ class mod_attendance_structure { return null; } -} \ No newline at end of file +} diff --git a/db/install.xml b/db/install.xml index 0704227..5b8bf56 100644 --- a/db/install.xml +++ b/db/install.xml @@ -12,6 +12,8 @@ + + diff --git a/db/upgrade.php b/db/upgrade.php index ce819a3..405b08e 100644 --- a/db/upgrade.php +++ b/db/upgrade.php @@ -201,5 +201,18 @@ function xmldb_attendance_upgrade($oldversion=0) { upgrade_mod_savepoint(true, 2016112100, 'attendance'); } + if ($oldversion < 2016121300) { + $table = new xmldb_table('attendance'); + $field = new xmldb_field('sessiondetailspos', XMLDB_TYPE_CHAR, '5', null, null, null, 'left', 'subnet'); + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + $field = new xmldb_field('showsessiondetails', XMLDB_TYPE_INTEGER, '1', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '1', 'subnet'); + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + upgrade_mod_savepoint(true, 2016121300, 'attendance'); + } + return $result; -} \ No newline at end of file +} diff --git a/export.php b/export.php index 5dcd2ac..beba01b 100644 --- a/export.php +++ b/export.php @@ -122,6 +122,16 @@ if ($formdata = $mform->get_data()) { } else { print_error('sessionsnotfound', 'attendance', $att->url_manage()); } + + $setnumber = -1; + foreach ($reportdata->statuses as $sts) { + if ($sts->setnumber != $setnumber) { + $setnumber = $sts->setnumber; + } + + $data->tabhead[] = $sts->acronym; + } + $data->tabhead[] = get_string('takensessions', 'attendance'); $data->tabhead[] = get_string('points', 'attendance'); $data->tabhead[] = get_string('percentage', 'attendance'); @@ -158,6 +168,15 @@ if ($formdata = $mform->get_data()) { $data->table[$i] = array_merge($data->table[$i], $cellsgenerator->get_cells(isset($formdata->includeremarks))); $usersummary = $reportdata->summary->get_taken_sessions_summary_for($user->id); + + foreach ($reportdata->statuses as $sts) { + if (isset($usersummary->userstakensessionsbyacronym[$sts->setnumber][$sts->acronym])) { + $data->table[$i][] = $usersummary->userstakensessionsbyacronym[$sts->setnumber][$sts->acronym]; + } else { + $data->table[$i][] = 0; + } + } + $data->table[$i][] = $usersummary->numtakensessions; $data->table[$i][] = format_float($usersummary->takensessionspoints, 1, true, true) . ' / ' . format_float($usersummary->takensessionsmaxpoints, 1, true, true); diff --git a/lang/en/attendance.php b/lang/en/attendance.php index 69d072b..7d7fdce 100644 --- a/lang/en/attendance.php +++ b/lang/en/attendance.php @@ -26,6 +26,7 @@ $string['attendance:addinstance'] = 'Add a new attendance activity'; $string['Aacronym'] = 'A'; $string['adduser'] = 'Add user'; $string['Afull'] = 'Absent'; +$string['allsessions'] = 'All sessions'; $string['Eacronym'] = 'E'; $string['Efull'] = 'Excused'; $string['Lacronym'] = 'L'; @@ -127,6 +128,7 @@ $string['hiddensessions'] = 'Hidden sessions'; $string['hiddensessions_help'] = 'Sessions are hidden if they are scheduled before the course start date. You can use this feature to hide older sessions instead of deleting them. Only visible sessions will appear in the Gradebook.'; +$string['hidensessiondetails'] = 'Hide session details'; $string['identifyby'] = 'Identify student by'; $string['includeall'] = 'Select all sessions'; $string['includenottaken'] = 'Include not taken sessions'; @@ -135,6 +137,12 @@ $string['indetail'] = 'In detail...'; $string['invalidsessionenddate'] = 'This date can not be earlier than the session date'; $string['invalidaction'] = 'You must select an action'; $string['jumpto'] = 'Jump to'; +$string['maxpossible'] = 'Maximum possible'; +$string['maxpossible_help'] = 'Shows the maximum points and percentages that each user can reach if they receive the maximum points of each session not yet taken (past and future): +
    +
  • Points: maximum points each user can reach over all sessions.
  • +
  • Percentage: maximum percentage each user can reach over all sessions.
  • +
'; $string['maxpossiblepoints'] = 'Maximum possible points'; $string['maxpossiblepercentage'] = 'Maximum possible percentage'; $string['mergeuser'] = 'Merge user'; @@ -147,6 +155,8 @@ 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['moveleft'] = 'Move left'; +$string['moveright'] = 'Move right'; $string['mustselectusers'] = 'Must select users to export'; $string['myvariables'] = 'My Variables'; $string['newdate'] = 'New date'; @@ -249,6 +259,7 @@ $string['setallstatusesto'] = 'Set status for all users to «{$a}»'; $string['settings'] = 'Settings'; $string['showdefaults'] = 'Show defaults'; $string['showduration'] = 'Show duration'; +$string['showsessiondetails'] = 'Show session details'; $string['sortedgrid'] = 'Sorted grid'; $string['sortedlist'] = 'Sorted list'; $string['startofperiod'] = 'Start of period'; @@ -312,6 +323,20 @@ $string['submitattendance'] = 'Submit attendance'; $string['attendancenotset'] = 'You must set your attendance'; $string['export'] = 'Export'; $string['points'] = 'Points'; +$string['oversessionstaken'] = 'Over taken sessions'; +$string['oversessionstaken_help'] = 'Shows the points and percentages of each user over the taken sessions: +
    +
  • Sessions: number of already taken sessions.
  • +
  • Points: points due to each user based on the taken sessions.
  • +
  • Percentage: percentage of points due to each user over the maxium possible points of the taken sessions.
  • +
'; +$string['overallsessions'] = 'Over all sessions'; +$string['overallsessions_help'] = 'Shows the points and percentages of each user over all sessions including those not yet taken (past and future): +
    +
  • Sessions: total number of sessions.
  • +
  • Points: points due to each user based on all sessions.
  • +
  • Percentage: percentage of points due to each user over the maxium possible points of all sessions.
  • +
'; $string['pointssessionscompleted'] = 'Points over taken sessions'; $string['pointsallsessions'] = 'Points over all sessions'; $string['unknowngroup'] = 'Unknown group'; @@ -336,4 +361,4 @@ $string['deletedgroup'] = 'The group associated with this session has been delet $string['extrarestrictions'] = 'Extra restrictions'; $string['requiresubnet'] = 'Students can only record own attendance from these computers.'; $string['subnetwrong'] = 'Attendance can only be recorded from certain locations, and this computer is not on the allowed list.'; -$string['requiresubnet_help'] = 'Attendance recording may be restricted to particular subnets by specifying a comma-separated list of partial or full IP addresses.'; \ No newline at end of file +$string['requiresubnet_help'] = 'Attendance recording may be restricted to particular subnets by specifying a comma-separated list of partial or full IP addresses.'; diff --git a/renderer.php b/renderer.php index cba7e5c..315f536 100644 --- a/renderer.php +++ b/renderer.php @@ -622,12 +622,15 @@ class mod_attendance_renderer extends plugin_renderer_base { private function construct_fullname_head($data) { global $CFG; + $url = $data->url(); if ($data->pageparams->sort == ATT_SORT_LASTNAME) { - $firstname = html_writer::link($data->url(array('sort' => ATT_SORT_FIRSTNAME)), get_string('firstname')); + $url->param('sort', ATT_SORT_FIRSTNAME); + $firstname = html_writer::link($url, get_string('firstname')); $lastname = get_string('lastname'); } else if ($data->pageparams->sort == ATT_SORT_FIRSTNAME) { $firstname = get_string('firstname'); - $lastname = html_writer::link($data->url(array('sort' => ATT_SORT_LASTNAME)), get_string('lastname')); + $url->param('sort', ATT_SORT_LASTNAME); + $lastname = html_writer::link($url, get_string('lastname')); } else { $firstname = html_writer::link($data->url(array('sort' => ATT_SORT_FIRSTNAME)), get_string('firstname')); $lastname = html_writer::link($data->url(array('sort' => ATT_SORT_LASTNAME)), get_string('lastname')); @@ -846,175 +849,357 @@ class mod_attendance_renderer extends plugin_renderer_base { // Initilise Javascript used to (un)check all checkboxes. $this->page->requires->js_init_call('M.mod_attendance.init_manage'); - // Check if the user should be able to bulk send messages to other users on the course. - $bulkmessagecapability = has_capability('moodle/course:bulkmessaging', $PAGE->context); - $table = new html_table(); + $table->attributes['class'] = 'generaltable attwidth attreport'; - $table->attributes['class'] = 'generaltable attwidth'; + $userrows = $this->get_user_rows($reportdata); if ($reportdata->pageparams->view == ATT_VIEW_SUMMARY) { - $table->attributes['class'] .= ' summaryreport'; - } - - $colclass = null; - - // User picture. - $table->head[] = ''; - $table->align[] = 'left'; - $table->size[] = '1px'; - $table->colclasses[] = $colclass; - - $table->head[] = $this->construct_fullname_head($reportdata); - $table->align[] = 'left'; - $table->size[] = ''; - $table->colclasses[] = $colclass; - $sessionstats = array(); - - foreach ($reportdata->sessions as $sess) { - $sesstext = userdate($sess->sessdate, get_string('strftimedm', 'attendance')); - $sesstext .= html_writer::empty_tag('br'); - $sesstext .= userdate($sess->sessdate, '('.get_string('strftimehm', 'attendance').')'); - $capabilities = array( - 'mod/attendance:takeattendances', - 'mod/attendance:changeattendances' - ); - if (is_null($sess->lasttaken) and has_any_capability($capabilities, $reportdata->att->context)) { - $sesstext = html_writer::link($reportdata->url_take($sess->id, $sess->groupid), $sesstext); - } - $sesstext .= html_writer::empty_tag('br'); - if ($sess->groupid) { - if (empty($reportdata->groups[$sess->groupid])) { - $sesstext .= get_string('deletedgroup', 'attendance'); - } else { - $sesstext .= get_string('group') . ': ' . $reportdata->groups[$sess->groupid]->name; - } - - } else { - $sesstext .= get_string('commonsession', 'attendance'); - } - - $table->head[] = $sesstext; - $table->align[] = 'center'; - $table->size[] = '1px'; - $table->colclasses[] = $colclass; + $sessionrows = array(); + } else { + $sessionrows = $this->get_session_rows($reportdata); } $setnumber = -1; + $statusetcount = 0; foreach ($reportdata->statuses as $sts) { if ($sts->setnumber != $setnumber) { - $colclass = empty($colclass) ? 'columncontrast' : null; + $statusetcount++; $setnumber = $sts->setnumber; } - - $table->head[] = $sts->acronym; - $table->align[] = 'center'; - $table->size[] = '1px'; - $table->colclasses[] = $colclass; } - $table->head[] = get_string('takensessions', 'attendance'); - $table->align[] = 'center'; - $table->size[] = '1px'; - $colclass = empty($colclass) ? 'columncontrast' : null; - $table->colclasses[] = $colclass; + $acronymrows = $this->get_acronym_rows($reportdata, true); + $startwithcontrast = $statusetcount % 2 == 0; + $summaryrows = $this->get_summary_rows($reportdata, $startwithcontrast); - $table->head[] = get_string('points', 'attendance'); - $table->align[] = 'center'; - $table->size[] = '1px'; - $table->colclasses[] = $colclass; + // Check if the user should be able to bulk send messages to other users on the course. + $bulkmessagecapability = has_capability('moodle/course:bulkmessaging', $PAGE->context); + if ($bulkmessagecapability) { + $bulkmessagingrows = $this->get_bulkmessage_rows($reportdata); + } - $table->head[] = get_string('percentage', 'attendance'); - $table->align[] = 'center'; - $table->size[] = '1px'; - $table->colclasses[] = $colclass; + // Extract rows from each part and collate them into one row each. + $sessiondetailsleft = $reportdata->pageparams->sessiondetailspos == 'left'; + foreach ($userrows as $index => $row) { + $summaryrow = isset($summaryrows[$index]->cells) ? $summaryrows[$index]->cells : array(); + $bulkmessagingrow = isset($bulkmessagingrows[$index]->cells) ? $bulkmessagingrows[$index]->cells : array(); + $sessionrow = isset($sessionrows[$index]->cells) ? $sessionrows[$index]->cells : array(); + if ($sessiondetailsleft) { + $row->cells = array_merge($row->cells, $sessionrow, $acronymrows[$index]->cells, $summaryrow, $bulkmessagingrow); + } else { + $row->cells = array_merge($row->cells, $acronymrows[$index]->cells, $summaryrow, $sessionrow, $bulkmessagingrow); + } + $table->data[] = $row; + } - if ($reportdata->pageparams->view == ATT_VIEW_SUMMARY) { - $table->head[] = get_string('sessionstotal', 'attendance'); - $table->align[] = 'center'; - $table->size[] = '1px'; - $colclass = empty($colclass) ? 'columncontrast' : null; - $table->colclasses[] = $colclass; + if ($bulkmessagecapability) { // Require that the user can bulk message users. + // Display check boxes that will allow the user to send a message to the students that have been checked. + $output = html_writer::empty_tag('input', array('name' => 'sesskey', 'type' => 'hidden', 'value' => sesskey())); + $output .= html_writer::empty_tag('input', array('name' => 'formaction', 'type' => 'hidden', + 'value' => 'messageselect.php')); + $output .= html_writer::empty_tag('input', array('name' => 'id', 'type' => 'hidden', 'value' => $COURSE->id)); + $output .= html_writer::empty_tag('input', array('name' => 'returnto', 'type' => 'hidden', 'value' => s(me()))); + $output .= html_writer::table($table).html_writer::tag('div', get_string('users').': '.count($reportdata->users));; + $output .= html_writer::tag('div', + html_writer::empty_tag('input', array('type' => 'submit', 'value' => get_string('messageselectadd'))), + array('class' => 'buttons')); + $url = new moodle_url('/user/action_redir.php'); + return html_writer::tag('form', $output, array('action' => $url->out(), 'method' => 'post')); + } else { + return html_writer::table($table).html_writer::tag('div', get_string('users').': '.count($reportdata->users)); + } + } - $table->head[] = get_string('pointsallsessions', 'attendance'); - $table->align[] = 'center'; - $table->size[] = '1px'; - $table->colclasses[] = $colclass; + /** + * Build and return the rows that will make up the left part of the attendance report. + * This consists of student names and icons, as well as header cells for these columns. + * + * @param attendance_report_data $reportdata the report data + * @return array Array of html_table_row objects + */ + protected function get_user_rows(attendance_report_data $reportdata) { + $rows = array(); - $table->head[] = get_string('percentageallsessions', 'attendance'); - $table->align[] = 'center'; - $table->size[] = '1px'; - $table->colclasses[] = $colclass; + $row = new html_table_row(); + $row->cells[] = $this->build_header_cell(''); + $row->cells[] = $this->build_header_cell(get_string('users'), false, false); + $rows[] = $row; - $table->head[] = get_string('maxpossiblepoints', 'attendance'); - $table->align[] = 'center'; - $table->size[] = '1px'; - $colclass = empty($colclass) ? 'columncontrast' : null; - $table->colclasses[] = $colclass; + $row = new html_table_row(); + $row->cells[] = $this->build_header_cell(''); + $row->cells[] = $this->build_header_cell($this->construct_fullname_head($reportdata), false, false); + $rows[] = $row; - $table->head[] = get_string('maxpossiblepercentage', 'attendance'); - $table->align[] = 'center'; - $table->size[] = '1px'; - $table->colclasses[] = $colclass; + foreach ($reportdata->users as $user) { + $row = new html_table_row(); + $row->cells[] = $this->build_data_cell($this->user_picture($user)); + $text = html_writer::link($reportdata->url_view(array('studentid' => $user->id)), fullname($user)); + $row->cells[] = $this->build_data_cell($text, false, false, null, null, false); + $rows[] = $row; } - if ($bulkmessagecapability) { // Display the table header for bulk messaging. - // The checkbox must have an id of cb_selector so that the JavaScript will pick it up. - $table->head[] = html_writer::checkbox('cb_selector', 0, false, '', array('id' => 'cb_selector')); - $table->align[] = 'center'; - $table->size[] = '1px'; - } + $row = new html_table_row(); + $row->cells[] = $this->build_data_cell(''); + $text = ($reportdata->pageparams->view == ATT_VIEW_SUMMARY) ? '' : get_string('summary'); + $row->cells[] = $this->build_data_cell($text); + $rows[] = $row; - foreach ($reportdata->users as $user) { - $row = new html_table_row(); + return $rows; + } + + /** + * Build and return the rows that will make up the summary part of the attendance report. + * This consists of countings for each status set acronyms, as well as header cells for these columns. + * + * @param attendance_report_data $reportdata the report data + * @param boolean $startwithcontrast true if the first column must start with contrast (bgcolor) + * @return array Array of html_table_row objects + */ + protected function get_acronym_rows(attendance_report_data $reportdata, $startwithcontrast=false) { + $rows = array(); + + $summarycells = array(); - $row->cells[] = $this->user_picture($user); // Show different picture if it is a temporary user. - $row->cells[] = html_writer::link($reportdata->url_view(array('studentid' => $user->id)), fullname($user)); - $cellsgenerator = new user_sessions_cells_html_generator($reportdata, $user); - $row->cells = array_merge($row->cells, $cellsgenerator->get_cells(true)); + $row1 = new html_table_row(); + $row2 = new html_table_row(); + $setnumber = -1; + $contrast = !$startwithcontrast; + foreach ($reportdata->statuses as $sts) { + if ($sts->setnumber != $setnumber) { + $contrast = !$contrast; + $setnumber = $sts->setnumber; + $text = attendance_get_setname($reportdata->att->id, $setnumber, false); + $cell = $this->build_header_cell($text, $contrast); + $row1->cells[] = $cell; + } + $cell->colspan++; + $sts->contrast = $contrast; + $row2->cells[] = $this->build_header_cell($sts->acronym, $contrast); + $summarycells[] = $this->build_data_cell('', $contrast); + } + + $rows[] = $row1; + $rows[] = $row2; + + foreach ($reportdata->users as $user) { if ($reportdata->pageparams->view == ATT_VIEW_SUMMARY) { $usersummary = $reportdata->summary->get_all_sessions_summary_for($user->id); } else { $usersummary = $reportdata->summary->get_taken_sessions_summary_for($user->id); } + $row = new html_table_row(); foreach ($reportdata->statuses as $sts) { if (isset($usersummary->userstakensessionsbyacronym[$sts->setnumber][$sts->acronym])) { - $row->cells[] = $usersummary->userstakensessionsbyacronym[$sts->setnumber][$sts->acronym]; + $text = $usersummary->userstakensessionsbyacronym[$sts->setnumber][$sts->acronym]; } else { - $row->cells[] = 0; + $text = 0; } + $row->cells[] = $this->build_data_cell($text, $sts->contrast); + } + + $rows[] = $row; + } + + $rows[] = new html_table_row($summarycells); + + return $rows; + } + + /** + * Build and return the rows that will make up the summary part of the attendance report. + * This consists of counts and percentages for taken sessions (all sessions for summary report), + * as well as header cells for these columns. + * + * @param attendance_report_data $reportdata the report data + * @param boolean $startwithcontrast true if the first column must start with contrast (bgcolor) + * @return array Array of html_table_row objects + */ + protected function get_summary_rows(attendance_report_data $reportdata, $startwithcontrast=false) { + $rows = array(); + + $contrast = $startwithcontrast; + $summarycells = array(); + + $row1 = new html_table_row(); + $helpicon = $this->output->help_icon('oversessionstaken', 'attendance'); + $row1->cells[] = $this->build_header_cell(get_string('oversessionstaken', 'attendance') . $helpicon, $contrast, true, 3); + + $row2 = new html_table_row(); + $row2->cells[] = $this->build_header_cell(get_string('sessions', 'attendance'), $contrast); + $row2->cells[] = $this->build_header_cell(get_string('points', 'attendance'), $contrast); + $row2->cells[] = $this->build_header_cell(get_string('percentage', 'attendance'), $contrast); + $summarycells[] = $this->build_data_cell('', $contrast); + $summarycells[] = $this->build_data_cell('', $contrast); + $summarycells[] = $this->build_data_cell('', $contrast); + + if ($reportdata->pageparams->view == ATT_VIEW_SUMMARY) { + $contrast = !$contrast; + + $helpicon = $this->output->help_icon('overallsessions', 'attendance'); + $row1->cells[] = $this->build_header_cell(get_string('overallsessions', 'attendance') . $helpicon, $contrast, true, 3); + + $row2->cells[] = $this->build_header_cell(get_string('sessions', 'attendance'), $contrast); + $row2->cells[] = $this->build_header_cell(get_string('points', 'attendance'), $contrast); + $row2->cells[] = $this->build_header_cell(get_string('percentage', 'attendance'), $contrast); + $summarycells[] = $this->build_data_cell('', $contrast); + $summarycells[] = $this->build_data_cell('', $contrast); + $summarycells[] = $this->build_data_cell('', $contrast); + + $contrast = !$contrast; + $helpicon = $this->output->help_icon('maxpossible', 'attendance'); + $row1->cells[] = $this->build_header_cell(get_string('maxpossible', 'attendance') . $helpicon, $contrast, true, 2); + + $row2->cells[] = $this->build_header_cell(get_string('points', 'attendance'), $contrast); + $row2->cells[] = $this->build_header_cell(get_string('percentage', 'attendance'), $contrast); + $summarycells[] = $this->build_data_cell('', $contrast); + $summarycells[] = $this->build_data_cell('', $contrast); + } + + $rows[] = $row1; + $rows[] = $row2; + + foreach ($reportdata->users as $user) { + if ($reportdata->pageparams->view == ATT_VIEW_SUMMARY) { + $usersummary = $reportdata->summary->get_all_sessions_summary_for($user->id); + } else { + $usersummary = $reportdata->summary->get_taken_sessions_summary_for($user->id); } - $row->cells[] = $usersummary->numtakensessions; - $row->cells[] = format_float($usersummary->takensessionspoints, 1, true, true) . ' / ' . + $contrast = $startwithcontrast; + $row = new html_table_row(); + $row->cells[] = $this->build_data_cell($usersummary->numtakensessions, $contrast); + $text = format_float($usersummary->takensessionspoints, 1, true, true) . ' / ' . format_float($usersummary->takensessionsmaxpoints, 1, true, true); - $row->cells[] = format_float($usersummary->takensessionspercentage * 100) . '%'; + $row->cells[] = $this->build_data_cell($text, $contrast); + $row->cells[] = $this->build_data_cell(format_float($usersummary->takensessionspercentage * 100) . '%', $contrast); if ($reportdata->pageparams->view == ATT_VIEW_SUMMARY) { - $row->cells[] = $usersummary->numallsessions; - $row->cells[] = format_float($usersummary->takensessionspoints, 1, true, true) . ' / ' . + $contrast = !$contrast; + $row->cells[] = $this->build_data_cell($usersummary->numallsessions, $contrast); + $text = format_float($usersummary->takensessionspoints, 1, true, true) . ' / ' . format_float($usersummary->allsessionsmaxpoints, 1, true, true); - $row->cells[] = format_float($usersummary->allsessionspercentage * 100) . '%'; + $row->cells[] = $this->build_data_cell($text, $contrast); + $row->cells[] = $this->build_data_cell(format_float($usersummary->allsessionspercentage * 100) . '%', $contrast); - $row->cells[] = format_float($usersummary->maxpossiblepoints, 1, true, true) . ' / ' . + $contrast = !$contrast; + $text = format_float($usersummary->maxpossiblepoints, 1, true, true) . ' / ' . format_float($usersummary->allsessionsmaxpoints, 1, true, true); - $row->cells[] = format_float($usersummary->maxpossiblepercentage * 100) . '%'; + $row->cells[] = $this->build_data_cell($text, $contrast); + $row->cells[] = $this->build_data_cell(format_float($usersummary->maxpossiblepercentage * 100) . '%', $contrast); } - if ($bulkmessagecapability) { // Create the checkbox for bulk messaging. - $row->cells[] = html_writer::checkbox('user'.$user->id, 'on', false, '', - array('class' => 'attendancesesscheckbox')); + $rows[] = $row; + } + + $rows[] = new html_table_row($summarycells); + + return $rows; + } + + /** + * Build and return the rows that will make up the attendance report. + * This consists of details for each selected session, as well as header and summary cells for these columns. + * + * @param attendance_report_data $reportdata the report data + * @param boolean $startwithcontrast true if the first column must start with contrast (bgcolor) + * @return array Array of html_table_row objects + */ + protected function get_session_rows(attendance_report_data $reportdata, $startwithcontrast=false) { + global $OUTPUT; + + $rows = array(); + + $row = new html_table_row(); + + $showsessiondetails = $reportdata->pageparams->showsessiondetails; + $text = get_string('sessions', 'attendance'); + $params = $reportdata->pageparams->get_significant_params(); + if (count($reportdata->sessions) > 1) { + if ($showsessiondetails) { + $params['showsessiondetails'] = 0; + $url = $reportdata->att->url_report($params); + $text .= $OUTPUT->action_icon($url, new pix_icon('t/switch_minus', + get_string('hidensessiondetails', 'attendance')), null, null); + $colspan = count($reportdata->sessions); + } else { + $params['showsessiondetails'] = 1; + $url = $reportdata->att->url_report($params); + $text .= $OUTPUT->action_icon($url, new pix_icon('t/switch_plus', + get_string('showsessiondetails', 'attendance')), null, null); + $colspan = 1; } + } else { + $colspan = 1; + } - $table->data[] = $row; + $params = $reportdata->pageparams->get_significant_params(); + if ($reportdata->pageparams->sessiondetailspos == 'left') { + $params['sessiondetailspos'] = 'right'; + $url = $reportdata->att->url_report($params); + $text .= $OUTPUT->action_icon($url, new pix_icon('t/right', get_string('moveright', 'attendance')), null, null); + } else { + $params['sessiondetailspos'] = 'left'; + $url = $reportdata->att->url_report($params); + $text = $OUTPUT->action_icon($url, new pix_icon('t/left', get_string('moveleft', 'attendance')), null, null) . $text; + } + + $row->cells[] = $this->build_header_cell($text, '', true, $colspan); + $rows[] = $row; + + $row = new html_table_row(); + if ($showsessiondetails && !empty($reportdata->sessions)) { + foreach ($reportdata->sessions as $sess) { + $sesstext = userdate($sess->sessdate, get_string('strftimedm', 'attendance')); + $sesstext .= html_writer::empty_tag('br'); + $sesstext .= userdate($sess->sessdate, '('.get_string('strftimehm', 'attendance').')'); + $capabilities = array( + 'mod/attendance:takeattendances', + 'mod/attendance:changeattendances' + ); + if (is_null($sess->lasttaken) and has_any_capability($capabilities, $reportdata->att->context)) { + $sesstext = html_writer::link($reportdata->url_take($sess->id, $sess->groupid), $sesstext); + } + $sesstext .= html_writer::empty_tag('br'); + if ($sess->groupid) { + if (empty($reportdata->groups[$sess->groupid])) { + $sesstext .= html_writer::tag('small', get_string('deletedgroup', 'attendance')); + } else { + $sesstext .= html_writer::tag('small', $reportdata->groups[$sess->groupid]->name); + } + + } else { + $sesstext .= html_writer::tag('small', get_string('commonsession', 'attendance')); + } + + $row->cells[] = $this->build_header_cell($sesstext, false, true, null, null, false); + } + } else { + $row->cells[] = $this->build_header_cell(''); } + $rows[] = $row; - if ($reportdata->pageparams->view != ATT_VIEW_SUMMARY) { - // Calculate the sum of statuses for each user. - $statrow = new html_table_row(); - $statrow->cells[] = ''; - $statrow->cells[] = get_string('summary'); + foreach ($reportdata->users as $user) { + $row = new html_table_row(); + if ($showsessiondetails && !empty($reportdata->sessions)) { + $cellsgenerator = new user_sessions_cells_html_generator($reportdata, $user); + foreach ($cellsgenerator->get_cells(true) as $cell) { + if ($cell instanceof html_table_cell) { + $cell->attributes['class'] .= ' center'; + $row->cells[] = $cell; + } else { + $row->cells[] = $this->build_data_cell($cell); + } + } + } else { + $row->cells[] = $this->build_data_cell(''); + } + $rows[] = $row; + } + + $row = new html_table_row(); + if ($showsessiondetails && !empty($reportdata->sessions)) { foreach ($reportdata->sessions as $sess) { $sessionstats = array(); foreach ($reportdata->statuses as $status) { @@ -1037,36 +1222,143 @@ class mod_attendance_renderer extends plugin_renderer_base { foreach ($sessionstats as $status) { $statsoutput .= "$status->description: {$status->count}
"; } - $cell = new html_table_cell($statsoutput); - $cell->style = 'white-space:nowrap;'; - $statrow->cells[] = $cell; + $row->cells[] = $this->build_data_cell($statsoutput); } - foreach ($reportdata->statuses as $sts) { - $statrow->cells[] = ''; - } - $statrow->cells[] = ''; - $statrow->cells[] = ''; - $statrow->cells[] = ''; - $statrow->cells[] = ''; - $table->data[] = $statrow; + } else { + $row->cells[] = $this->build_header_cell(''); } + $rows[] = $row; - if ($bulkmessagecapability) { // Require that the user can bulk message users. - // Display check boxes that will allow the user to send a message to the students that have been checked. - $output = html_writer::empty_tag('input', array('name' => 'sesskey', 'type' => 'hidden', 'value' => sesskey())); - $output .= html_writer::empty_tag('input', array('name' => 'formaction', 'type' => 'hidden', - 'value' => 'messageselect.php')); - $output .= html_writer::empty_tag('input', array('name' => 'id', 'type' => 'hidden', 'value' => $COURSE->id)); - $output .= html_writer::empty_tag('input', array('name' => 'returnto', 'type' => 'hidden', 'value' => s(me()))); - $output .= html_writer::table($table).html_writer::tag('div', get_string('users').': '.count($reportdata->users));; - $output .= html_writer::tag('div', - html_writer::empty_tag('input', array('type' => 'submit', 'value' => get_string('messageselectadd'))), - array('class' => 'buttons')); - $url = new moodle_url('/user/action_redir.php'); - return html_writer::tag('form', $output, array('action' => $url->out(), 'method' => 'post')); + return $rows; + } + + /** + * Build and return the rows that will make up the right part of the attendance report. + * This consists of checkbox column for bulk message. + * + * @param attendance_report_data $reportdata the report data + * @return array Array of html_table_row objects + */ + protected function get_bulkmessage_rows(attendance_report_data $reportdata) { + $rows = array(); + + $row = new html_table_row(); + $row->cells[] = $this->build_header_cell(''); + $rows[] = $row; + + // Display the table header for bulk messaging. + // The checkbox must have an id of cb_selector so that the JavaScript will pick it up. + $row = new html_table_row(); + $text = html_writer::checkbox('cb_selector', 0, false, '', array('id' => 'cb_selector')); + $row->cells[] = $this->build_header_cell($text); + $rows[] = $row; + + foreach ($reportdata->users as $user) { + // Create the checkbox for bulk messaging. + $row = new html_table_row(); + $text = html_writer::checkbox('user'.$user->id, 'on', false, '', array('class' => 'attendancesesscheckbox')); + $row->cells[] = $this->build_data_cell($text); + $rows[] = $row; + } + + $row = new html_table_row(); + $row->cells[] = $this->build_data_cell(''); + $rows[] = $row; + + return $rows; + } + + /** + * Build and return a html_table_cell for header rows + * + * @param Mixed (html_table_cell or string) $cell the cell or a label for a cell + * @param boolean $contrast true menans the cell must be shown with bgcolor contrast + * @param boolean $center true means the cell text should be centered. Othersiwe it should be left-aligned. + * @param int $colspan how many columns should cell spans + * @param int $rowspan how many rows should cell spans + * @param boolean $nowrap true means the cell text must be shown with nowrap option + * @return html_table_cell a html table cell + */ + protected function build_header_cell($cell, $contrast=false, $center=true, $colspan=null, $rowspan=null, $nowrap=true) { + $classes = array('header', 'bottom'); + if ($center) { + $classes[] = 'center'; + $classes[] = 'narrow'; } else { - return html_writer::table($table).html_writer::tag('div', get_string('users').': '.count($reportdata->users)); + $classes[] = 'left'; + } + if ($contrast) { + $classes[] = 'contrast'; } + if ($nowrap) { + $classes[] = 'nowrap'; + } + return $this->build_cell($cell, $classes, $colspan, $rowspan, true); + } + + /** + * Build and return a html_table_cell for data rows + * + * @param Mixed (html_table_cell or string) $cell the cell or a label for a cell + * @param boolean $contrast true menans the cell must be shown with bgcolor contrast + * @param boolean $center true means the cell text should be centered. Othersiwe it should be left-aligned. + * @param int $colspan how many columns should cell spans + * @param int $rowspan how many rows should cell spans + * @param boolean $nowrap true means the cell text must be shown with nowrap option + * @return html_table_cell a html table cell + */ + protected function build_data_cell($cell, $contrast=false, $center=true, $colspan=null, $rowspan=null, $nowrap=true) { + $classes = array(); + if ($center) { + $classes[] = 'center'; + $classes[] = 'narrow'; + } else { + $classes[] = 'left'; + } + if ($nowrap) { + $classes[] = 'nowrap'; + } + if ($contrast) { + $classes[] = 'contrast'; + } + return $this->build_cell($cell, $classes, $colspan, $rowspan, false); + } + + /** + * Build and return a html_table_cell for header or data rows + * + * @param Mixed (html_table_cell or string) $cell the cell or a label for a cell + * @param Array $classes a list of css classes + * @param int $colspan how many columns should cell spans + * @param int $rowspan how many rows should cell spans + * @param boolean $header true if this should be a header cell + * @return html_table_cell a html table cell + */ + protected function build_cell($cell, $classes, $colspan=null, $rowspan=null, $header=false) { + if (!($cell instanceof html_table_cell)) { + $cell = new html_table_cell($cell); + } + $cell->header = $header; + $cell->scope = 'col'; + + if (!empty($colspan) && $colspan > 1) { + $cell->colspan = $colspan; + } + + if (!empty($rowspan) && $rowspan > 1) { + $cell->rowspan = $rowspan; + } + + if (!empty($classes)) { + $classes = implode(' ', $classes); + if (empty($cell->attributes['class'])) { + $cell->attributes['class'] = $classes; + } else { + $cell->attributes['class'] .= ' ' . $classes; + } + } + + return $cell; } /** diff --git a/report.php b/report.php index 4a84f9f..d98f437 100644 --- a/report.php +++ b/report.php @@ -46,6 +46,9 @@ $context = context_module::instance($cm->id); require_capability('mod/attendance:viewreports', $context); $pageparams->init($cm); +$pageparams->showsessiondetails = optional_param('showsessiondetails', $attrecord->showsessiondetails, PARAM_INT); +$pageparams->sessiondetailspos = optional_param('sessiondetailspos', $attrecord->sessiondetailspos, PARAM_TEXT); + $att = new mod_attendance_structure($attrecord, $cm, $course, $context, $pageparams); $PAGE->set_url($att->url_report()); diff --git a/styles.css b/styles.css index 6966546..7e7782d 100644 --- a/styles.css +++ b/styles.css @@ -163,6 +163,26 @@ color: red; } -.path-mod-attendance .columncontrast { +.path-mod-attendance .attreport .contrast { background-color: #EAEAEA; } + +.path-mod-attendance .attreport .center { + text-align:center; +} + +.path-mod-attendance .attreport .left { + text-align:left; +} + +.path-mod-attendance .attreport .bottom { + vertical-align:bottom; +} + +.path-mod-attendance .attreport .nowrap { + white-space:nowrap; +} + +.path-mod-attendance .attreport .narrow { + width:1px; +} diff --git a/tests/behat/attendance_mod.feature b/tests/behat/attendance_mod.feature index aa3ad98..1204a8e 100644 --- a/tests/behat/attendance_mod.feature +++ b/tests/behat/attendance_mod.feature @@ -14,19 +14,22 @@ Feature: Teachers and Students can record session attendance Background: Given the following "courses" exist: - | fullname | shortname | summary | category | - | Course 1 | C101 | Prove the attendance activity works | 0 | + | fullname | shortname | summary | category | timecreated | timemodified | + | Course 1 | C1 | Prove the attendance activity works | 0 | ##yesterday## | ##yesterday## | And the following "users" exist: | username | firstname | lastname | email | idnumber | department | institution | | student1 | Sam | Student | student1@asd.com | 1234 | computer science | University of Nottingham | | teacher1 | Teacher | One | teacher1@asd.com | 5678 | computer science | University of Nottingham | And the following "course enrolments" exist: - | user | course | role | - | student1 | C101 | student | - | teacher1 | C101 | editingteacher | + | course | user | role | timestart | + | C1 | student1 | student | ##yesterday## | + | C1 | teacher1 | editingteacher | ##yesterday## | + When I log in as "teacher1" And I follow "Course 1" And I turn editing mode on + And I follow "Add a block" + And I follow "Administration" And I add a "Attendance" to section "1" and I fill the form with: | Name | Attendance | And I log out @@ -76,6 +79,7 @@ Feature: Teachers and Students can record session attendance And I click on "Send a message" "button" Then I should see "Message body" And I should see "student1@asd.com" + And I follow "Course 1" And I expand "Reports" node And I follow "Logs" And I click on "Get these logs" "button" diff --git a/tests/behat/calendar_features.feature b/tests/behat/calendar_features.feature index 80d59f8..8be1af4 100644 --- a/tests/behat/calendar_features.feature +++ b/tests/behat/calendar_features.feature @@ -3,16 +3,17 @@ Feature: Test the calendar related features in the attendance module Background: Given the following "courses" exist: - | fullname | shortname | - | Course 1 | C1 | + | fullname | shortname | summary | category | timecreated | timemodified | + | Course 1 | C1 | Prove the attendance activity works | 0 | ##yesterday## | ##yesterday## | And the following "users" exist: | username | firstname | lastname | email | | teacher1 | Teacher | 1 | teacher1@example.com | | student1 | Student | 1 | student1@example.com | And the following "course enrolments" exist: - | course | user | role | - | C1 | teacher1 | editingteacher | - | C1 | student1 | student | + | course | user | role | timestart | + | C1 | student1 | student | ##yesterday## | + | C1 | teacher1 | editingteacher | ##yesterday## | + And I log in as "teacher1" And I follow "Course 1" And I turn editing mode on @@ -36,4 +37,4 @@ Feature: Test the calendar related features in the attendance module And I log out And I log in as "student1" And I follow "Go to calendar" - Then I should see "Test attendance" \ No newline at end of file + Then I should see "Test attendance" diff --git a/tests/behat/extra_features.feature b/tests/behat/extra_features.feature index 93280fb..51333be 100644 --- a/tests/behat/extra_features.feature +++ b/tests/behat/extra_features.feature @@ -3,8 +3,8 @@ Feature: Test the various new features in the attendance module Background: Given the following "courses" exist: - | fullname | shortname | - | Course 1 | C1 | + | fullname | shortname | summary | category | timecreated | timemodified | + | Course 1 | C1 | Prove the attendance activity works | 0 | ##yesterday## | ##yesterday## | And the following "users" exist: | username | firstname | lastname | email | | teacher1 | Teacher | 1 | teacher1@example.com | @@ -14,11 +14,12 @@ Feature: Test the various new features in the attendance module | student4 | Student | 4 | student4@example.com | | student5 | Student | 5 | student5@example.com | And the following "course enrolments" exist: - | course | user | role | - | C1 | teacher1 | editingteacher | - | C1 | student1 | student | - | C1 | student2 | student | - | C1 | student3 | student | + | course | user | role | timestart | + | C1 | teacher1 | editingteacher | ##yesterday## | + | C1 | student1 | student | ##yesterday## | + | C1 | student2 | student | ##yesterday## | + | C1 | student3 | student | ##yesterday## | + And I log in as "teacher1" And I follow "Course 1" And I turn editing mode on diff --git a/tests/behat/preferences.feature b/tests/behat/preferences.feature index 54e4ac5..dfef092 100644 --- a/tests/behat/preferences.feature +++ b/tests/behat/preferences.feature @@ -6,16 +6,17 @@ Feature: Teachers can't change status variables to have empty acronyms or descri Background: Given the following "courses" exist: - | fullname | shortname | summary | category | - | Course 1 | C101 | Prove the attendance activity settings works | 0 | + | fullname | shortname | summary | category | timecreated | timemodified | + | Course 1 | C1 | Prove the attendance activity works | 0 | ##yesterday## | ##yesterday## | And the following "users" exist: | username | firstname | lastname | | student1 | Sam | Student | | teacher1 | Teacher | One | And the following "course enrolments" exist: - | user | course | role | - | student1 | C101 | student | - | teacher1 | C101 | editingteacher | + | course | user | role | timestart | + | C1 | student1 | student | ##yesterday## | + | C1 | teacher1 | editingteacher | ##yesterday## | + And I log in as "teacher1" And I follow "Course 1" And I turn editing mode on diff --git a/tests/behat/report.feature b/tests/behat/report.feature index 58fdbb6..48a25bf 100644 --- a/tests/behat/report.feature +++ b/tests/behat/report.feature @@ -4,23 +4,25 @@ Feature: Visiting reports Background: Given the following "courses" exist: - | fullname | shortname | summary | category | - | Course 1 | C101 | Prove the attendance activity works | 0 | + | fullname | shortname | summary | category | timecreated | timemodified | + | Course 1 | C1 | Prove the attendance activity works | 0 | ##yesterday## | ##yesterday## | And the following "users" exist: | username | firstname | lastname | email | idnumber | department | institution | | student1 | Student | 1 | student1@asd.com | 1234 | computer science | University of Nottingham | | teacher1 | Teacher | 1 | teacher1@asd.com | 5678 | computer science | University of Nottingham | And the following "course enrolments" exist: - | user | course | role | - | student1 | C101 | student | - | teacher1 | C101 | editingteacher | + | course | user | role | timestart | + | C1 | student1 | student | ##yesterday## | + | C1 | teacher1 | editingteacher | ##yesterday## | And I log in as "teacher1" And I follow "Course 1" And I turn editing mode on - And I add a "Attendance" to section "1" and I fill the form with: - | Name | Attendance | + And I add a "Attendance" to section "1" and I fill the form with: + | Name | Attendance | And I follow "Attendance" + And I follow "Add a block" + And I follow "Administration" And I follow "Add session" And I set the following fields to these values: | id_sestime_starthour | 01 | @@ -99,7 +101,7 @@ Feature: Visiting reports Scenario: Teacher take attendance of group session Given the following "groups" exist: | course | name | idnumber | - | C101 | Group1 | Group1 | + | C1 | Group1 | Group1 | And the following "group members" exist: | group | user | | Group1 | student1 | @@ -136,8 +138,8 @@ Feature: Visiting reports And I press "Save attendance" When I follow "Report" - Then "Student 1" row "Points" column of "generaltable" table should contain "3 / 4" - And "Student 1" row "Percentage" column of "generaltable" table should contain "75.0%" + Then "3 / 4" "text" should exist in the "Student 1" "table_row" + And "75.0%" "text" should exist in the "Student 1" "table_row" When I follow "Grades" in the user menu And I follow "Course 1" @@ -181,11 +183,11 @@ Feature: Visiting reports When I follow "Report" And I click on "Summary" "link" in the "All" "table_row" - Then "Student 1" row "Total number of sessions" column of "generaltable" table should contain "3" - And "Student 1" row "Points over all sessions" column of "generaltable" table should contain "3 / 6" - And "Student 1" row "Percentage over all sessions" column of "generaltable" table should contain "50.0%" - And "Student 1" row "Maximum possible points" column of "generaltable" table should contain "5 / 6" - And "Student 1" row "Maximum possible percentage" column of "generaltable" table should contain "83.3%" + + Then "3 / 6" "text" should exist in the "Student 1" "table_row" + And "50.0%" "text" should exist in the "Student 1" "table_row" + And "5 / 6" "text" should exist in the "Student 1" "table_row" + And "83.3%" "text" should exist in the "Student 1" "table_row" And I log out @@ -194,7 +196,7 @@ Feature: Visiting reports And I follow "Course 1" And I follow "Attendance" And I follow "Edit settings" - And I set the following fields to these values: + Then I set the following fields to these values: | id_grade_modgrade_type | Point | | id_grade_modgrade_point | 50 | And I press "Save and display" diff --git a/version.php b/version.php index 68c9d3c..9913c3b 100644 --- a/version.php +++ b/version.php @@ -23,9 +23,9 @@ */ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2016113001; +$plugin->version = 2016121300; $plugin->requires = 2016111800; $plugin->release = '3.2.2'; $plugin->maturity = MATURITY_STABLE; $plugin->cron = 0; -$plugin->component = 'mod_attendance'; \ No newline at end of file +$plugin->component = 'mod_attendance';