mirror of
https://github.com/moodle/moodle.git
synced 2025-04-19 07:25:30 +02:00
MDL-52661 gradingform_gudie: Accessibility fixes for marking guide
This commit is contained in:
parent
ef343c3299
commit
fb43a326c2
1
grade/grading/form/guide/amd/build/comment_chooser.min.js
vendored
Normal file
1
grade/grading/form/guide/amd/build/comment_chooser.min.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
define(["jquery","core/templates","core/notification","core/yui"],function(a,b,c){return{initialise:function(d,e,f,g){function h(b,c){var e="<label>"+M.util.get_string("insertcomment","gradingform_guide")+"</label>",g="comment-chooser-"+d+"-cancel",h='<button id="'+g+'">'+M.util.get_string("cancel","moodle")+"</button>";"undefined"==typeof j&&(j=new M.core.dialogue({modal:!0,headerContent:e,bodyContent:b,footerContent:h,focusAfterHide:"#"+f,id:"comments-chooser-dialog-"+d}),a("#"+g).click(function(){"undefined"!=typeof j&&j.hide()}),a.each(c,function(b,c){var e="#comment-option-"+d+"-"+c.id;a(e).click(function(){var b=a("#"+f),d=b.val();""!==a.trim(d)&&(d+="\n"),d+=c.description,b.val(d),"undefined"!=typeof j&&j.hide()}),a(document).off("keypress",e).on("keypress",e,function(){var b=event.which||event.keyCode;(13==b||32==b)&&a(e).click()})})),j.show()}function i(){var a={criterionId:d,comments:g};b.render("gradingform_guide/comment_chooser",a).done(function(a){h(a,g)}).fail(c.exception)}var j;a("#"+e).click(function(a){a.preventDefault(),i()})}}});
|
139
grade/grading/form/guide/amd/src/comment_chooser.js
Normal file
139
grade/grading/form/guide/amd/src/comment_chooser.js
Normal file
@ -0,0 +1,139 @@
|
||||
// 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/>.
|
||||
|
||||
/**
|
||||
* AMD code for the frequently used comments chooser for the marking guide grading form.
|
||||
*
|
||||
* @module gradingform_guide/comment_chooser
|
||||
* @class comment_chooser
|
||||
* @package core
|
||||
* @copyright 2015 Jun Pataleta <jun@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
define(['jquery', 'core/templates', 'core/notification', 'core/yui'], function ($, templates, notification) {
|
||||
|
||||
// Private variables and functions.
|
||||
|
||||
return /** @alias module:gradingform_guide/comment_chooser */ {
|
||||
// Public variables and functions.
|
||||
/**
|
||||
* Initialises the module.
|
||||
*
|
||||
* Basically, it performs the binding and handling of the button click event for
|
||||
* the 'Insert frequently used comment' button.
|
||||
*
|
||||
* @param criterionId The criterion ID.
|
||||
* @param buttonId The element ID of the button which the handler will be bound to.
|
||||
* @param remarkId The element ID of the remark text area where the text of the selected comment will be copied to.
|
||||
* @param commentOptions The array of frequently used comments to be used as options.
|
||||
*/
|
||||
initialise: function (criterionId, buttonId, remarkId, commentOptions) {
|
||||
var chooserDialog;
|
||||
|
||||
/**
|
||||
* Display the chooser dialog using the compiled HTML from the mustache template
|
||||
* and binds onclick events for the generated comment options.
|
||||
*
|
||||
* @param compiledSource The compiled HTML from the mustache template
|
||||
* @param comments Array containing comments.
|
||||
*/
|
||||
function displayChooserDialog(compiledSource, comments) {
|
||||
var titleLabel = '<label>' + M.util.get_string('insertcomment', 'gradingform_guide') + '</label>';
|
||||
var cancelButtonId = 'comment-chooser-' + criterionId + '-cancel';
|
||||
var cancelButton = '<button id="' + cancelButtonId + '">' + M.util.get_string('cancel', 'moodle') + '</button>';
|
||||
|
||||
if (typeof chooserDialog === 'undefined') {
|
||||
// Set dialog's body content.
|
||||
chooserDialog = new M.core.dialogue({
|
||||
modal: true,
|
||||
headerContent: titleLabel,
|
||||
bodyContent: compiledSource,
|
||||
footerContent: cancelButton,
|
||||
focusAfterHide: '#' + remarkId,
|
||||
id: "comments-chooser-dialog-" + criterionId
|
||||
});
|
||||
|
||||
// Bind click event to the cancel button.
|
||||
$("#" + cancelButtonId).click(function() {
|
||||
if (typeof chooserDialog !== 'undefined') {
|
||||
chooserDialog.hide();
|
||||
}
|
||||
});
|
||||
|
||||
// Loop over each comment item and bind click events.
|
||||
$.each(comments, function (index, comment) {
|
||||
var commentOptionId = '#comment-option-' + criterionId + '-' + comment.id;
|
||||
|
||||
// Delegate click event for the generated option link.
|
||||
$(commentOptionId).click(function () {
|
||||
var remarkTextArea = $('#' + remarkId);
|
||||
var remarkText = remarkTextArea.val();
|
||||
|
||||
// Add line break if the current value of the remark text is not empty.
|
||||
if ($.trim(remarkText) !== '') {
|
||||
remarkText += '\n';
|
||||
}
|
||||
remarkText += comment.description;
|
||||
|
||||
remarkTextArea.val(remarkText);
|
||||
|
||||
if (typeof chooserDialog !== 'undefined') {
|
||||
chooserDialog.hide();
|
||||
}
|
||||
});
|
||||
|
||||
// Handle keypress on list items.
|
||||
$(document).off('keypress', commentOptionId).on('keypress', commentOptionId, function () {
|
||||
var keyCode = event.which || event.keyCode;
|
||||
|
||||
// Enter or space key.
|
||||
if (keyCode == 13 || keyCode == 32) {
|
||||
// Trigger click event.
|
||||
$(commentOptionId).click();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Show dialog.
|
||||
chooserDialog.show();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the comments chooser dialog from the grading_form/comment_chooser mustache template.
|
||||
*/
|
||||
function generateCommentsChooser() {
|
||||
// Template context.
|
||||
var context = {
|
||||
criterionId: criterionId,
|
||||
comments: commentOptions
|
||||
};
|
||||
|
||||
// Render the template and display the comment chooser dialog.
|
||||
templates.render('gradingform_guide/comment_chooser', context)
|
||||
.done(function (compiledSource) {
|
||||
displayChooserDialog(compiledSource, commentOptions);
|
||||
})
|
||||
.fail(notification.exception);
|
||||
}
|
||||
|
||||
// Bind click event for the comments chooser button.
|
||||
$("#" + buttonId).click(function (e) {
|
||||
e.preventDefault();
|
||||
generateCommentsChooser();
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
@ -53,7 +53,7 @@ class gradingform_guide_editguide extends moodleform {
|
||||
// Name.
|
||||
$form->addElement('text', 'name', get_string('name', 'gradingform_guide'),
|
||||
array('size' => 52, 'maxlength' => 255));
|
||||
$form->addRule('name', get_string('required'), 'required');
|
||||
$form->addRule('name', get_string('required'), 'required', null, 'client');
|
||||
$form->setType('name', PARAM_TEXT);
|
||||
$form->addRule('name', null, 'maxlength', 255, 'client');
|
||||
|
||||
|
@ -137,7 +137,7 @@ class moodlequickform_guideeditor extends HTML_QuickForm_input {
|
||||
$html .= $renderer->display_regrade_confirmation($this->getName(), $this->regradeconfirmation, $data['regrade']);
|
||||
}
|
||||
if ($this->validationerrors) {
|
||||
$html .= $renderer->notification($this->validationerrors, 'error');
|
||||
$html .= html_writer::div($renderer->notification($this->validationerrors, 'error'), '', array('role' => 'alert'));
|
||||
}
|
||||
$html .= $renderer->display_guide($data['criteria'], $data['comments'], $data['options'], $mode, $this->getName());
|
||||
return $html;
|
||||
|
@ -168,14 +168,15 @@ M.gradingform_guideeditor.buttonclick = function(e, confirmed) {
|
||||
return;
|
||||
}
|
||||
// prepare the id of the next inserted criterion
|
||||
|
||||
var elements_str;
|
||||
if (section == 'criteria') {
|
||||
elements_str = '#guide-'+name+' .criteria .criterion'
|
||||
} else if (section == 'comments') {
|
||||
elements_str = '#guide-'+name+' .comments .criterion'
|
||||
}
|
||||
var newid = 0;
|
||||
if (action == 'addcriterion' || action == 'addcomment') {
|
||||
var newid = M.gradingform_guideeditor.calculatenewid(elements_str)
|
||||
newid = M.gradingform_guideeditor.calculatenewid(elements_str);
|
||||
}
|
||||
var dialog_options = {
|
||||
'scope' : this,
|
||||
@ -199,7 +200,14 @@ M.gradingform_guideeditor.buttonclick = function(e, confirmed) {
|
||||
M.gradingform_guideeditor.addhandlers();
|
||||
M.gradingform_guideeditor.disablealleditors()
|
||||
M.gradingform_guideeditor.assignclasses(elements_str)
|
||||
//M.gradingform_guideeditor.editmode(Y.one('#guide-'+name+' #'+name+'-'+section+'-NEWID'+newid+'-shortname'),true)
|
||||
|
||||
// Enable edit mode of the newly added criterion/comment entry.
|
||||
var inputTarget = 'shortname';
|
||||
if (action == 'addcomment') {
|
||||
inputTarget = 'description';
|
||||
}
|
||||
var inputTargetId = '#guide-' + name + ' #' + name + '-' + section + '-NEWID' + newid + '-' + inputTarget;
|
||||
M.gradingform_guideeditor.editmode(Y.one(inputTargetId), true);
|
||||
} else if (chunks.length == 4 && action == 'moveup') {
|
||||
// MOVE UP
|
||||
el = Y.one('#'+name+'-'+section+'-'+chunks[2])
|
||||
|
@ -31,6 +31,7 @@ $string['backtoediting'] = 'Back to editing';
|
||||
$string['clicktocopy'] = 'Click to copy this text into the criteria feedback';
|
||||
$string['clicktoedit'] = 'Click to edit';
|
||||
$string['clicktoeditname'] = 'Click to edit criterion name';
|
||||
$string['comment'] = 'Comment';
|
||||
$string['comments'] = 'Frequently used comments';
|
||||
$string['commentsdelete'] = 'Delete comment';
|
||||
$string['commentsempty'] = 'Click to edit comment';
|
||||
@ -38,12 +39,13 @@ $string['commentsmovedown'] = 'Move down';
|
||||
$string['commentsmoveup'] = 'Move up';
|
||||
$string['confirmdeletecriterion'] = 'Are you sure you want to delete this item?';
|
||||
$string['confirmdeletelevel'] = 'Are you sure you want to delete this level?';
|
||||
$string['criterion'] = 'Criterion';
|
||||
$string['criterion'] = 'Criterion name';
|
||||
$string['criteriondelete'] = 'Delete criterion';
|
||||
$string['criterionempty'] = 'Click to edit criterion';
|
||||
$string['criterionmovedown'] = 'Move down';
|
||||
$string['criterionmoveup'] = 'Move up';
|
||||
$string['criterionname'] = 'Criterion name';
|
||||
$string['criterionremark'] = '{$a} criterion remark';
|
||||
$string['definemarkingguide'] = 'Define marking guide';
|
||||
$string['description'] = 'Description';
|
||||
$string['descriptionmarkers'] = 'Description for Markers';
|
||||
@ -57,6 +59,7 @@ $string['err_noshortname'] = 'Criterion name can not be empty';
|
||||
$string['err_shortnametoolong'] = 'Criterion name must be less than 256 characters';
|
||||
$string['err_scoreinvalid'] = 'The score given to {$a->criterianame} is not valid, the max score is: {$a->maxscore}';
|
||||
$string['gradingof'] = '{$a} grading';
|
||||
$string['guide'] = 'Marking guide';
|
||||
$string['guidemappingexplained'] = 'WARNING: Your marking guide has a maximum grade of <b>{$a->maxscore} points</b> but the maximum grade set in your activity is {$a->modulegrade} The maximum score set in your marking guide will be scaled to the maximum grade in the module.<br />
|
||||
Intermediate scores will be converted respectively and rounded to the nearest available grade.';
|
||||
$string['guidenotcompleted'] = 'Please provide a valid grade for each criterion';
|
||||
@ -64,6 +67,7 @@ $string['guideoptions'] = 'Marking guide options';
|
||||
$string['guidestatus'] = 'Current marking guide status';
|
||||
$string['hidemarkerdesc'] = 'Hide marker criterion descriptions';
|
||||
$string['hidestudentdesc'] = 'Hide student criterion descriptions';
|
||||
$string['insertcomment'] = 'Insert frequently used comment';
|
||||
$string['maxscore'] = 'Maximum mark';
|
||||
$string['name'] = 'Name';
|
||||
$string['needregrademessage'] = 'The marking guide definition was changed after this student had been graded. The student can not see this marking guide until you check the marking guide and update the grade.';
|
||||
|
@ -951,7 +951,7 @@ class gradingform_guide_instance extends gradingform_instance {
|
||||
$currentinstance = $this->get_current_instance();
|
||||
if ($currentinstance && $currentinstance->get_status() == gradingform_instance::INSTANCE_STATUS_NEEDUPDATE) {
|
||||
$html .= html_writer::tag('div', get_string('needregrademessage', 'gradingform_guide'),
|
||||
array('class' => 'gradingform_guide-regrade'));
|
||||
array('class' => 'gradingform_guide-regrade', 'role' => 'alert'));
|
||||
}
|
||||
$haschanges = false;
|
||||
if ($currentinstance) {
|
||||
|
@ -55,10 +55,13 @@ class gradingform_guide_renderer extends plugin_renderer_base {
|
||||
* @param array $criterion criterion data
|
||||
* @param array $value (only in view mode) teacher's feedback on this criterion
|
||||
* @param array $validationerrors An array containing validation errors to be shown
|
||||
* @param array $comments Array of frequently used comments.
|
||||
* @return string
|
||||
*/
|
||||
public function criterion_template($mode, $options, $elementname = '{NAME}', $criterion = null, $value = null,
|
||||
$validationerrors = null) {
|
||||
$validationerrors = null, $comments = null) {
|
||||
global $PAGE;
|
||||
|
||||
if ($criterion === null || !is_array($criterion) || !array_key_exists('id', $criterion)) {
|
||||
$criterion = array('id' => '{CRITERION-id}',
|
||||
'description' => '{CRITERION-description}',
|
||||
@ -85,24 +88,28 @@ class gradingform_guide_renderer extends plugin_renderer_base {
|
||||
$value = get_string('criterion'.$key, 'gradingform_guide');
|
||||
$button = html_writer::empty_tag('input', array('type' => 'submit',
|
||||
'name' => '{NAME}[criteria][{CRITERION-id}]['.$key.']',
|
||||
'id' => '{NAME}-criteria-{CRITERION-id}-'.$key, 'value' => $value, 'title' => $value, 'tabindex' => -1));
|
||||
'id' => '{NAME}-criteria-{CRITERION-id}-'.$key, 'value' => $value, 'title' => $value));
|
||||
$criteriontemplate .= html_writer::tag('div', $button, array('class' => $key));
|
||||
}
|
||||
$criteriontemplate .= html_writer::end_tag('td'); // Controls.
|
||||
$criteriontemplate .= html_writer::empty_tag('input', array('type' => 'hidden',
|
||||
'name' => '{NAME}[criteria][{CRITERION-id}][sortorder]', 'value' => $criterion['sortorder']));
|
||||
|
||||
$shortname = html_writer::empty_tag('input', array('type'=> 'text',
|
||||
'name' => '{NAME}[criteria][{CRITERION-id}][shortname]', 'value' => $criterion['shortname'],
|
||||
'id ' => '{NAME}[criteria][{CRITERION-id}][shortname]'));
|
||||
$shortname = html_writer::tag('div', $shortname, array('class'=>'criterionname'));
|
||||
$description = html_writer::tag('textarea', s($criterion['description']),
|
||||
array('name' => '{NAME}[criteria][{CRITERION-id}][description]', 'cols' => '65', 'rows' => '5'));
|
||||
$description = html_writer::tag('div', $description, array('class'=>'criteriondesc'));
|
||||
$shortnameinput = html_writer::empty_tag('input', array('type' => 'text',
|
||||
'name' => '{NAME}[criteria][{CRITERION-id}][shortname]',
|
||||
'id ' => '{NAME}-criteria-{CRITERION-id}-shortname',
|
||||
'value' => $criterion['shortname'],
|
||||
'aria-labelledby' => '{NAME}-criterion-name-label'));
|
||||
$shortname = html_writer::tag('div', $shortnameinput, array('class' => 'criterionname'));
|
||||
$descriptioninput = html_writer::tag('textarea', s($criterion['description']),
|
||||
array('name' => '{NAME}[criteria][{CRITERION-id}][description]',
|
||||
'id' => '{NAME}[criteria][{CRITERION-id}][description]', 'cols' => '65', 'rows' => '5'));
|
||||
$description = html_writer::tag('div', $descriptioninput, array('class' => 'criteriondesc'));
|
||||
|
||||
$descriptionmarkers = html_writer::tag('textarea', s($criterion['descriptionmarkers']),
|
||||
array('name' => '{NAME}[criteria][{CRITERION-id}][descriptionmarkers]', 'cols' => '65', 'rows' => '5'));
|
||||
$descriptionmarkers = html_writer::tag('div', $descriptionmarkers, array('class'=>'criteriondescmarkers'));
|
||||
$descriptionmarkersinput = html_writer::tag('textarea', s($criterion['descriptionmarkers']),
|
||||
array('name' => '{NAME}[criteria][{CRITERION-id}][descriptionmarkers]',
|
||||
'id' => '{NAME}[criteria][{CRITERION-id}][descriptionmarkers]', 'cols' => '65', 'rows' => '5'));
|
||||
$descriptionmarkers = html_writer::tag('div', $descriptionmarkersinput, array('class' => 'criteriondescmarkers'));
|
||||
|
||||
$maxscore = html_writer::empty_tag('input', array('type'=> 'text',
|
||||
'name' => '{NAME}[criteria][{CRITERION-id}][maxscore]', 'size' => '3',
|
||||
@ -125,8 +132,14 @@ class gradingform_guide_renderer extends plugin_renderer_base {
|
||||
$mode == gradingform_guide_controller::DISPLAY_VIEW) {
|
||||
$descriptionclass = 'descriptionreadonly';
|
||||
}
|
||||
$shortname = html_writer::tag('div', s($criterion['shortname']),
|
||||
array('class'=>'criterionshortname', 'name' => '{NAME}[criteria][{CRITERION-id}][shortname]'));
|
||||
|
||||
$shortnameparams = array(
|
||||
'name' => '{NAME}[criteria][{CRITERION-id}][shortname]',
|
||||
'id' => '{NAME}[criteria][{CRITERION-id}][shortname]',
|
||||
'aria-describedby' => '{NAME}-criterion-name-label'
|
||||
);
|
||||
$shortname = html_writer::div(s($criterion['shortname']), 'criterionshortname', $shortnameparams);
|
||||
|
||||
$descmarkerclass = '';
|
||||
$descstudentclass = '';
|
||||
if ($mode == gradingform_guide_controller::DISPLAY_EVAL) {
|
||||
@ -155,9 +168,7 @@ class gradingform_guide_renderer extends plugin_renderer_base {
|
||||
$descriptionclass .= ' error';
|
||||
}
|
||||
|
||||
$title = html_writer::tag('label', get_string('criterion', 'gradingform_guide'),
|
||||
array('for'=>'{NAME}[criteria][{CRITERION-id}][shortname]', 'class' => 'criterionnamelabel'));
|
||||
$title .= $shortname;
|
||||
$title = $shortname;
|
||||
if ($mode == gradingform_guide_controller::DISPLAY_EDIT_FULL ||
|
||||
$mode == gradingform_guide_controller::DISPLAY_PREVIEW) {
|
||||
$title .= html_writer::tag('label', get_string('descriptionstudents', 'gradingform_guide'),
|
||||
@ -173,15 +184,26 @@ class gradingform_guide_renderer extends plugin_renderer_base {
|
||||
$mode == gradingform_guide_controller::DISPLAY_VIEW) {
|
||||
$title .= $description;
|
||||
if (!empty($options['showmarkspercriterionstudents'])) {
|
||||
$title .= html_writer::tag('label', get_string('maxscore', 'gradingform_guide'),
|
||||
array('for' => '{NAME}[criteria][{CRITERION-id}][maxscore]'));
|
||||
$title .= html_writer::label(get_string('maxscore', 'gradingform_guide'), null);
|
||||
$title .= $maxscore;
|
||||
}
|
||||
} else {
|
||||
$title .= $description . $descriptionmarkers;
|
||||
}
|
||||
$criteriontemplate .= html_writer::tag('td', $title, array('class' => $descriptionclass,
|
||||
'id' => '{NAME}-criteria-{CRITERION-id}-shortname'));
|
||||
|
||||
// Title cell params.
|
||||
$titletdparams = array(
|
||||
'class' => $descriptionclass,
|
||||
'id' => '{NAME}-criteria-{CRITERION-id}-shortname-cell'
|
||||
);
|
||||
|
||||
if ($mode != gradingform_guide_controller::DISPLAY_EDIT_FULL &&
|
||||
$mode != gradingform_guide_controller::DISPLAY_EDIT_FROZEN) {
|
||||
// Set description's cell as tab-focusable.
|
||||
$titletdparams['tabindex'] = '0';
|
||||
}
|
||||
|
||||
$criteriontemplate .= html_writer::tag('td', $title, $titletdparams);
|
||||
|
||||
$currentremark = '';
|
||||
$currentscore = '';
|
||||
@ -191,23 +213,70 @@ class gradingform_guide_renderer extends plugin_renderer_base {
|
||||
if (isset($value['score'])) {
|
||||
$currentscore = $value['score'];
|
||||
}
|
||||
|
||||
// Element ID of the remark text area.
|
||||
$remarkid = $elementname . '-criteria-' . $criterion['id'] . '-remark';
|
||||
|
||||
if ($mode == gradingform_guide_controller::DISPLAY_EVAL) {
|
||||
$scoreclass = '';
|
||||
if (!empty($validationerrors[$criterion['id']]['score'])) {
|
||||
$scoreclass = 'error';
|
||||
$currentscore = $validationerrors[$criterion['id']]['score']; // Show invalid score in form.
|
||||
}
|
||||
$input = html_writer::tag('textarea', s($currentremark),
|
||||
array('name' => '{NAME}[criteria][{CRITERION-id}][remark]', 'cols' => '65', 'rows' => '5',
|
||||
'class' => 'markingguideremark'));
|
||||
$criteriontemplate .= html_writer::tag('td', $input, array('class' => 'remark'));
|
||||
$score = html_writer::tag('label', get_string('score', 'gradingform_guide'),
|
||||
array('for'=>'{NAME}[criteria][{CRITERION-id}][score]', 'class' => $scoreclass));
|
||||
$score .= html_writer::empty_tag('input', array('type'=> 'text',
|
||||
'name' => '{NAME}[criteria][{CRITERION-id}][score]', 'class' => $scoreclass,
|
||||
'id' => '{NAME}[criteria][{CRITERION-id}][score]',
|
||||
'size' => '3', 'value' => $currentscore));
|
||||
$score .= '/'.$maxscore;
|
||||
|
||||
// Grading remark text area parameters.
|
||||
$remarkparams = array(
|
||||
'name' => '{NAME}[criteria][{CRITERION-id}][remark]',
|
||||
'id' => $remarkid,
|
||||
'cols' => '65', 'rows' => '5', 'class' => 'markingguideremark',
|
||||
'aria-labelledby' => '{NAME}-remarklabel{CRITERION-id}'
|
||||
);
|
||||
|
||||
// Grading remark text area.
|
||||
$input = html_writer::tag('textarea', s($currentremark), $remarkparams);
|
||||
|
||||
// Frequently used comments chooser.
|
||||
$chooserbuttonid = 'criteria-' . $criterion['id'] . '-commentchooser';
|
||||
$commentchooserparams = array('id' => $chooserbuttonid, 'class' => 'commentchooser');
|
||||
$commentchooser = html_writer::tag('button', get_string('insertcomment', 'gradingform_guide'), $commentchooserparams);
|
||||
|
||||
// Option items for the frequently used comments chooser dialog.
|
||||
$commentoptions = array();
|
||||
foreach ($comments as $id => $comment) {
|
||||
$commentoption = new stdClass();
|
||||
$commentoption->id = $id;
|
||||
$commentoption->description = s($comment['description']);
|
||||
$commentoptions[] = $commentoption;
|
||||
}
|
||||
|
||||
// Include string for JS for the comment chooser title.
|
||||
$PAGE->requires->string_for_js('insertcomment', 'gradingform_guide');
|
||||
// Include comment_chooser module.
|
||||
$PAGE->requires->js_call_amd('gradingform_guide/comment_chooser', 'initialise',
|
||||
array($criterion['id'], $chooserbuttonid, $remarkid, $commentoptions));
|
||||
|
||||
// Hidden marking guide remark label.
|
||||
$remarklabelparams = array(
|
||||
'class' => 'hidden',
|
||||
'id' => '{NAME}-remarklabel{CRITERION-id}'
|
||||
);
|
||||
$remarklabeltext = get_string('criterionremark', 'gradingform_guide', $criterion['shortname']);
|
||||
$remarklabel = html_writer::label($remarklabeltext, $remarkid, false, $remarklabelparams);
|
||||
|
||||
$criteriontemplate .= html_writer::tag('td', $remarklabel . $input . $commentchooser, array('class' => 'remark'));
|
||||
|
||||
// Score input and max score.
|
||||
$scoreinputparams = array(
|
||||
'type' => 'text',
|
||||
'name' => '{NAME}[criteria][{CRITERION-id}][score]',
|
||||
'class' => $scoreclass,
|
||||
'id' => '{NAME}-criteria-{CRITERION-id}-score',
|
||||
'size' => '3',
|
||||
'value' => $currentscore,
|
||||
'aria-labelledby' => '{NAME}-score-label'
|
||||
);
|
||||
$score = html_writer::empty_tag('input', $scoreinputparams);
|
||||
$score .= html_writer::div('/' . s($criterion['maxscore']));
|
||||
|
||||
$criteriontemplate .= html_writer::tag('td', $score, array('class' => 'score'));
|
||||
} else if ($mode == gradingform_guide_controller::DISPLAY_EVAL_FROZEN) {
|
||||
@ -215,10 +284,34 @@ class gradingform_guide_renderer extends plugin_renderer_base {
|
||||
'name' => '{NAME}[criteria][{CRITERION-id}][remark]', 'value' => $currentremark));
|
||||
} else if ($mode == gradingform_guide_controller::DISPLAY_REVIEW ||
|
||||
$mode == gradingform_guide_controller::DISPLAY_VIEW) {
|
||||
$criteriontemplate .= html_writer::tag('td', s($currentremark), array('class' => 'remark'));
|
||||
|
||||
// Hidden marking guide remark description.
|
||||
$remarkdescparams = array(
|
||||
'id' => '{NAME}-criteria-{CRITERION-id}-remark-desc'
|
||||
);
|
||||
$remarkdesctext = get_string('criterionremark', 'gradingform_guide', $criterion['shortname']);
|
||||
$remarkdesc = html_writer::div($remarkdesctext, 'hidden', $remarkdescparams);
|
||||
|
||||
// Remarks cell.
|
||||
$remarkdiv = html_writer::div(s($currentremark));
|
||||
$remarkcellparams = array(
|
||||
'class' => 'remark',
|
||||
'tabindex' => '0',
|
||||
'id' => '{NAME}-criteria-{CRITERION-id}-remark',
|
||||
'aria-describedby' => '{NAME}-criteria-{CRITERION-id}-remark-desc'
|
||||
);
|
||||
$criteriontemplate .= html_writer::tag('td', $remarkdesc . $remarkdiv, $remarkcellparams);
|
||||
|
||||
// Score cell.
|
||||
if (!empty($options['showmarkspercriterionstudents'])) {
|
||||
$criteriontemplate .= html_writer::tag('td', s($currentscore). ' / '.$maxscore,
|
||||
array('class' => 'score'));
|
||||
$scorecellparams = array(
|
||||
'class' => 'score',
|
||||
'tabindex' => '0',
|
||||
'id' => '{NAME}-criteria-{CRITERION-id}-score',
|
||||
'aria-describedby' => '{NAME}-score-label'
|
||||
);
|
||||
$scorediv = html_writer::div(s($currentscore) . ' / ' . s($criterion['maxscore']));
|
||||
$criteriontemplate .= html_writer::tag('td', $scorediv, $scorecellparams);
|
||||
}
|
||||
}
|
||||
$criteriontemplate .= html_writer::end_tag('tr'); // Criterion.
|
||||
@ -262,28 +355,30 @@ class gradingform_guide_renderer extends plugin_renderer_base {
|
||||
}
|
||||
}
|
||||
}
|
||||
$criteriontemplate = html_writer::start_tag('tr', array('class' => 'criterion'. $comment['class'],
|
||||
$commenttemplate = html_writer::start_tag('tr', array('class' => 'criterion'. $comment['class'],
|
||||
'id' => '{NAME}-comments-{COMMENT-id}'));
|
||||
if ($mode == gradingform_guide_controller::DISPLAY_EDIT_FULL) {
|
||||
$criteriontemplate .= html_writer::start_tag('td', array('class' => 'controls'));
|
||||
$commenttemplate .= html_writer::start_tag('td', array('class' => 'controls'));
|
||||
foreach (array('moveup', 'delete', 'movedown') as $key) {
|
||||
$value = get_string('comments'.$key, 'gradingform_guide');
|
||||
$button = html_writer::empty_tag('input', array('type' => 'submit',
|
||||
'name' => '{NAME}[comments][{COMMENT-id}]['.$key.']', 'id' => '{NAME}-comments-{COMMENT-id}-'.$key,
|
||||
'value' => $value, 'title' => $value, 'tabindex' => -1));
|
||||
$criteriontemplate .= html_writer::tag('div', $button, array('class' => $key));
|
||||
'value' => $value, 'title' => $value));
|
||||
$commenttemplate .= html_writer::tag('div', $button, array('class' => $key));
|
||||
}
|
||||
$criteriontemplate .= html_writer::end_tag('td'); // Controls.
|
||||
$criteriontemplate .= html_writer::empty_tag('input', array('type' => 'hidden',
|
||||
$commenttemplate .= html_writer::end_tag('td'); // Controls.
|
||||
$commenttemplate .= html_writer::empty_tag('input', array('type' => 'hidden',
|
||||
'name' => '{NAME}[comments][{COMMENT-id}][sortorder]', 'value' => $comment['sortorder']));
|
||||
$description = html_writer::tag('textarea', s($comment['description']),
|
||||
array('name' => '{NAME}[comments][{COMMENT-id}][description]', 'cols' => '65', 'rows' => '5'));
|
||||
array('name' => '{NAME}[comments][{COMMENT-id}][description]',
|
||||
'id' => '{NAME}-comments-{COMMENT-id}-description',
|
||||
'aria-labelledby' => '{NAME}-comment-label', 'cols' => '65', 'rows' => '5'));
|
||||
$description = html_writer::tag('div', $description, array('class'=>'criteriondesc'));
|
||||
} else {
|
||||
if ($mode == gradingform_guide_controller::DISPLAY_EDIT_FROZEN) {
|
||||
$criteriontemplate .= html_writer::empty_tag('input', array('type' => 'hidden',
|
||||
$commenttemplate .= html_writer::empty_tag('input', array('type' => 'hidden',
|
||||
'name' => '{NAME}[comments][{COMMENT-id}][sortorder]', 'value' => $comment['sortorder']));
|
||||
$criteriontemplate .= html_writer::empty_tag('input', array('type' => 'hidden',
|
||||
$commenttemplate .= html_writer::empty_tag('input', array('type' => 'hidden',
|
||||
'name' => '{NAME}[comments][{COMMENT-id}][description]', 'value' => $comment['description']));
|
||||
}
|
||||
if ($mode == gradingform_guide_controller::DISPLAY_EVAL) {
|
||||
@ -301,13 +396,21 @@ class gradingform_guide_renderer extends plugin_renderer_base {
|
||||
if (isset($comment['error_description'])) {
|
||||
$descriptionclass .= ' error';
|
||||
}
|
||||
$criteriontemplate .= html_writer::tag('td', $description, array('class' => $descriptionclass,
|
||||
'id' => '{NAME}-comments-{COMMENT-id}-description'));
|
||||
$criteriontemplate .= html_writer::end_tag('tr'); // Criterion.
|
||||
$descriptioncellparams = array(
|
||||
'class' => $descriptionclass,
|
||||
'id' => '{NAME}-comments-{COMMENT-id}-description-cell'
|
||||
);
|
||||
// Make description cell tab-focusable when in review mode.
|
||||
if ($mode != gradingform_guide_controller::DISPLAY_EDIT_FULL &&
|
||||
$mode != gradingform_guide_controller::DISPLAY_EDIT_FROZEN) {
|
||||
$descriptioncellparams['tabindex'] = '0';
|
||||
}
|
||||
$commenttemplate .= html_writer::tag('td', $description, $descriptioncellparams);
|
||||
$commenttemplate .= html_writer::end_tag('tr'); // Criterion.
|
||||
|
||||
$criteriontemplate = str_replace('{NAME}', $elementname, $criteriontemplate);
|
||||
$criteriontemplate = str_replace('{COMMENT-id}', $comment['id'], $criteriontemplate);
|
||||
return $criteriontemplate;
|
||||
$commenttemplate = str_replace('{NAME}', $elementname, $commenttemplate);
|
||||
$commenttemplate = str_replace('{COMMENT-id}', $comment['id'], $commenttemplate);
|
||||
return $commenttemplate;
|
||||
}
|
||||
/**
|
||||
* This function returns html code for displaying guide template (content before and after
|
||||
@ -358,7 +461,27 @@ class gradingform_guide_renderer extends plugin_renderer_base {
|
||||
|
||||
$guidetemplate = html_writer::start_tag('div', array('id' => 'guide-{NAME}',
|
||||
'class' => 'clearfix gradingform_guide'.$classsuffix));
|
||||
$guidetemplate .= html_writer::tag('table', $criteriastr, array('class' => 'criteria', 'id' => '{NAME}-criteria'));
|
||||
|
||||
// Hidden guide label.
|
||||
$guidedescparams = array(
|
||||
'id' => 'guide-{NAME}-desc',
|
||||
'aria-hidden' => 'true'
|
||||
);
|
||||
$guidetemplate .= html_writer::div(get_string('guide', 'gradingform_guide'), 'hidden', $guidedescparams);
|
||||
|
||||
// Hidden criterion name label/description.
|
||||
$guidetemplate .= html_writer::div(get_string('criterionname', 'gradingform_guide'), 'hidden',
|
||||
array('id' => '{NAME}-criterion-name-label'));
|
||||
|
||||
// Hidden score label/description.
|
||||
$guidetemplate .= html_writer::div(get_string('score', 'gradingform_guide'), 'hidden', array('id' => '{NAME}-score-label'));
|
||||
|
||||
// Criteria table parameters.
|
||||
$criteriatableparams = array(
|
||||
'class' => 'criteria',
|
||||
'id' => '{NAME}-criteria',
|
||||
'aria-describedby' => 'guide-{NAME}-desc');
|
||||
$guidetemplate .= html_writer::tag('table', $criteriastr, $criteriatableparams);
|
||||
if ($mode == gradingform_guide_controller::DISPLAY_EDIT_FULL) {
|
||||
$value = get_string('addcriterion', 'gradingform_guide');
|
||||
$input = html_writer::empty_tag('input', array('type' => 'submit', 'name' => '{NAME}[criteria][addcriterion]',
|
||||
@ -367,9 +490,15 @@ class gradingform_guide_renderer extends plugin_renderer_base {
|
||||
}
|
||||
|
||||
if (!empty($commentstr)) {
|
||||
$guidetemplate .= html_writer::tag('label', get_string('comments', 'gradingform_guide'),
|
||||
array('for' => '{NAME}-comments', 'class' => 'commentheader'));
|
||||
$guidetemplate .= html_writer::tag('table', $commentstr, array('class' => 'comments', 'id' => '{NAME}-comments'));
|
||||
$guidetemplate .= html_writer::div(get_string('comments', 'gradingform_guide'), 'commentheader',
|
||||
array('id' => '{NAME}-comments-label'));
|
||||
$guidetemplate .= html_writer::div(get_string('comment', 'gradingform_guide'), 'hidden',
|
||||
array('id' => '{NAME}-comment-label', 'aria-hidden' => 'true'));
|
||||
$commentstableparams = array(
|
||||
'class' => 'comments',
|
||||
'id' => '{NAME}-comments',
|
||||
'aria-describedby' => '{NAME}-comments-label');
|
||||
$guidetemplate .= html_writer::tag('table', $commentstr, $commentstableparams);
|
||||
}
|
||||
if ($mode == gradingform_guide_controller::DISPLAY_EDIT_FULL) {
|
||||
$value = get_string('addcomment', 'gradingform_guide');
|
||||
@ -481,21 +610,21 @@ class gradingform_guide_renderer extends plugin_renderer_base {
|
||||
$criterionvalue = null;
|
||||
}
|
||||
$criteriastr .= $this->criterion_template($mode, $options, $elementname, $criterion, $criterionvalue,
|
||||
$validationerrors);
|
||||
$validationerrors, $comments);
|
||||
}
|
||||
|
||||
$cnt = 0;
|
||||
$commentstr = '';
|
||||
// Check if comments should be displayed.
|
||||
if ($mode == gradingform_guide_controller::DISPLAY_EDIT_FULL ||
|
||||
$mode == gradingform_guide_controller::DISPLAY_EDIT_FROZEN ||
|
||||
$mode == gradingform_guide_controller::DISPLAY_PREVIEW ||
|
||||
$mode == gradingform_guide_controller::DISPLAY_EVAL ||
|
||||
$mode == gradingform_guide_controller::DISPLAY_EVAL_FROZEN) {
|
||||
|
||||
foreach ($comments as $id => $comment) {
|
||||
$comment['id'] = $id;
|
||||
$comment['class'] = $this->get_css_class_suffix($cnt++, count($comments) -1);
|
||||
$commentstr .= $this->comment_template($mode, $elementname, $comment);
|
||||
$commentstr .= $this->comment_template($mode, $elementname, $comment);
|
||||
}
|
||||
}
|
||||
$output = $this->guide_template($mode, $options, $elementname, $criteriastr, $commentstr);
|
||||
@ -613,7 +742,7 @@ class gradingform_guide_renderer extends plugin_renderer_base {
|
||||
* @return string
|
||||
*/
|
||||
public function display_regrade_confirmation($elementname, $changelevel, $value) {
|
||||
$html = html_writer::start_tag('div', array('class' => 'gradingform_guide-regrade'));
|
||||
$html = html_writer::start_tag('div', array('class' => 'gradingform_guide-regrade', 'role' => 'alert'));
|
||||
if ($changelevel<=2) {
|
||||
$html .= get_string('regrademessage1', 'gradingform_guide');
|
||||
$selectoptions = array(
|
||||
|
59
grade/grading/form/guide/templates/comment_chooser.mustache
Normal file
59
grade/grading/form/guide/templates/comment_chooser.mustache
Normal file
@ -0,0 +1,59 @@
|
||||
{{!
|
||||
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 gradingform_guide/comment_chooser
|
||||
|
||||
Moodle comment chooser template for marking guide.
|
||||
|
||||
The purpose of this template is to render a list of frequently used comments that can be used by the comment chooser dialog.
|
||||
|
||||
Classes required for JS:
|
||||
* none
|
||||
|
||||
Data attributes required for JS:
|
||||
* none
|
||||
|
||||
Context variables required for this template:
|
||||
* criterionId The criterion ID this chooser template is being generated for.
|
||||
* comments Array of id / description pairs.
|
||||
|
||||
Example context (json):
|
||||
{
|
||||
"criterionId": "1",
|
||||
"comments": [
|
||||
{
|
||||
"id": "1",
|
||||
"description": "Test comment description 1"
|
||||
},
|
||||
{
|
||||
"id": "2",
|
||||
"description": "Test comment description 2"
|
||||
}
|
||||
]
|
||||
}
|
||||
}}
|
||||
<div class="gradingform_guide_comment_chooser" id="comment_chooser">
|
||||
<ul role="list">
|
||||
{{#comments}}
|
||||
<li role="listitem">
|
||||
<button id="comment-option-{{criterionId}}-{{id}}" class="btn btn-link" tabindex="0">
|
||||
{{description}}
|
||||
</button>
|
||||
</li>
|
||||
{{/comments}}
|
||||
</ul>
|
||||
</div>
|
223
grade/grading/form/guide/tests/behat/behat_gradingform_guide.php
Normal file
223
grade/grading/form/guide/tests/behat/behat_gradingform_guide.php
Normal file
@ -0,0 +1,223 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Steps definitions for marking guides.
|
||||
*
|
||||
* @package gradingform_guide
|
||||
* @category test
|
||||
* @copyright 2015 Jun Pataleta
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
require_once(__DIR__ . '/../../../../../../lib/behat/behat_base.php');
|
||||
|
||||
use Behat\Gherkin\Node\TableNode as TableNode,
|
||||
Behat\Behat\Context\Step\Given as Given,
|
||||
Behat\Behat\Context\Step\When as When,
|
||||
Behat\Behat\Context\Step\Then as Then,
|
||||
Behat\Mink\Exception\ElementNotFoundException as ElementNotFoundException,
|
||||
Behat\Mink\Exception\ExpectationException as ExpectationException;
|
||||
|
||||
/**
|
||||
* Steps definitions to help with marking guides.
|
||||
*
|
||||
* @package gradingform_guide
|
||||
* @category test
|
||||
* @copyright 2015 Jun Pataleta
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class behat_gradingform_guide extends behat_base {
|
||||
|
||||
/**
|
||||
* Defines the marking guide with the provided data, following marking guide's definition grid cells.
|
||||
*
|
||||
* This method fills the marking guide of the marking guide definition
|
||||
* form; the provided TableNode should contain one row for
|
||||
* each criterion and each cell of the row should contain:
|
||||
* # Criterion name, a.k.a. shortname
|
||||
* # Description for students
|
||||
* # Description for markers
|
||||
* # Max score
|
||||
*
|
||||
* Works with both JS and non-JS.
|
||||
*
|
||||
* @When /^I define the following marking guide:$/
|
||||
* @throws ExpectationException
|
||||
* @param TableNode $guide
|
||||
*/
|
||||
public function i_define_the_following_marking_guide(TableNode $guide) {
|
||||
$steptableinfo = '| Criterion name | Description for students | Description for markers | Maximum mark |';
|
||||
|
||||
if ($criteria = $guide->getHash()) {
|
||||
$addcriterionbutton = $this->find_button(get_string('addcriterion', 'gradingform_guide'));
|
||||
|
||||
foreach ($criteria as $index => $criterion) {
|
||||
// Make sure the criterion array has 4 elements.
|
||||
if (count($criterion) != 4) {
|
||||
throw new ExpectationException(
|
||||
'The criterion definition should contain name, description for students and markers, and maximum points. ' .
|
||||
'Please follow this format: ' . $steptableinfo,
|
||||
$this->getSession()
|
||||
);
|
||||
}
|
||||
|
||||
// On load, there's already a criterion template ready.
|
||||
$shortnamevisible = false;
|
||||
if ($index > 0) {
|
||||
// So if the index is greater than 0, we click the Add new criterion button to add a new criterion.
|
||||
$addcriterionbutton->click();
|
||||
$shortnamevisible = true;
|
||||
}
|
||||
|
||||
$criterionroot = 'guide[criteria][NEWID' . ($index + 1) . ']';
|
||||
|
||||
// Set the field value for the Criterion name.
|
||||
$this->set_guide_field_value($criterionroot . '[shortname]', $criterion['Criterion name'], $shortnamevisible);
|
||||
|
||||
// Set the field value for the Description for students field.
|
||||
$this->set_guide_field_value($criterionroot . '[description]', $criterion['Description for students']);
|
||||
|
||||
// Set the field value for the Description for markers field.
|
||||
$this->set_guide_field_value($criterionroot . '[descriptionmarkers]', $criterion['Description for markers']);
|
||||
|
||||
// Set the field value for the Max score field.
|
||||
$this->set_guide_field_value($criterionroot . '[maxscore]', $criterion['Maximum mark']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines the marking guide with the provided data, following marking guide's definition grid cells.
|
||||
*
|
||||
* This method fills the table of frequently used comments of the marking guide definition form.
|
||||
* The provided TableNode should contain one row for each frequently used comment.
|
||||
* Each row contains:
|
||||
* # Comment
|
||||
*
|
||||
* Works with both JS and non-JS.
|
||||
*
|
||||
* @When /^I define the following frequently used comments:$/
|
||||
* @throws ExpectationException
|
||||
* @param TableNode $commentstable
|
||||
*/
|
||||
public function i_define_the_following_frequently_used_comments(TableNode $commentstable) {
|
||||
$steptableinfo = '| Comment |';
|
||||
|
||||
if ($comments = $commentstable->getRows()) {
|
||||
$addcommentbutton = $this->find_button(get_string('addcomment', 'gradingform_guide'));
|
||||
|
||||
foreach ($comments as $index => $comment) {
|
||||
// Make sure the comment array has only 1 element.
|
||||
if (count($comment) != 1) {
|
||||
throw new ExpectationException(
|
||||
'The comment cannot be empty. Please follow this format: ' . $steptableinfo,
|
||||
$this->getSession()
|
||||
);
|
||||
}
|
||||
|
||||
// On load, there's already a comment template ready.
|
||||
$commentfieldvisible = false;
|
||||
if ($index > 0) {
|
||||
// So if the index is greater than 0, we click the Add frequently used comment button to add a new criterion.
|
||||
$addcommentbutton->click();
|
||||
$commentfieldvisible = true;
|
||||
}
|
||||
|
||||
$commentroot = 'guide[comments][NEWID' . ($index + 1) . ']';
|
||||
|
||||
// Set the field value for the frequently used comment.
|
||||
$this->set_guide_field_value($commentroot . '[description]', $comment[0], $commentfieldvisible);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs grading of the student by filling out the marking guide.
|
||||
* Set one line per criterion and for each criterion set "| Criterion name | Points | Remark |".
|
||||
*
|
||||
* @When /^I grade by filling the marking guide with:$/
|
||||
*
|
||||
* @throws ExpectationException
|
||||
* @param TableNode $guide
|
||||
* @return void
|
||||
*/
|
||||
public function i_grade_by_filling_the_marking_guide_with(TableNode $guide) {
|
||||
|
||||
$criteria = $guide->getRowsHash();
|
||||
|
||||
$stepusage = '"I grade by filling the rubric with:" step needs you to provide a table where each row is a criterion' .
|
||||
' and each criterion has 3 different values: | Criterion name | Number of points | Remark text |';
|
||||
|
||||
// To fill with the steps to execute.
|
||||
$steps = array();
|
||||
|
||||
// First element -> name, second -> points, third -> Remark.
|
||||
foreach ($criteria as $name => $criterion) {
|
||||
|
||||
// We only expect the points and the remark, as the criterion name is $name.
|
||||
if (count($criterion) !== 2) {
|
||||
throw new ExpectationException($stepusage, $this->getSession());
|
||||
}
|
||||
|
||||
// Numeric value here.
|
||||
$points = $criterion[0];
|
||||
if (!is_numeric($points)) {
|
||||
throw new ExpectationException($stepusage, $this->getSession());
|
||||
}
|
||||
|
||||
$criterionid = 0;
|
||||
if ($criterionnamediv = $this->find('xpath', "//div[@class='criterionshortname'][text()='$name']")) {
|
||||
$criteriondivname = $criterionnamediv->getAttribute('name');
|
||||
// Criterion's name is of the format "advancedgrading[criteria][ID][shortname]".
|
||||
// So just explode the string with "][" as delimiter to extract the criterion ID.
|
||||
if ($nameparts = explode('][', $criteriondivname)) {
|
||||
$criterionid = $nameparts[1];
|
||||
}
|
||||
}
|
||||
|
||||
if ($criterionid) {
|
||||
$criterionroot = 'advancedgrading[criteria]' . '[' . $criterionid . ']';
|
||||
|
||||
$steps[] = new Given('I set the field "' . $criterionroot . '[score]' . '" to "' . $points . '"');
|
||||
$steps[] = new Given('I set the field "' . $criterionroot . '[remark]' . '" to "' . $criterion[1] . '"');
|
||||
}
|
||||
}
|
||||
|
||||
return $steps;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes a hidden marking guide field visible (if necessary) and sets a value on it.
|
||||
*
|
||||
* @param string $name The name of the field
|
||||
* @param string $value The value to set
|
||||
* @param bool $visible
|
||||
* @return void
|
||||
*/
|
||||
protected function set_guide_field_value($name, $value, $visible = false) {
|
||||
// Fields are hidden by default.
|
||||
if ($this->running_javascript() && $visible === false) {
|
||||
$xpath = "//*[@name='$name']/following-sibling::*[contains(concat(' ', normalize-space(@class), ' '), ' plainvalue ')]";
|
||||
$textnode = $this->find('xpath', $xpath);
|
||||
$textnode->click();
|
||||
}
|
||||
|
||||
// Set the value now.
|
||||
$field = $this->find_field($name);
|
||||
$field->setValue($value);
|
||||
}
|
||||
}
|
102
grade/grading/form/guide/tests/behat/edit_guide.feature
Normal file
102
grade/grading/form/guide/tests/behat/edit_guide.feature
Normal file
@ -0,0 +1,102 @@
|
||||
@gradingform @gradingform_guide
|
||||
Feature: Marking guides can be created and edited
|
||||
In order to use and refine marking guide to grade students
|
||||
As a teacher
|
||||
I need to edit previously used marking guides
|
||||
|
||||
Background:
|
||||
Given the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| teacher1 | Teacher | 1 | teacher1@example.com |
|
||||
| student1 | Student | 1 | student1@example.com |
|
||||
And the following "courses" exist:
|
||||
| fullname | shortname | format |
|
||||
| Course 1 | C1 | topics |
|
||||
And the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
| student1 | C1 | student |
|
||||
And I log in as "teacher1"
|
||||
And I follow "Course 1"
|
||||
And I turn editing mode on
|
||||
And I add a "Assignment" to section "1" and I fill the form with:
|
||||
| Assignment name | Test assignment 1 name |
|
||||
| Description | Test assignment description |
|
||||
| Grading method | Marking guide |
|
||||
# Defining a marking guide
|
||||
When I go to "Test assignment 1 name" advanced grading definition page
|
||||
And I set the following fields to these values:
|
||||
| Name | Assignment 1 marking guide |
|
||||
| Description | Marking guide test description |
|
||||
And I define the following marking guide:
|
||||
| Criterion name | Description for students | Description for markers | Maximum mark |
|
||||
| Guide criterion A | Guide A description for students | Guide A description for markers | 30 |
|
||||
| Guide criterion B | Guide B description for students | Guide B description for markers | 30 |
|
||||
| Guide criterion C | Guide C description for students | Guide C description for markers | 40 |
|
||||
And I define the following frequently used comments:
|
||||
| Comment 1 |
|
||||
| Comment 2 |
|
||||
| Comment 3 |
|
||||
| Comment 4 |
|
||||
And I press "Save marking guide and make it ready"
|
||||
Then I should see "Ready for use"
|
||||
And I should see "Guide criterion A"
|
||||
And I should see "Guide criterion B"
|
||||
And I should see "Guide criterion C"
|
||||
And I should see "Comment 1"
|
||||
And I should see "Comment 2"
|
||||
And I should see "Comment 3"
|
||||
And I should see "Comment 4"
|
||||
|
||||
@javascript
|
||||
Scenario: Deleting criterion and comment
|
||||
# Deleting criterion
|
||||
When I go to "Test assignment 1 name" advanced grading definition page
|
||||
And I click on "Delete criterion" "button" in the "Guide criterion B" "table_row"
|
||||
And I press "Yes"
|
||||
And I press "Save"
|
||||
Then I should see "Guide criterion A"
|
||||
And I should see "Guide criterion C"
|
||||
And I should see "WARNING: Your marking guide has a maximum grade of 70 points"
|
||||
But I should not see "Guide criterion B"
|
||||
# Deleting a frequently used comment
|
||||
When I go to "Test assignment 1 name" advanced grading definition page
|
||||
And I click on "Delete comment" "button" in the "Comment 3" "table_row"
|
||||
And I press "Yes"
|
||||
And I press "Save"
|
||||
Then I should see "Comment 1"
|
||||
And I should see "Comment 2"
|
||||
And I should see "Comment 4"
|
||||
But I should not see "Comment 3"
|
||||
|
||||
@javascript
|
||||
Scenario: Grading and viewing graded marking guide
|
||||
# Grading a student.
|
||||
When I go to "Student 1" "Test assignment 1 name" activity advanced grading page
|
||||
And I grade by filling the marking guide with:
|
||||
| Guide criterion A | 25 | Very good |
|
||||
| Guide criterion B | 20 | |
|
||||
| Guide criterion C | 35 | Nice! |
|
||||
# Inserting frequently used comment.
|
||||
And I click on "Insert frequently used comment" "button" in the "Guide criterion B" "table_row"
|
||||
And I wait "1" seconds
|
||||
And I press "Comment 4"
|
||||
And I wait "1" seconds
|
||||
Then the field "Guide criterion B criterion remark" matches value "Comment 4"
|
||||
When I press "Save changes"
|
||||
Then I should see "The grade changes were saved"
|
||||
# Checking that the user grade is correct.
|
||||
When I press "Continue"
|
||||
Then I should see "80" in the "Student 1" "table_row"
|
||||
And I log out
|
||||
# Viewing it as a student.
|
||||
And I log in as "student1"
|
||||
And I follow "Course 1"
|
||||
And I follow "Test assignment 1 name"
|
||||
And I should see "80" in the ".feedback" "css_element"
|
||||
And I should see "Marking guide test description" in the ".feedback" "css_element"
|
||||
And I should see "Very good"
|
||||
And I should see "Comment 4"
|
||||
And I should see "Nice!"
|
||||
|
||||
Scenario: I can use marking guides to grade and edit them later updating students grades with Javascript disabled
|
Loading…
x
Reference in New Issue
Block a user