Skip to content

Commit

Permalink
SAK-42905 Gradebook add ability to have comments for the course grade (
Browse files Browse the repository at this point in the history
…sakaiproject#10807)

Co-authored-by: jkozar2 <moronzac@moronzac-hpzbook15g2>
  • Loading branch information
jkozar2 and jkozar2 authored Nov 13, 2022
1 parent 012bc09 commit 2d3eb7b
Show file tree
Hide file tree
Showing 19 changed files with 421 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -733,6 +733,8 @@ public void setAssignmentScoreString(String gradebookUid, String assignmentName,
*/
public String getAverageCourseGrade(String gradebookUid);

public Long getCourseGradeId(final Long gradebookId);

/**
* Update the ordering of an assignment. This can be performed on internal and external assignments.
* @param gradebookUid uid of the gradebook
Expand Down
1 change: 1 addition & 0 deletions gradebookng/bundle/src/main/bundle/gradebookng.properties
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ label.updateungradeditems.confirmation.cancel=Cancel
label.updateungradeditems.groups=Group / Section

label.studentsummary.coursegrade = Course Grade:
label.studentsummary.coursegradecomment = Comment:
label.studentsummary.gradeitems = Gradebook Items
label.studentsummary.outof = /{0}
label.studentsummary.coursegrade.display = {0} ({1})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2846,6 +2846,15 @@ private void postUpdateGradeEvent(String gradebookUid, String assignmentName, St
"/gradebook/" + gradebookUid + "/" + assignmentName + "/" + studentUid + "/" + pointsEarned + "/student");
}

/**
* Get the student's course grade's GradableObject ID.
*
* @return coursegrade's GradableObject ID.
*/
public Long getCourseGradeId(Long gradebookId) {
return getCourseGrade(gradebookId).getId();
}

/**
* Send a GradebookEvent to Sakai's event table
*
Expand Down Expand Up @@ -4983,18 +4992,24 @@ public CommentDefinition getAssignmentScoreComment(String gradebookUid, Long ass
if (StringUtils.isBlank(gradebookUid) || assignmentId == null || StringUtils.isBlank(studentUid)) {
throw new IllegalArgumentException("gradebookUid, assignmentId and studentUid must be valid.");
}

String assignmentName = "";
final GradebookAssignment assignment = getAssignmentWithoutStats(gradebookUid, assignmentId);
if (assignment == null) {
throw new AssessmentNotFoundException("There is no assignmentId " + assignmentId + " for gradebookUid " + gradebookUid);
CourseGrade courseGrade = getCourseGrade(getGradebook(gradebookUid).getId());
if(courseGrade != null && courseGrade.getId().equals(assignmentId)){ //check if this is a course grade before declaring it Not Found
assignmentName = courseGrade.getName();
} else {
throw new AssessmentNotFoundException("There is no assignmentId " + assignmentId + " for gradebookUid " + gradebookUid);
}
} else {
assignmentName = assignment.getName();
}

CommentDefinition commentDefinition = null;
final Optional<Comment> optComment = gradingPersistenceManager.getInternalComment(studentUid, gradebookUid, assignmentId);
if (optComment.isPresent()) {
Comment comment = optComment.get();
commentDefinition = new CommentDefinition();
commentDefinition.setAssignmentName(assignment.getName());
commentDefinition.setAssignmentName(assignmentName);
commentDefinition.setCommentText(comment.getCommentText());
commentDefinition.setDateRecorded(comment.getDateRecorded());
commentDefinition.setGraderUid(comment.getGraderId());
Expand All @@ -5013,6 +5028,12 @@ public void setAssignmentScoreComment(String gradebookUid, Long assignmentId, St
Comment comment = null;
if (optComment.isEmpty()) {
comment = new Comment(studentUid, commentText, getAssignmentWithoutStats(gradebookUid, assignmentId));
if(getAssignmentWithoutStats(gradebookUid, assignmentId) == null){ //will happen if we are commenting on Course Grade
CourseGrade courseGrade = getCourseGrade(getGradebook(gradebookUid).getId());
if(courseGrade != null && courseGrade.getId().equals(assignmentId)){ //make sure ID is actually making reference to the course grade
comment = new Comment(studentUid, commentText, courseGrade);
}
}
} else {
comment = optComment.get();
comment.setCommentText(commentText);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,20 @@ public void assignmentScoreComment() {
assertNull(commentDefinition);
}

@Test
public void courseGradeComment() {
Gradebook gradebook = createGradebook();
String comment = "This is your course grade.";

gradingService.setAssignmentScoreComment(gradebook.getUid(), gradingService.getCourseGradeId(gradebook.getId()), user1, comment);
CommentDefinition commentDefinition = gradingService.getAssignmentScoreComment(gradebook.getUid(), gradingService.getCourseGradeId(gradebook.getId()), user1);
assertEquals(comment, commentDefinition.getCommentText());

gradingService.deleteAssignmentScoreComment(gradebook.getUid(), gradingService.getCourseGradeId(gradebook.getId()), user1);
commentDefinition = gradingService.getAssignmentScoreComment(gradebook.getUid(), gradingService.getCourseGradeId(gradebook.getId()), user1);
assertNull(commentDefinition);
}

@Test
public void getAssignmentByNameOrId() {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -698,6 +698,14 @@ public CourseGradeTransferBean getCourseGrade(final String studentUuid) {
return courseGrade;
}

/**
* Get the student's course grade's GradableObject ID.
* @return coursegrade's GradableObject ID.
*/
public Long getCourseGradeId(Long gradebookId){
return this.gradingService.getCourseGradeId(gradebookId);
}

/**
* Save the grade and comment for a student's assignment and do concurrency checking
*
Expand Down Expand Up @@ -1283,7 +1291,7 @@ public void putCourseGradesInMatrix(Map<String, GbStudentGradeInfo> matrix, List
final CourseGradeTransferBean gbCourseGrade = courseGrades.get(uid);
gbCourseGrade.setDisplayString(courseGradeFormatter.format(courseGrade));
sg.setCourseGrade(gbCourseGrade);

sg.setHasCourseGradeComment(StringUtils.isNotBlank(getAssignmentGradeComment(getCurrentSiteId(),courseGrade.getId(),uid)));
// Add to map so we can build on it later
matrix.put(uid, sg);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ public class GbStudentGradeInfo implements Serializable {
private CourseGradeTransferBean courseGrade;
private Map<Long, GbGradeInfo> grades;
private Map<Long, Double> categoryAverages;
@Setter
private boolean hasCourseGradeComment;
private List<String> sections;

public GbStudentGradeInfo() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,23 @@ public String getComments(final EntityView view, final Map<String, Object> param
return formattedText.escapeHtml(businessService.getAssignmentGradeComment(siteId, assignmentId, studentUuid));
}

@SuppressWarnings("unused")
@EntityCustomAction(action = "courseGradeComment", viewKey = EntityView.VIEW_LIST)
public String getCourseGradeComment(final EntityView view, final Map<String, Object> params) {
// get params
final String siteId = (String) params.get("siteId");
final long courseGradeId = NumberUtils.toLong((String) params.get("courseGradeId"));
final String studentUuid = (String) params.get("studentUuid");
final long gradebookId = NumberUtils.toLong((String) params.get("gradebookId"));
// check params supplied are valid
if (StringUtils.isBlank(siteId) || gradebookId==0 || courseGradeId == 0 || StringUtils.isBlank(studentUuid)) {
throw new IllegalArgumentException("Request data was missing / invalid");
}
checkValidSite(siteId);
checkInstructorOrTA(siteId);
return this.businessService.getAssignmentGradeComment(siteId, courseGradeId, studentUuid);
}

private Set<String> getRecipients(Map<String, Object> params) {

final String siteId = (String) params.get("siteId");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package org.sakaiproject.gradebookng.tool.actions;

import com.fasterxml.jackson.databind.JsonNode;
import org.apache.commons.lang3.StringUtils;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
import org.apache.wicket.model.Model;
import org.sakaiproject.gradebookng.tool.model.GbModalWindow;
import org.sakaiproject.gradebookng.tool.pages.GradebookPage;
import org.sakaiproject.gradebookng.tool.panels.EditCourseGradeCommentPanel;
import org.sakaiproject.gradebookng.business.GradebookNgBusinessService;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;

public class EditCourseGradeCommentAction extends InjectableAction implements Serializable{
private class EmptyOkResponse implements ActionResponse {
public EmptyOkResponse() {
}

public String getStatus() {
return "OK";
}

public String toJson() {
return "{}";
}
}

@Override
public ActionResponse handleEvent(final JsonNode params, final AjaxRequestTarget target) {
final String courseGradeId = params.get("courseGradeId").asText();
final String studentUuid = params.get("studentId").asText();
final String gradebookId = params.get("gradebookId").asText();
final Map<String, Object> model = new HashMap<>();
model.put("courseGradeId", Long.valueOf(courseGradeId));
model.put("studentUuid", studentUuid);
model.put("gradebookId", Long.valueOf(gradebookId));
final GradebookPage gradebookPage = (GradebookPage) target.getPage();
final GbModalWindow window = gradebookPage.getGradeCommentWindow();
final EditCourseGradeCommentPanel panel = new EditCourseGradeCommentPanel(window.getContentId(), Model.ofMap(model), window);
window.setContent(panel);
window.showUnloadConfirmation(false);
window.clearWindowClosedCallbacks();
window.setAssignmentToReturnFocusTo(courseGradeId);
window.setStudentToReturnFocusTo(studentUuid);
window.addWindowClosedCallback(new ModalWindow.WindowClosedCallback() {
private static final long serialVersionUID = 1L;

@Override
public void onClose(final AjaxRequestTarget target) {
final String comment = panel.getComment();
target.appendJavaScript(
String.format("GbGradeTable.updateCourseGradeComment('%s', '%s', '%s');",
courseGradeId,
studentUuid,
comment == null ? "" : comment));
}
});
window.show(target);
return new EditCourseGradeCommentAction.EmptyOkResponse();
}

public boolean hasCourseGradeComment(final String studentId, final Long courseGradeId, final Long gradebookId){
GradebookNgBusinessService businessService = new GradebookNgBusinessService();
String comment = businessService.getAssignmentGradeComment(gradebookId.toString(),courseGradeId.longValue(),studentId);
if(StringUtils.isBlank(comment)){
return false;
}
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,8 @@
<span class="gb-value {if isOverridden} gb-overridden {/if}">
${value}
</span>
<span class="gb-notification"></span>
<span class="gb-course-comment-notification"></span>
{if GbGradeTable.settings.isUserAbleToEditAssessments}
<div class="btn-group">
<button type="button"
Expand All @@ -333,6 +335,7 @@
tabindex="-1">
</button>
<ul class="dropdown-menu dropdown-menu-right">
<li><a class="gb-edit-course-grade-comments dropdown-item" href="#" role="menuitem"><wicket:message key="comment.option.edit" /></a></li>
<li><a href="javascript:void(0);" class="gb-course-grade-override dropdown-item"><wicket:message key="coursegrade.option.override"/></a></li>
<li><a href="javascript:void(0);" class="gb-course-grade-override-log dropdown-item"><wicket:message key="coursegrade.option.overridelog"/></a></li>
</ul>
Expand Down Expand Up @@ -419,10 +422,16 @@ <h4 class="sr-only"><wicket:message key="metadata.header" /></h4>
<li class="gb-metadata-comment-notification">
<span class="gb-flag-comment"></span> <wicket:message key="grade.notifications.hascomment"/>
<blockquote><wicket:message key="grade.notifications.commentloading"/></blockquote>
{if defined('readonly') && !readonly}
<div>
<a href="javascript:void(0);" class="gb-edit-comments"><wicket:message key="grade.notifications.editcomment"/></a>
</div>
{if defined('readonly') && !readonly}
{if defined('hasCourseGradeComment') && hasCourseGradeComment == 1}
<div>
<a href="javascript:void(0);" class="gb-edit-course-grade-comments"><wicket:message key="grade.notifications.editcomment"/></a>
</div>
{else}
<div>
<a href="javascript:void(0);" class="gb-edit-comments"><wicket:message key="grade.notifications.editcomment"/></a>
</div>
{/if}
{/if}
</li>
{elseif notification.type == 'extra-credit'}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ public class GbGradeTableData {
private boolean isUserAbleToEditAssessments;
private Map<String, Double> courseGradeMap;
private Map<String, Boolean> hasAssociatedRubricMap;
private Long courseGradeId;
private Long gradebookId;
private boolean isStudentNumberVisible;
private boolean isSectionsVisible;

Expand Down Expand Up @@ -95,7 +97,8 @@ public GbGradeTableData(final GradebookNgBusinessService businessService,
courseGradeMap = gradebook.getSelectedGradeMapping().getGradeMap();

hasAssociatedRubricMap = businessService.buildHasAssociatedRubricMap(assignments);

gradebookId = gradebook.getId();
courseGradeId = businessService.getCourseGradeId(gradebookId);
isStudentNumberVisible = businessService.isStudentNumberVisible();

isSectionsVisible = businessService.isSectionsVisible();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ public class GbGradebookData {

private final List<StudentDefinition> students;
private final List<ColumnDefinition> columns;
private final Long courseGradeId;
private final Long gradebookId;
private final List<GbStudentGradeInfo> studentGradeInfoList;
private final List<CategoryDefinition> categories;
private final GradebookInformation settings;
Expand Down Expand Up @@ -92,7 +94,7 @@ private class StudentDefinition {
private String hasConcurrentEdit;
private String readonly;
private String hasExcuse;

private String hasCourseGradeComment;
private String studentNumber;
private String hasDroppedScores;
private List<String> sections;
Expand Down Expand Up @@ -200,21 +202,25 @@ private class DataSet {
private List<String[]> courseGrades;
private String serializedGrades;
private Map<String, Object> settings;

private Long courseGradeId;
private Long gradebookId;
private int rowCount;
private int columnCount;

public DataSet(final List<StudentDefinition> students,
final List<ColumnDefinition> columns,
final List<String[]> courseGrades,
final String serializedGrades,
final Map<String, Object> settings) {
final Map<String, Object> settings,
final Long courseGradeId,
final Long gradebookId) {
this.students = students;
this.columns = columns;
this.courseGrades = courseGrades;
this.serializedGrades = serializedGrades;
this.settings = settings;

this.courseGradeId = courseGradeId;
this.gradebookId = gradebookId;
this.rowCount = students.size();
this.columnCount = columns.size();
}
Expand All @@ -231,7 +237,8 @@ public GbGradebookData(final GbGradeTableData gbGradeTableData, final Component
this.isUserAbleToEditAssessments = gbGradeTableData.isUserAbleToEditAssessments();

this.courseGradeMap = gbGradeTableData.getCourseGradeMap();

this.courseGradeId = gbGradeTableData.getCourseGradeId();
this.gradebookId = gbGradeTableData.getGradebookId();
this.isStudentNumberVisible = gbGradeTableData.isStudentNumberVisible();
this.isSectionsVisible = gbGradeTableData.isSectionsVisible();

Expand Down Expand Up @@ -279,7 +286,9 @@ public String toScript() {
GbGradebookData.this.columns,
courseGrades(),
serializeGrades(grades),
serializeSettings());
serializeSettings(),
GbGradebookData.this.courseGradeId,
GbGradebookData.this.gradebookId);

try {
// TODO: Can we serialize Booleans without the get prefix?
Expand Down Expand Up @@ -493,7 +502,7 @@ private List<StudentDefinition> loadStudents(final List<GbStudentGradeInfo> stud
studentDefinition.setHasComments(formatColumnFlags(student, g -> StringUtils.isNotBlank(g.getGradeComment())));
studentDefinition.setHasDroppedScores(formatColumnFlags(student, g -> g.isDroppedFromCategoryScore()));
studentDefinition.setHasExcuse(formatColumnFlags(student, g -> g.isExcused()));

studentDefinition.setHasCourseGradeComment(student.isHasCourseGradeComment() ? "1" : "0");
if (this.isStudentNumberVisible) {
studentDefinition.setStudentNumber(student.getStudentNumber());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
import org.sakaiproject.gradebookng.tool.actions.DeleteAssignmentAction;
import org.sakaiproject.gradebookng.tool.actions.EditAssignmentAction;
import org.sakaiproject.gradebookng.tool.actions.EditCommentAction;
import org.sakaiproject.gradebookng.tool.actions.EditCourseGradeCommentAction;
import org.sakaiproject.gradebookng.tool.actions.EditSettingsAction;
import org.sakaiproject.gradebookng.tool.actions.ExcuseGradeAction;
import org.sakaiproject.gradebookng.tool.actions.GradeUpdateAction;
Expand Down Expand Up @@ -301,6 +302,7 @@ public GbGradeTableData load() {
this.gradeTable.addEventListener("previewRubric", new ViewRubricPreviewAction());
this.gradeTable.addEventListener("overrideCourseGrade", new OverrideCourseGradeAction());
this.gradeTable.addEventListener("editComment", new EditCommentAction());
this.gradeTable.addEventListener("editCourseGradeComment", new EditCourseGradeCommentAction());
this.gradeTable.addEventListener("viewGradeSummary", new ViewGradeSummaryAction());
this.gradeTable.addEventListener("setZeroScore", new SetZeroScoreAction());
this.gradeTable.addEventListener("viewCourseGradeLog", new ViewCourseGradeLogAction());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<!DOCTYPE html>
<html xmlns:wicket="http://wicket.apache.org">
<body>
<wicket:panel>
<form class="form-vertical" wicket:id="form">
<textarea wicket:id="comment" rows="4" class="form-control form-group"></textarea>
<div class="">
<input type="submit" wicket:id="submit" wicket:message="value:button.savecomment" />
<input type="submit" wicket:id="cancel" wicket:message="value:button.cancel" />
</div>
</form>
</wicket:panel>
</body>
</html>
Loading

0 comments on commit 2d3eb7b

Please sign in to comment.