Skip to content

Commit 9e84a98

Browse files
authored
Merge branch 'develop' into feature-1957/decline-received-feedback-request
2 parents 7427a46 + 437283b commit 9e84a98

File tree

60 files changed

+1750
-738
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+1750
-738
lines changed

README.md

Lines changed: 2 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
[![Gradle Build & Deploy - Develop](https://github.com/objectcomputing/check-ins/actions/workflows/gradle-build-development.yml/badge.svg)](https://github.com/objectcomputing/check-ins/actions/workflows/gradle-build-development.yml)
1+
[![Gradle Build & Deploy - Develop](https://github.com/objectcomputing/check-ins/actions/workflows/gradle-build-develop.yml/badge.svg)](https://github.com/objectcomputing/check-ins/actions/workflows/gradle-build-develop.yml)
22
[![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-2.1-4baaaa.svg)](CODE_OF_CONDUCT.md)
33

44
<!-- TOC -->
@@ -29,99 +29,9 @@ This web application is written in [Micronaut](https://micronaut.io) for uploadi
2929

3030
See [Setting up your environment](https://objectcomputing.github.io/check-ins/getting-started/setup/) for instructions on setting up your development environment.
3131

32-
# Project setup
33-
34-
There are two files required to run the application successfully. Both of which must be created and placed in
35-
`src/main/resources/secrets`.
36-
37-
### directory.json
38-
39-
This is a simple JSON file containing the identifier for the Google Drive folder into which the uploaded files are to be deposited.
40-
41-
```json
42-
{
43-
"upload-directory-id": "GOOGLE_DRIVE_FOLDER_ID"
44-
}
45-
```
46-
47-
### credentials.json
48-
49-
This JSON file should create the generated credentials for a service account that has access to write to the identified Google Drive folder. Information on configuring GCP service account credentials can be [found here](https://cloud.google.com/iam/docs/creating-managing-service-account-keys).
50-
51-
Note: Be sure that the target Google Drive folder has edit access granted to the service account.
52-
53-
<!-- the two required files are no longer needed -->
54-
5532
## Running the application
5633

57-
#### Installs
58-
59-
- [Podman](https://podman.io/)
60-
- [Podman-Compose](https://github.com/containers/podman-compose)
61-
62-
#### Building
63-
64-
1. Start the database in a Podman container:
65-
- Initialize and start a Podman VM:
66-
```shell
67-
$ podman machine init
68-
$ podman machine start
69-
```
70-
- Start the Podman container:
71-
```shell
72-
$ podman-compose up
73-
```
74-
2. In a different terminal, execute the following commands :
75-
76-
- On Bash/Zsh -
77-
78-
```sh
79-
$ OAUTH_CLIENT_ID=<Insert_Client_ID> OAUTH_CLIENT_SECRET=<Insert_Client_Secret> MICRONAUT_ENVIRONMENTS=local ./gradlew build
80-
```
81-
82-
```sh
83-
$ ./gradlew assemble
84-
```
85-
86-
```sh
87-
$ OAUTH_CLIENT_ID=<Insert_Client_ID> OAUTH_CLIENT_SECRET=<Insert_Client_Secret> MICRONAUT_ENVIRONMENTS=local ./gradlew run
88-
```
89-
90-
- On Powershell/Command-Line -
91-
Set the following environment variables -
92-
```sh
93-
MICRONAUT_ENVIRONMENTS=local
94-
OAUTH_CLIENT_ID=<Client_ID>
95-
OAUTH_CLIENT_SECRET=<Client_Secret>
96-
```
97-
Build and run the application -
98-
```sh
99-
$ gradlew build
100-
```
101-
```sh
102-
$ gradlew assemble
103-
```
104-
```sh
105-
$ gradlew run
106-
```
107-
108-
3. Open the browser to run the application at `http://localhost:8080`
109-
4. Access swagger-UI at - `http://localhost:8080/swagger-ui`
110-
111-
# Testing
112-
113-
1. To run the server tests, run the following:
114-
```sh
115-
$ ./gradlew :server:check
116-
```
117-
2. To run the UI tests, run the following:
118-
```sh
119-
$ ./gradlew :web-ui:check
120-
```
121-
3. To update snapshots, run the following:
122-
```sh
123-
$ cd web-ui && yarn test -u
124-
```
34+
See [Running the Application](https://objectcomputing.github.io/check-ins/getting-started/running/) for instructions on running the application locally.
12535

12636
# Contributing
12737

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
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package com.objectcomputing.checkins.services.email;
2+
3+
import io.micronaut.data.annotation.TypeDef;
4+
import io.micronaut.data.model.DataType;
5+
import io.swagger.v3.oas.annotations.media.Schema;
6+
import jakarta.persistence.Column;
7+
import jakarta.persistence.Entity;
8+
import jakarta.persistence.Id;
9+
import jakarta.persistence.Table;
10+
import jakarta.validation.constraints.NotNull;
11+
import lombok.AllArgsConstructor;
12+
import lombok.Getter;
13+
import lombok.Setter;
14+
15+
import java.util.Objects;
16+
17+
@Setter
18+
@Getter
19+
@Entity
20+
@AllArgsConstructor
21+
@Table(name = "automated_email_sent")
22+
public class AutomatedEmail {
23+
@Id
24+
@Column(name = "id")
25+
@TypeDef(type = DataType.STRING)
26+
@Schema(description = "id of the email")
27+
private String id;
28+
29+
@Override
30+
public boolean equals(Object o) {
31+
if (this == o) return true;
32+
if (o == null || getClass() != o.getClass()) return false;
33+
AutomatedEmail email = (AutomatedEmail) o;
34+
return id.equals(email.id);
35+
}
36+
37+
@Override
38+
public int hashCode() {
39+
return id.hashCode();
40+
}
41+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package com.objectcomputing.checkins.services.email;
2+
3+
import io.micronaut.data.jdbc.annotation.JdbcRepository;
4+
import io.micronaut.data.model.query.builder.sql.Dialect;
5+
import io.micronaut.data.repository.CrudRepository;
6+
import jakarta.validation.Valid;
7+
import jakarta.validation.constraints.NotNull;
8+
9+
@JdbcRepository(dialect = Dialect.POSTGRES)
10+
public interface AutomatedEmailRepository extends CrudRepository<AutomatedEmail, String> {
11+
12+
@Override
13+
<S extends AutomatedEmail> S save(@Valid @NotNull S entity);
14+
15+
}

0 commit comments

Comments
 (0)