From 46750b7690854d4275d3efd5e91849920592d17f Mon Sep 17 00:00:00 2001 From: Sam Ottenhoff Date: Wed, 29 Jan 2025 16:30:50 -0500 Subject: [PATCH 1/7] SAK-50853 wip --- .../rest/GradebookNgEntityProvider.java | 41 +++++++++---------- .../src/SakaiSubmissionMessager.js | 10 ++++- 2 files changed, 27 insertions(+), 24 deletions(-) diff --git a/gradebookng/tool/src/java/org/sakaiproject/gradebookng/rest/GradebookNgEntityProvider.java b/gradebookng/tool/src/java/org/sakaiproject/gradebookng/rest/GradebookNgEntityProvider.java index 333fcd3a0955..acd69cc03f17 100644 --- a/gradebookng/tool/src/java/org/sakaiproject/gradebookng/rest/GradebookNgEntityProvider.java +++ b/gradebookng/tool/src/java/org/sakaiproject/gradebookng/rest/GradebookNgEntityProvider.java @@ -359,40 +359,37 @@ public ActionReturn listMessageRecipients(final EntityView view, final Map params) { + int success = 0; Set recipients = getRecipients(params); - if (!recipients.isEmpty()) { recipients.add(getCurrentUserId()); + List users = userDirectoryService.getUsers(recipients); - List users = recipients.stream().map(s -> { - try { - return userDirectoryService.getUser(s); - } catch (UserNotDefinedException unde) { - return null; - } - }).collect(Collectors.toList()); - - if (users.contains(null)) { - String errorMsg = "At least one of the students to message is null. No messsages sent."; - log.warn(errorMsg); - throw new EntityException(errorMsg, "", HttpServletResponse.SC_INTERNAL_SERVER_ERROR); - } else { + if (!users.isEmpty()) { String from = serverConfigurationService.getSmtpFrom(); List headers = new ArrayList<>(); String subject = (String) params.get("subject"); headers.add("Subject: " + subject); headers.add("From: " + "\"" + serverConfigurationService.getString("ui.service", "Sakai") + "\" <" + from + ">"); - users.forEach(u -> emailService.send(from, u.getEmail(), subject, (String) params.get("body"), null, null, headers)); - Map data = new HashMap<>(); - data.put("result", "SUCCESS"); - return new ActionReturn(data); + + for (User u : users) { + if (u != null && u.getEmail() != null && !u.getEmail().isEmpty()) { + try { + emailService.send(from, u.getEmail(), subject, (String) params.get("body"), null, null, headers); + success++; + } catch (Exception e) { + log.error("Error sending email to {}", u.getEmail(), e); + } + } + } } - } else { - Map data = new HashMap<>(); - data.put("result", "SUCCESS"); - return new ActionReturn(data); } + + Map data = new HashMap<>(); + data.put("result", "SUCCESS"); + data.put("num_sent", success); + return new ActionReturn(data); } /** diff --git a/webcomponents/tool/src/main/frontend/packages/sakai-submission-messager/src/SakaiSubmissionMessager.js b/webcomponents/tool/src/main/frontend/packages/sakai-submission-messager/src/SakaiSubmissionMessager.js index 0a8ffa14a56b..06c5df2f30b0 100644 --- a/webcomponents/tool/src/main/frontend/packages/sakai-submission-messager/src/SakaiSubmissionMessager.js +++ b/webcomponents/tool/src/main/frontend/packages/sakai-submission-messager/src/SakaiSubmissionMessager.js @@ -21,6 +21,7 @@ export class SakaiSubmissionMessager extends SakaiElement { recipientsToCheck: Array, sending: Boolean, recipientsRequested: { type: Boolean }, + numSent: { type: Number }, }; constructor() { @@ -33,6 +34,7 @@ export class SakaiSubmissionMessager extends SakaiElement { this._i18n = {}; this.reset(); this.loadTranslations("submission-messager").then(t => this._i18n = t); + this.numSent = 0; } shouldUpdate() { @@ -151,7 +153,9 @@ export class SakaiSubmissionMessager extends SakaiElement { ` : nothing} ${this.success ? html` -
${this._i18n.success}
+
+ ${this._i18n.success} ${this.numSent} ${this._i18n.messages_sent || "messages sent"}. +
` : nothing} ${this.error ? html`
${this._i18n.error}
@@ -198,6 +202,7 @@ export class SakaiSubmissionMessager extends SakaiElement { this.maxScore = ""; this.validationError = ""; this.recipientsRequested = false; + this.numSent = 0; } getFormData() { @@ -248,8 +253,9 @@ export class SakaiSubmissionMessager extends SakaiElement { }) .then(data => { - if (data.result) { + if (data.result === "SUCCESS") { this.success = true; + this.numSent = data.num_sent; this.sending = false; window.setTimeout(() => { this.success = false; From d5e7875176040bd9ecaa5a7338517461d690be4a Mon Sep 17 00:00:00 2001 From: Sam Ottenhoff Date: Wed, 29 Jan 2025 16:46:27 -0500 Subject: [PATCH 2/7] SAK-50853-b --- .../rest/GradebookNgEntityProvider.java | 5 ++- .../bundle/submission-messager.properties | 2 ++ .../src/SakaiSubmissionMessager.js | 33 +++++++++++-------- 3 files changed, 25 insertions(+), 15 deletions(-) diff --git a/gradebookng/tool/src/java/org/sakaiproject/gradebookng/rest/GradebookNgEntityProvider.java b/gradebookng/tool/src/java/org/sakaiproject/gradebookng/rest/GradebookNgEntityProvider.java index acd69cc03f17..37f12b1c14b8 100644 --- a/gradebookng/tool/src/java/org/sakaiproject/gradebookng/rest/GradebookNgEntityProvider.java +++ b/gradebookng/tool/src/java/org/sakaiproject/gradebookng/rest/GradebookNgEntityProvider.java @@ -377,7 +377,10 @@ public ActionReturn messageStudents(final EntityView view, final Map +
+
${this._i18n.success}
+

${this.formatMessage(this._i18n.messages_sent_detail || "Successfully sent messages to {numSent} recipients.", { numSent: this.numSent })}

+ +
+ + `; + } return html`
@@ -152,11 +165,6 @@ export class SakaiSubmissionMessager extends SakaiElement {
` : nothing} - ${this.success ? html` -
- ${this._i18n.success} ${this.numSent} ${this._i18n.messages_sent || "messages sent"}. -
- ` : nothing} ${this.error ? html`
${this._i18n.error}
` : nothing} @@ -195,7 +203,6 @@ export class SakaiSubmissionMessager extends SakaiElement { this.action = "1"; this.subject = ""; this.body = ""; - this.success = false; this.error = false; this.recipientsToCheck = []; this.minScore = ""; @@ -203,6 +210,7 @@ export class SakaiSubmissionMessager extends SakaiElement { this.validationError = ""; this.recipientsRequested = false; this.numSent = 0; + this.success = false; } getFormData() { @@ -243,25 +251,22 @@ export class SakaiSubmissionMessager extends SakaiElement { fetch("/direct/gbng/messageStudents.json", { method: "POST", cache: "no-cache", credentials: "same-origin", body: formData }) .then(r => { - if (r.ok) { this.error = false; return r.json(); } this.error = true; - }) .then(data => { - if (data.result === "SUCCESS") { - this.success = true; this.numSent = data.num_sent; this.sending = false; - window.setTimeout(() => { - this.success = false; - this.reset(); - }, 1500); + this.success = true; } }); } + + formatMessage(msg, values) { + return msg.replace(/\{(\w+)\}/g, (match, key) => values[key] !== undefined ? values[key] : match); + } } From 726db36fb96ffe3f124126645422eef680cdbab1 Mon Sep 17 00:00:00 2001 From: Adrian Fish Date: Thu, 30 Jan 2025 12:48:08 +0000 Subject: [PATCH 3/7] ES6 Cleanup Used state = true for all the internal state vars Removed some unnecessary member var assignments Removed formatMessage, tr does the job --- .../src/SakaiSubmissionMessager.js | 50 ++++++++----------- 1 file changed, 21 insertions(+), 29 deletions(-) diff --git a/webcomponents/tool/src/main/frontend/packages/sakai-submission-messager/src/SakaiSubmissionMessager.js b/webcomponents/tool/src/main/frontend/packages/sakai-submission-messager/src/SakaiSubmissionMessager.js index 2a56929d980e..63ac62953027 100644 --- a/webcomponents/tool/src/main/frontend/packages/sakai-submission-messager/src/SakaiSubmissionMessager.js +++ b/webcomponents/tool/src/main/frontend/packages/sakai-submission-messager/src/SakaiSubmissionMessager.js @@ -1,7 +1,7 @@ import { SakaiElement } from "@sakai-ui/sakai-element"; import { html, nothing } from "lit"; import { ifDefined } from "lit/directives/if-defined.js"; -import "@sakai-ui/sakai-group-picker"; +import "@sakai-ui/sakai-group-picker/sakai-group-picker.js"; import "@spectrum-web-components/progress-bar/sp-progress-bar.js"; export class SakaiSubmissionMessager extends SakaiElement { @@ -9,32 +9,26 @@ export class SakaiSubmissionMessager extends SakaiElement { static properties = { assignmentId: { attribute: "assignment-id", type: String }, - groups: { type: Array }, - title: String, - action: String, - subject: String, - body: String, - error: Boolean, - success: Boolean, - groupId: String, - validationError: String, - recipientsToCheck: Array, - sending: Boolean, - recipientsRequested: { type: Boolean }, - numSent: { type: Number }, + title: { type: String }, + action: { state: true }, + subject: { state: true }, + body: { state: true }, + error: { state: true }, + success: { state: true }, + groupId: { state: true }, + validationError: { state: true }, + recipientsToCheck: { state: true }, + sending: { state: true }, + recipientsRequested: { state: true }, + numSent: { state: true }, }; constructor() { super(); - this.groups = []; - this.recipientsToCheck = []; - this.recipientsRequested = false; - this._i18n = {}; this.reset(); this.loadTranslations("submission-messager").then(t => this._i18n = t); - this.numSent = 0; } shouldUpdate() { @@ -47,9 +41,9 @@ export class SakaiSubmissionMessager extends SakaiElement {
${this._i18n.success}
-

${this.formatMessage(this._i18n.messages_sent_detail || "Successfully sent messages to {numSent} recipients.", { numSent: this.numSent })}

+

${this.tr("messages_sent_detail", { numSent: this.numSent })}

@@ -57,7 +51,7 @@ export class SakaiSubmissionMessager extends SakaiElement { } return html` -
+
${this.validationError ? html`