mirror of
https://github.com/moodle/moodle.git
synced 2025-01-18 22:08:20 +01:00
MDL-36606 gradereport: Update AJAX grader to understand gradeless cells
This commit is contained in:
parent
df65120a75
commit
12f946d999
@ -747,7 +747,7 @@ class grade_report_grader extends grade_report {
|
||||
'items' => array(),
|
||||
'users' => array(),
|
||||
'feedback' => array(),
|
||||
'grades' => array(),
|
||||
'grades' => array()
|
||||
);
|
||||
$jsscales = array();
|
||||
|
||||
@ -1001,6 +1001,14 @@ class grade_report_grader extends grade_report {
|
||||
|
||||
} else if ($USER->gradeediting[$this->courseid]) {
|
||||
|
||||
if ($item->scaleid && !empty($scalesarray[$item->scaleid])) {
|
||||
$itemcell->attributes['class'] .= ' grade_type_scale';
|
||||
} else if ($item->gradetype == GRADE_TYPE_VALUE) {
|
||||
$itemcell->attributes['class'] .= ' grade_type_value';
|
||||
} else if ($item->gradetype == GRADE_TYPE_TEXT) {
|
||||
$itemcell->attributes['class'] .= ' grade_type_text';
|
||||
}
|
||||
|
||||
if ($item->scaleid && !empty($scalesarray[$item->scaleid])) {
|
||||
$scale = $scalesarray[$item->scaleid];
|
||||
$gradeval = (int)$gradeval; // scales use only integers
|
||||
@ -1070,16 +1078,16 @@ class grade_report_grader extends grade_report {
|
||||
|
||||
if ($item->scaleid && !empty($scalesarray[$item->scaleid])) {
|
||||
$itemcell->attributes['class'] .= ' grade_type_scale';
|
||||
} else if ($item->gradetype != GRADE_TYPE_TEXT) {
|
||||
} else if ($item->gradetype == GRADE_TYPE_VALUE) {
|
||||
$itemcell->attributes['class'] .= ' grade_type_value';
|
||||
} else if ($item->gradetype == GRADE_TYPE_TEXT) {
|
||||
$itemcell->attributes['class'] .= ' grade_type_text';
|
||||
}
|
||||
|
||||
if ($enableajax) {
|
||||
$canoverride = true;
|
||||
if ($item->is_category_item() || $item->is_course_item()) {
|
||||
$canoverride = (bool) get_config('moodle', 'grade_overridecat');
|
||||
}
|
||||
if ($canoverride) {
|
||||
// Only allow edting if the grade is editable (not locked, not in a unoverridable category, etc).
|
||||
if ($enableajax && $grade->is_editable()) {
|
||||
// If a grade item is type text, and we don't have show quick feedback on, it can't be edited.
|
||||
if ($item->gradetype != GRADE_TYPE_TEXT || $showquickfeedback) {
|
||||
$itemcell->attributes['class'] .= ' clickable';
|
||||
}
|
||||
}
|
||||
@ -1114,7 +1122,8 @@ class grade_report_grader extends grade_report {
|
||||
$jsarguments['cfg']['ajaxenabled'] = true;
|
||||
$jsarguments['cfg']['scales'] = array();
|
||||
foreach ($jsscales as $scale) {
|
||||
$jsarguments['cfg']['scales'][$scale->id] = explode(',', $scale->scale);
|
||||
// Trim the scale values, as they may have a space that is ommitted from values later.
|
||||
$jsarguments['cfg']['scales'][$scale->id] = array_map('trim', explode(',', $scale->scale));
|
||||
}
|
||||
$jsarguments['cfg']['feedbacktrunclength'] = $this->feedback_trunc_length;
|
||||
|
||||
|
@ -209,9 +209,11 @@ M.gradereport_grader.classes.ajax.prototype.make_editable = function(e) {
|
||||
}
|
||||
|
||||
// Sort out the field type
|
||||
var fieldtype = 'text';
|
||||
var fieldtype = 'value';
|
||||
if (node.hasClass('grade_type_scale')) {
|
||||
fieldtype = 'scale';
|
||||
} else if (node.hasClass('grade_type_text')) {
|
||||
fieldtype = 'text';
|
||||
}
|
||||
// Create the appropriate field widget
|
||||
switch (fieldtype) {
|
||||
@ -219,6 +221,8 @@ M.gradereport_grader.classes.ajax.prototype.make_editable = function(e) {
|
||||
this.current = new M.gradereport_grader.classes.scalefield(this.report, node);
|
||||
break;
|
||||
case 'text':
|
||||
this.current = new M.gradereport_grader.classes.feedbackfield(this.report, node);
|
||||
break;
|
||||
default:
|
||||
this.current = new M.gradereport_grader.classes.textfield(this.report, node);
|
||||
break;
|
||||
@ -322,7 +326,11 @@ M.gradereport_grader.classes.ajax.prototype.get_next_cell = function(cell) {
|
||||
next = tr.all('.grade').item(0);
|
||||
}
|
||||
if (!next) {
|
||||
next = this.current.node;
|
||||
return this.current.node;
|
||||
}
|
||||
// Continue on until we find a clickable cell
|
||||
if (!next.hasClass('clickable')) {
|
||||
return this.get_next_cell(next);
|
||||
}
|
||||
return next;
|
||||
};
|
||||
@ -342,7 +350,11 @@ M.gradereport_grader.classes.ajax.prototype.get_prev_cell = function(cell) {
|
||||
next = cells.item(cells.size()-1);
|
||||
}
|
||||
if (!next) {
|
||||
next = this.current.node;
|
||||
return this.current.node;
|
||||
}
|
||||
// Continue on until we find a clickable cell
|
||||
if (!next.hasClass('clickable')) {
|
||||
return this.get_prev_cell(next);
|
||||
}
|
||||
return next;
|
||||
};
|
||||
@ -366,7 +378,11 @@ M.gradereport_grader.classes.ajax.prototype.get_above_cell = function(cell) {
|
||||
next = tr.all('td.cell').item(column);
|
||||
}
|
||||
if (!next) {
|
||||
next = this.current.node;
|
||||
return this.current.node;
|
||||
}
|
||||
// Continue on until we find a clickable cell
|
||||
if (!next.hasClass('clickable')) {
|
||||
return this.get_above_cell(next);
|
||||
}
|
||||
return next;
|
||||
};
|
||||
@ -389,7 +405,13 @@ M.gradereport_grader.classes.ajax.prototype.get_below_cell = function(cell) {
|
||||
}
|
||||
next = tr.all('td.cell').item(column);
|
||||
}
|
||||
// next will be null when we get to the bottom of a column
|
||||
if (!next) {
|
||||
return this.current.node;
|
||||
}
|
||||
// Continue on until we find a clickable cell
|
||||
if (!next.hasClass('clickable')) {
|
||||
return this.get_below_cell(next);
|
||||
}
|
||||
return next;
|
||||
};
|
||||
/**
|
||||
@ -478,6 +500,7 @@ M.gradereport_grader.classes.ajax.prototype.submission_outcome = function(tid, o
|
||||
}
|
||||
// Calculate the final grade for the cell
|
||||
var finalgrade = '';
|
||||
var scalegrade = -1;
|
||||
if (!r.finalgrade) {
|
||||
if (this.report.isediting) {
|
||||
// In edit mode don't put hyphens in the grade text boxes
|
||||
@ -488,35 +511,51 @@ M.gradereport_grader.classes.ajax.prototype.submission_outcome = function(tid, o
|
||||
}
|
||||
} else {
|
||||
if (r.scale) {
|
||||
finalgrade = this.scales[r.scale][parseFloat(r.finalgrade)-1];
|
||||
scalegrade = parseFloat(r.finalgrade);
|
||||
finalgrade = this.scales[r.scale][scalegrade-1];
|
||||
} else {
|
||||
finalgrade = parseFloat(r.finalgrade).toFixed(info.itemdp);
|
||||
}
|
||||
}
|
||||
if (this.report.isediting) {
|
||||
if (args.properties.itemtype == 'scale') {
|
||||
info.cell.one('#grade_'+r.userid+'_'+r.itemid).all('options').each(function(option){
|
||||
if (option.get('value') == finalgrade) {
|
||||
option.setAttribute('selected', 'selected');
|
||||
} else {
|
||||
option.removeAttribute('selected');
|
||||
}
|
||||
});
|
||||
} else {
|
||||
info.cell.one('#grade_'+r.userid+'_'+r.itemid).set('value', finalgrade);
|
||||
var grade = info.cell.one('#grade_'+r.userid+'_'+r.itemid);
|
||||
if (grade) {
|
||||
// This means the item has a input element to update.
|
||||
var parent = grade.ancestor('td');
|
||||
if (parent.hasClass('grade_type_scale')) {
|
||||
grade.all('option').each(function(option) {
|
||||
if (option.get('value') == scalegrade) {
|
||||
option.setAttribute('selected', 'selected');
|
||||
} else {
|
||||
option.removeAttribute('selected');
|
||||
}
|
||||
});
|
||||
} else {
|
||||
grade.set('value', finalgrade);
|
||||
}
|
||||
} else if (info.cell.one('.gradevalue')) {
|
||||
// This means we are updating a value for something without editing boxed (locked, etc).
|
||||
info.cell.one('.gradevalue').set('innerHTML', finalgrade);
|
||||
}
|
||||
} else {
|
||||
// If there is no currently editing field or if this cell is not being currently edited
|
||||
if (!this.current || info.cell.get('id') != this.current.node.get('id')) {
|
||||
// Update the value
|
||||
info.cell.one('.gradevalue').set('innerHTML',finalgrade);
|
||||
var node = info.cell.one('.gradevalue');
|
||||
var td = node.ancestor('td');
|
||||
// Only scale and value type grades should have their content updated in this way.
|
||||
if (td.hasClass('grade_type_value') || td.hasClass('grade_type_scale')) {
|
||||
node.set('innerHTML', finalgrade);
|
||||
}
|
||||
} else if (this.current && info.cell.get('id') == this.current.node.get('id')) {
|
||||
// If we are here the grade value of the cell currently being edited has changed !!!!!!!!!
|
||||
// If the user has not actually changed the old value yet we will automatically correct it
|
||||
// otherwise we will prompt the user to choose to use their value or the new value!
|
||||
if (!this.current.has_changed() || confirm(M.util.get_string('ajaxfieldchanged', 'gradereport_grader'))) {
|
||||
this.current.set_grade(finalgrade);
|
||||
this.current.grade.set('value', finalgrade);
|
||||
if (this.current.grade) {
|
||||
this.current.grade.set('value', finalgrade);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -594,9 +633,10 @@ M.gradereport_grader.classes.existingfield = function(ajax, userid, itemid) {
|
||||
this.editfeedback = ajax.showquickfeedback;
|
||||
this.grade = this.report.Y.one('#grade_'+userid+'_'+itemid);
|
||||
|
||||
if (this.grade !== null) {
|
||||
for (var i = 0; i < this.report.grades.length; i++) {
|
||||
if (this.report.grades[i]['user']==this.userid && this.report.grades[i]['item']==this.itemid) {
|
||||
var i = 0;
|
||||
if (this.grade) {
|
||||
for (i = 0; i < this.report.grades.length; i++) {
|
||||
if (this.report.grades[i]['user'] == this.userid && this.report.grades[i]['item'] == this.itemid) {
|
||||
this.oldgrade = this.report.grades[i]['grade'];
|
||||
}
|
||||
}
|
||||
@ -609,7 +649,6 @@ M.gradereport_grader.classes.existingfield = function(ajax, userid, itemid) {
|
||||
|
||||
// On blur save any changes in the grade field
|
||||
this.grade.on('blur', this.submit, this);
|
||||
|
||||
}
|
||||
|
||||
// Check if feedback is enabled
|
||||
@ -617,9 +656,9 @@ M.gradereport_grader.classes.existingfield = function(ajax, userid, itemid) {
|
||||
// Get the feedback fields
|
||||
this.feedback = this.report.Y.one('#feedback_'+userid+'_'+itemid);
|
||||
|
||||
if (this.feedback !== null) {
|
||||
for(var i = 0; i < this.report.feedback.length; i++) {
|
||||
if (this.report.feedback[i]['user']==this.userid && this.report.feedback[i]['item']==this.itemid) {
|
||||
if (this.feedback) {
|
||||
for(i = 0; i < this.report.feedback.length; i++) {
|
||||
if (this.report.feedback[i]['user'] == this.userid && this.report.feedback[i]['item'] == this.itemid) {
|
||||
this.oldfeedback = this.report.feedback[i]['content'];
|
||||
}
|
||||
}
|
||||
@ -634,28 +673,40 @@ M.gradereport_grader.classes.existingfield = function(ajax, userid, itemid) {
|
||||
this.feedback.on('blur', this.submit, this);
|
||||
|
||||
// Override the default tab movements when moving between cells
|
||||
this.keyevents.push(this.report.Y.on('key', this.keypress_tab, this.feedback, 'press:9', this, true)); // Handle Tab
|
||||
this.keyevents.push(this.report.Y.on('key', this.keypress_enter, this.feedback, 'press:13', this)); // Handle the Enter key being pressed
|
||||
this.keyevents.push(this.report.Y.on('key', this.keypress_arrows, this.feedback, 'press:37,38,39,40+ctrl', this)); // Handle CTRL + arrow keys
|
||||
|
||||
|
||||
if (this.grade !== null) {
|
||||
// Override the default tab movements for fields in the same cell
|
||||
this.keyevents.push(this.report.Y.on('key', function(e){e.preventDefault();this.grade.focus();}, this.feedback, 'press:9+shift', this));
|
||||
this.keyevents.push(this.report.Y.on('key', function(e){if (e.shiftKey) {return;}e.preventDefault();this.feedback.focus();}, this.grade, 'press:9', this));
|
||||
// Handle Tab.
|
||||
this.keyevents.push(this.report.Y.on('key', this.keypress_tab, this.feedback, 'press:9', this, true));
|
||||
// Handle the Enter key being pressed.
|
||||
this.keyevents.push(this.report.Y.on('key', this.keypress_enter, this.feedback, 'press:13', this));
|
||||
// Handle CTRL + arrow keys.
|
||||
this.keyevents.push(this.report.Y.on('key', this.keypress_arrows, this.feedback, 'press:37,38,39,40+ctrl', this));
|
||||
|
||||
if (this.grade) {
|
||||
// Override the default tab movements when moving between cells
|
||||
if (this.editfeedback) {
|
||||
this.keyevents.push(this.report.Y.on('key', this.keypress_tab, this.grade, 'press:9+shift', this)); // Handle Shift+Tab
|
||||
}
|
||||
// Handle Shift+Tab.
|
||||
this.keyevents.push(this.report.Y.on('key', this.keypress_tab, this.grade, 'press:9+shift', this));
|
||||
|
||||
// Override the default tab movements for fields in the same cell
|
||||
this.keyevents.push(this.report.Y.on('key',
|
||||
function(e){e.preventDefault();this.grade.focus();},
|
||||
this.feedback,
|
||||
'press:9+shift',
|
||||
this));
|
||||
this.keyevents.push(this.report.Y.on('key',
|
||||
function(e){if (e.shiftKey) {return;}e.preventDefault();this.feedback.focus();},
|
||||
this.grade,
|
||||
'press:9',
|
||||
this));
|
||||
}
|
||||
}
|
||||
} else if (this.grade !== null) {
|
||||
this.keyevents.push(this.report.Y.on('key', this.keypress_tab, this.grade, 'press:9', this)); // Handle Tab and Shift+Tab
|
||||
} else if (this.grade) {
|
||||
// Handle Tab and Shift+Tab.
|
||||
this.keyevents.push(this.report.Y.on('key', this.keypress_tab, this.grade, 'press:9', this));
|
||||
}
|
||||
if (this.feedback !== null) {
|
||||
this.keyevents.push(this.report.Y.on('key', this.keypress_enter, this.grade, 'press:13', this)); // Handle the Enter key being pressed
|
||||
this.keyevents.push(this.report.Y.on('key', this.keypress_arrows, this.grade, 'press:37,38,39,40+ctrl', this)); // Handle CTRL + arrow keys
|
||||
if (this.grade) {
|
||||
// Handle the Enter key being pressed.
|
||||
this.keyevents.push(this.report.Y.on('key', this.keypress_enter, this.grade, 'press:13', this));
|
||||
// Handle CTRL + arrow keys.
|
||||
this.keyevents.push(this.report.Y.on('key', this.keypress_arrows, this.grade, 'press:37,38,39,40+ctrl', this));
|
||||
}
|
||||
};
|
||||
/**
|
||||
@ -753,10 +804,17 @@ M.gradereport_grader.classes.existingfield.prototype.move_focus = function(node)
|
||||
* @return {Bool}
|
||||
*/
|
||||
M.gradereport_grader.classes.existingfield.prototype.has_changed = function() {
|
||||
if (this.editfeedback) {
|
||||
return (this.grade.get('value') !== this.oldgrade || this.feedback.get('value') !== this.oldfeedback);
|
||||
if (this.grade) {
|
||||
if (this.grade.get('value') !== this.oldgrade) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return (this.grade.get('value') !== this.oldgrade);
|
||||
if (this.editfeedback && this.feedback) {
|
||||
if (this.feedback.get('value') !== this.oldfeedback) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
/**
|
||||
* Submits any changes and then updates the fields accordingly
|
||||
@ -771,15 +829,19 @@ M.gradereport_grader.classes.existingfield.prototype.submit = function() {
|
||||
|
||||
var properties = this.report.get_cell_info([this.userid,this.itemid]);
|
||||
var values = (function(f){
|
||||
var feedback, oldfeedback = null;
|
||||
if (f.editfeedback) {
|
||||
var feedback, oldfeedback, grade, oldgrade = null;
|
||||
if (f.editfeedback && f.feedback) {
|
||||
feedback = f.feedback.get('value');
|
||||
oldfeedback = f.oldfeedback;
|
||||
}
|
||||
if (f.grade) {
|
||||
grade = f.grade.get('value');
|
||||
oldgrade = f.oldgrade;
|
||||
}
|
||||
return {
|
||||
editablefeedback : f.editfeedback,
|
||||
grade : f.grade.get('value'),
|
||||
oldgrade : f.oldgrade,
|
||||
grade : grade,
|
||||
oldgrade : oldgrade,
|
||||
feedback : feedback,
|
||||
oldfeedback : oldfeedback
|
||||
};
|
||||
@ -811,11 +873,11 @@ M.gradereport_grader.classes.textfield = function(report, node) {
|
||||
this.gradespan = node.one('.gradevalue');
|
||||
this.inputdiv = this.report.Y.Node.create('<div></div>');
|
||||
this.editfeedback = this.report.ajax.showquickfeedback;
|
||||
this.grade = this.report.Y.Node.create('<input type="text" class="text" value="" />');
|
||||
this.grade = this.report.Y.Node.create('<input type="text" class="text" value="" name="ajaxgrade" />');
|
||||
this.gradetype = 'value';
|
||||
this.inputdiv.append(this.grade);
|
||||
if (this.report.ajax.showquickfeedback) {
|
||||
this.feedback = this.report.Y.Node.create('<input type="text" class="quickfeedback" value="" />');
|
||||
this.feedback = this.report.Y.Node.create('<input type="text" class="quickfeedback" value="" name="ajaxfeedback" />');
|
||||
this.inputdiv.append(this.feedback);
|
||||
}
|
||||
};
|
||||
@ -844,7 +906,11 @@ M.gradereport_grader.classes.textfield.prototype.replace = function() {
|
||||
this.set_feedback(this.get_feedback());
|
||||
}
|
||||
this.node.replaceChild(this.inputdiv, this.gradespan);
|
||||
this.grade.focus();
|
||||
if (this.grade) {
|
||||
this.grade.focus();
|
||||
} else if (this.feedback) {
|
||||
this.feedback.focus();
|
||||
}
|
||||
this.editable = true;
|
||||
return this;
|
||||
};
|
||||
@ -857,6 +923,7 @@ M.gradereport_grader.classes.textfield.prototype.replace = function() {
|
||||
M.gradereport_grader.classes.textfield.prototype.commit = function() {
|
||||
// Produce an anonymous result object contianing all values
|
||||
var result = (function(field){
|
||||
// Editable false lets us get the pre-update values.
|
||||
field.editable = false;
|
||||
var oldgrade = field.get_grade();
|
||||
if (oldgrade == '-') {
|
||||
@ -867,6 +934,8 @@ M.gradereport_grader.classes.textfield.prototype.commit = function() {
|
||||
if (field.editfeedback) {
|
||||
oldfeedback = field.get_feedback();
|
||||
}
|
||||
|
||||
// Now back to editable gives us the values in the edit areas.
|
||||
field.editable = true;
|
||||
if (field.editfeedback) {
|
||||
feedback = field.get_feedback();
|
||||
@ -943,7 +1012,11 @@ M.gradereport_grader.classes.textfield.prototype.set_grade = function(value) {
|
||||
*/
|
||||
M.gradereport_grader.classes.textfield.prototype.get_feedback = function() {
|
||||
if (this.editable) {
|
||||
return this.feedback.get('value');
|
||||
if (this.feedback) {
|
||||
return this.feedback.get('value');
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
var properties = this.report.get_cell_info(this.node);
|
||||
if (properties) {
|
||||
@ -959,7 +1032,9 @@ M.gradereport_grader.classes.textfield.prototype.get_feedback = function() {
|
||||
*/
|
||||
M.gradereport_grader.classes.textfield.prototype.set_feedback = function(value) {
|
||||
if (!this.editable) {
|
||||
this.feedback.set('value', value);
|
||||
if (this.feedback) {
|
||||
this.feedback.set('value', value);
|
||||
}
|
||||
} else {
|
||||
var properties = this.report.get_cell_info(this.node);
|
||||
this.report.update_feedback(properties.userid, properties.itemid, value);
|
||||
@ -983,7 +1058,12 @@ M.gradereport_grader.classes.textfield.prototype.has_changed = function() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return (this.get_grade() != this.gradespan.get('innerHTML'));
|
||||
|
||||
if (this.grade) {
|
||||
return (this.get_grade() != this.gradespan.get('innerHTML'));
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
/**
|
||||
* Attaches the key listeners for the editable fields and stored the event references
|
||||
@ -996,22 +1076,93 @@ M.gradereport_grader.classes.textfield.prototype.attach_key_events = function()
|
||||
var a = this.report.ajax;
|
||||
// Setup the default key events for tab and enter
|
||||
if (this.editfeedback) {
|
||||
this.keyevents.push(this.report.Y.on('key', a.keypress_tab, this.grade, 'press:9+shift', a)); // Handle Shift+Tab
|
||||
this.keyevents.push(this.report.Y.on('key', a.keypress_tab, this.feedback, 'press:9', a, true)); // Handle Tab
|
||||
this.keyevents.push(this.report.Y.on('key', a.keypress_enter, this.feedback, 'press:13', a)); // Handle the Enter key being pressed
|
||||
if (this.grade) {
|
||||
// Handle Shift+Tab.
|
||||
this.keyevents.push(this.report.Y.on('key', a.keypress_tab, this.grade, 'press:9+shift', a));
|
||||
}
|
||||
// Handle Tab.
|
||||
this.keyevents.push(this.report.Y.on('key', a.keypress_tab, this.feedback, 'press:9', a, true));
|
||||
// Handle the Enter key being pressed.
|
||||
this.keyevents.push(this.report.Y.on('key', a.keypress_enter, this.feedback, 'press:13', a));
|
||||
} else {
|
||||
this.keyevents.push(this.report.Y.on('key', a.keypress_tab, this.grade, 'press:9', a)); // Handle Tab and Shift+Tab
|
||||
if (this.grade) {
|
||||
// Handle Tab and Shift+Tab.
|
||||
this.keyevents.push(this.report.Y.on('key', a.keypress_tab, this.grade, 'press:9', a));
|
||||
}
|
||||
}
|
||||
|
||||
// Setup the arrow key events.
|
||||
// Handle CTRL + arrow keys.
|
||||
this.keyevents.push(this.report.Y.on('key', a.keypress_arrows, this.inputdiv.ancestor('td'), 'down:37,38,39,40+ctrl', a));
|
||||
|
||||
if (this.grade) {
|
||||
// Handle the Enter key being pressed.
|
||||
this.keyevents.push(this.report.Y.on('key', a.keypress_enter, this.grade, 'press:13', a));
|
||||
// Prevent the default key action on all fields for arrow keys on all key events!
|
||||
// Note: this still does not work in FF!!!!!
|
||||
this.keyevents.push(this.report.Y.on('key', function(e){e.preventDefault();}, this.grade, 'down:37,38,39,40+ctrl'));
|
||||
this.keyevents.push(this.report.Y.on('key', function(e){e.preventDefault();}, this.grade, 'press:37,38,39,40+ctrl'));
|
||||
this.keyevents.push(this.report.Y.on('key', function(e){e.preventDefault();}, this.grade, 'up:37,38,39,40+ctrl'));
|
||||
}
|
||||
this.keyevents.push(this.report.Y.on('key', a.keypress_enter, this.grade, 'press:13', a)); // Handle the Enter key being pressed
|
||||
// Setup the arrow key events
|
||||
this.keyevents.push(this.report.Y.on('key', a.keypress_arrows, this.grade.ancestor('td'), 'down:37,38,39,40+ctrl', a)); // Handle CTRL + arrow keys
|
||||
// Prevent the default key action on all fields for arrow keys on all key events!
|
||||
// Note: this still does not work in FF!!!!!
|
||||
this.keyevents.push(this.report.Y.on('key', function(e){e.preventDefault();}, this.grade, 'down:37,38,39,40+ctrl'));
|
||||
this.keyevents.push(this.report.Y.on('key', function(e){e.preventDefault();}, this.grade, 'press:37,38,39,40+ctrl'));
|
||||
this.keyevents.push(this.report.Y.on('key', function(e){e.preventDefault();}, this.grade, 'up:37,38,39,40+ctrl'));
|
||||
};
|
||||
|
||||
/**
|
||||
* Feedback field class
|
||||
* This classes gets used in conjunction with the report running with AJAX enabled
|
||||
* and is used to manage a cell that no editable grade, only possibly feedback
|
||||
*
|
||||
* @class feedbackfield
|
||||
* @constructor
|
||||
* @this {M.gradereport_grader.classes.feedbackfield}
|
||||
* @param {M.gradereport_grader.classes.report} report
|
||||
* @param {Y.Node} node
|
||||
*/
|
||||
M.gradereport_grader.classes.feedbackfield = function(report, node) {
|
||||
this.report = report;
|
||||
this.node = node;
|
||||
this.gradespan = node.one('.gradevalue');
|
||||
this.inputdiv = this.report.Y.Node.create('<div></div>');
|
||||
this.editfeedback = this.report.ajax.showquickfeedback;
|
||||
this.gradetype = 'text';
|
||||
if (this.report.ajax.showquickfeedback) {
|
||||
this.feedback = this.report.Y.Node.create('<input type="text" class="quickfeedback" value="" name="ajaxfeedback" />');
|
||||
this.inputdiv.append(this.feedback);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the grade for current cell (which will always be null)
|
||||
*
|
||||
* @function
|
||||
* @this {M.gradereport_grader.classes.feedbackfield}
|
||||
* @return {Mixed}
|
||||
*/
|
||||
M.gradereport_grader.classes.feedbackfield.prototype.get_grade = function() {
|
||||
return null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Overrides the set_grade function of textfield so that it can ignore the set-grade
|
||||
* for grade cells without grades
|
||||
*
|
||||
* @function
|
||||
* @this {M.gradereport_grader.classes.feedbackfield}
|
||||
* @param {String} value
|
||||
*/
|
||||
M.gradereport_grader.classes.feedbackfield.prototype.set_grade = function() {
|
||||
return;
|
||||
};
|
||||
|
||||
/**
|
||||
* Manually extend the feedbackfield class with the properties and methods of the
|
||||
* textfield class that have not been defined
|
||||
*/
|
||||
for (var i in M.gradereport_grader.classes.textfield.prototype) {
|
||||
if (!M.gradereport_grader.classes.feedbackfield.prototype[i]) {
|
||||
M.gradereport_grader.classes.feedbackfield.prototype[i] = M.gradereport_grader.classes.textfield.prototype[i];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An editable scale field
|
||||
*
|
||||
@ -1029,11 +1180,12 @@ M.gradereport_grader.classes.scalefield = function(report, node) {
|
||||
this.gradespan = node.one('.gradevalue');
|
||||
this.inputdiv = this.report.Y.Node.create('<div></div>');
|
||||
this.editfeedback = this.report.ajax.showquickfeedback;
|
||||
this.grade = this.report.Y.Node.create('<select type="text" class="text" /><option value="-1">'+M.util.get_string('ajaxchoosescale', 'gradereport_grader')+'</option></select>');
|
||||
this.grade = this.report.Y.Node.create('<select type="text" class="text" name="ajaxgrade" /><option value="-1">'+
|
||||
M.util.get_string('ajaxchoosescale', 'gradereport_grader')+'</option></select>');
|
||||
this.gradetype = 'scale';
|
||||
this.inputdiv.append(this.grade);
|
||||
if (this.editfeedback) {
|
||||
this.feedback = this.report.Y.Node.create('<input type="text" class="quickfeedback" value="" />');
|
||||
this.feedback = this.report.Y.Node.create('<input type="text" class="quickfeedback" value="" name="ajaxfeedback"/>');
|
||||
this.inputdiv.append(this.feedback);
|
||||
}
|
||||
var properties = this.report.get_cell_info(node);
|
||||
|
212
grade/report/grader/tests/behat/ajax_grader.feature
Normal file
212
grade/report/grader/tests/behat/ajax_grader.feature
Normal file
@ -0,0 +1,212 @@
|
||||
@gradereport @gradereport_grader
|
||||
Feature: Using the AJAX grading feature of Grader report to update grades and feedback
|
||||
In order to use AJAX grading
|
||||
As a teacher
|
||||
I need to be able to update and verify grades
|
||||
|
||||
|
||||
Background:
|
||||
Given the following "courses" exist:
|
||||
| fullname | shortname | category | groupmode |
|
||||
| Course 1 | C1 | 0 | 1 |
|
||||
And the following "users" exist:
|
||||
| username | firstname | lastname | email | idnumber |
|
||||
| teacher1 | Teacher | 1 | teacher1@example.com | t1 |
|
||||
| student1 | Student | 1 | student1@example.com | s1 |
|
||||
| student2 | Student | 2 | student2@example.com | s2 |
|
||||
| student3 | Student | 3 | student3@example.com | s3 |
|
||||
And the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
| student1 | C1 | student |
|
||||
| student2 | C1 | student |
|
||||
| student3 | C1 | student |
|
||||
And the following "scales" exist:
|
||||
| name | scale |
|
||||
| Test Scale | Disappointing,Good,Very good,Excellent |
|
||||
And the following "grade categories" exist:
|
||||
| fullname | course |
|
||||
| Grade Cat | C1 |
|
||||
And the following "grade items" exist:
|
||||
| itemname | course | locked | gradetype | gradecategory |
|
||||
| Item 1 | C1 | 0 | value | Grade Cat |
|
||||
| Item VU | C1 | 0 | value | Grade Cat |
|
||||
| Item VL | C1 | 1 | value | Grade Cat |
|
||||
| Item TU | C1 | 0 | text | Grade Cat |
|
||||
| Item TL | C1 | 1 | text | Grade Cat |
|
||||
And the following "grade items" exist:
|
||||
| itemname | course | locked | gradetype | scale | gradecategory |
|
||||
| Item SU | C1 | 0 | scale | Test Scale | Grade Cat |
|
||||
| Item SL | C1 | 1 | scale | Test Scale | Grade Cat |
|
||||
And the following "grade items" exist:
|
||||
| itemname | course | locked | gradetype | gradecategory |
|
||||
| Item 3 | C1 | 0 | value | Grade Cat |
|
||||
And the following config values are set as admin:
|
||||
| grade_report_showaverages | 0 |
|
||||
| grade_report_enableajax | 1 |
|
||||
|
||||
|
||||
@javascript
|
||||
Scenario: Use the grader report without editing, with AJAX on and quick feedback off
|
||||
When the following config values are set as admin:
|
||||
| grade_overridecat | 1 |
|
||||
| grade_report_showquickfeedback | 0 |
|
||||
And I log in as "teacher1"
|
||||
And I follow "Course 1"
|
||||
And I navigate to "Grades" node in "Course administration"
|
||||
And I click on student "Student 2" for grade item "Item VU"
|
||||
Then I should see a grade field for "Student 2" and grade item "Item VU"
|
||||
And I should not see a feedback field for "Student 2" and grade item "Item VU"
|
||||
And I set the field "ajaxgrade" to "33"
|
||||
And I press key "13" in the field "ajaxgrade"
|
||||
And I should not see a grade field for "Student 2" and grade item "Item VU"
|
||||
And I should not see a feedback field for "Student 2" and grade item "Item VU"
|
||||
And I click on student "Student 3" for grade item "Item VU"
|
||||
And I set the field "ajaxgrade" to "50"
|
||||
And I press key "13" in the field "ajaxgrade"
|
||||
And I click on student "Student 3" for grade item "Item 1"
|
||||
And I set the field "ajaxgrade" to "80"
|
||||
And I press key "13" in the field "ajaxgrade"
|
||||
And I click on student "Student 3" for grade item "Item SU"
|
||||
And I set the field "ajaxgrade" to "Very good"
|
||||
And I press key "13" in the field "ajaxgrade"
|
||||
And the following should exist in the "user-grades" table:
|
||||
| -1- | -4- | -5- | -9- | -13- |
|
||||
| Student 2 | - | 33.00 | - | 33.00 |
|
||||
| Student 3 | 80.00 | 50.00 | Very good | 133.00 |
|
||||
And I click on student "Student 3" for grade item "Item VL"
|
||||
And I should not see a grade field for "Student 3" and grade item "Item VL"
|
||||
And I should not see a feedback field for "Student 3" and grade item "Item VL"
|
||||
And I click on student "Student 3" for grade item "Item SL"
|
||||
And I should not see a grade field for "Student 3" and grade item "Item SL"
|
||||
And I should not see a feedback field for "Student 3" and grade item "Item SL"
|
||||
And I click on student "Student 3" for grade item "Item TU"
|
||||
And I should not see a grade field for "Student 3" and grade item "Item TU"
|
||||
And I should not see a feedback field for "Student 3" and grade item "Item TU"
|
||||
And I click on student "Student 1" for grade item "Course total"
|
||||
And I should see a grade field for "Student 1" and grade item "Course total"
|
||||
And I should not see a feedback field for "Student 1" and grade item "Course total"
|
||||
And I set the field "ajaxgrade" to "90"
|
||||
And I press key "13" in the field "ajaxgrade"
|
||||
And the following should exist in the "user-grades" table:
|
||||
| -1- | -13- |
|
||||
| Student 1 | 90.00 |
|
||||
And I navigate to "Grader report" node in "Grade administration"
|
||||
And the following should exist in the "user-grades" table:
|
||||
| -1- | -4- | -5- | -9- | -13- |
|
||||
| Student 1 | - | - | - | 90.00 |
|
||||
| Student 2 | - | 33.00 | - | 33.00 |
|
||||
| Student 3 | 80.00 | 50.00 | Very good | 133.00 |
|
||||
|
||||
@javascript
|
||||
Scenario: Use the grader report without editing, with AJAX and quick feedback on
|
||||
When the following config values are set as admin:
|
||||
| grade_overridecat | 1 |
|
||||
| grade_report_showquickfeedback | 1 |
|
||||
And I log in as "teacher1"
|
||||
And I follow "Course 1"
|
||||
And I navigate to "Grades" node in "Course administration"
|
||||
And I click on student "Student 2" for grade item "Item VU"
|
||||
Then I should see a grade field for "Student 2" and grade item "Item VU"
|
||||
And I should see a feedback field for "Student 2" and grade item "Item VU"
|
||||
And I set the field "ajaxgrade" to "33"
|
||||
And I set the field "ajaxfeedback" to "Student 2 VU feedback"
|
||||
And I press key "13" in the field "ajaxfeedback"
|
||||
And I click on student "Student 3" for grade item "Item VL"
|
||||
And I should not see a grade field for "Student 3" and grade item "Item VL"
|
||||
And I should not see a feedback field for "Student 3" and grade item "Item VL"
|
||||
And I click on student "Student 3" for grade item "Item TU"
|
||||
And I should not see a grade field for "Student 3" and grade item "Item TU"
|
||||
And I should see a feedback field for "Student 3" and grade item "Item TU"
|
||||
And I set the field "ajaxfeedback" to "Student 3 TU feedback"
|
||||
And I press key "13" in the field "ajaxfeedback"
|
||||
And I click on student "Student 2" for grade item "Item SU"
|
||||
And I set the field "ajaxgrade" to "Very good"
|
||||
And I set the field "ajaxfeedback" to "Student 2 SU feedback"
|
||||
And I press key "13" in the field "ajaxfeedback"
|
||||
And I navigate to "Grader report" node in "Grade administration"
|
||||
And the following should exist in the "user-grades" table:
|
||||
| -1- | -5- | -9- | -13- |
|
||||
| Student 2 | 33.00 | Very good | 36.00 |
|
||||
And I click on student "Student 3" for grade item "Item TU"
|
||||
And the field "ajaxfeedback" matches value "Student 3 TU feedback"
|
||||
And I click on student "Student 2" for grade item "Item SU"
|
||||
And the field "ajaxfeedback" matches value "Student 2 SU feedback"
|
||||
|
||||
@javascript
|
||||
Scenario: Use the grader report without editing, with AJAX and quick feedback on, without category override
|
||||
When the following config values are set as admin:
|
||||
| grade_overridecat | 0 |
|
||||
| grade_report_showquickfeedback | 1 |
|
||||
And I log in as "teacher1"
|
||||
And I follow "Course 1"
|
||||
And I navigate to "Grades" node in "Course administration"
|
||||
And I click on student "Student 2" for grade item "Item VU"
|
||||
Then I should see a grade field for "Student 2" and grade item "Item VU"
|
||||
And I should see a feedback field for "Student 2" and grade item "Item VU"
|
||||
And I set the field "ajaxgrade" to "33"
|
||||
And I press key "13" in the field "ajaxgrade"
|
||||
And I click on student "Student 2" for grade item "Course total"
|
||||
And I should not see a grade field for "Student 3" and grade item "Course total"
|
||||
And I should not see a feedback field for "Student 3" and grade item "Course total"
|
||||
And the following should exist in the "user-grades" table:
|
||||
| -1- | -5- | -13- |
|
||||
| Student 2 | 33.00 | 33.00 |
|
||||
|
||||
@javascript
|
||||
Scenario: Use the grader report with editing, with AJAX and quick feedback on, with category override
|
||||
When the following config values are set as admin:
|
||||
| grade_overridecat | 1 |
|
||||
| grade_report_showquickfeedback | 1 |
|
||||
And I log in as "teacher1"
|
||||
And I follow "Course 1"
|
||||
And I navigate to "Grades" node in "Course administration"
|
||||
And I turn editing mode on
|
||||
Then I should not see a grade field for "Student 2" and grade item "Item VL"
|
||||
And I should not see a feedback field for "Student 2" and grade item "Item VL"
|
||||
And I should not see a grade field for "Student 2" and grade item "Item TU"
|
||||
And I should see a feedback field for "Student 2" and grade item "Item TU"
|
||||
And I should see a grade field for "Student 2" and grade item "Course total"
|
||||
And I should see a feedback field for "Student 2" and grade item "Course total"
|
||||
And I give the grade "20.00" to the user "Student 2" for the grade item "Item VU"
|
||||
And I click away from student "Student 2" and grade item "Item VU" value
|
||||
And I give the grade "30.00" to the user "Student 2" for the grade item "Item 1"
|
||||
And I give the feedback "Some feedback" to the user "Student 2" for the grade item "Item 1"
|
||||
And I click away from student "Student 2" and grade item "Item 1" feedback
|
||||
And I give the grade "Very good" to the user "Student 2" for the grade item "Item SU"
|
||||
And I click away from student "Student 2" and grade item "Item SU" value
|
||||
And the grade for "Student 2" in grade item "Grade Cat" should match "53.00"
|
||||
And the grade for "Student 2" in grade item "Course total" should match "53.00"
|
||||
And I turn editing mode off
|
||||
And the following should exist in the "user-grades" table:
|
||||
| -1- | -4- | -5- | -9- | -12- | -13- |
|
||||
| Student 2 | 30.00 | 20.00 | Very good | 53.00 | 53.00 |
|
||||
And I click on student "Student 2" for grade item "Item 1"
|
||||
And the field "ajaxfeedback" matches value "Some feedback"
|
||||
|
||||
@javascript
|
||||
Scenario: Use the grader report with editing, with AJAX and quick feedback on, without category override
|
||||
When the following config values are set as admin:
|
||||
| grade_overridecat | 0 |
|
||||
| grade_report_showquickfeedback | 1 |
|
||||
And I log in as "teacher1"
|
||||
And I follow "Course 1"
|
||||
And I navigate to "Grades" node in "Course administration"
|
||||
And I turn editing mode on
|
||||
Then I should not see a grade field for "Student 2" and grade item "Course total"
|
||||
And I should not see a feedback field for "Student 2" and grade item "Course total"
|
||||
And I give the grade "20.00" to the user "Student 2" for the grade item "Item VU"
|
||||
And I click away from student "Student 2" and grade item "Item VU" value
|
||||
And I give the grade "30.00" to the user "Student 2" for the grade item "Item 1"
|
||||
And I click away from student "Student 2" and grade item "Item 1" value
|
||||
And I give the feedback "Some feedback" to the user "Student 2" for the grade item "Item 1"
|
||||
And I click away from student "Student 2" and grade item "Item 1" feedback
|
||||
And the following should exist in the "user-grades" table:
|
||||
| -1- | -13- |
|
||||
| Student 2 | 50.00 |
|
||||
And I turn editing mode off
|
||||
And the following should exist in the "user-grades" table:
|
||||
| -1- | -4- | -5- | -13- |
|
||||
| Student 2 | 30.00 | 20.00 | 50.00 |
|
||||
And I click on student "Student 2" for grade item "Item 1"
|
||||
And the field "ajaxfeedback" matches value "Some feedback"
|
273
grade/report/grader/tests/behat/behat_gradereport_grader.php
Normal file
273
grade/report/grader/tests/behat/behat_gradereport_grader.php
Normal file
@ -0,0 +1,273 @@
|
||||
<?php
|
||||
// This file is part of Stack - http://stack.bham.ac.uk/
|
||||
//
|
||||
// Stack 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.
|
||||
//
|
||||
// Stack 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 Stack. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Behat steps definitions for drag and drop onto image.
|
||||
*
|
||||
* @package gradereport_grader
|
||||
* @category test
|
||||
* @copyright 2015 Oakland University
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
// NOTE: no MOODLE_INTERNAL test here, this file may be required by behat before including /config.php.
|
||||
|
||||
require_once(__DIR__ . '/../../../../../lib/behat/behat_base.php');
|
||||
|
||||
use Behat\Behat\Context\Step\Given,
|
||||
Behat\Behat\Context\Step\Then,
|
||||
Behat\Mink\Exception\ExpectationException as ExpectationException,
|
||||
Behat\Mink\Exception\ElementNotFoundException as ElementNotFoundException;
|
||||
|
||||
/**
|
||||
* Steps definitions related with the drag and drop onto image question type.
|
||||
*
|
||||
* @copyright 2015 Oakland University
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class behat_gradereport_grader extends behat_base {
|
||||
/**
|
||||
* Click a given user grade cell.
|
||||
*
|
||||
* @Given /^I click on student "([^"]*)" for grade item "([^"]*)"$/
|
||||
* @param string $student
|
||||
* @param string $itemname
|
||||
* @return Given
|
||||
*/
|
||||
public function i_click_on_student_and_grade_item($student, $itemname) {
|
||||
$xpath = $this->get_student_and_grade_cell_selector($student, $itemname);
|
||||
|
||||
return new Given('I click on "' . $this->escape($xpath) . '" "xpath_element"');
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove focus for a grade value cell.
|
||||
*
|
||||
* @Given /^I click away from student "([^"]*)" and grade item "([^"]*)" value$/
|
||||
* @param string $student
|
||||
* @param string $itemname
|
||||
* @return Given
|
||||
*/
|
||||
public function i_click_away_from_student_and_grade_value($student, $itemname) {
|
||||
$xpath = $this->get_student_and_grade_value_selector($student, $itemname);
|
||||
|
||||
return new Given('I take focus off "' . $this->escape($xpath) . '" "xpath_element"');
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove focus for a grade value cell.
|
||||
*
|
||||
* @Given /^I click away from student "([^"]*)" and grade item "([^"]*)" feedback$/
|
||||
* @param string $student
|
||||
* @param string $itemname
|
||||
* @return Given
|
||||
*/
|
||||
public function i_click_away_from_student_and_grade_feedback($student, $itemname) {
|
||||
$xpath = $this->get_student_and_grade_feedback_selector($student, $itemname);
|
||||
|
||||
return new Given('I take focus off "' . $this->escape($xpath) . '" "xpath_element"');
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks grade values with or without a edit box.
|
||||
*
|
||||
* @Then /^the grade for "([^"]*)" in grade item "([^"]*)" should match "([^"]*)"$/
|
||||
* @throws Exception
|
||||
* @throws ElementNotFoundException
|
||||
* @param string $student
|
||||
* @param string $itemname
|
||||
* @param string $value
|
||||
* @return Then
|
||||
*/
|
||||
public function the_grade_should_match($student, $itemname, $value) {
|
||||
$xpath = $this->get_student_and_grade_value_selector($student, $itemname);
|
||||
|
||||
$gradefield = $this->getSession()->getPage()->find('xpath', $xpath);
|
||||
if (!empty($gradefield)) {
|
||||
// Get the field.
|
||||
$fieldtype = behat_field_manager::guess_field_type($gradefield, $this->getSession());
|
||||
if (!$fieldtype) {
|
||||
throw new Exception('Could not get field type for grade field "' . $itemname . '"');
|
||||
}
|
||||
$field = behat_field_manager::get_field_instance($fieldtype, $gradefield, $this->getSession());
|
||||
if (!$field->matches($value)) {
|
||||
$fieldvalue = $field->get_value();
|
||||
throw new ExpectationException(
|
||||
'The "' . $student . '" and "' . $itemname . '" grade is "' . $fieldvalue . '", "' . $value . '" expected' ,
|
||||
$this->getSession()
|
||||
);
|
||||
}
|
||||
} else {
|
||||
// If there isn't a form field, just search for contents.
|
||||
$valueliteral = $this->getSession()->getSelectorsHandler()->xpathLiteral($value);
|
||||
|
||||
$xpath = $this->get_student_and_grade_cell_selector($student, $itemname);
|
||||
$xpath .= "[contains(normalize-space(.)," . $valueliteral . ")]";
|
||||
|
||||
$node = $this->getSession()->getDriver()->find($xpath);
|
||||
if (empty($node)) {
|
||||
$locatorexceptionmsg = 'Cell for "' . $student . '" and "' . $itemname . '" with value "' . $value . '"';
|
||||
throw new ElementNotFoundException($this->getSession(), $locatorexceptionmsg, null, $xpath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Look for a grade editing field.
|
||||
*
|
||||
* @Then /^I should see a grade field for "([^"]*)" and grade item "([^"]*)"$/
|
||||
* @param string $student
|
||||
* @param string $itemname
|
||||
* @return Then
|
||||
*/
|
||||
public function i_should_see_grade_field($student, $itemname) {
|
||||
$xpath = $this->get_student_and_grade_value_selector($student, $itemname);
|
||||
|
||||
return new Then('"' . $this->escape($xpath) . '" "xpath_element" should be visible');
|
||||
}
|
||||
|
||||
/**
|
||||
* Look for a feedback editing field.
|
||||
*
|
||||
* @Then /^I should see a feedback field for "([^"]*)" and grade item "([^"]*)"$/
|
||||
* @param string $student
|
||||
* @param string $itemname
|
||||
* @return Then
|
||||
*/
|
||||
public function i_should_see_feedback_field($student, $itemname) {
|
||||
$xpath = $this->get_student_and_grade_feedback_selector($student, $itemname);
|
||||
|
||||
return new Then('"' . $this->escape($xpath) . '" "xpath_element" should be visible');
|
||||
}
|
||||
|
||||
/**
|
||||
* Look for a lack of the grade editing field.
|
||||
*
|
||||
* @Then /^I should not see a grade field for "([^"]*)" and grade item "([^"]*)"$/
|
||||
* @param string $student
|
||||
* @param string $itemname
|
||||
* @return Then
|
||||
*/
|
||||
public function i_should_not_see_grade_field($student, $itemname) {
|
||||
$xpath = $this->get_student_and_grade_value_selector($student, $itemname);
|
||||
|
||||
return new Then('"' . $this->escape($xpath) . '" "xpath_element" should not exist');
|
||||
}
|
||||
|
||||
/**
|
||||
* Look for a lack of the feedback editing field.
|
||||
*
|
||||
* @Then /^I should not see a feedback field for "([^"]*)" and grade item "([^"]*)"$/
|
||||
* @param string $student
|
||||
* @param string $itemname
|
||||
* @return Then
|
||||
*/
|
||||
public function i_should_not_see_feedback_field($student, $itemname) {
|
||||
$xpath = $this->get_student_and_grade_feedback_selector($student, $itemname);
|
||||
|
||||
return new Then('"' . $this->escape($xpath) . '" "xpath_element" should not exist');
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the user id from its name.
|
||||
*
|
||||
* @throws Exception
|
||||
* @param string $name
|
||||
* @return int
|
||||
*/
|
||||
protected function get_user_id($name) {
|
||||
global $DB;
|
||||
$names = explode(' ', $name);
|
||||
|
||||
if (!$id = $DB->get_field('user', 'id', array('firstname' => $names[0], 'lastname' => $names[1]))) {
|
||||
throw new Exception('The specified user with username "' . $name . '" does not exist');
|
||||
}
|
||||
return $id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the grade item id from its name.
|
||||
*
|
||||
* @throws Exception
|
||||
* @param string $itemname
|
||||
* @return int
|
||||
*/
|
||||
protected function get_grade_item_id($itemname) {
|
||||
global $DB;
|
||||
|
||||
if ($id = $DB->get_field('grade_items', 'id', array('itemname' => $itemname))) {
|
||||
return $id;
|
||||
}
|
||||
|
||||
// The course total is a special case.
|
||||
if ($itemname === "Course total") {
|
||||
if (!$id = $DB->get_field('grade_items', 'id', array('itemtype' => 'course'))) {
|
||||
throw new Exception('The specified grade_item with name "' . $itemname . '" does not exist');
|
||||
}
|
||||
return $id;
|
||||
}
|
||||
|
||||
// Find a category with the name.
|
||||
if ($catid = $DB->get_field('grade_categories', 'id', array('fullname' => $itemname))) {
|
||||
if ($id = $DB->get_field('grade_items', 'id', array('iteminstance' => $catid))) {
|
||||
return $id;
|
||||
}
|
||||
}
|
||||
|
||||
throw new Exception('The specified grade_item with name "' . $itemname . '" does not exist');
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets unique xpath selector for a student/grade item combo.
|
||||
*
|
||||
* @throws Exception
|
||||
* @param string $student
|
||||
* @param string $itemname
|
||||
* @return string
|
||||
*/
|
||||
protected function get_student_and_grade_cell_selector($student, $itemname) {
|
||||
$itemid = 'u' . $this->get_user_id($student) . 'i' . $this->get_grade_item_id($itemname);
|
||||
return "//table[@id='user-grades']//td[@id='" . $itemid . "']";
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets xpath for a particular student/grade item grade value cell.
|
||||
*
|
||||
* @throws Exception
|
||||
* @param string $student
|
||||
* @param string $itemname
|
||||
* @return string
|
||||
*/
|
||||
protected function get_student_and_grade_value_selector($student, $itemname) {
|
||||
$cell = $this->get_student_and_grade_cell_selector($student, $itemname);
|
||||
return $cell . "//*[contains(@id, 'grade_') or @name='ajaxgrade']";
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets xpath for a particular student/grade item feedback cell.
|
||||
*
|
||||
* @throws Exception
|
||||
* @param string $student
|
||||
* @param string $itemname
|
||||
* @return string
|
||||
*/
|
||||
protected function get_student_and_grade_feedback_selector($student, $itemname) {
|
||||
$cell = $this->get_student_and_grade_cell_selector($student, $itemname);
|
||||
return $cell . "//input[contains(@id, 'feedback_') or @name='ajaxfeedback']";
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -48,6 +48,23 @@ class behat_grade extends behat_base {
|
||||
return new Given('I set the field "' . $this->escape($fieldstr) . '" to "' . $grade . '"');
|
||||
}
|
||||
|
||||
/**
|
||||
* Enters a quick feedback via the gradebook for a specific grade item and user when viewing
|
||||
* the 'Grader report' with editing mode turned on.
|
||||
*
|
||||
* @Given /^I give the feedback "(?P<grade_number>(?:[^"]|\\")*)" to the user "(?P<username_string>(?:[^"]|\\")*)" for the grade item "(?P<grade_activity_string>(?:[^"]|\\")*)"$/
|
||||
* @param string $feedback
|
||||
* @param string $userfullname the user's fullname as returned by fullname()
|
||||
* @param string $itemname
|
||||
* @return Given
|
||||
*/
|
||||
public function i_give_the_feedback($feedback, $userfullname, $itemname) {
|
||||
$gradelabel = $userfullname . ' ' . $itemname;
|
||||
$fieldstr = get_string('useractivityfeedback', 'gradereport_grader', $gradelabel);
|
||||
|
||||
return new Given('I set the field "' . $this->escape($fieldstr) . '" to "' . $this->escape($feedback) . '"');
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the settings of a grade item or category or the course.
|
||||
*
|
||||
|
Loading…
x
Reference in New Issue
Block a user