Commit 34d43cd9 authored by mathieso's avatar mathieso

Working on the grading interface.

parent e49ab7f4
This diff is collapsed.
This diff is collapsed.
......@@ -7,7 +7,11 @@
:class="{'js-collapse-panel-body':!submissionGraded}"
>
{{ rubricItem.title }}
<span class="glyphicon glyphicon-trash" aria-hidden="true"></span>
<span
v-show="isAnyOptionSelected"
@click.stop="clearChoice"
title="Clear your choice"
>Clear</span>
<div class="pull-right">
<!--Button to collapse/expand rubric item option deets.
Used Bootstrap animations rather than Vue transitions, because I like the effect.
......@@ -95,7 +99,7 @@
data() {
return {
//Which response did the grader choose for this item?
responseOptionIdChosen: 0,
// responseOptionIdChosen: 0,
//Max length in characters of an option summary.
maxOptionSummaryLength: 80,
/**
......@@ -106,6 +110,7 @@
* keep: boolean
*/
newOptions: [],
isAnyOptionSelected: false
}
},
computed: {
......@@ -122,6 +127,7 @@
let optionIndex = changeObject.optionIndex;
let newText = changeObject.text;
this.newOptions[optionIndex].title = newText;
this.isAnyOptionSelected = this.computeIsAnyOptionSelected();
},
/**
* Is there a new option that has MT text?
......@@ -145,6 +151,7 @@
this.$nextTick(()=>{
this.$forceUpdate();
});
this.isAnyOptionSelected = this.computeIsAnyOptionSelected();
},
/**
* User clicked keep button on a new option.
......@@ -157,6 +164,7 @@
this.$nextTick(()=>{
this.$forceUpdate();
});
this.isAnyOptionSelected = this.computeIsAnyOptionSelected();
},
/**
* User clicked delete button on a new option.
......@@ -167,6 +175,7 @@
this.$nextTick(()=>{
this.$forceUpdate();
});
this.isAnyOptionSelected = this.computeIsAnyOptionSelected();
},
/**
* User clicked button to add a new option.
......@@ -181,31 +190,21 @@
keep: true
}
);
this.isAnyOptionSelected = this.computeIsAnyOptionSelected();
},
rubricItemUpdate(){
this.isAnyOptionSelected = this.computeIsAnyOptionSelected();
this.$forceUpdate();
},
/**
* This rubric item is complete, collapse it.
*/
rubricItemComplete() {
let $collapseButton = $(this.$refs.collapseButton);
//Only collapse if not already collapsed.
if ( $collapseButton.find('span.glyphicon').hasClass('glyphicon-triangle-top') ) {
$collapseButton.click();
}
},
/**
* Pass event emitted by option up to parent.
*/
rubricItemsPaneUpdate() {
// console.log('RI emitting');
this.$emit('rubricItemsPaneUpdate');
computeIsAnyOptionSelected() {
// console.log("call computeIsAnyOptionSelected");
let chosen = this.getChosenOptionsText();
const isAnythingSelected = (chosen.length > 0);
// console.log("isAnythingSelected", isAnythingSelected);
return isAnythingSelected;
},
/**
* Summarize the options chosen for this rubric.
*/
summarizeOptionsChosen(){
getChosenOptionsText() {
let chosen = [];
let submissionRubricItemChoices = window.submissions[this.submissionId].rubricItemChoices;
//Are there entries for this rubric item?
......@@ -228,6 +227,57 @@
chosen.push( newOption.title.trim() );
}
});
// console.log("chosen", chosen);
return chosen;
},
/**
* This rubric item is complete, collapse it.
*/
rubricItemComplete() {
let $collapseButton = $(this.$refs.collapseButton);
//Only collapse if not already collapsed.
if ( $collapseButton.find('span.glyphicon').hasClass('glyphicon-triangle-top') ) {
$collapseButton.click();
}
},
/**
* Pass event emitted by option up to parent.
*/
rubricItemsPaneUpdate() {
// console.log('RI emitting');
this.$emit('rubricItemsPaneUpdate');
},
/**
* User wants to forget choices.
*/
clearChoice(event) {
console.log("clear event", event);
// Show the RI choices.
const target = $(event.target);
var $panel = target.closest('.panel');
var panelBody = $panel.find('.panel-body');
$(panelBody).show("medium");
window.submissions[this.submissionId].rubricItemChoices = [];
this.newOptions = [];
this.rubricItemUpdate();
this.summarizeOptionsChosen();
// window.thing = this;
// console.log("this", this);
// console.log("this.$refs", this.$refs);
// console.log("this.$children", this.$children);
// console.log("this.$options", this.$options);
for (const index in this.$children) {
const child = this.$children[index];
// console.log("child", child);
child.updateSelf();
}
this.isAnyOptionSelected = this.computeIsAnyOptionSelected();
},
/**
* Summarize the options chosen for this rubric.
*/
summarizeOptionsChosen(){
let chosen = this.getChosenOptionsText();
let result = '';
if ( chosen.length === 0 ) {
result = '(Nothing chosen)';
......@@ -236,6 +286,36 @@
result = chosen.join('<br>');
}
return '<small>' + result + '</small>';
// let chosen = [];
// let submissionRubricItemChoices = window.submissions[this.submissionId].rubricItemChoices;
// //Are there entries for this rubric item?
// if ( submissionRubricItemChoices[this.rubricItemId] !== undefined ) {
// //Yes.
// //Get the choices for this rubric item.
// let choiceIds = submissionRubricItemChoices[this.rubricItemId];
// choiceIds.forEach( choiceId => {
// let choiceResponse = window.responseOptions[choiceId].response;
// //Trim to max length.
// if ( choiceResponse.length > this.maxOptionSummaryLength ) {
// choiceResponse = choiceResponse.substring(0, this.maxOptionSummaryLength - 4) + '...';
// }
// chosen.push(choiceResponse);
// });
// } //End if there are choices.
// //See if there are any new items that need to be added.
// this.newOptions.forEach( newOption => {
// if ( newOption.chosen ) {
// chosen.push( newOption.title.trim() );
// }
// });
// let result = '';
// if ( chosen.length === 0 ) {
// result = '(Nothing chosen)';
// }
// else {
// result = chosen.join('<br>');
// }
// return '<small>' + result + '</small>';
},
}
}
......
......@@ -50,6 +50,10 @@
},
},
methods: {
updateSelf() {
this.$forceUpdate();
},
/**
* Get the existing choices for this submission.
*/
......
......@@ -345,7 +345,7 @@
// },
//User clicked the Create message button.
createMessage() {
// console.log('createMessage');
console.log('createMessage');
let message = '';
const student = window.students[
window.submissions[this.submissionId].studentId
......@@ -374,16 +374,49 @@
}
message += overallEvalMessage; // + '<br><br>';
//Chosen rubric responses.
// Sort them by order of RIs they're in, in the exercise.
const rubricItemChoicesUnsorted = window.submissions[this.submissionId].rubricItemChoices;
console.log("rubricItemChoicesUnsorted", rubricItemChoicesUnsorted);
const exerciseId = window.submissions[this.submissionId].exerciseId;
console.log("exerciseId", exerciseId);
const exerciseRubricItemIds = window.exercises[exerciseId].rubricItemIds;
console.log("exerciseRubricItemIds", exerciseRubricItemIds);
// The target array.
const graderChoices = [];
for (let exerciseRubricItemIdIndex = 0;
exerciseRubricItemIdIndex < exerciseRubricItemIds.length;
exerciseRubricItemIdIndex ++) {
// if (exerciseRubricItemIds[exerciseRubricItemIdIndex]) {
// Get a rubric item id that is in the exercise.
const rubricItemId = exerciseRubricItemIds[exerciseRubricItemIdIndex];
console.log("start outer loop rubricItemId", rubricItemId);
// Find this one in the unsorted array.
for (const rubricItemId in rubricItemChoicesUnsorted) {
console.log("inner loop rubricItemId", rubricItemId);
if (rubricItemChoicesUnsorted[rubricItemId]) {
console.log("inner loop found rubricItemChoicesUnsorted[rubricItemId]",
rubricItemChoicesUnsorted[rubricItemId]);
graderChoices.push(rubricItemChoicesUnsorted[rubricItemId]);
break;
}
}
// }
}
console.log("graderChoices", graderChoices);
return;
// Get the options for that RI.
// const rubricItemOptions = window.rubricItems[rubricItemId].responseOptionIds;
message += '<ul>';
let graderChoices = window.submissions[this.submissionId].rubricItemChoices;
let that = this;
graderChoices.forEach( function(choicesForRubricItem) {
choicesForRubricItem.forEach( function(responseOptionId){
let responseText = window.responseOptions[responseOptionId].response;
if (isCanSeeNames) {
responseText = this.replaceStudentNameTokens(responseText, student);
responseText = that.replaceStudentNameTokens(responseText, student);
}
else {
responseText = this.killStudentNameTokens(responseText);
responseText = that.killStudentNameTokens(responseText);
}
message += `<li>${responseText}</li>`;
});
......@@ -395,10 +428,10 @@
if ( newOption.chosen ) {
let newOptionTitle = newOption.title;
if (isCanSeeNames) {
newOptionTitle = this.replaceStudentNameTokens(newOptionTitle, student);
newOptionTitle = that.replaceStudentNameTokens(newOptionTitle, student);
}
else {
newOptionTitle = this.killStudentNameTokens(newOptionTitle);
newOptionTitle = that.killStudentNameTokens(newOptionTitle);
}
// console.log('',);
if ( newOptionTitle.trim() === '' ) {
......
......@@ -3,10 +3,13 @@ $(document).ready(function () {
//When js-collapse-panel-body elements are nested, propagation causes problems.
e.stopPropagation();
e.preventDefault();
console.log("collapse clicked");
var $this = $(this);
var $panel = $this.closest('.panel');
var panelBody = $panel.find('.panel-body');
$(panelBody).collapse('toggle'); //toggle();
$(panelBody).toggle("medium");
// $(panelBody).collapse('toggle'); //toggle();
var iconSpan = $this.find('span.glyphicon');
iconSpan.toggleClass('glyphicon-triangle-bottom');
iconSpan.toggleClass('glyphicon-triangle-top');
......
......@@ -31,6 +31,10 @@ Students can see own history
Add multifield for exercies on due, even if just use first one.
When add response, can have old text, instead of MT.
Didn't save text of response, when edited multiple RIs.
# Testing
......@@ -47,8 +51,6 @@ Toggle of keep-this-response unclear, when id on or off.
Refresh after a while crashes.
Show RIs where uncollapsey items not changed.
**2.0** Show prior submissions.
**2.0** Maintain order of RIs in text message
......@@ -57,11 +59,10 @@ Show RIs where uncollapsey items not changed.
**2.0** Allow ungrade option. Allow regrade option. Delay notification?
**2.0** Allow RI to be unset while grading.
F/b allows building for dist. Why not exercise RI editor?
Save and edit fior exercises
......@@ -298,8 +299,6 @@ Toggle of keep-this-response unclear, when id on or off.
Refresh after a while crashes.
Show RIs where uncollapsey items not changed.
**2.0** Show prior submissions.
**2.0** Maintain order of RIs in text message
......@@ -308,8 +307,6 @@ Show RIs where uncollapsey items not changed.
**2.0** Allow ungrade option. Allow regrade option. Delay notification?
**2.0** Allow RI to be unset while grading.
......
......@@ -86,7 +86,7 @@ class Assessment {
* @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
* @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
*/
public function computeNumSubmissionsWaitingAssessment() {
public function computeNumSubmissionsWaitingAssessment($includeUnpublishedExercises = TRUE) {
// Exit if not grader.
if (!$this->currentUser->isGrader()) {
return NULL;
......@@ -106,7 +106,7 @@ class Assessment {
$class = $this->entityTypeManager
->getStorage('node')->load($classNid);
$classUngradedSubmissions
= $this->countUngradedSubmissionsForClass($class);
= $this->countUngradedSubmissionsForClass($class, $includeUnpublishedExercises);
$totalSubmissionsToGrade += $classUngradedSubmissions;
}
return $totalSubmissionsToGrade;
......@@ -130,7 +130,7 @@ class Assessment {
* @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
* @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
*/
public function countUngradedSubmissionsForClass(Node $class) {
public function countUngradedSubmissionsForClass(Node $class, $includeUnpublishedExercises = TRUE) {
// Another redundant check. Paranoia much?
if (!$class->isPublished()) {
return 0;
......@@ -161,16 +161,19 @@ class Assessment {
}
// Query to grab ids of published submissions from those students
// that have not been graded.
$submissionCount = $this->entityTypeManager->getStorage('node')
$query = $this->entityTypeManager->getStorage('node')
->getQuery()
->condition('type', SkillingConstants::EXERCISE_SUBMISSION_CONTENT_TYPE)
// Published submissions.
->condition('status', 1)
->condition('field_user', $studentIds, 'IN')
// Published exercises only.
->condition('field_exercise.entity.status', 1)
// No feedback given.
->notExists('field_when_feedback_given')
->notExists('field_when_feedback_given');
if (!$includeUnpublishedExercises) {
// Published exercises only.
$query->condition('field_exercise.entity.status', 1);
}
$submissionCount = $query
->count()
->execute();
return $submissionCount;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment