Skip to content

Commit 4302d85

Browse files
authored
Merge branch 'develop' into feature-2608/adjustments-to-volunteer-tracking
2 parents 94270a6 + 64736d8 commit 4302d85

File tree

23 files changed

+561
-376
lines changed

23 files changed

+561
-376
lines changed

server/build.gradle

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,8 @@ dependencies {
115115
implementation("io.micronaut.reactor:micronaut-reactor")
116116
implementation("io.micrometer:context-propagation")
117117

118+
implementation 'ch.digitalfondue.mjml4j:mjml4j:1.0.3'
119+
118120
testRuntimeOnly "org.seleniumhq.selenium:selenium-chrome-driver:$seleniumVersion"
119121
testRuntimeOnly "org.seleniumhq.selenium:selenium-firefox-driver:$seleniumVersion"
120122

@@ -213,3 +215,5 @@ java {
213215
}
214216

215217
run.jvmArgs('-Dcom.sun.management.jmxremote', '-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=8000')
218+
219+

server/src/main/java/com/objectcomputing/checkins/notifications/email/MailJetFactory.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
public class MailJetFactory {
1515

1616
public static final String HTML_FORMAT = "html";
17+
public static final String MJML_FORMAT = "mjml";
1718
public static final String TEXT_FORMAT = "text";
1819

1920
@Bean
@@ -34,6 +35,13 @@ EmailSender getHtmlSender(MailJetSender sender) {
3435
return sender;
3536
}
3637

38+
@Singleton
39+
@Named(MJML_FORMAT)
40+
EmailSender getMjmlSender(MailJetSender sender) {
41+
sender.setEmailFormat(MailJetSender.MJMLPART);
42+
return sender;
43+
}
44+
3745
@Singleton
3846
@Named(TEXT_FORMAT)
3947
EmailSender getTextSender(MailJetSender sender) {

server/src/main/java/com/objectcomputing/checkins/notifications/email/MailJetSender.java

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import com.mailjet.client.MailjetResponse;
66
import com.mailjet.client.errors.MailjetException;
77
import com.mailjet.client.resource.Emailv31;
8+
import ch.digitalfondue.mjml4j.Mjml4j;
89
import com.objectcomputing.checkins.exceptions.BadArgException;
910
import io.micronaut.context.annotation.Prototype;
1011
import io.micronaut.context.annotation.Requires;
@@ -20,6 +21,7 @@
2021
@Prototype
2122
@Requires(bean = MailJetConfiguration.class)
2223
public class MailJetSender implements EmailSender {
24+
public static final String MJMLPART = "MJMLPART";
2325

2426
private static final Logger LOG = LoggerFactory.getLogger(MailJetSender.class);
2527
private final MailjetClient client;
@@ -94,6 +96,16 @@ public void sendEmail(String fromName, String fromAddress, String subject, Strin
9496
.put("Email", fromAddress)
9597
.put("Name", fromName);
9698

99+
String modifiedEmailFormat = emailFormat;
100+
if (modifiedEmailFormat.equals(MJMLPART)) {
101+
// Convert the MJML to HTML and update the local email format.
102+
var configuration = new Mjml4j.Configuration("en");
103+
content = Mjml4j.render(content, configuration);
104+
modifiedEmailFormat = Emailv31.Message.HTMLPART;
105+
}
106+
final String localEmailFormat = modifiedEmailFormat;
107+
final String localContent = content;
108+
97109
emailBatches.forEach((recipientList) -> {
98110
MailjetRequest request = new MailjetRequest(Emailv31.resource)
99111
.property(Emailv31.MESSAGES, new JSONArray()
@@ -102,7 +114,7 @@ public void sendEmail(String fromName, String fromAddress, String subject, Strin
102114
.put(Emailv31.Message.TO, new JSONArray().put(sender))
103115
.put(Emailv31.Message.BCC, recipientList)
104116
.put(Emailv31.Message.SUBJECT, subject)
105-
.put(emailFormat, content)));
117+
.put(localEmailFormat, localContent)));
106118
try {
107119
MailjetResponse response = client.post(request);
108120
LOG.info("Mailjet response status: {}", response.getStatus());
@@ -134,10 +146,12 @@ public boolean sendEmailReceivesStatus(String fromName, String fromAddress, Stri
134146

135147
@Override
136148
public void setEmailFormat(String format) {
137-
if (format.equals(Emailv31.Message.HTMLPART) || format.equals(Emailv31.Message.TEXTPART)) {
149+
if (format.equals(MJMLPART) ||
150+
format.equals(Emailv31.Message.HTMLPART) ||
151+
format.equals(Emailv31.Message.TEXTPART)) {
138152
this.emailFormat = format;
139153
} else {
140-
throw new BadArgException(String.format("Email format must be either HTMLPART or TEXTPART, got %s", format));
154+
throw new BadArgException(String.format("Email format must be either HTMLPART, MJMLPART or TEXTPART, got %s", format));
141155
}
142156
}
143157
}

server/src/main/java/com/objectcomputing/checkins/services/feedback_request/FeedbackRequestServicesImpl.java

Lines changed: 155 additions & 116 deletions
Large diffs are not rendered by default.

server/src/main/java/com/objectcomputing/checkins/services/pulse/PulseEmail.java

Lines changed: 25 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,32 @@
55
import com.objectcomputing.checkins.notifications.email.MailJetFactory;
66
import com.objectcomputing.checkins.services.memberprofile.MemberProfileServices;
77

8+
import jakarta.inject.Singleton;
89
import jakarta.inject.Named;
910

11+
import org.slf4j.Logger;
12+
import org.slf4j.LoggerFactory;
13+
14+
import io.micronaut.context.annotation.Value;
15+
import io.micronaut.core.io.Readable;
16+
import io.micronaut.core.io.IOUtils;
17+
18+
import java.io.BufferedReader;
1019
import java.util.List;
1120

21+
@Singleton
1222
class PulseEmail {
23+
private static final Logger LOG = LoggerFactory.getLogger(PulseEmail.class);
1324
private final EmailSender emailSender;
1425
private final CheckInsConfiguration checkInsConfiguration;
1526
private final MemberProfileServices memberProfileServices;
1627

1728
private final String SUBJECT = "Check Out the Pulse Survey!";
29+
30+
@Value("classpath:mjml/pulse_email.mjml")
31+
private Readable pulseEmailTemplate;
1832

19-
public PulseEmail(@Named(MailJetFactory.HTML_FORMAT) EmailSender emailSender,
33+
public PulseEmail(@Named(MailJetFactory.MJML_FORMAT) EmailSender emailSender,
2034
CheckInsConfiguration checkInsConfiguration,
2135
MemberProfileServices memberProfileServices) {
2236
this.emailSender = emailSender;
@@ -25,43 +39,22 @@ public PulseEmail(@Named(MailJetFactory.HTML_FORMAT) EmailSender emailSender,
2539
}
2640

2741
private List<String> getActiveTeamMembers() {
28-
List<String> profiles = memberProfileServices.findAll().stream()
42+
List<String> addresses = memberProfileServices.findAll().stream()
2943
.filter(p -> p.getTerminationDate() == null)
3044
.map(p -> p.getWorkEmail())
3145
.toList();
32-
return profiles;
46+
return addresses;
3347
}
3448

3549
private String getEmailContent() {
36-
/*
37-
<mjml>
38-
<mj-body>
39-
<mj-section>
40-
<mj-column>
41-
<mj-divider border-color="#2559a7"></mj-divider>
42-
<mj-text font-size="16px" font-family="'Helvetica Neue', Helvetica, Arial, sans-serif" color="#4d4c4f">Please fill out your Pulse survey, if you haven't already done so. We want to know how you're doing!</mj-text>
43-
<mj-text font-size="16px" font-family="'Helvetica Neue', Helvetica, Arial, sans-serif" color="#4d4c4f">Click <a href="%s/pulse" target="_blank">here</a> to begin.</mj-text>
44-
</mj-column>
45-
</mj-section>
46-
</mj-body>
47-
</mjml>
48-
*/
49-
return String.format("""
50-
<html>
51-
<body>
52-
<div style="margin:0px auto;float: left; max-width:600px;">
53-
<p style="border-top:solid 4px #2559a7;font-size:1px;margin:0px auto;width:100%%;"></p>
54-
<p></p>
55-
<div style="font-family:'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:16px;line-height:1;text-align:left;color:#4d4c4f;">
56-
Please fill out your Pulse survey, if you haven't already done so. We want to know how you're doing!</div>
57-
<p></p>
58-
<div style="font-family:'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:16px;line-height:1;text-align:left;color:#4d4c4f;">
59-
Click <a href="%s/pulse" target="_blank">here</a> to begin.</div>
60-
</div>
61-
</div>
62-
</body>
63-
</html>
64-
""", checkInsConfiguration.getWebAddress());
50+
try {
51+
return String.format(IOUtils.readText(
52+
new BufferedReader(pulseEmailTemplate.asReader())),
53+
checkInsConfiguration.getWebAddress());
54+
} catch(Exception ex) {
55+
LOG.error(ex.toString());
56+
return "";
57+
}
6558
}
6659

6760
public void send() {

server/src/main/java/com/objectcomputing/checkins/services/pulse/PulseServicesImpl.java

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import lombok.Getter;
1212
import lombok.AllArgsConstructor;
1313

14+
import jakarta.inject.Inject;
1415
import jakarta.inject.Named;
1516
import jakarta.inject.Singleton;
1617

@@ -40,6 +41,9 @@ private class Frequency {
4041
private final SettingsServices settingsServices;
4142
private final Map<String, Boolean> sent = new HashMap<String, Boolean>();
4243

44+
@Inject
45+
private PulseEmail email;
46+
4347
private final DayOfWeek emailDay = DayOfWeek.MONDAY;
4448

4549
private String setting = "bi-weekly";
@@ -50,7 +54,7 @@ private class Frequency {
5054
);
5155

5256
public PulseServicesImpl(
53-
@Named(MailJetFactory.HTML_FORMAT) EmailSender emailSender,
57+
@Named(MailJetFactory.MJML_FORMAT) EmailSender emailSender,
5458
CheckInsConfiguration checkInsConfiguration,
5559
MemberProfileServices memberProfileServices,
5660
SettingsServices settingsServices) {
@@ -93,7 +97,7 @@ public void sendPendingEmail(LocalDate check) {
9397
LOG.info("The Pulse Email has already been sent today");
9498
} else {
9599
LOG.info("Sending Pulse Email");
96-
send();
100+
email.send();
97101
sent.put(key, true);
98102
}
99103
break;
@@ -110,10 +114,4 @@ public void sendPendingEmail(LocalDate check) {
110114
} while(start.isBefore(check) || start.isEqual(check));
111115
}
112116
}
113-
114-
private void send() {
115-
PulseEmail email = new PulseEmail(emailSender, checkInsConfiguration,
116-
memberProfileServices);
117-
email.send();
118-
}
119117
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# Templates
2+
3+
Place MJML templates here. If they are going to be used within a call to `String.format()`, be sure to double up on any percent signs (i.e., `width="100%%"`).
4+
5+
### Micronaut Usage
6+
7+
```java
8+
@Value("classpath:mjml/feedback_request.mjml")
9+
private Readable feedbackRequestTemplate;
10+
```
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<mjml>
2+
<mj-head>
3+
<mj-title>Feedback Request</mj-title>
4+
<mj-preview>Feedback Request</mj-preview>
5+
<mj-attributes>
6+
<mj-class name="preheader" color="#000000" font-size="11px" font-family="Ubuntu, Helvetica, Arial, sans-serif" padding="0px"></mj-class>
7+
</mj-attributes>
8+
</mj-head>
9+
<mj-body background-color="#e0f2ff">
10+
<mj-section background-color="#2559a7">
11+
<mj-column>
12+
<mj-image src="https://objectcomputing.com/files/6416/4277/8012/ObjectComputingLogo_version2_white.png" alt="logo" width="150px"></mj-image>
13+
</mj-column>
14+
</mj-section>
15+
<mj-hero mode="fluid-height" background-url="https://lh3.googleusercontent.com/pw/AL9nZEXvzBSrNroLHtqfW8W5_oM296XY7FPJqz15RNP3RBcf_XEkyZ0gn5JVkDCSTWA-loYTeVL5c-ycoAEOh_3dFBpPju1UmfGt7tLPCMFQdf5IVeHipmhyOV4fZnCWSl0n-b3tsHB4THfub4Mtknvz8R4t=w900-h600-no" background-color="#FFF" padding="100px 0px">
16+
<mj-text padding="20px" font-family="Helvetica" align="center" font-size="45px" line-height="45px" font-weight="900"> Give Your Feedback! </mj-text>
17+
18+
</mj-hero>
19+
<mj-section background-color="#ffffff">
20+
<mj-column>
21+
<mj-text>
22+
<h2>You have received a feedback request.</h2>
23+
</mj-text>
24+
<mj-text font-size="16px">Hello, %s!</mj-text>
25+
<mj-text font-size="16px"><strong>%s</strong> is requesting feedback %sfrom you.</mj-text>
26+
<mj-text font-size="16px">%s</mj-text>
27+
<mj-text font-size="16px">Please go to <a href="%s">your unique link</a> to complete this request.</mj-text>
28+
</mj-column>
29+
</mj-section>
30+
<mj-section background-color="#feb672" padding="10px">
31+
<mj-column vertical-align="top" width="100%%">
32+
<mj-text align="center" color="#FFF" font-size="16px">Thank you for everything you do!</mj-text>
33+
</mj-column>
34+
</mj-section>
35+
</mj-body>
36+
</mjml>
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<mjml>
2+
<mj-body>
3+
<mj-section>
4+
<mj-column>
5+
<mj-divider border-color="#2559a7"></mj-divider>
6+
<mj-text font-size="16px" font-family="'Helvetica Neue', Helvetica, Arial, sans-serif" color="#4d4c4f">Please fill out your Pulse survey, if you haven't already done so. We want to know how you're doing!</mj-text>
7+
<mj-text font-size="16px" font-family="'Helvetica Neue', Helvetica, Arial, sans-serif" color="#4d4c4f">Click <a href="%s/pulse" target="_blank">here</a> to begin.</mj-text>
8+
</mj-column>
9+
</mj-section>
10+
</mj-body>
11+
</mjml>
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<mjml>
2+
<mj-head>
3+
<mj-title>Self-Review Completion</mj-title>
4+
<mj-preview>Self-Reviews Completion for Reviewer</mj-preview>
5+
<mj-attributes>
6+
<mj-class name="preheader" color="#000000" font-size="11px" font-family="Ubuntu, Helvetica, Arial, sans-serif" padding="0px"></mj-class>
7+
</mj-attributes>
8+
</mj-head>
9+
<mj-body background-color="#e0f2ff">
10+
<mj-section background-color="#2559a7">
11+
<mj-column>
12+
<mj-image src="https://objectcomputing.com/files/6416/4277/8012/ObjectComputingLogo_version2_white.png" alt="logo" width="150px"></mj-image>
13+
</mj-column>
14+
</mj-section>
15+
<mj-hero mode="fluid-height" background-url="https://lh3.googleusercontent.com/pw/AL9nZEXvzBSrNroLHtqfW8W5_oM296XY7FPJqz15RNP3RBcf_XEkyZ0gn5JVkDCSTWA-loYTeVL5c-ycoAEOh_3dFBpPju1UmfGt7tLPCMFQdf5IVeHipmhyOV4fZnCWSl0n-b3tsHB4THfub4Mtknvz8R4t=w900-h600-no" background-color="#FFF" padding="100px 0px">
16+
<mj-text padding="20px" font-family="Helvetica" align="center" font-size="45px" line-height="45px" font-weight="900"> It's Your Turn! </mj-text>
17+
18+
</mj-hero>
19+
<mj-section background-color="#ffffff">
20+
<mj-column>
21+
<mj-text>
22+
<h2>It's time to begin your review of %s</h2>
23+
</mj-text>
24+
<mj-text font-size="16px">Hello, %s!</mj-text>
25+
<mj-text font-size="16px">%s has completed their self-review and it can be viewed <a href="%s">here</a>.</mj-text> <mj-text font-size="16px">It's your turn to share your thoughts and complete your review. Please complete your review before %s. </strong></mj-text>
26+
27+
</mj-column>
28+
</mj-section>
29+
<mj-section background-color="#feb672" padding="10px">
30+
<mj-column vertical-align="top" width="100%%">
31+
<mj-text align="center" color="#FFF" font-size="16px">Thank you for everything you do!</mj-text>
32+
</mj-column>
33+
</mj-section>
34+
</mj-body>
35+
</mjml>

0 commit comments

Comments
 (0)