Skip to content

Commit

Permalink
SAK-44853 Create unified UserMessagingService (sakaiproject#9887)
Browse files Browse the repository at this point in the history
* SAK-44853 Create unified UserMessagingService

https://jira.sakaiproject.org/browse/SAK-44853

* Remove spring-data-commons version override

Co-authored-by: Earle Nietzel <[email protected]>
  • Loading branch information
adrianfish and ern authored Sep 30, 2021
1 parent 0eb1e03 commit a010fe4
Show file tree
Hide file tree
Showing 242 changed files with 2,612 additions and 4,696 deletions.
1 change: 1 addition & 0 deletions assignment/api/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
<includes>
<include>**/*.properties</include>
<include>**/*.metaprops</include>
<include>**/*.xml</include>
</includes>
</resource>
<resource>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
*/
public final class AssignmentConstants {

public static final String TOOL_ID = "sakai.assignment.grades";

public final static String MODEL_ANSWER_SHOW_TO_STUDENT = "show_to_student";
public final static int MODEL_ANSWER_SHOW_TO_STUDENT_BEFORE_STARTS = 1;
public final static int MODEL_ANSWER_SHOW_TO_STUDENT_AFTER_SUBMIT = 2;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
*/

public interface AssignmentService extends EntityProducer {

Entity createAssignmentEntity(String assignmentId);

Entity createAssignmentEntity(Assignment assignment);
Expand Down
10 changes: 6 additions & 4 deletions assignment/api/src/resources/assignment.properties
Original file line number Diff line number Diff line change
Expand Up @@ -932,7 +932,9 @@ send.submission.releasegrade.email.none=Do not send notification email to studen
send.submission.releasegrade.email=Send notification email to student when the grade is released

noti.releasegrade.subject.content=Email notification for assignment released grade
noti.releasegrade.text=Your submission to assignment ''{0}'' has been returned. Please go to {1} to view details.
#noti.releasegrade.text=Your submission to assignment ''{0}'' has been returned. Please go to {1} to view details.
noti.releasegrade.text=Your submission to assignment ''{0}'' has been returned. To view the details, click
noti.here=here

not_allowed_to_grade_in_gradebook=The assignment is associated with a Gradebook item. Since you are not allowed to grade in Gradebook, you cannot grade here in Assignments tool. However, you can still update the comment area and upload attachment(s) for grading purposes.

Expand Down Expand Up @@ -1158,9 +1160,9 @@ submissionConfirmMessage=You are about to submit this assignment for grading. Pl
email.reminder.hello=Hello {0}
email.reminder.subject=Assignment ''{0}'' Due on {1}
email.reminder.duewithin=Reminder: An assignment is due within {0}
email.reminder.assignment=<strong>Assignment</strong> : {0}
email.reminder.duedate=<strong>Due</strong> : {0}
email.reminder.site=<strong>Site</strong> : {0}
email.reminder.assignment=Assignment :
email.reminder.duedate=>Due :
email.reminder.site=Site :
email.reminder.andhours=and {0} hours.
email.reminder.hours={0} hours.
email.reminder.days={0} days
Expand Down
36 changes: 36 additions & 0 deletions assignment/api/src/resources/templates/dueReminder.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<emailTemplates>
<emailTemplate>
<subject>${bundle["email.reminder.subject"]?replace("{0}", assignmentTitle)?replace("{1}", subjectDate)}</subject>
<message>
${bundle["email.reminder.hello"]?replace("{0}", firstName)}

${bundle["email.reminder.duewithin"]?replace("{0}", timeText)}

${bundle["gen.assig"]} : ${assignmentTitle}
${bundle["gen.due"]} : ${bodyDate}
${bundle["email.reminder.site"]} &lt;a href="${siteUrl}"&gt;${siteTitle}&lt;/a&gt;

- ${localSakaiName}
</message>
<messagehtml>
${bundle["email.reminder.hello"]?replace("{0}", firstName)}
&lt;br&gt;
&lt;br&gt;
${bundle["email.reminder.duewithin"]?replace("{0}", timeText)}
&lt;br&gt;
${bundle["gen.assig"]} : &lt;a href="${assignmentUrl}"&gt;${assignmentTitle}&lt;/a&gt;
&lt;br&gt;
${bundle["gen.due"]} : ${bodyDate}
&lt;br&gt;
${bundle["email.reminder.site"]} &lt;a href="${siteUrl}"&gt;${siteTitle}&lt;/a&gt;
&lt;br&gt;
- ${localSakaiName}
</messagehtml>
<version>1</version>
<owner>admin</owner>
<key>sakai.assignment.grades.duereminder</key>
<locale></locale>
<localeLangTag></localeLangTag>
</emailTemplate>
</emailTemplates>
23 changes: 23 additions & 0 deletions assignment/api/src/resources/templates/releaseGrade.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<emailTemplates>
<emailTemplate>
<subject>[${localSakaiName}] ${bundle["noti.releasegrade.subject.content"]} </subject>
<message>
${bundle["noti.site.title"]} ${siteTitle}
${bundle["noti.site.url"]} ${siteUrl}

${bundle["noti.releasegrade.text"]?replace("{0}", assignmentTitle)?replace("{1}", assignmentUrl)}
</message>
<messagehtml>
${bundle["noti.site.title"]} &lt;a href="${siteUrl}"&gt;${siteTitle}&lt;/a&gt;
&lt;br /&gt;
&lt;br /&gt;
${bundle["noti.releasegrade.text"]?replace("{0}", assignmentTitle)} &lt;a href="${assignmentUrl}"&gt;${bundle["noti.here"]}&lt;/a&gt;
</messagehtml>
<version>1</version>
<owner>admin</owner>
<key>sakai.assignment.grades.releasegrade</key>
<locale></locale>
<localeLangTag></localeLangTag>
</emailTemplate>
</emailTemplates>
29 changes: 29 additions & 0 deletions assignment/api/src/resources/templates/releaseResubmission.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<emailTemplates>
<emailTemplate>
<subject>[${localSakaiName}] ${bundle["noti.releasegrade.subject.content"]}</subject>
<message>${bundle["noti.site.title"]} ${siteTitle}
${bundle["noti.site.url"]} &lt;a href="${siteUrl}"&gt;${siteUrl}&lt;/a&gt;

&lt;#if canSubmit>
${bundle["noti.releaseresubmission.text"]?replace("{0}", assignmentTitle)?replace("{1}", assignmentUrl)}
&lt;#else&gt;
${bundle["noti.releaseresubmission.noresubmit.text"]?replace("{0}", assignmentTitle)?replace("{1}", assignmentUrl)}
&lt;/#if&gt;
</message>
<messagehtml>${bundle["noti.site.title"]} ${siteTitle}
${bundle["noti.site.url"]} &lt;a href="${siteUrl}">${siteUrl}&lt;/a&gt;
&lt;br /&gt;
&lt;#if canSubmit>
${bundle["noti.releaseresubmission.text"]?replace("{0}", assignmentTitle)?replace("{1}", assignmentUrl)}
&lt;#else&gt;
${bundle["noti.releaseresubmission.noresubmit.text"]?replace("{0}", assignmentTitle)?replace("{1}", assignmentUrl)}
&lt;/#if&gt;
</messagehtml>
<version>1</version>
<owner>admin</owner>
<key>sakai.assignment.grades.releaseresubmission</key>
<locale></locale>
<localeLangTag></localeLangTag>
</emailTemplate>
</emailTemplates>
61 changes: 61 additions & 0 deletions assignment/api/src/resources/templates/submission.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="UTF-8"?>
<emailTemplates>
<emailTemplate>
<subject>[${localSakaiName}] ${bundle["noti.subject.content"]} </subject>
<message>${bundle["noti.site.title"]} ${siteTitle}
${bundle["noti.site.url"]} ${siteUrl}
${bundle["assignment.title"]} ${assignmentTitle}

&lt;#if !hideDueDate&gt;
${bundle["noti.assignment.duedate"]} ${dueDate}
&lt;/#if&gt;

${bundle["noti.student"]} ${submitterNames} ${submitterIds}

${bundle["submission.id"]} ${submissionId}

${bundle["noti.submit.time"]} ${submittedDate}

${bundle["gen.submittedtext"]}


${submittedText!""}

${attachmentType!""}


${attachmentsBlock!""}
</message>
<messagehtml>
${bundle["noti.site.title"]} &lt;a href="${siteUrl}"&gt;${siteTitle}&lt;/a&gt;
&lt;br&gt;
&lt;br&gt;
${bundle["assignment.title"]} &lt;a href="${assignmentUrl}"&gt;${assignmentTitle}&lt;/a&gt;
&lt;br&gt;
&lt;br&gt;

&lt;#if !hideDueDate&gt;
${bundle["noti.assignment.duedate"]} ${dueDate}
&lt;/#if&gt;
&lt;br&gt;

${bundle["noti.student"]} ${submitterNames} ${submitterIds}
&lt;br /&gt;
${bundle["noti.submit.time"]} ${submittedDate}
&lt;br /&gt;

&lt;h4&gt;${bundle["gen.submittedtext"]}&lt;/h4&gt;
${submittedText!""}
&lt;br /&gt;

${attachmentType!""}
&lt;br /&gt;
${attachmentsBlock!""}
</messagehtml>
<version>1</version>
<owner>admin</owner>
<key>sakai.assignment.grades.submission</key>
<locale></locale>
<localeLangTag></localeLangTag>
</emailTemplate>
</emailTemplates>
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
import java.util.zip.ZipOutputStream;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.annotation.Resource;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.io.FilenameUtils;
Expand Down Expand Up @@ -116,7 +117,6 @@
import org.sakaiproject.contentreview.exception.QueueException;
import org.sakaiproject.contentreview.service.ContentReviewService;
import org.sakaiproject.email.api.DigestService;
import org.sakaiproject.email.api.EmailService;
import org.sakaiproject.entity.api.Entity;
import org.sakaiproject.entity.api.EntityManager;
import org.sakaiproject.entity.api.EntityTransferrer;
Expand All @@ -141,6 +141,9 @@
import org.sakaiproject.exception.PermissionException;
import org.sakaiproject.exception.ServerOverloadException;
import org.sakaiproject.exception.TypeException;
import org.sakaiproject.messaging.api.Message;
import org.sakaiproject.messaging.api.MessageMedium;
import org.sakaiproject.messaging.api.UserMessagingService;
import org.sakaiproject.rubrics.logic.RubricsConstants;
import org.sakaiproject.rubrics.logic.RubricsService;
import org.sakaiproject.rubrics.logic.model.ToolItemRubricAssociation;
Expand Down Expand Up @@ -215,8 +218,6 @@ public class AssignmentServiceImpl implements AssignmentService, EntityTransferr
@Setter private CandidateDetailProvider candidateDetailProvider;
@Setter private ContentHostingService contentHostingService;
@Setter private ContentReviewService contentReviewService;
@Setter private DigestService digestService;
@Setter private EmailService emailService;
@Setter private EmailUtil emailUtil;
@Setter private EntityManager entityManager;
@Setter private EventTrackingService eventTrackingService;
Expand All @@ -241,6 +242,7 @@ public class AssignmentServiceImpl implements AssignmentService, EntityTransferr
@Setter private TimeService timeService;
@Setter private ToolManager toolManager;
@Setter private UserDirectoryService userDirectoryService;
@Resource private UserMessagingService userMessagingService;
@Setter private UserTimeService userTimeService;

private boolean allowSubmitByInstructor;
Expand Down Expand Up @@ -276,6 +278,11 @@ public void init() {

// this is needed to avoid a circular dependency, notice we set the AssignmentService proxy and not this
assignmentSupplementItemService.setAssignmentService(applicationContext.getBean(AssignmentService.class));

userMessagingService.importTemplateFromResourceXmlFile("templates/releaseGrade.xml", AssignmentConstants.TOOL_ID + ".releasegrade");
userMessagingService.importTemplateFromResourceXmlFile("templates/releaseResubmission.xml", AssignmentConstants.TOOL_ID + ".releaseresubmission");
userMessagingService.importTemplateFromResourceXmlFile("templates/submission.xml", AssignmentConstants.TOOL_ID + ".submission");
userMessagingService.importTemplateFromResourceXmlFile("templates/dueReminder.xml", AssignmentConstants.TOOL_ID + ".duereminder");
}

@Override
Expand Down Expand Up @@ -2141,7 +2148,6 @@ public void getSubmissionsZip(OutputStream out, String reference, String query)
}
} else {

//List<String> submitterIds = getSubmitterIdList(searchFilterOnly, viewString.length() == 0 ? AssignmentConstants.ALL:viewString, searchString, aRef, contextString == null? a.getContext():contextString);
Map<User, AssignmentSubmission> submitters = getSubmitterMap(searchFilterOnly,
viewString.length() == 0 ? AssignmentConstants.ALL : viewString,
searchString,
Expand Down Expand Up @@ -3441,15 +3447,24 @@ private void zipSubmissions(String assignmentReference, String assignmentTitle,
final ZipEntry additionalEntry = new ZipEntry(root + resourceLoader.getString("assignment.additional.notes.file.title") + ".html");
out.putNextEntry(additionalEntry);

String htmlString = emailUtil.htmlPreamble("additionalnotes");
htmlString += "<h1>" + resourceLoader.getString("assignment.additional.notes.export.title") + "</h1>";
htmlString += "<div>" + resourceLoader.getString("assignment.additional.notes.export.header") + "</div><br/>";
htmlString += "<table border=\"1\" style=\"border-collapse:collapse;\"><tr><th>" + resourceLoader.getString("gen.student") + "</th><th>" + resourceLoader.getString("gen.notes") + "</th>" + submittersAdditionalNotesHtml + "</table>";
htmlString += "<br/><div>" + resourceLoader.getString("assignment.additional.notes.export.footer") + "</div>";
htmlString += emailUtil.htmlEnd();
log.debug("Additional information html: " + htmlString);

final byte[] wes = htmlString.getBytes();
StringBuilder htmlString = new StringBuilder();
htmlString.append("<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\n")
.append(" \"http://www.w3.org/TR/html4/loose.dtd\">\n")
.append("<html>\n")
.append(" <head><title>additionalnotes</title></head>\n")
.append(" <body>\n")
.append("<h1>").append(resourceLoader.getString("assignment.additional.notes.export.title")).append("</h1>")
.append("<div>").append(resourceLoader.getString("assignment.additional.notes.export.header")).append("</div><br/>")
.append("<table border=\"1\" style=\"border-collapse:collapse;\"><tr><th>")
.append(resourceLoader.getString("gen.student")).append("</th><th>")
.append(resourceLoader.getString("gen.notes")).append("</th>").append(submittersAdditionalNotesHtml)
.append("</table>")
.append("<br/><div>").append(resourceLoader.getString("assignment.additional.notes.export.footer")).append("</div>")
.append("\n </body>\n</html>\n");

log.debug("Additional information html: {}", htmlString.toString());

final byte[] wes = htmlString.toString().getBytes();
out.write(wes);
additionalEntry.setSize(wes.length);
out.closeEntry();
Expand Down Expand Up @@ -4456,10 +4471,11 @@ private void sendGradeReleaseNotification(AssignmentSubmission submission) {
String resubmitNumber = submission.getProperties().get(AssignmentConstants.ALLOW_RESUBMIT_NUMBER);

boolean released = BooleanUtils.toBoolean(submission.getGradeReleased());
Set<String> submitterIds = submission.getSubmitters().stream().map(AssignmentSubmissionSubmitter::getSubmitter).collect(Collectors.toSet());
Set<String> submitterIds = new HashSet<>();
try {
Set<String> siteUsers = siteService.getSite(siteId).getUsers();
filteredUsers = submitterIds.stream().filter(siteUsers::contains).map(id -> {
submitterIds = submission.getSubmitters().stream().map(AssignmentSubmissionSubmitter::getSubmitter).filter(siteUsers::contains).collect(Collectors.toSet());
filteredUsers = submitterIds.stream().map(id -> {
try {
return userDirectoryService.getUser(id);
} catch (UserNotDefinedException e) {
Expand All @@ -4475,15 +4491,19 @@ private void sendGradeReleaseNotification(AssignmentSubmission submission) {
if (released && StringUtils.equals(AssignmentConstants.ASSIGNMENT_RELEASEGRADE_NOTIFICATION_EACH, assignmentProperties.get(AssignmentConstants.ASSIGNMENT_RELEASEGRADE_NOTIFICATION_VALUE))) {
// send email to every submitters
if (!filteredUsers.isEmpty()) {
// send the message immidiately
emailService.sendToUsers(filteredUsers, emailUtil.getHeaders(null, "releasegrade"), emailUtil.getNotificationMessage(submission, "releasegrade"));
// send the message immediately
userMessagingService.message(filteredUsers,
Message.builder().tool(AssignmentConstants.TOOL_ID).type("releasegrade").build(),
Arrays.asList(new MessageMedium[] {MessageMedium.EMAIL}), emailUtil.getReleaseGradeReplacements(assignment, siteId), NotificationService.NOTI_REQUIRED);
}
}
if (StringUtils.isNotBlank(resubmitNumber) && StringUtils.equals(AssignmentConstants.ASSIGNMENT_RELEASERESUBMISSION_NOTIFICATION_EACH, assignmentProperties.get(AssignmentConstants.ASSIGNMENT_RELEASERESUBMISSION_NOTIFICATION_VALUE))) {
// send email to every submitters
if (!filteredUsers.isEmpty()) {
// send the message immidiately
emailService.sendToUsers(filteredUsers, emailUtil.getHeaders(null, "releaseresumbission"), emailUtil.getNotificationMessage(submission, "releaseresumbission"));
userMessagingService.message(filteredUsers,
Message.builder().tool(AssignmentConstants.TOOL_ID).type("releaseresubmission").build(),
Arrays.asList(new MessageMedium[] {MessageMedium.EMAIL}), emailUtil.getReleaseResubmissionReplacements(submission), NotificationService.NOTI_REQUIRED);
}
}
}
Expand All @@ -4500,19 +4520,17 @@ private void notificationToInstructors(AssignmentSubmission submission, Assignme
List allowGradeAssignmentUsers = allowGradeAssignmentUsers(assignmentReference);
receivers.retainAll(allowGradeAssignmentUsers);

String messageBody = emailUtil.getNotificationMessage(submission, "submission");

Map<String, Object> replacements = emailUtil.getSubmissionReplacements(submission);
if (notiOption.equals(AssignmentConstants.ASSIGNMENT_INSTRUCTOR_NOTIFICATIONS_EACH)) {
// send the message immediately
emailService.sendToUsers(receivers, emailUtil.getHeaders(null, "submission"), messageBody);
userMessagingService.message(new HashSet<>(receivers),
Message.builder().tool(AssignmentConstants.TOOL_ID).type("submission").build(),
Arrays.asList(new MessageMedium[] {MessageMedium.EMAIL}), replacements, NotificationService.NOTI_REQUIRED);
} else if (notiOption.equals(AssignmentConstants.ASSIGNMENT_INSTRUCTOR_NOTIFICATIONS_DIGEST)) {
// just send plain/text version for now
String digestMsgBody = emailUtil.getPlainTextNotificationMessage(submission, "submission");

// digest the message to each user
for (User user : receivers) {
digestService.digest(user.getId(), emailUtil.getSubject("submission"), digestMsgBody);
}
userMessagingService.message(new HashSet<>(receivers),
Message.builder().tool(AssignmentConstants.TOOL_ID).type("submission").build(),
Arrays.asList(new MessageMedium[] {MessageMedium.DIGEST}), replacements, NotificationService.NOTI_REQUIRED);
}
}
}
Expand All @@ -4528,7 +4546,10 @@ private void notificationToStudent(AssignmentSubmission submission) {
}
return null;
}).filter(Objects::nonNull).collect(Collectors.toSet());
emailService.sendToUsers(users, emailUtil.getHeaders(null, "submission"), emailUtil.getNotificationMessage(submission, "submission"));

userMessagingService.message(users,
Message.builder().tool(AssignmentConstants.TOOL_ID).type("submission").build(),
Arrays.asList(new MessageMedium[] {MessageMedium.EMAIL}), emailUtil.getSubmissionReplacements(submission), NotificationService.NOTI_REQUIRED);
}
}

Expand Down
Loading

0 comments on commit a010fe4

Please sign in to comment.